--- /dev/null
+================
+ Docutils_ Bugs
+================
+
+:Author: David Goodger; open to all Docutils developers
+:Contact: goodger@python.org
+:Date: $Date: 2017-06-09 13:02:35 +0200 (Fr, 09. Jun 2017) $
+:Revision: $Revision: 8103 $
+:Copyright: This document has been placed in the public domain.
+
+.. _Docutils: http://docutils.sourceforge.net/
+
+
+Bugs in Docutils?!? Yes, we do have a few. Some are old-timers that
+tend to stay in the shadows and don't bother anybody. Once in a while
+new bugs are born. From time to time some bugs (new and old) crawl
+out into the light and must be dealt with. Icky.
+
+This document describes how to report a bug, and lists known bugs.
+
+.. contents::
+
+
+How To Report A Bug
+===================
+
+If you think you've discovered a bug, please read through these
+guidelines before reporting it.
+
+First, make sure it's a new bug:
+
+* Please check the list of `known bugs`_ below and the `SourceForge
+ Bug Tracker`_ to see if it has already been reported.
+
+* Are you using the very latest version of Docutils? The bug may have
+ already been fixed. Please get the latest version of Docutils from
+ the repository_ or from the current snapshot_ and check again. Even
+ if your bug has not been fixed, others probably have, and you're
+ better off with the most up-to-date code.
+
+ If you don't have time to check the latest snapshot, please report
+ the bug anyway. We'd rather tell you that it's already fixed than
+ miss reports of unfixed bugs.
+
+* If Docutils does not behave the way you expect, look in the
+ documentation_ (don't forget the FAQ_!) and `mailing list archives`_
+ for evidence that it should behave the way you expect.
+
+If you're not sure, please ask on the Docutils-users_ mailing list
+first.
+
+---------------------------------------------------------------------
+
+If it's a new bug, the most important thing you can do is to write a
+simple description and a recipe that reproduces the bug. Try to
+create a `minimal example`_ that demonstrates the bug. The easier you
+make it to understand and track down the bug, the more likely a fix
+will be.
+
+.. _minimal example:
+
+.. sidebar:: minimal example
+
+ A `minimal working example` is a complete example which is as as small and
+ simple as possible. It should be complete and working, so that
+
+ * you cannot accidentally omit information important to diagnosing
+ the problem and
+ * the person responding can just copy-and-paste the code to try it out.
+
+ To construct an example which is as small as possible, the rule
+ quite simple: *remove/leave out anything which is not necessary*.
+
+ See also: `What is a minimal working example?`__, `LaTeX FAQ`__
+
+ __ http://www.minimalbeispiel.de/mini-en.html
+ __ http://www.tex.ac.uk/cgi-bin/texfaq2html?label=minxampl
+
+Now you're ready to write the bug report. Please include:
+
+* A clear description of the bug. Describe how you expected Docutils
+ to behave, and contrast that with how it actually behaved. While
+ the bug may seem obvious to you, it may not be so obvious to someone
+ else, so it's best to avoid a guessing game.
+
+* A complete description of the environment in which you reproduced
+ the bug:
+
+ - Your operating system & version.
+ - The version of Python (``python -V``).
+ - The version of Docutils (use the "-V" option to most Docutils
+ front-end tools).
+ - Any private modifications you made to Docutils.
+ - Anything else that could possibly be relevant. Err on the side
+ of too much information, rather than too little.
+
+* A literal transcript of the *exact* command you ran, and the *exact*
+ output. Use the "--traceback" option to get a complete picture.
+
+* The exact input and output files. Create a `minimal example`_
+ of the failing behaviour — it is better to attach complete files
+ to your bug report than to include just a summary or excerpt.
+
+* If you also want to include speculation as to the cause, and even a
+ patch to fix the bug, that would be great!
+
+The best place to send your bug report is to the `SourceForge Bug
+Tracker`_. That way, it won't be misplaced or forgotten. In fact, an
+open bug report on SourceForge is a constant irritant that begs to be
+squashed.
+
+Thank you!
+
+(This section was inspired by the `Subversion project's`__ BUGS__
+file.)
+
+__ http://subversion.tigris.org/
+__ http://svn.collab.net/viewcvs/svn/trunk/BUGS?view=markup
+
+.. _repository: docs/dev/repository.html
+.. _snapshot: http://docutils.sourceforge.net/#download
+.. _documentation: docs/
+.. _FAQ: FAQ.html
+.. _mailing list archives: http://docutils.sf.net/#mailing-lists
+.. _Docutils-users: docs/user/mailing-lists.html#docutils-users
+.. _SourceForge Bug Tracker:
+ http://sourceforge.net/p/docutils/bugs/
+
+
+Known Bugs
+==========
+
+Also see the `SourceForge Bug Tracker`_.
+
+* .. _error reporting:
+
+ Calling rst2s5.py with a non-existent theme (``--theme
+ does_not_exist``)
+ causes exceptions. Such errors should be handled more gracefully.
+
+* The "stylesheet" setting (a URL, to be used verbatim) should be
+ allowed to be combined with "embed_stylesheet". The stylesheet data
+ should be read in using urllib. There was an assumption that a
+ stylesheet to be embedded should exist as a file on the local
+ system, and only the "stylesheet_path" setting should be used.
+
+* ``utils.relative_path()`` sometimes returns absolute _`paths on
+ Windows` (like ``C:/test/foo.css``) where it could have chosen a
+ relative path.
+
+ Furthermore, absolute pathnames are inserted verbatim, like
+ ``href="C:/test/foo.css"`` instead of
+ ``href="file:///C:/test/foo.css"``.
+
+ .. gmane web interface is down.
+ TODO: find this article in the Sourceforge mail archives
+ For details, see `this posting by Alan G. Isaac
+ <http://article.gmane.org/gmane.text.docutils.user/1569>`_.
+
+* Footnote label "5" should be "4" when processing the following
+ input::
+
+ ref [#abc]_ [#]_ [1]_ [#4]_
+
+ .. [#abc] footnote
+ .. [#] two
+ .. [1] one
+ .. [#4] four
+
+ Output::
+
+ <document source="<stdin>">
+ <paragraph>
+ ref
+ <footnote_reference auto="1" ids="id1" refid="abc">
+ 2
+
+ <footnote_reference auto="1" ids="id2" refid="id5">
+ 3
+
+ <footnote_reference ids="id3" refid="id6">
+ 1
+
+ <footnote_reference auto="1" ids="id4" refid="id7">
+ 5
+ <footnote auto="1" backrefs="id1" ids="abc" names="abc">
+ <label>
+ 2
+ <paragraph>
+ footnote
+ <footnote auto="1" backrefs="id2" ids="id5" names="3">
+ <label>
+ 3
+ <paragraph>
+ two
+ <footnote backrefs="id3" ids="id6" names="1">
+ <label>
+ 1
+ <paragraph>
+ one
+ <footnote auto="1" backrefs="id4" ids="id7" names="4">
+ <label>
+ 5
+ <paragraph>
+ four
+
+* IDs are based on names. Explicit hyperlink targets have priority
+ over implicit targets. But if an explicit target comes after an
+ implicit target with the same name, the ID of the first (implicit)
+ target remains based on the implicit name. Since HTML fragment
+ identifiers based on the IDs, the first target keeps the name. For
+ example::
+
+ .. contents::
+
+ Section
+ =======
+
+ .. _contents:
+
+ Subsection
+ ----------
+
+ text with a reference to contents_ and section_
+
+ .. _section:
+
+ This paragraph is explicitly targeted with the name "section".
+
+ When processed to HTML, the 2 internal hyperlinks (to "contents" &
+ "section") will work fine, but hyperlinks from outside the document
+ using ``href="...#contents"`` and ``href="...#section"`` won't work.
+ Such external links will connect to the implicit targets (table of
+ contents and "Section" title) instead of the explicit targets
+ ("Subsection" title and last paragraph).
+
+ Hyperlink targets with duplicate names should be assigned new IDs
+ unrelated to the target names (i.e., "id"-prefix serial IDs).
+
+* The "contents" ID of the local table of contents in
+ ``test/functional/expected/standalone_rst_pseudoxml.txt`` is lost in
+ the HTML output at
+ ``test/functional/expected/standalone_rst_html4css1.html``.
+
+* _`Blank first columns` in simple tables with explicit row separators
+ silently swallow their input. They should at least produce system
+ error messages. But, with explicit row separators, the meaning is
+ unambiguous and ought to be supported::
+
+ ============== ==========
+ Table with row separators
+ ============== ==========
+ and blank
+ -------------- ----------
+ entries
+ -------------- ----------
+ in first
+ -------------- ----------
+ columns.
+ ============== ==========
+
+ Added a commented-out test case to
+ test/test_parsers/test_rst/test_SimpleTableParser.py.
+
+* _`Footnote references with hyperlink targets` cause a possibly
+ invalid node tree and make the HTML writer crash::
+
+ $ rst2pseudoxml.py
+ [1]_
+
+ .. _1: URI
+ <document source="<stdin>">
+ <paragraph>
+ <footnote_reference ids="id1" refuri="URI">
+ 1
+ <target ids="id2" names="1" refuri="URI">
+
+* Anonymous references have "name" attributes. Should they? Are they
+ used? See ``test/test_parsers/test_rst/test_inline_markup.py``.
+
+* <reference> elements have a "name" attribute, not "names". The
+ attribute should be "names"; this is an inconsistency.
+
+\f
+..
+ Local Variables:
+ mode: indented-text
+ indent-tabs-mode: nil
+ sentence-end-double-space: t
+ fill-column: 70
+ End:
--- /dev/null
+==================
+ Copying Docutils
+==================
+
+:Author: David Goodger
+:Contact: goodger@python.org
+:Date: $Date: 2015-05-08 17:56:32 +0200 (Fr, 08. Mai 2015) $
+:Web site: http://docutils.sourceforge.net/
+:Copyright: This document has been placed in the public domain.
+
+Most of the files included in this project have been placed in the
+public domain, and therefore have no license requirements and no
+restrictions on copying or usage; see the `Public Domain Dedication`_
+below. There are a few exceptions_, listed below.
+Files in the Sandbox_ are not distributed with Docutils releases and
+may have different license terms.
+
+
+Public Domain Dedication
+========================
+
+The persons who have associated their work with this project (the
+"Dedicator": David Goodger and the many contributors to the Docutils
+project) hereby dedicate the entire copyright, less the exceptions_
+listed below, in the work of authorship known as "Docutils" identified
+below (the "Work") to the public domain.
+
+The primary repository for the Work is the Internet World Wide Web
+site <http://docutils.sourceforge.net/>. The Work consists of the
+files within the "docutils" module of the Docutils project Subversion
+repository (Internet host docutils.svn.sourceforge.net, filesystem path
+/svnroot/docutils), whose Internet web interface is located at
+<http://docutils.svn.sourceforge.net/viewvc/docutils/>. Files dedicated to the
+public domain may be identified by the inclusion, near the beginning
+of each file, of a declaration of the form::
+
+ Copyright: This document/module/DTD/stylesheet/file/etc. has been
+ placed in the public domain.
+
+Dedicator makes this dedication for the benefit of the public at large
+and to the detriment of Dedicator's heirs and successors. Dedicator
+intends this dedication to be an overt act of relinquishment in
+perpetuity of all present and future rights under copyright law,
+whether vested or contingent, in the Work. Dedicator understands that
+such relinquishment of all rights includes the relinquishment of all
+rights to enforce (by lawsuit or otherwise) those copyrights in the
+Work.
+
+Dedicator recognizes that, once placed in the public domain, the Work
+may be freely reproduced, distributed, transmitted, used, modified,
+built upon, or otherwise exploited by anyone for any purpose,
+commercial or non-commercial, and in any way, including by methods
+that have not yet been invented or conceived.
+
+(This dedication is derived from the text of the `Creative Commons
+Public Domain Dedication`. [#]_)
+
+.. [#] Creative Commons has `retired this legal tool`__ and does not
+ recommend that it be applied to works: This tool is based on United
+ States law and may not be applicable outside the US. For dedicating new
+ works to the public domain, Creative Commons recommend the replacement
+ Public Domain Dedication CC0_ (CC zero, "No Rights Reserved"). So does
+ the Free Software Foundation in its license-list_.
+
+ __ http://creativecommons.org/retiredlicenses
+ .. _CC0: http://creativecommons.org/about/cc0
+
+Exceptions
+==========
+
+The exceptions to the `Public Domain Dedication`_ above are:
+
+* docutils/writers/s5_html/themes/default/iepngfix.htc:
+
+ IE5.5+ PNG Alpha Fix v1.0 by Angus Turnbull
+ <http://www.twinhelix.com>. Free usage permitted as long as
+ this notice remains intact.
+
+* docutils/utils/math/__init__.py,
+ docutils/utils/math/latex2mathml.py,
+ docutils/writers/xetex/__init__.py,
+ docutils/writers/latex2e/docutils-05-compat.sty,
+ docs/user/docutils-05-compat.sty.txt,
+ docutils/utils/error_reporting.py,
+ docutils/test/transforms/test_smartquotes.py:
+
+ Copyright © Günter Milde.
+ Released under the terms of the `2-Clause BSD license`_
+ (`local copy <licenses/BSD-2-Clause.txt>`__).
+
+* docutils/utils/smartquotes.py
+
+ Copyright © 2011 Günter Milde,
+ based on `SmartyPants`_ © 2003 John Gruber
+ (released under a 3-Clause BSD license included in the file)
+ and smartypants.py © 2004, 2007 Chad Miller.
+ Released under the terms of the `2-Clause BSD license`_
+ (`local copy <licenses/BSD-2-Clause.txt>`__).
+
+ .. _SmartyPants: http://daringfireball.net/projects/smartypants/
+
+* docutils/utils/math/math2html.py,
+ docutils/writers/html4css1/math.css
+
+ Copyright © Alex Fernández
+ These files are part of eLyXer_, released under the `GNU
+ General Public License`_ version 3 or later. The author relicensed
+ them for Docutils under the terms of the `2-Clause BSD license`_
+ (`local copy <licenses/BSD-2-Clause.txt>`__).
+
+ .. _eLyXer: http://www.nongnu.org/elyxer/
+
+* docutils/utils/roman.py, copyright by Mark Pilgrim, released under the
+ `Python 2.1.1 license`_ (`local copy`__).
+
+ __ licenses/python-2-1-1.txt
+
+* tools/editors/emacs/rst.el, copyright by Free Software Foundation,
+ Inc., released under the `GNU General Public License`_ version 3 or
+ later (`local copy`__).
+
+ __ licenses/gpl-3-0.txt
+
+The `2-Clause BSD license`_ and the Python licenses are OSI-approved_
+and GPL-compatible_.
+
+Plaintext versions of all the linked-to licenses are provided in the
+licenses_ directory.
+
+.. _sandbox: http://docutils.sourceforge.net/sandbox/README.html
+.. _licenses: licenses/
+.. _Python 2.1.1 license: http://www.python.org/2.1.1/license.html
+.. _GNU General Public License: http://www.gnu.org/copyleft/gpl.html
+.. _2-Clause BSD license: http://www.spdx.org/licenses/BSD-2-Clause
+.. _OSI-approved: http://opensource.org/licenses/
+.. _license-list:
+.. _GPL-compatible: http://www.gnu.org/licenses/license-list.html
--- /dev/null
+.. -*- coding: utf-8 -*-
+
+
+.. NOTE TO MAINTAINERS: Please add new questions to the end of their
+ sections, so section/question numbers remain stable.
+
+
+===========================================
+ Docutils FAQ (Frequently Asked Questions)
+===========================================
+
+:Date: $Date: 2016-02-26 22:40:17 +0100 (Fr, 26. Feb 2016) $
+:Revision: $Revision: 7934 $
+:Web site: http://docutils.sourceforge.net/
+:Copyright: This document has been placed in the public domain.
+
+.. contents::
+.. sectnum::
+
+
+This is a work in progress. If you are reading a local copy, the
+`master copy`_ might be newer. This document uses are relative links;
+if they don't work, please use the `master copy`_.
+
+Please feel free to ask questions and/or provide answers; send email
+to the `Docutils-users`_ mailing list. Project members should feel
+free to edit the source text file directly.
+
+.. _master copy: http://docutils.sourceforge.net/FAQ.html
+.. _let us know:
+.. _Docutils-users: docs/user/mailing-lists.html#docutils-users
+
+
+
+Docutils
+========
+
+What is Docutils?
+-----------------
+
+Docutils_ is a system for processing plaintext documentation into
+useful formats, such as HTML, XML, and LaTeX. It supports multiple
+types of input, such as standalone files (implemented), inline
+documentation from Python modules and packages (under development),
+`PEPs (Python Enhancement Proposals)`_ (implemented), and others as
+discovered.
+
+The Docutils distribution consists of:
+
+* a library (the "docutils" package), which `can be used by client
+ code`_;
+* several `front-end tools`_ (such as ``rst2html.py``, which converts
+ reStructuredText input into HTML output);
+* a `test suite`_; and
+* extensive documentation_.
+
+For an overview of the Docutils project implementation, see `PEP
+258`_, "Docutils Design Specification".
+
+Docutils is implemented in Python_.
+
+.. _Docutils: http://docutils.sourceforge.net/
+.. _PEPs (Python Enhancement Proposals):
+ http://www.python.org/peps/pep-0012.html
+.. _can be used by client code: docs/api/publisher.html
+.. _front-end tools: docs/user/tools.html
+.. _test suite: docs/dev/testing.html
+.. _documentation: docs/index.html
+.. _PEP 258: http://www.python.org/peps/pep-0258.html
+.. _Python: http://www.python.org/
+
+
+Why is it called "Docutils"?
+----------------------------
+
+Docutils is short for "Python Documentation Utilities". The name
+"Docutils" was inspired by "Distutils", the Python Distribution
+Utilities architected by Greg Ward, a component of Python's standard
+library.
+
+The earliest known use of the term "docutils" in a Python context was
+a `fleeting reference`__ in a message by Fred Drake on 1999-12-02 in
+the Python Doc-SIG mailing list. It was suggested `as a project
+name`__ on 2000-11-27 on Doc-SIG, again by Fred Drake, in response to
+a question from Tony "Tibs" Ibbs: "What do we want to *call* this
+thing?". This was shortly after David Goodger first `announced
+reStructuredText`__ on Doc-SIG.
+
+Tibs used the name "Docutils" for `his effort`__ "to document what the
+Python docutils package should support, with a particular emphasis on
+documentation strings". Tibs joined the current project (and its
+predecessors) and graciously donated the name.
+
+For more history of reStructuredText and the Docutils project, see `An
+Introduction to reStructuredText`_.
+
+Please note that the name is "Docutils", not "DocUtils" or "Doc-Utils"
+or any other variation. It is pronounced as in "DOCumentation
+UTILitieS", with emphasis on the first syllable.
+
+.. _An Introduction to reStructuredText: docs/ref/rst/introduction.html
+__ http://mail.python.org/pipermail/doc-sig/1999-December/000878.html
+__ http://mail.python.org/pipermail/doc-sig/2000-November/001252.html
+__ http://mail.python.org/pipermail/doc-sig/2000-November/001239.html
+__ http://homepage.ntlworld.com/tibsnjoan/docutils/STpy.html
+
+
+Is there a GUI authoring environment for Docutils?
+--------------------------------------------------
+
+DocFactory_ is under development. It uses wxPython and looks very
+promising.
+
+.. _DocFactory:
+ http://docutils.sf.net/sandbox/gschwant/docfactory/doc/
+
+
+What is the status of the Docutils project?
+-------------------------------------------
+
+Although useful and relatively stable, Docutils is experimental code,
+with APIs and architecture subject to change.
+
+Our highest priority is to fix bugs as they are reported. So the
+latest code from the repository_ (or the snapshots_) is almost always
+the most stable (bug-free) as well as the most featureful.
+
+
+What is the Docutils project release policy?
+--------------------------------------------
+
+It's "release early & often". We also have automatically-generated
+snapshots_ which always contain the latest code from the repository_.
+As the project matures, we may formalize on a
+stable/development-branch scheme, but we're not using anything like
+that yet.
+
+.. _repository: docs/dev/repository.html
+.. _snapshots: http://docutils.sourceforge.net/#download
+
+
+reStructuredText
+================
+
+What is reStructuredText?
+-------------------------
+
+reStructuredText_ is an easy-to-read, what-you-see-is-what-you-get
+plaintext markup syntax and parser system. The reStructuredText
+parser is a component of Docutils_. reStructuredText is a revision
+and reinterpretation of the StructuredText_ and Setext_ lightweight
+markup systems.
+
+If you are reading this on the web, you can see for yourself. `The
+source for this FAQ <FAQ.txt>`_ is written in reStructuredText; open
+it in another window and compare them side by side.
+
+`A ReStructuredText Primer`_ and the `Quick reStructuredText`_ user
+reference are a good place to start. The `reStructuredText Markup
+Specification`_ is a detailed technical specification.
+
+.. _A ReStructuredText Primer: docs/user/rst/quickstart.html
+.. _Quick reStructuredText: docs/user/rst/quickref.html
+.. _reStructuredText Markup Specification:
+ docs/ref/rst/restructuredtext.html
+.. _reStructuredText: http://docutils.sourceforge.net/rst.html
+.. _StructuredText:
+ http://dev.zope.org/Members/jim/StructuredTextWiki/FrontPage/
+.. _Setext: http://docutils.sourceforge.net/mirror/setext.html
+
+
+Why is it called "reStructuredText"?
+------------------------------------
+
+The name came from a combination of "StructuredText", one of
+reStructuredText's predecessors, with "re": "revised", "reworked", and
+"reinterpreted", and as in the ``re.py`` regular expression module.
+For a detailed history of reStructuredText and the Docutils project,
+see `An Introduction to reStructuredText`_.
+
+"reStructuredText" is **ONE** word, *not two!*
+
+
+What's the standard abbreviation for "reStructuredText"?
+--------------------------------------------------------
+
+"RST" and "ReST" (or "reST") are both acceptable. Care should be
+taken with capitalization, to avoid confusion with "REST__", an
+acronym for "Representational State Transfer".
+
+The abbreviations "reSTX" and "rSTX"/"rstx" should **not** be used;
+they overemphasize reStructuredText's precedessor, Zope's
+StructuredText.
+
+__ http://en.wikipedia.org/wiki/Representational_State_Transfer
+
+
+What's the standard filename extension for a reStructuredText file?
+-------------------------------------------------------------------
+
+It's ".txt". Some people would like to use ".rest" or ".rst" or
+".restx", but why bother? ReStructuredText source files are meant to
+be readable as plaintext, and most operating systems already associate
+".txt" with text files. Using a specialized filename extension would
+require that users alter their OS settings, which is something that
+many users will not be willing or able to do.
+
+Also see `What's the official MIME type for reStructuredText data?`_
+
+
+Are there any reStructuredText editor extensions?
+-------------------------------------------------
+
+See `Editor Support for reStructuredText`__.
+
+__ tools/editors/README.html
+
+
+How can I indicate the document title? Subtitle?
+-------------------------------------------------
+
+A uniquely-adorned section title at the beginning of a document is
+treated specially, as the document title. Similarly, a
+uniquely-adorned section title immediately after the document title
+becomes the document subtitle. For example::
+
+ This is the Document Title
+ ==========================
+
+ This is the Document Subtitle
+ -----------------------------
+
+ Here's an ordinary paragraph.
+
+Counterexample::
+
+ Here's an ordinary paragraph.
+
+ This is *not* a Document Title
+ ==============================
+
+ The "ordinary paragraph" above the section title
+ prevents it from becoming the document title.
+
+Another counterexample::
+
+ This is not the Document Title, because...
+ ===========================================
+
+ Here's an ordinary paragraph.
+
+ ... the title adornment is not unique
+ =====================================
+
+ Another ordinary paragraph.
+
+
+How can I represent esoteric characters (e.g. character entities) in a document?
+--------------------------------------------------------------------------------
+
+For example, say you want an em-dash (XML character entity —,
+Unicode character U+2014) in your document: use a real em-dash.
+Insert concrete characters (e.g. type a *real* em-dash) into your
+input file, using whatever encoding suits your application, and tell
+Docutils the input encoding. Docutils uses Unicode internally, so the
+em-dash character is a real em-dash internally.
+
+Emacs users should refer to the `Emacs Support for reStructuredText`__
+document. Tips for other editors are welcome.
+
+__ tools/editors/emacs/README.html
+
+ReStructuredText has no character entity subsystem; it doesn't know
+anything about XML charents. To Docutils, "—" in input text is
+7 discrete characters; no interpretation happens. When writing HTML,
+the "&" is converted to "&", so in the raw output you'd see
+"&mdash;". There's no difference in interpretation for text
+inside or outside inline literals or literal blocks -- there's no
+character entity interpretation in either case.
+
+If you can't use a Unicode-compatible encoding and must rely on 7-bit
+ASCII, there is a workaround. New in Docutils 0.3.10 is a set of
+`Standard Substitution Definition Sets`_, which provide equivalents of
+XML & HTML character entity sets as substitution definitions. For
+example, the Japanese yen currency symbol can be used as follows::
+
+ .. include:: <xhtml1-lat1.txt>
+
+ |yen| 600 for a complete meal? That's cheap!
+
+For earlier versions of Docutils, equivalent files containing
+character entity set substitution definitions using the "unicode_"
+directive `are available`_. Please read the `description and
+instructions`_ for use. Thanks to David Priest for the original idea.
+
+If you insist on using XML-style charents, you'll have to implement a
+pre-processing system to convert to UTF-8 or something. That
+introduces complications though; you can no longer *write* about
+charents naturally; instead of writing "—" you'd have to write
+"&mdash;".
+
+For the common case of long dashes, you might also want to insert the
+following substitution definitons into your document (both of them are
+using the "unicode_" directive)::
+
+ .. |--| unicode:: U+2013 .. en dash
+ .. |---| unicode:: U+2014 .. em dash, trimming surrounding whitespace
+ :trim:
+
+.. |--| unicode:: U+2013 .. en dash
+.. |---| unicode:: U+2014 .. em dash, trimming surrounding whitespace
+ :trim:
+
+Now you can write dashes using pure ASCII: "``foo |--| bar; foo |---|
+bar``", rendered as "foo |--| bar; foo |---| bar". (Note that Mozilla
+and Firefox may render this incorrectly.) The ``:trim:`` option for
+the em dash is necessary because you cannot write "``foo|---|bar``";
+thus you need to add spaces ("``foo |---| bar``") and advise the
+reStructuredText parser to trim the spaces.
+
+.. _Standard Substitution Definition Sets: docs/ref/rst/substitutions.html
+.. _unicode: docs/ref/rst/directives.html#unicode-character-codes
+.. _are available: http://docutils.sourceforge.net/tmp/charents/
+.. _tarball: http://docutils.sourceforge.net/tmp/charents.tgz
+.. _description and instructions:
+ http://docutils.sourceforge.net/tmp/charents/README.html
+.. _to-do list: docs/dev/todo.html
+
+
+How can I generate backticks using a Scandinavian keyboard?
+-----------------------------------------------------------
+
+The use of backticks in reStructuredText is a bit awkward with
+Scandinavian keyboards, where the backtick is a "dead" key. To get
+one ` character one must press SHIFT-` + SPACE.
+
+Unfortunately, with all the variations out there, there's no way to
+please everyone. For Scandinavian programmers and technical writers,
+this is not limited to reStructuredText but affects many languages and
+environments.
+
+Possible solutions include
+
+* If you have to input a lot of backticks, simply type one in the
+ normal/awkward way, select it, copy and then paste the rest (CTRL-V
+ is a lot faster than SHIFT-` + SPACE).
+
+* Use keyboard macros.
+
+* Remap the keyboard. The Scandinavian keyboard layout is awkward for
+ other programming/technical characters too; for example, []{}
+ etc. are a bit awkward compared to US keyboards.
+
+ According to Axel Kollmorgen,
+
+ Under Windows, you can use the `Microsoft Keyboard Layout Creator
+ <http://www.microsoft.com/globaldev/tools/msklc.mspx>`__ to easily
+ map the backtick key to a real backtick (no dead key). took me
+ five minutes to load my default (german) keyboard layout, untick
+ "Dead Key?" from the backtick key properties ("in all shift
+ states"), "build dll and setup package", install the generated
+ .msi, and add my custom keyboard layout via Control Panel >
+ Regional and Language Options > Languages > Details > Add
+ Keyboard layout (and setting it as default "when you start your
+ computer").
+
+* Use a virtual/screen keyboard or character palette, such as:
+
+ - `Web-based keyboards <http://keyboard.lab.co.il/>`__ (IE only
+ unfortunately).
+ - Windows: `Click-N-Type <http://www.lakefolks.org/cnt/>`__.
+ - Mac OS X: the Character Palette can store a set of favorite
+ characters for easy input. Open System Preferences,
+ International, Input Menu tab, enable "Show input menu in menu
+ bar", and be sure that Character Palette is enabled in the list.
+
+If anyone knows of other/better solutions, please `let us know`_.
+
+
+Are there any tools for HTML/XML-to-reStructuredText? (Round-tripping)
+-----------------------------------------------------------------------
+
+People have tossed the idea around, and some implementations of
+reStructuredText-generating tools can be found in the `Docutils Link
+List`_.
+
+There's no reason why reStructuredText should not be round-trippable
+to/from XML; any technicalities which prevent round-tripping would be
+considered bugs. Whitespace would not be identical, but paragraphs
+shouldn't suffer. The tricky parts would be the smaller details, like
+links and IDs and other bookkeeping.
+
+For HTML, true round-tripping may not be possible. Even adding lots
+of extra "class" attributes may not be enough. A "simple HTML" to RST
+filter is possible -- for some definition of "simple HTML" -- but HTML
+is used as dumb formatting so much that such a filter may not be
+particularly useful. An 80/20 approach should work though: build a
+tool that does 80% of the work automatically, leaving the other 20%
+for manual tweaks.
+
+.. _Docutils Link List: docs/user/links.html
+
+
+Are there any Wikis that use reStructuredText syntax?
+-----------------------------------------------------
+
+There are several, with various degrees of completeness. With no
+implied endorsement or recommendation, and in no particular order:
+
+* `Ian Bicking's experimental code
+ <http://docutils.sf.net/sandbox/ianb/wiki/Wiki.py>`__
+
+* `MoinMoin <http://moinmoin.wikiwikiweb.de/>`__ has some support;
+ `here's a sample <http://moinmoin.wikiwikiweb.de/RestSample>`__
+
+* Zope-based `Zwiki <http://zwiki.org/>`__
+
+* Zope3-based Zwiki (in the Zope 3 source tree as
+ ``zope.products.zwiki``)
+
+* `StikiWiki <http://mithrandr.moria.org/code/stikiwiki/>`__
+
+* `Trac <http://trac.edgewall.com//>`__ `supports using
+ reStructuredText
+ <http://trac.edgewall.com//wiki/WikiRestructuredText>`__ as
+ an alternative to wiki markup. This includes support for `TracLinks
+ <http://trac.edgewall.com//wiki/TracLinks>`__ from within
+ RST text via a custom RST reference-directive or, even easier, an
+ interpreted text role 'trac'
+
+Please `let us know`_ of any other reStructuredText Wikis.
+
+.. dead link
+.. The example application for the `Web Framework Shootout
+.. <http://colorstudy.com/docs/shootout.html>`__ article is a Wiki using
+.. reStructuredText.
+
+
+Are there any Weblog (Blog) projects that use reStructuredText syntax?
+----------------------------------------------------------------------
+
+With no implied endorsement or recommendation, and in no particular
+order:
+
+* `Firedrop <http://www.voidspace.org.uk/python/firedrop2/>`__
+* `PyBloxsom <http://pyblosxom.sourceforge.net/>`__
+* `Lino WebMan <http://lino.sourceforge.net/webman.html>`__
+* `Pelican <http://blog.getpelican.com/>`__
+ (also listed `on PyPi <http://pypi.python.org/pypi/pelican>`__)
+
+Please `let us know`_ of any other reStructuredText Blogs.
+
+
+.. _Can lists be indented without generating block quotes?:
+
+How should I mark up lists?
+---------------------------
+
+Bullet_ & enumerated_ list markup is very intuitive but there are 2
+points that must be noted:
+
+.. _bullet: docs/ref/rst/restructuredtext.html#bullet-lists
+.. _enumerated: docs/ref/rst/restructuredtext.html#enumerated-lists
+
+1. Lists should **not** be indented. This is correct::
+
+ paragraph
+
+ * list item 1
+
+ * nested item 1.1
+ * nested item 1.2
+
+ * list item 2
+
+ while this is probably incorrect::
+
+ paragraph
+
+ * list item 1
+
+ * nested item 1.1
+ * nested item 1.2
+
+ * list item 2
+
+ The extra indentation (of the list containing items 1.1 and 1.2) is
+ recognized as a block quote. This is usually not what you mean and
+ it causes the list in the output to be indented too much.
+
+2. There **must** be blank lines around list items, except between
+ items of the same level, where blank lines are optional. The
+ example above shows this.
+
+Note that formatting of the *output* is independent of the input, and
+is decided by the writer and the stylesheet. For instance, lists
+*are* indented in HTML output by default. See `How are lists
+formatted in HTML?`_ for details.
+
+
+Could lists be indented without generating block quotes?
+--------------------------------------------------------
+
+Some people like to write lists with indentation but don't intend a
+blockquote context. There has been a lot of discussion about allowing
+this in reStructuredText, but there are some issues that would need to
+be resolved before it could be implemented. There is a summary of the
+issues and pointers to the discussions in `the to-do list`__.
+
+__ docs/dev/todo.html#indented-lists
+
+
+Could the requirement for blank lines around lists be relaxed?
+--------------------------------------------------------------
+
+Short answer: no.
+
+In reStructuredText, it would be impossible to unambigously mark up
+and parse lists without blank lines before and after. Deeply nested
+lists may look ugly with so many blank lines, but it's a price we pay
+for unambiguous markup. Some other plaintext markup systems do not
+require blank lines in nested lists, but they have to compromise
+somehow, either accepting ambiguity or requiring extra complexity.
+For example, `Epytext <http://epydoc.sf.net/epytext.html#list>`__ does
+not require blank lines around lists, but it does require that lists
+be indented and that ambiguous cases be escaped.
+
+
+How can I include mathematical equations in documents?
+------------------------------------------------------
+
+Use the `math directive`_ and `math role`_, available since Docutils 0.8.
+
+.. _math directive: docs/ref/rst/directives.html#math
+.. _math role: docs/ref/rst/roles.html#math
+
+
+Is nested inline markup possible?
+---------------------------------
+
+Not currently, no. It's on the `to-do list`__ (`details here`__), and
+hopefully will be part of the reStructuredText parser soon. At that
+time, markup like this will become possible::
+
+ Here is some *emphasized text containing a `hyperlink`_ and
+ ``inline literals``*.
+
+__ docs/dev/todo.html#nested-inline-markup
+__ docs/dev/rst/alternatives.html#nested-inline-markup
+
+There are workarounds, but they are either convoluted or ugly or both.
+They are not recommended.
+
+* Inline markup can be combined with hyperlinks using `substitution
+ definitions`__ and references__ with the `"replace" directive`__.
+ For example::
+
+ Here is an |emphasized hyperlink|_.
+
+ .. |emphasized hyperlink| replace:: *emphasized hyperlink*
+ .. _emphasized hyperlink: http://example.org
+
+ It is not possible for just a portion of the replacement text to be
+ a hyperlink; it's the entire replacement text or nothing.
+
+ __ docs/ref/rst/restructuredtext.html#substitution-definitions
+ __ docs/ref/rst/restructuredtext.html#substitution-references
+ __ docs/ref/rst/directives.html#replace
+
+* The `"raw" directive`__ can be used to insert raw HTML into HTML
+ output::
+
+ Here is some |stuff|.
+
+ .. |stuff| raw:: html
+
+ <em>emphasized text containing a
+ <a href="http://example.org">hyperlink</a> and
+ <tt>inline literals</tt></em>
+
+ Raw LaTeX is supported for LaTeX output, etc.
+
+ __ docs/ref/rst/directives.html#raw
+
+
+How to indicate a line break or a significant newline?
+------------------------------------------------------
+
+`Line blocks`__ are designed for address blocks, verse, and other
+cases where line breaks are significant and must be preserved. Unlike
+literal blocks, the typeface is not changed, and inline markup is
+recognized. For example::
+
+ | A one, two, a one two three four
+ |
+ | Half a bee, philosophically,
+ | must, *ipso facto*, half not be.
+ | But half the bee has got to be,
+ | *vis a vis* its entity. D'you see?
+ |
+ | But can a bee be said to be
+ | or not to be an entire bee,
+ | when half the bee is not a bee,
+ | due to some ancient injury?
+ |
+ | Singing...
+
+__ docs/ref/rst/restructuredtext.html#line-blocks
+
+Here's a workaround for manually inserting explicit line breaks in
+HTML output::
+
+ .. |br| raw:: html
+
+ <br />
+
+ I want to break this line here: |br| this is after the break.
+
+ If the extra whitespace bothers you, |br|\ backslash-escape it.
+
+
+A URL containing asterisks doesn't work. What to do?
+-----------------------------------------------------
+
+Asterisks are valid URL characters (see :RFC:`2396`), sometimes used
+in URLs. For example::
+
+ http://cvs.example.org/viewcvs.py/*checkout*/module/file
+
+Unfortunately, the parser thinks the asterisks are indicating
+emphasis. The slashes serve as delineating punctuation, allowing the
+asterisks to be recognized as markup. The example above is separated
+by the parser into a truncated URL, an emphasized word, and some
+regular text::
+
+ http://cvs.example.org/viewcvs.py/
+ *checkout*
+ /module/file
+
+To turn off markup recognition, use a backslash to escape at least the
+first asterisk, like this::
+
+ http://cvs.example.org/viewcvs.py/\*checkout*/module/file
+
+Escaping the second asterisk doesn't hurt, but it isn't necessary.
+
+
+How can I make a literal block with *some* formatting?
+------------------------------------------------------
+
+Use the `parsed-literal`_ directive.
+
+.. _parsed-literal: docs/ref/rst/directives.html#parsed-literal
+
+Scenario: a document contains some source code, which calls for a
+literal block to preserve linebreaks and whitespace. But part of the
+source code should be formatted, for example as emphasis or as a
+hyperlink. This calls for a *parsed* literal block::
+
+ .. parsed-literal::
+
+ print "Hello world!" # *tricky* code [1]_
+
+The emphasis (``*tricky*``) and footnote reference (``[1]_``) will be
+parsed.
+
+
+Can reStructuredText be used for web or generic templating?
+-----------------------------------------------------------
+
+Docutils and reStructuredText can be used with or as a component of a
+templating system, but they do not themselves include templating
+functionality. Templating should simply be left to dedicated
+templating systems. Users can choose a templating system to apply to
+their reStructuredText documents as best serves their interests.
+
+There are many good templating systems for Python (ht2html_, YAPTU_,
+Quixote_'s PTL, Cheetah_, etc.; see this non-exhaustive list of `some
+other templating systems`_), and many more for other languages, each
+with different approaches. We invite you to try several and find one
+you like. If you adapt it to use Docutils/reStructuredText, please
+consider contributing the code to Docutils or `let us know`_ and we'll
+keep a list here.
+
+One reST-specific web templating system is `rest2web
+<http://www.voidspace.org.uk/python/rest2web>`_, a tool for
+automatically building websites, or parts of websites.
+
+.. _ht2html: http://ht2html.sourceforge.net/
+.. _YAPTU:
+ http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/52305
+.. _Quixote: http://www.mems-exchange.org/software/quixote/
+.. _Cheetah: http://www.cheetahtemplate.org/
+.. _some other templating systems:
+ http://webware.sourceforge.net/Papers/Templates/
+
+
+How can I mark up a FAQ or other list of questions & answers?
+-------------------------------------------------------------
+
+There is no specific syntax for FAQs and Q&A lists. Here are two
+options:
+
+1. For a FAQ (Frequently Asked Questions, usually with answers), a
+ convenient way to mark up the questions is as section titles, with
+ the answer(s) as section content. This document is marked up in
+ this way.
+
+ The advantages of using section titles for questions are: sections
+ can be numbered automatically, and a table of contents can be
+ generated automatically. One limitation of this format is that
+ questions must fit on one line (section titles may not wrap, in the
+ source text). For very long questions, the title may be a summary
+ of the question, with the full question in the section body.
+
+2. Field lists work well as Q&A lists::
+
+ :Q: What kind of questions can we
+ put here?
+
+ :A: Any kind we like!
+
+ In order to separate questions, lists can be used:
+
+ 1. :Q: What kind of question can we
+ put here?
+ :A: Any kind we like!
+
+ 2. :Q: How many answers can a question have?
+ :A: It can have one,
+ :A: or more.
+ :A3: Answers can be numbered like this.
+ :A: 1. Or like this.
+ 2. We're flexible!
+
+ If you don't want to number or otherwise mark questions, you can
+ use an empty comment between individual field lists to separate
+ them::
+
+ :Q: First question?
+ :A: Answer.
+
+ ..
+
+ :Q: Second question?
+ :A: Answer.
+
+
+.. _bidi:
+
+Can I produce documents in right-to-left languages?
+---------------------------------------------------
+
+Languages written from right to left, such as Arabic and Hebrew, must
+be reordered according to the `Unicode Bidi Algorithm`_. This
+requires support from the editor and special markup in the output
+format.
+
+The source format of reStructuredText is relatively bidi-friendly:
+most constructs are denoted by punctuation without intrusion of
+English and when you must write in English, it's usually on a separate
+line. So any editor that auto-detects direction per-line (like gedit
+or geresh_) will suffice.
+
+Moreover, it's possible to translate_ all reStructuredText keywords.
+This was not yet done for any RTL language, but when it is, it will be
+possible to write an RTL document with vitually no English. This will
+allow reasonable use of editors limited to a single base direction for
+the whole document (like Notepad, Vim and text boxes in Firefox).
+
+.. _Unicode Bidi Algorithm: http://www.unicode.org/reports/tr9/
+.. _geresh: http://www.typo.co.il/~mooffie/geresh/
+.. _translate: docs/howto/i18n.html
+
+The second problem is bidi markup of the output. There is an almost
+transparent implicit solution for HTML:
+
+* Grab http://cben-hacks.sourceforge.net/bidi/hibidi.py and
+ http://cben-hacks.sourceforge.net/bidi/rst2html_hibidi.py.
+ Put them both in the same directory and make them executable.
+
+* Use ``rst2html_hibidi.py`` instead of ``rst2html.py``.
+
+* It infers dir attributes in the HTML from the text. It does it
+ hierachically, giving much better results than usual. You can still
+ use LRM/RLM and LRE/RLE/PDF control codes to help it.
+
+ * If you want the gory details: See the full theory_, and note the
+ incomplete practice_ (this is still a partial implementation - but
+ sufficient for most needs).
+
+ .. _theory: http://cben-hacks.sf.net/bidi/hibidi.html
+ .. _practice: http://cben-hacks.sf.net/bidi/hibidi.html#practice
+
+There is also an explicit way to set directions through CSS and
+classes in the HTML:
+
+* Copy ``default.css`` to a new file and add relevant parts of the
+ following::
+
+ /* Use these two if the main document direction is RTL */
+ body { direction: rtl; }
+ div.sidebar { float: left !important; }
+
+ /* The next 3 rules are very useful in documents containing pieces
+ of code in english */
+ /* Use this if you all your literal blocks (::) are LTR */
+ pre {direction: ltr; unicode-bidi: embed; }
+ /* Use this if you all your inline literals (``) are LTR */
+ tt {direction: ltr; unicode-bidi: embed; }
+ /* Use this if you all your interpretted text (`) is LTR */
+ cite {direction: ltr; unicode-bidi: embed; }
+
+ /* Allow manual direction override by class directive and roles */
+ .rtl { direction: rtl; }
+ .ltr { direction: ltr; }
+
+* Select this new stylesheet with ``--stylesheet=<file>`` or the
+ stylesheet_ setting.
+
+* Now if you need to override the direction of some element (from a
+ paragraph to a whole section), write::
+
+ .. class:: rtl
+
+ or::
+
+ .. class:: ltr
+
+ before it (see the class_ directive for details).
+
+* To change the direction of some inline text fragment, you can use
+ RLE/LRE/PDF control characters, or write ``:rtl:`RTL text``` /
+ ``:ltr:`RTL text```. To use the latter syntax, you must write this
+ once at the beginning of your document::
+
+ .. role:: ltr
+ .. role:: rtl
+
+.. _stylesheet: docs/user/config.html#stylesheet
+.. _class: docs/ref/rst/directives.txt#class
+
+LaTeX is quite hard to implement (it doesn't support the bidi
+algorithm, so all direction changes - even numbers in RTL text - must
+be explicitly marked). Other formats are more-or-less easy.
+
+If you have any questions/problems/bugs related to bidi with docutils,
+ask `Beni Cherniavsky`__ directly or the `Docutils-users`_ mailing
+list.
+
+__ mailto:cben@users.sf.net
+
+
+What's the official MIME type for reStructuredText data?
+--------------------------------------------------------
+
+While there is no registered MIME type for reStructuredText, the
+"official unofficial" standard MIME type is "text/x-rst". This was
+invented for the build system for PEPs (Python Enhancement Proposals),
+and it's used by the python.org web site build system.
+
+(The "x-" prefix means it's an unregistered MIME type.)
+
+Also see `What's the standard filename extension for a
+reStructuredText file?`_
+
+
+HTML Writer
+===========
+
+What is the status of the HTML Writer?
+--------------------------------------
+
+The HTML Writer module, ``docutils/writers/html4css1.py``, is a
+proof-of-concept reference implementation. While it is a complete
+implementation, some aspects of the HTML it produces may be incompatible
+with older browsers or specialized applications (such as web templating).
+The sandbox has some alternative HTML writers, contributions are welcome.
+
+
+What kind of HTML does it produce?
+----------------------------------
+
+It produces XHTML compatible with the `XHTML 1.0`_ specification. A
+cascading stylesheet is required for proper viewing with a modern
+graphical browser. Correct rendering of the HTML produced depends on
+the CSS support of the browser. A general-purpose stylesheet,
+``html4css1.css`` is provided with the code, and is embedded by
+default. It is installed in the "writers/html4css1/" subdirectory
+within the Docutils package. Use the ``--help`` command-line option
+to see the specific location on your machine.
+
+.. _XHTML 1.0: http://www.w3.org/TR/xhtml1/
+
+
+What browsers are supported?
+----------------------------
+
+No specific browser is targeted; all modern graphical browsers should
+work. Some older browsers, text-only browsers, and browsers without
+full CSS support are known to produce inferior results. Firefox,
+Safari, Mozilla (version 1.0 and up), Opera, and MS Internet Explorer
+(version 5.0 and up) are known to give good results. Reports of
+experiences with other browsers are welcome.
+
+
+Unexpected results from tools/rst2html.py: H1, H1 instead of H1, H2. Why?
+--------------------------------------------------------------------------
+
+Here's the question in full:
+
+ I have this text::
+
+ Heading 1
+ =========
+
+ All my life, I wanted to be H1.
+
+ Heading 1.1
+ -----------
+
+ But along came H1, and so shouldn't I be H2?
+ No! I'm H1!
+
+ Heading 1.1.1
+ *************
+
+ Yeah, imagine me, I'm stuck at H3! No?!?
+
+ When I run it through tools/rst2html.py, I get unexpected results
+ (below). I was expecting H1, H2, then H3; instead, I get H1, H1,
+ H2::
+
+ ...
+ <html lang="en">
+ <head>
+ ...
+ <title>Heading 1</title>
+ </head>
+ <body>
+ <div class="document" id="heading-1">
+ <h1 class="title">Heading 1</h1> <-- first H1
+ <p>All my life, I wanted to be H1.</p>
+ <div class="section" id="heading-1-1">
+ <h1><a name="heading-1-1">Heading 1.1</a></h1> <-- H1
+ <p>But along came H1, and so now I must be H2.</p>
+ <div class="section" id="heading-1-1-1">
+ <h2><a name="heading-1-1-1">Heading 1.1.1</a></h2>
+ <p>Yeah, imagine me, I'm stuck at H3!</p>
+ ...
+
+ What gives?
+
+Check the "class" attribute on the H1 tags, and you will see a
+difference. The first H1 is actually ``<h1 class="title">``; this is
+the document title, and the default stylesheet renders it centered.
+There can also be an ``<h2 class="subtitle">`` for the document
+subtitle.
+
+If there's only one highest-level section title at the beginning of a
+document, it is treated specially, as the document title. (Similarly, a
+lone second-highest-level section title may become the document
+subtitle.) See `How can I indicate the document title? Subtitle?`_ for
+details. Rather than use a plain H1 for the document title, we use ``<h1
+class="title">`` so that we can use H1 again within the document. Why
+do we do this? HTML only has H1-H6, so by making H1 do double duty, we
+effectively reserve these tags to provide 6 levels of heading beyond the
+single document title.
+
+HTML is being used for dumb formatting for nothing but final display.
+A stylesheet *is required*, and one is provided; see `What kind of
+HTML does it produce?`_ above. Of course, you're welcome to roll your
+own. The default stylesheet provides rules to format ``<h1
+class="title">`` and ``<h2 class="subtitle">`` differently from
+ordinary ``<h1>`` and ``<h2>``::
+
+ h1.title {
+ text-align: center }
+
+ h2.subtitle {
+ text-align: center }
+
+If you don't want the top section heading to be interpreted as a
+title at all, disable the `doctitle_xform`_ setting
+(``--no-doc-title`` option). This will interpret your document
+differently from the standard settings, which might not be a good
+idea. If you don't like the reuse of the H1 in the HTML output, you
+can tweak the `initial_header_level`_ setting
+(``--initial-header-level`` option) -- but unless you match its value
+to your specific document, you might end up with bad HTML (e.g. H3
+without H2).
+
+.. _doctitle_xform: docs/user/config.html#doctitle-xform
+.. _initial_header_level: docs/user/config.html#initial-header-level
+
+(Thanks to Mark McEahern for the question and much of the answer.)
+
+
+How are lists formatted in HTML?
+--------------------------------
+
+If list formatting looks strange, first check that you understand
+`list markup`__.
+
+__ `How should I mark up lists?`_
+
+* By default, HTML browsers indent lists relative to their context.
+ This follows a long tradition in browsers (but isn't so established
+ in print). If you don't like it, you should change the stylesheet.
+
+ This is different from how lists look in reStructuredText source.
+ Extra indentation in the source indicates a blockquote, resulting in
+ too much indentation in the browser.
+
+* A list item can contain multiple paragraphs etc. In complex cases
+ list items are separated by vertical space. By default this spacing
+ is omitted in "simple" lists. A list is simple if every item
+ contains a simple paragraph and/or a "simple" nested list. For
+ example:
+
+ * text
+
+ * simple
+
+ * simple
+ * simple
+
+ * simple
+
+ text after a nested list
+
+ * multiple
+
+ paragraphs
+
+ In this example the nested lists are simple (and should appear
+ compacted) but the outer list is not.
+
+ If you want all lists to have equal spacing, disable the
+ `compact_lists`_ setting (``--no-compact-lists`` option). The
+ precise spacing can be controlled in the stylesheet.
+
+ Note again that this is not exactly WYSIWYG: it partially resembles
+ the rules about blank lines being optional between list items in
+ reStructuredText -- but adding/removing optional blank lines does
+ not affect spacing in the output! It's a feature, not a bug: you
+ write it as you like but the output is styled consistently.
+
+ .. _compact_lists: docs/user/config.html#compact-lists
+
+
+Why do enumerated lists only use numbers (no letters or roman numerals)?
+------------------------------------------------------------------------
+
+The rendering of enumerators (the numbers or letters acting as list
+markers) is completely governed by the stylesheet, so either the
+browser can't find the stylesheet (try enabling the
+`embed_stylesheet`_ setting [``--embed-stylesheet`` option]), or the
+browser can't understand it (try a recent Firefox, Mozilla, Konqueror,
+Opera, Safari, or even MSIE).
+
+.. _embed_stylesheet: docs/user/config.html#embed-stylesheet
+
+
+There appear to be garbage characters in the HTML. What's up?
+--------------------------------------------------------------
+
+What you're seeing is most probably not garbage, but the result of a
+mismatch between the actual encoding of the HTML output and the
+encoding your browser is expecting. Your browser is misinterpreting
+the HTML data, which is encoded text. A discussion of text encodings
+is beyond the scope of this FAQ; see one or more of these documents
+for more info:
+
+* `UTF-8 and Unicode FAQ for Unix/Linux
+ <http://www.cl.cam.ac.uk/~mgk25/unicode.html>`_
+
+* Chapters 3 and 4 of `Introduction to i18n [Internationalization]
+ <http://www.debian.org/doc/manuals/intro-i18n/>`_
+
+* `Python Unicode Tutorial
+ <http://www.reportlab.com/i18n/python_unicode_tutorial.html>`_
+
+* `Python Unicode Objects: Some Observations on Working With Non-ASCII
+ Character Sets <http://effbot.org/zone/unicode-objects.htm>`_
+
+The common case is with the default output encoding (UTF-8), when
+either numbered sections are used (via the "sectnum_" directive) or
+symbol-footnotes. 3 non-breaking spaces are inserted in each numbered
+section title, between the generated number and the title text. Most
+footnote symbols are not available in ASCII, nor are non-breaking
+spaces. When encoded with UTF-8 and viewed with ordinary ASCII tools,
+these characters will appear to be multi-character garbage.
+
+You may have an decoding problem in your browser (or editor, etc.).
+The encoding of the output is set to "utf-8", but your browswer isn't
+recognizing that. You can either try to fix your browser (enable
+"UTF-8 character set", sometimes called "Unicode"), or choose a
+different encoding for the HTML output. You can also try
+``--output-encoding=ascii:xmlcharrefreplace`` for HTML or XML, but not
+applicable to non-XMLish outputs (if using runtime
+settings/configuration files, use ``output_encoding=ascii`` and
+``output_encoding_error_handler=xmlcharrefreplace``).
+
+If you're generating document fragments, the "Content-Type" metadata
+(between the HTML ``<head>`` and ``</head>`` tags) must agree with the
+encoding of the rest of the document. For UTF-8, it should be::
+
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+
+Also, Docutils normally generates an XML declaration as the first line
+of the output. It must also match the document encoding. For UTF-8::
+
+ <?xml version="1.0" encoding="utf-8" ?>
+
+.. _sectnum: docs/ref/rst/directives.html#sectnum
+
+
+How can I retrieve the body of the HTML document?
+-------------------------------------------------
+
+(This is usually needed when using Docutils in conjunction with a
+templating system.)
+
+You can use the `docutils.core.publish_parts()`_ function, which
+returns a dictionary containing an 'html_body_' entry.
+
+.. _docutils.core.publish_parts(): docs/api/publisher.html#publish-parts
+.. _html_body: docs/api/publisher.html#html-body
+
+
+Why is the Docutils XHTML served as "Content-type: text/html"?
+--------------------------------------------------------------
+
+Full question:
+
+ Docutils' HTML output looks like XHTML and is advertised as such::
+
+ <?xml version="1.0" encoding="utf-8" ?>
+ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+ "http://www.w3.org/TR/xht ml1/DTD/xhtml1-transitional.dtd">
+
+ But this is followed by::
+
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+
+ Shouldn't this be "application/xhtml+xml" instead of "text/html"?
+
+In a perfect web, the Docutils XHTML output would be 100% strict
+XHTML. But it's not a perfect web, and a major source of imperfection
+is Internet Explorer. Despite it's drawbacks, IE still represents the
+majority of web browsers, and cannot be ignored.
+
+Short answer: if we didn't serve XHTML as "text/html" (which is a
+perfectly valid thing to do), it couldn't be viewed in Internet
+Explorer.
+
+Long answer: see the `"Criticisms of Internet Explorer" Wikipedia
+entry <http://en.wikipedia.org/wiki/Criticisms_of_Internet_Explorer#XHTML>`__.
+
+However, there's also `Sending XHTML as text/html Considered
+Harmful`__. What to do, what to do? We're damned no matter what we
+do. So we'll continue to do the practical instead of the pure:
+support the browsers that are actually out there, and not fight for
+strict standards compliance.
+
+__ http://hixie.ch/advocacy/xhtml
+
+(Thanks to Martin F. Krafft, Robert Kern, Michael Foord, and Alan
+G. Isaac.)
+
+
+Python Source Reader
+====================
+
+Can I use Docutils for Python auto-documentation?
+-------------------------------------------------
+
+Yes, in conjunction with other projects.
+
+The Sphinx_ documentation generator includes an autodoc module.
+
+.. _Sphinx: http://sphinx.pocoo.org/index.html
+
+Version 2.0 of Ed Loper's `Epydoc <http://epydoc.sourceforge.net/>`_
+supports reStructuredText-format docstrings for HTML output. Docutils
+0.3 or newer is required. Development of a Docutils-specific
+auto-documentation tool will continue. Epydoc works by importing
+Python modules to be documented, whereas the Docutils-specific tool,
+described above, will parse modules without importing them (as with
+`HappyDoc <http://happydoc.sourceforge.net/>`_, which doesn't support
+reStructuredText).
+
+The advantages of parsing over importing are security and flexibility;
+the disadvantage is complexity/difficulty.
+
+* Security: untrusted code that shouldn't be executed can be parsed;
+ importing a module executes its top-level code.
+* Flexibility: comments and unofficial docstrings (those not supported
+ by Python syntax) can only be processed by parsing.
+* Complexity/difficulty: it's a lot harder to parse and analyze a
+ module than it is to ``import`` and analyze one.
+
+For more details, please see "Docstring Extraction Rules" in `PEP
+258`_, item 3 ("How").
+
+
+Miscellaneous
+=============
+
+Is the Docutils document model based on any existing XML models?
+----------------------------------------------------------------
+
+Not directly, no. It borrows bits from DocBook, HTML, and others. I
+(David Goodger) have designed several document models over the years,
+and have my own biases. The Docutils document model is designed for
+simplicity and extensibility, and has been influenced by the needs of
+the reStructuredText markup.
+
+\f
+..
+ Local Variables:
+ mode: indented-text
+ indent-tabs-mode: nil
+ sentence-end-double-space: t
+ fill-column: 70
+ End:
+
+.. Here's a code css to make a table colourful::
+
+ /* Table: */
+
+ th {
+ background-color: #ede;
+ }
+
+ /* alternating colors in table rows */
+ table.docutils tr:nth-child(even) {
+ background-color: #F3F3FF;
+ }
+ table.docutils tr:nth-child(odd) {
+ background-color: #FFFFEE;
+ }
+
+ table.docutils tr {
+ border-style: solid none solid none;
+ border-width: 1px 0 1px 0;
+ border-color: #AAAAAA;
+ }
--- /dev/null
+.. -*- coding: utf-8 -*-
+
+==================
+ Docutils History
+==================
+
+:Author: David Goodger; open to all Docutils developers
+:Contact: docutils-develop@lists.sourceforge.net
+:Date: $Date: 2019-12-01 23:16:45 +0100 (So, 01. Dez 2019) $
+:Revision: $Revision: 8427 $
+:Web site: http://docutils.sourceforge.net/
+:Copyright: This document has been placed in the public domain.
+
+.. contents::
+
+2019-07-23 : Branch: branches/rel-0.15 created to investigate import problems: bugs#366
+
+Changes Since 0.15
+==================
+
+* General
+
+ - Dropped support for Python 2.6, 3.3 and 3.4
+ - Docutils now supports Python 2.7 and Python 3.5+ natively
+ (without conversion by ``2to3``).
+ - Keep `backslash escapes`__ in the document tree. Backslash characters in
+ text are be represented by NULL characters in the ``text`` attribute of
+ Doctree nodes and removed in the writing stage by the node's
+ ``astext()`` method.
+
+ __ http://docutils.sourceforge.net/docs/ref/rst/restructuredtext.html#escaping-mechanism
+
+* docutils/io.py
+
+ - Remove the `handle_io_errors` option from io.FileInput/Output.
+
+* docutils/nodes.py
+
+ - Speed up Node.next_node().
+ - If `auto_id_prefix`_ ends with "%", this is replaced with the tag name.
+ - Warn about Node.traverse() returning an iterator instead of a list
+ in future.
+
+ .. _auto_id_prefix: docs/user/config.html#auto-id-prefix
+
+* docutils/statemachine.py
+
+ - Patch [ 158 ]: Speed up patterns by saving compiled versions (eric89gxl)
+
+* docutils/transforms/universal.py
+
+ - Fix [ 332 ]: Standard backslash escape for smartquotes.
+ - Fix [ 342 ]: No escape in roles descending from `inline literal`.
+
+* docutils/utils/__init__.py
+
+ - unescape() definition moved to `nodes` to avoid circular import
+ dependency. Fixes [ 366 ].
+
+* docutils/writers/latex2e/__init__.py:
+
+ - Fix topic subtitle.
+ - Make "rubric" bold-italic and left aligned.
+ - Fix [ 339 ] don't use "alltt" or literal-block-environment
+ in admonitions and footnotes.
+ - Deprecation warning for ``\docutilsrole``-prefixed styling commands.
+ - Add "latex writers" to the `config_section_dependencies`.
+ - Ignore classes for `rubric` elements
+ (class wrapper interferes with LaTeX formatting).
+
+* docutils/writers/manpage.py
+
+ - Apply fix for [ 287 ] comma after option is bold.
+ - Apply fix for [ 289 ], line starting with ``.`` in a text.
+
+* docutils/writers/odf_odt/__init__.py:
+
+ - Fix: ElementTree.getchildren deprecated warning
+
+* docutils/writers/xetex/__init__.py:
+
+ - Add "latex writers" to the `config_section_dependencies`.
+
+* test/alltests.py
+
+ - Fix: 377 ResourceWarning: unclosed file python3.8
+ Close alltests.out with atexit.
+
+* test/functional/*
+
+ - Fix: 377 ResourceWarning: unclosed file python3.8
+ Read defaults file with context.
+
+ - Set "auto_id_prefix" to "%" (expands to tag-names).
+ Results in descriptive links in HTML and more localized changes when
+ editions to the input add or remove auto-ids.
+
+* test/test_io.py:
+
+ - Apply patch #157: avoid test failure because of a ``ResourceWarning``.
+
+* test/test_writers/test_odt.py:
+
+ - Fix [ 359 ]: Test suite failes on Python 3.8. odt xml sorting.
+ Use ElementTree instead of minidom.
+
+* tools/buildhtml.py
+
+ - New option "--html-writer" allows to select "html__" (default),
+ "html4" or "html5".
+
+ __ html: docs/user/html.html#html
+
+
+Release 0.15.1 (2019-07-24)
+===========================
+
+source: branches/rel-0.15
+
+Bugs #366 fix release for python2 only.
+
+
+Release 0.15 (2019-07-20)
+=========================
+
+* General
+
+ - Dropped support for Python 2.4, 2.5, 3.1, and 3.2.
+ - Infrastructure automation.
+
+* docs/ref/rst/restructuredtext.txt:
+
+ - Document rST syntax change: Tokens like ``:this:example:`` are now valid
+ field list names (instead of ordinary text).
+
+* docutils/io.py
+
+ - Fix [ 348 ] Since Python 3.4, the 'U' universal newlines mode has been
+ deprecated (thanks to hugovk).
+
+* docutils/languages/la.py
+ docutils/parsers/rst/languages/la.py:
+
+ - Apply [ 153 ] Korean mappings by Thomas Sungjin Kang.
+
+* docutils/nodes.py
+
+ - Fix [ 251 ] system_message.copy() TypeError.
+ - Element.copy() also copies `document`, `line`, and `source` attributes.
+
+* docutils/parsers/rst/__init__.py:
+
+ - Apply [ 152 ] reset `default role` at end of document.
+
+* docutils/parsers/rst/states.py:
+
+ - Allow embedded colons in field list field names.
+ - Add `rawsource` attribute for text of inline elements.
+
+* docutils/parsers/rst/directives/html.py:
+
+ - Fix bug #281: Remove escaping backslashes in meta directive content.
+
+* docutils/parsers/rst/directives/misc.py:
+
+ - Don't convert tabs to spaces, if `tab_width` is negative in
+ `include` directive with `code` option.
+
+* docutils/parsers/rst/directives/tables.py:
+
+ - Apply patch #121: Add "width" option for the table directives.
+
+* docutils/transforms/frontmatter.py:
+
+ - Add field name as class argument to generic docinfo fields unconditionally.
+
+* docutils/transforms/references.py:
+
+ - Fix bug #331: fixed the "trim" options of the "unicode" directive.
+
+* docutils/utils/__init__.py:
+
+ - Deprecate `unique_combinations` (obsoleted by `itertools.combinations`).
+
+* docutils/utils/smartquotes.py:
+
+ - Fix bug #332: use open quote after whitespace, ZWSP, and ZWNJ.
+
+* docutils/writers/html5_polyglot/
+
+ - automatically add HTML5-compatible meta tags for docinfo items
+ "authors", "date", and "copyright".
+
+* docutils/writers/_html_base.py
+
+ - Fix bug #358: Non-breaking space removed from fixed-width literal.
+
+* docutils/writers/latex2e/__init__.py:
+
+ - Fix bug #323: spurious ``\phantomsection`` and whitespace in
+ ``parts['title']``.
+ - Fix bug #324: Invalid LaTeX for table with empty multicolumn cell.
+ - Fixes to literal block handling.
+
+
+Release 0.14 (2017-08-03)
+=========================
+
+* docs/ref/docutils.dtd:
+
+ - Enable validation of Docutils XML documents against the DTD:
+
+ Use attribute type NMTOKEN instead of REFID for the `refid` attribute
+ and NMTOKENS for `backrefs`: REFID refers to an ID type instance,
+ however, the `ids` attribute cannot use the ID type because `XML only
+ allows one ID per Element Type`__ and doesn't support a multiple-ID
+ "IDS" attribute type.
+
+ __ https://www.w3.org/TR/REC-xml/#sec-attribute-types
+
+* docs/ref/rst/restructuredtext.txt:
+
+ - Added documentation for escaped whitespace in URI contexts.
+ - Clarify use of Unicode character categories.
+
+* docutils/parsers/rst/states.py:
+
+ - Added functionality: escaped whitespace in URI contexts.
+ - Consistent handling of all whitespace characters in inline markup
+ recognition. Fixes [ 307 ] and [ 3402314 ] (now [ 173 ]).
+
+* docutils/parsers/rst/directives/images.py:
+
+ - Added support for escaped whitespace in URI contexts.
+
+* docutils/parsers/rst/directives/tables.py:
+
+ - Rework patch [ 120 ] (revert change to ``Table.get_column_widths()``
+ that led to problems in an application with a custom table directive).
+
+* docutils/transforms/frontmatter.py:
+
+ - Fix [ 320 ] Russian docinfo fields not recognized.
+
+* docutils/transforms/references.py:
+
+ - Don't add a second ID to problematic references.
+
+* docutils/transforms/universal.py:
+
+ Fix SmartQuotes: warn only once if language is unsupported,
+ keep "rawsource" when "educating" quotes.
+
+* docutils/utils/__init__.py:
+
+ - Added ``split_escaped_whitespace`` function, support for escaped
+ whitespace in URI contexts.
+
+* docutils/utils/error_reporting.py:
+
+ - Fix [ 321 ] Import block might cause name error.
+
+* docutils/utils/smartquotes.py:
+
+ - Update quote definitions for languages et, fi, fr, ro, sv, tr, uk.
+ - New quote definitions for hr, hsb, hu, lv, sh, sl, sr.
+ - Fix [ 313 ] Differentiate apostrophe from closing single quote
+ (if possible).
+ - Fix [ 317 ] Extra space inserted with French smartquotes.
+ - Add command line interface for stand-alone use (requires 2.7).
+
+* docutils/writers/_html_base.py:
+
+ - Provide default title in metadata (required by HTML5).
+ - Fix [ 312 ] HTML writer generates invalid HTML if the table has two tags.
+ - Fix [ 319 ] The MathJax CDN shut down on April 30, 2017. For security
+ reasons, we don't use a third party public installation as default but
+ warn if math-output_ is set to MathJax without specifying a URL.
+
+* docutils/writers/html4css1/__init__.py:
+
+ - Apply [ 125 ] HTML writer: respect automatic table column sizing.
+
+* docutils/writers/latex2e/__init__.py:
+
+ - Handle class arguments for block-level elements by wrapping them
+ in a "DUclass" environment. This replaces the special handling for
+ "epigraph" and "topic" elements.
+
+* docutils/writers/manpage.py:
+
+ - Apply [ 141 ] Handling inline in manpage writer.
+
+* docutils/writers/odf_odt/__init__.py:
+
+ - Command setting ``language`` now sets the default language
+ of the generated ODF document.
+ - The use of image directive options :width: (%), :scale:, etc now
+ set the width/height/size of images in the generated ODF
+ documents.
+ - The heading/title of admonitions now reflects the language
+ specified by the ``language`` setting.
+ - Fixed [ 306 ] only first of multiple "image" directives with the same URL
+ shown in output.
+ - Fixed [ 282 ] python3: AttributeError.
+
+* tools/rst2html4.py: New front-end.
+
+* tools/dev/generate_punctuation_chars.py: New skript
+ to test and update utils.punctuation_chars.
+
+
+Release 0.13.1 (2016-12-09)
+===========================
+
+* docutils/languages/fa.py
+ docutils/parsers/rst/languages/fa.py
+ docutils/languages/la.py
+ docutils/parsers/rst/languages/la.py:
+
+ - Apply [ 133 ] Persian mappings by Shahin Azad.
+ - Apply [ 135 ] Language modules for Latvian by Alexander Smishlajev
+
+* docutils/nodes.py
+
+ - Fix [ 253 ] Attribute key without value not allowed in XML.
+
+* docutils/parsers/
+
+ - Apply [ 103 ] Recognize inline markups without word boundaries.
+ - Enable escaping in embedded URIs and aliases (fixes [ 284 ]).
+
+* docutils/parsers/rst/__init__.py
+
+ - Fix [ 233 ] Change the base URL for the :rfc: role.
+
+* docutils/parsers/rst/directives/tables.py
+
+ - Apply [ 120 ] tables accept option widths: list of relative widths, 'auto'
+ or 'grid'.
+
+ - Implement feature request [ 48 ]
+ Add :align: option to the table directives.
+ Thanks to Takeshi KOMIYA for the patch.
+
+* docutils/parsers/rst/roles.py
+
+ - Fix [ 295 ] Class argument for custom role inheriting from math.
+
+* docutils/parsers/rst/tableparser.py
+
+ - Really fix [ 159 ] Spurious table column alignment errors.
+
+* docutils/transforms/frontmatter.py
+
+ - Add name of generic bibliographic fields as a "classes" attribute value
+ (after conversion to a valid identifier form).
+
+* docutils/utils/error_reporting.py
+
+ - Fix [ 130 ] support streams expectiong byte-strings in ErrorOutput.
+
+* docutils/utils/math/math2html.py
+
+ - Add ``\colon`` macro, fix spacing around colons. Fixes [ 246 ].
+ - New upstream version (additional macros, piecewise integrals and sums).
+
+* docutils/writers/_html_base.py
+
+ - New auxiliary module for definitions common to all HTML writers.
+
+* docutils/writers/html5_polyglot/
+
+ - New HTML writer generating clean, polyglot_ markup conforming to
+ `HTML 5`_.
+
+ The CSS stylesheets ``minimal.css`` and ``plain.css`` contain required
+ and recommended layout rules.
+
+* docutils/writers/html4css1/__init__.py
+
+ - Add "docutils" to class values for "container" object to address [ 267 ].
+ - Apply patch [ 119 ] by Anatoly Techtonik: use absolute paths for
+ ``default_stylesheet_path`` and ``default_template_path``.
+ - Fix [ 266 ] creating labels/class values in description list items.
+ - Do not use <sup> and <sub> tags inside <pre> (parsed-literal blocks).
+ - Fix footnotes with content that does not start with a paragraph.
+ - Use https in default MathJax URL (report Alan G Isaac).
+ - Outsourcing of common code to _html_base.py.
+
+* docutils/writers/latex2e/__init__.py
+
+ - Fix [ 262 ] Use ``\linewidth`` instead of ``\textwidth`` for figures,
+ admonitions and docinfo.
+
+ - Use absolute path for ``default_template_path``.
+
+ - Removed deprecated options ``--use-latex-footnotes`` and
+ ``--figure-footnotes``.
+
+ - Cleaner LaTeX code for enumerations and literal blocks.
+
+ - Use "hyperref" package together with "bookmark" (improved hyperlinking
+ by the same author).
+
+ - Fix [ 286 ] Empty column title cause invalid latex file.
+
+ - Fix [ 224 ] Fix rowspan support for tables.
+
+ - Let LaTeX determine the column widths in tables with "colwidths-auto".
+ Not suited for multi-paragraph cells!
+
+* docutils/writers/odf_odt/__init__.py
+
+ - remove decode.encode of filename stored in zip.
+
+* docutils/writers/xetex/__init__.py
+
+ - LuaLaTex compatibility: do not load "xunicode".
+
+* tools/
+
+ - New front-end ``rst2html5.py``.
+
+* tox.ini
+
+ - Test py26, py27, py33 and py34.
+
+ To use, install the ``tox`` package via pip or easy_install and use
+ tox from the project root directory.
+
+.. _polyglot: http://www.w3.org/TR/html-polyglot/
+.. _HTML 5: http://www.w3.org/TR/html5/
+.. _XHTML 1.0: http://www.w3.org/TR/xhtml1/
+
+
+Release 0.12 (2014-07-06)
+=========================
+
+* docs/ref/rst/directives.txt
+
+ - Update "math" and "csv-table" descriptions.
+
+* docutils/parsers/rst/directives/images.py
+
+ - Fix [ 258 ] figwidth="image" generates unitless width value.
+
+* docutils/parsers/rst/states.py
+
+ - Improve error report when a non-ASCII character is specified as
+ delimiter, quote or escape character under Python 2.
+ Fixes [ 249 ] and [ 250 ].
+
+* docutils/writers/html4css1/__init__.py
+
+ - Don't add newline after inline math.
+ Thanks to Yury G. Kudryashov for the patch.
+
+* docutils/writers/latex2e/__init__.py
+
+ - Fix [ 239 ] Latex writer glues paragraphs with figure floats.
+ - Apply [ 116 ] by Kirill Smelkov. Don't hardcode \large for subtitle.
+
+* docutils/writers/odf_odt/__init__.py
+
+ - Apply patch by Jakub Wilk to fix bug [ 100 ].
+
+* test/test_error_reporting.py
+
+ - Fix [ 223 ] by removing redundant tests we do not have control over.
+
+* test/test_nodes.py
+
+ - Apply [ 115 ] respect fixed 2to3 string literal conversion behavior.
+
+Release 0.11 (2013-07-22)
+=========================
+
+* General
+
+ - Apply [ 2714873 ] Fix for the overwritting of document attributes.
+ - Support embedded aliases within hyperlink references.
+ - Fix [ 228 ] try local import of docutils components (reader, writer, parser,
+ language module) before global search.
+
+* docutils/nodes.py
+
+ - Fix [ 3601607 ] node.__repr__() must return `str` instance.
+
+* docutils/parsers/rst/directives/__init__.py
+
+ - Fix [ 3606028 ] ``assert`` is skipped with ``python -O``.
+
+* docutils/parsers/rst/directives/images.py
+
+ - Apply [ 3599485 ] node source/line information for sphinx translation.
+
+* docutils/parsers/rst/directives/tables.py
+
+ - Fix [ 210 ] Python 3.3 checks CVS syntax only if "strict" is True.
+
+* docutils/parsers/rst/states.py
+
+ - Fix [ 157 ] Line block parsing doesn't like system message.
+ - Always import our local copy of roman.py (report Larry Hastings).
+
+* docutils/transforms/references.py
+
+ - Fix [ 3607029 ] traceback with embedded alias pointing to missing target.
+
+* docutils/utils/__init__.py
+
+ - Fix [ 3596884 ] exception importing ``docutils.io``.
+
+* docutils/writers/html4css1/__init__.py
+
+ - Fix [ 3600051 ] for tables in a list, table cells are not compacted.
+ - New setting `stylesheet_dirs`: Comma-separated list of directories
+ where stylesheets are found. Used by `stylesheet_path` when expanding
+ relative path arguments.
+ - New default for math-output_: ``HTML math.css``.
+ - Avoid repeated class declarations in html4css1 writer
+ (modified version of patch [ 104 ]).
+
+.. _math-output: docs/user/config.html#math-output
+
+* docutils/writers/latex2e/__init__.py
+
+ - Drop the simple algorithm replacing straight double quotes with
+ English typographic ones.
+ Activate the SmartQuotes_ transform if you want this feature.
+ - Fix literal use of babel shorthands (straight quote, tilde, ...).
+ - Fix [ 3603246 ] Bug in option "--graphicx-option=auto".
+ - New setting `stylesheet_dirs`.
+
+.. _SmartQuotes: docs/user/config.html#smart-quotes
+
+* docutils/writers/manpage.py
+
+ - Fix [3607063] handle lines starting with a period.
+ - Fix option separating comma was bold (thanks to Bill Morris).
+
+Release 0.10 (2012-12-16)
+=========================
+
+* General
+
+ - Dropped support for Python 2.3.
+ - ``docutils/math``, ``docutils/error_reporting.py``, and
+ ``docutils/urischemes.py`` moved to the utils package.
+ - Fix [3541369] Relative __import__ also with Python 3.3.
+ - Fix [3559988] and [3560841] __import__ local writer, reader, languages
+ and parsers for Python 2.7 up.
+ - Fix import of PIL.Image.
+ - Change default of "syntax highlight" option to "long",
+ basic syntax highlight styles for LaTeX and HTML.
+
+* docutils/io.py
+
+ - FileInput/FileOutput: no system-exit on IOError. The `handle_io_errors`
+ option is ignored and will be removed in a future release.
+ - Fix Py3k error writing to stdout with encoding differing from default.
+ - Fix opening binary files under Py3k (thanks to Dominic Fitzpatrick).
+
+* docutils/parsers/rst/directives/misc.py
+
+ - Fix [ 3546533 ] Unicode error with `date` directive.
+
+* docutils/transforms/universal.py
+
+ - SmartQuotes transform for typographic quotes and dashes.
+
+* docutils/utils/__init__.py
+
+ - normalize_language_tag() now returns `BCP 47`_ conformant tags
+ with subtags separated by ``-``.
+
+* docutils/writers/html4css1/__init__.py
+
+ - Use ``<code>`` tag for inline "code",
+ do not drop nested inline nodes (syntax highlight tokens).
+ - Customizable MathJax URL (based on patch by Dmitry Shachnev).
+ - No line break after opening inline math tag.
+
+* docutils/writers/manpage.py
+
+ - Apply [ 3527401 ] addmonition's don't preserve indentation
+ - Apply [ 3527397 ] Add indentation to literal blocks in manpage writer.
+
+* docutils/writers/xetex/__init__.py
+
+ - Apply [ 3555160 ] ensure order of "otherlanguages".
+ - Fix section numbering by LaTeX.
+
+* docutils/writers/s5_html/__init__.py
+
+ - Fix [ 3556388 ] Mathjax does not work with rst2s5.
+
+* docutils/writers/s5_html/docutils_xml.py
+
+ - Fix [ 3552403 ] Prevent broken PyXML replacing stdlibs xml module.
+ - Fix/improve output with ``--indent`` option.
+
+* setup.py
+
+ - Tag ``math.css`` stylesheet as data file (patch by Dmitry Shachnev).
+
+* tools/test/test_buildhtml.py
+
+ - Fix [ 3521167 ] allow running in any directory.
+ - Fix [ 3521168 ] allow running with Python 3.
+
+
+Release 0.9.1 (2012-06-17)
+==========================
+
+* setup.py
+
+ - Fix [ 3527842 ]. Under Python 3, converted tests and tools were
+ installed in the PYTHONPATH. Converted tests are now
+ stored in ``test3/``, tools no longer need conversion.
+
+ If you installed one of Docutils versions 0.7 ... 0.9 with
+ ``setup.py install`` under Python 3, remove the spurious
+ ``test/`` and ``tools/`` directories in the site library root.
+
+* test/
+
+ - Make tests independent from the location of the ``test/`` directory.
+ - Use converted sources (from the ``build/`` directory) for tests under
+ Python 3.
+
+* tools/
+
+ - Make tools compatible with both, Python 2 and 3 without 2to3-conversion.
+
+* docutils/io.py
+
+ - Fix writing binary data to sys.stdout under Python 3 (allows
+ ``rst2odt.py`` to be used with output redirection).
+
+* docutils/parsers/rst/directives/misc.py
+
+ - Fix [ 3525847 ]. Catch and report UnicodeEncodeError with
+ ``locale == C`` and 8-bit char in path argument of `include` directive.
+
+* test/alltests.py
+
+ - class `Tee`: catch UnicodeError when writing to "ascii" stream or
+ file under Python 3.
+
+Release 0.9 (2012-05-02)
+========================
+
+* General:
+
+ - New reStructuredText "code" role and directive and "code" option
+ of the "include" directive with syntax highlighting by Pygments_.
+ - Fix parse_option_marker for option arguments containing ``=``.
+ - Fix [ 2993756 ]: import Python Imaging Library's Image module
+ via ``import PIL`` as starting with PIL 1.2,
+ "PIL lives in the PIL namespace only" (announcement__).
+
+.. _Pygments: http://pygments.org/
+__ http://mail.python.org/pipermail/image-sig/2011-January/006650.html
+
+* setup.py
+
+ - Fix [ 2971827 ] and [ 3442827 ]
+ extras/roman.py moved to docutils/utils/roman.py
+
+* docutils/frontend.py
+
+ - Fix [ 3481980 ] Use os.getcwdu() in make_paths_absolute().
+
+* docutils/io.py
+
+ - Fix [ 3395948 ] (Work around encoding problems in Py3k).
+ - `mode` argument for FileOutput avoids code replication in
+ BinaryFileOutput.
+ - New exceptions InputError and OutputError for IO errors in
+ FileInput/FileOutput.
+
+* docutils/core.py:
+
+ - No "hard" system exit on file IO errors: catch and report them in
+ `Publisher.reportException` instead. Allows handling by a calling
+ application if the configuration setting `traceback` is True.
+
+* docutils/utils.py -> docutils/utils/__init__.py
+
+ - docutils.utils is now a package (providing a place for sub-modules)
+
+ .. note:: docutils/math, docutils/error_reporting.py, and
+ docutils/urischemes.py will move to the utils package in the next
+ release, too. See RELEASE-NOTES__
+
+ __ RELEASE-NOTES.html
+
+ - DependencyList uses io.FileOutput and 'utf8' encoding to prevent
+ errors recording non-ASCII filenames (fixes [ 3434355 ]).
+
+ - Fix relative_path() with source=None and `unicode` target.
+
+* docutils/parsers/rst/states.py
+
+ - Fix [ 3402314 ] allow non-ASCII whitespace, punctuation
+ characters and "international" quotes around inline markup.
+ - Use `field_marker` pattern to look for start of a
+ directive option block (fixes [ 3484857 ]).
+
+* docutils/parsers/rst/tableparser.py
+
+ - Fix [ 2926161 ] for simple tables.
+ (Combining chars in grid tables still contribute to cell width.)
+
+* docutils/writers/latex2e/__init__.py
+
+ - Support the `abbreviation` and `acronym` standard roles.
+ - Record only files required to generate the LaTeX source as dependencies.
+ - Fix handling of missing stylesheets.
+ - Use ``\setcounter{secnumdepth}{0}`` instead of ``*``-versions
+ when suppressing LaTeX section numbering.
+ - Use ``\DUtitle`` for unsupported section levels
+ - Apply [ 3512791 ] do not compare string literals with "is"
+
+* docutils/writers/xetex/__init__.py
+
+ - Avoid code duplication with latex2e writer (solves [ 3512728 ]).
+
+* docutils/writers/html4css1/__init__.py
+
+ - Change default for `math-output` setting to MathJax.
+ - Fix handling of missing stylesheets.
+
+* docutils/writers/docutils_xml.py
+
+ - Use the visitor pattern with default_visit()/default_depart() methods
+ instead of minidom to facilitate special handling of selected nodes.
+ - Support raw XML (inserted as-is inside a <raw></raw> node).
+
+* docutils/writers/manpage.py
+
+ - Do not emit comment line with trailing blank. Problematic for VCS.
+
+Release 0.8.1 (2011-08-30)
+==========================
+
+* General:
+
+ - Fix [ 3364658 ] (Change last file with Apache license to BSD-2-Clause)
+ and [ 3395920 ] (correct copyright info for rst.el).
+
+* test/
+
+ - Apply [ 3303733 ] and [ 3365041 ] to fix tests under Py3k.
+
+* docutils/writers/latex2e/__init__.py
+
+ - Clean up Babel language setting. Restores Sphinx compatibility.
+
+Release 0.8 (2011-07-07)
+========================
+
+* General:
+
+ - Handle language codes according to `BCP 47`_.
+ - If the specified language is not supported by Docutils,
+ warn and fall back to English.
+ - Math support: reStructuredText "math" role and directive,
+ ``math`` and ``math_block`` doctree elements.
+ - Decode command line arguments with the locale's preferred encoding
+ (to allow, e.g., ``--title=Dornröschen``).
+ - Orphaned "python" reader and "newlatex2e" writer moved to the sandbox.
+ - New sub-module `error_reporting`: handle encoding/decoding errors
+ when reporting exceptions.
+ - Some additions to the Docutils core are released under the 2-Clause BSD
+ license, see COPYING_ for details.
+
+ .. _BCP 47: http://www.rfc-editor.org/rfc/bcp/bcp47.txt
+ .. _COPYING: COPYING.html
+
+* reStructuredText:
+
+ - Most directives now support a "name" option that attaches a
+ reference name.
+
+ - Directive content may start on the first line also when the directive
+ type accepts options.
+
+* docs/dev/policies.txt:
+
+ - Recommend the 2-Clause BSD license
+ (http://www.spdx.org/licenses/BSD-2-Clause)
+ for code that is kept under the author's copyright.
+
+* tools/buildhtml.py:
+
+ - Fix ``--local`` switch.
+
+* Fix [ 3018371 ] Added Lithuanian mappings by Dalius Dobravolskas.
+
+* docutils/writers/html4css1/__init__.py
+
+ - Set "lang" argument for objects with class argument
+ "language-<language tag>".
+ - New setting "math-output" with support for HTML, MathML, and LaTeX.
+
+* docutils/writers/latex2e/__init__.py
+
+ - Fix [ 3043986 ] AttributeError using :local: with table of content.
+ - Place title data in the document preamble.
+ - Load `babel` package only if required.
+ - Update list of supported languages.
+ - New config setting "hyperref-options".
+ No hard-coded "unicode" hyperref option (clash with xetex).
+ - Set language for custom roles, paragraphs, block-quotes, and
+ line-quotes with class argument "language-<language tag>".
+ - Fix [ 3095603 ] wrong quotes output for russian and other languages.
+ - Convert image URI to a local file path.
+ - Apply [ 3148141 ] fix multicolumn support when a colspanning cell
+ has more than one paragraph (Wolfgang Scherer).
+ - \leavevmode before longtable only when needed (prevents spurious vspace)
+ - do not advance table counter for tables without caption
+
+* docutils/writers/xetex/__init__.py
+
+ - New writer generating LaTeX code for compiling with ``xelatex``.
+
+ A separate writer (inheriting from latex2e) instead of a ``--xetex``
+ option allows separate config options for XeTeX vs. LaTeX2e.
+
+* docutils/writers/manpage.py
+
+ - Fix: BUG#3219183 - vertical space in definition lists containing markup.
+ - Fix: vertical space cleaning for option group ``.``.
+
+* tools/editors/emacs/rst.el:
+
+ - Fix [ 3001100 ] does not handle spaces in filenames
+ (thanks to Jakub Wilk)
+
+* docutils/utils.py:
+
+ - strip whitespace from stylesheet arguments
+ - exclude combining chars from column_width()
+ (partial fix for [ 2926161 ])
+
+* docutils/parsers/rst/directives/misc.py:
+
+ - Fix [ 1830389 ] Replace not breaking on getting system_messages from
+ nested_parse
+
+* docutils/io.py:
+
+ - Do not close() sys.stdin, sys.stdout, or sys.stderr. Prevents
+ ``Exception ValueError: 'I/O operation on closed file.'`` with Python 3.
+
+Release 0.7 (2010-07-07)
+========================
+
+* General:
+
+ - Fix [ 2881769 ] setup configuration.
+ - Fix [ 2788716 ] reporting problems in included files.
+
+* docutils/io.py
+
+ - FileInput opens files as text files with universal newline support
+ (mode "rU", configurable with the new optional argument "mode").
+
+* docutils/nodes.py
+
+ - Fix [ 2975987 ] repr(Text) failed with long string (Jeffrey C. Jacobs).
+
+* docutils/utils.py
+
+ - Fix [ 2923723 ] let decode_path() tolerate path == None
+
+* docutils/writers/html4css1/__init__.py
+
+ - Support SVG and SWF images (thanks to Stefan Rank).
+ - Generate valid XHTML for centered images with targets.
+ Use CSS classes instead of "align" tags for image alignment.
+
+* docutils/writers/latex2e/__init__.py
+
+ - Use `transforms.writer_aux.Admonitions` to "normalize" special
+ admonitions.
+ - Use the ``\url`` command for URLs (breaks long URLs instead of
+ writing into the margin).
+ - Preserve runs of spaces in `inline literals`__.
+ - Deprecate ``figure_footnotes`` setting.
+ - Rename ``use_latex_footnotes`` setting to `docutils_footnotes`__.
+ - New ``latex_preamble`` setting.
+ - Use PDF standard fonts (Times/Helvetica/Courier) as default.
+ - Fix hyperlink targets (labels) for images, figures, and tables.
+ - Apply [ 2961988 ] Load babel after inputenc and fontenc.
+ - Apply [ 2961991 ] Call hyperref with unicode option.
+ - Drop the special `output_encoding`__ default ("latin-1").
+ The Docutils wide default (usually "UTF-8") is used instead.
+ - Render inline markup in document title and subtitle.
+ - Fix numbering depth with LaTeX section numbering.
+ - Update Unicode -> LaTeX translations.
+ - Fix bug with topic directive (thanks to Alan G Isaac for reporting).
+
+__ docs/ref/restructuredtext.html#inline-literals
+__ docs/user/config.html#docutils-footnotes
+__ docs/user/config.html#output_encoding
+
+* docutils/writers/manpage.py
+
+ - Fix: supported attribute (thanks to peter2108).
+ - Remove trailing blanks in code (keep in sync with mercurial version).
+ - Titles level 1, that is ``.SH``, always uppercase.
+ - Apply patch from mg: literal text should be bold in man-pages.
+
+* docutils/nodes.py
+
+ - Fix: encoding ``'ascii'`` must be lowercase to prevent problems for
+ turkish locale.
+
+* setup.py:
+
+ - Python 3 support: copy test/ and tools/ to the build-dir
+ and convert Python sources with 2to3.
+
+
+Release 0.6 (2009-10-11)
+========================
+
+* General:
+
+ - Docutils is now compatible with Python versions from 2.3 up to 2.6
+ and convertible to 3.1 code.
+
+ + Node.__nonzero__ returns True instead of 1.
+ + use os.walk instead os.path.walk.
+ + minimize "types" module where possible.
+ + Backwards-compatible changes to remove python2.6 -3 deprecation warnings
+ + Text nodes now subclass unicode rather than UserString
+ (which is gone in python 3.0).
+ + 3.0 compatibility module docutils._compat
+
+ + Drop 2.2 compatibility workarounds.
+ + Drop extras/optparse.py and extras/textwrap.py
+ (stdlib modules since 2.3).
+
+ - OpenOffice export: ODT writer moved from sandbox to Doctutils core.
+ - Unix man page export: manpage writer moved from sandbox to Doctutils
+ core.
+
+ - Apply [ 1719345 ] Galician translation
+ - Apply [ 1905741 ] Polish translation
+ - Apply [ 1878977 ] make_id(): deaccent characters.
+ - Apply [ 2029251 ] return nonzero when tests fail.
+ - Fix [ 1692788 ] allow UTF-8 in style sheets.
+ - Fix [ 2781629 ] support non-ASCII chars in file names.
+ - Apply [ 2845002 ] let ``--no-raw`` disable raw *roles* too.
+ - Fix [ 2831643 ] by renaming DirectiveError.message to DirectiveError.msg
+ - Fix [ 2821266 ] --strict option works now like --halt=info.
+ - Fix [ 2788716 ] DirectiveError now correctly reports source and line.
+ - Fix [ 1627229 ] hyperlink references in substitutions.
+
+ - The "newlatex" writer is orphaned.
+
+* reStructuredText:
+
+ - Documented Unicode characters allowed as inline markup openers,
+ closers, and delimiters.
+ - Allow units for all length specifications.
+ - Allow percent sign in "scale" argument of "figure" and "image" directives.
+ - Bugfix: The "figalign" argument of a figure now works as intended
+ (aligning the figure, not its contents).
+ - Align images with class "align-[right|center|left]"
+ (allows setting the alignment of an image in a figure).
+
+* docutils/nodes.py:
+
+ - Added ``Element.__contains__`` method, for the in-operator.
+
+* docutils/parsers/rst/states.py:
+
+ - Apply [ 1994493 ] Patch to support all kinds of quotes in inline markup.
+ - Added support for Unicode inline markup delimiters "‐ ‑ ‒ – —" and
+ " " (non-breaking space), and "¡ ¿" openers.
+
+* docutils/parsers/directives/misc.py:
+
+ - Added ``start-line`` and ``end-line`` options to "include"
+ directive to select a range of lines.
+ - Hard tabs in literal inclusions are replaced by spaces. This is
+ configurable via the new ``tab-width`` option of the "include" directive
+ (a negative tab-width prevents tab expansion).
+
+* docutils/utils.py:
+
+ - Add ``get_stylesheet_list`` function.
+ - Apply [ 2834836 ] print info at halt
+
+* docutils/transforms/universal.py:
+
+ - Raise default priority of StripClasses to exclude stripped classes from
+ the ToC.
+
+* docutils/writers/html4css1/__init__.py:
+
+ - ``--stylesheet`` and ``--stylesheet-path`` options support a comma
+ separated list of stylesheets.
+ - Address [ 1938891 ] Inline literal text creates "pre" span only when
+ needed to prevent inter-word line wraps.
+ - Use `translate` method instead of repeated `replace` calls.
+ - Fix [ 1757105 ] New ``table-style`` option. Added to standard table
+ classes to allow CSS styling that does not interfere with other
+ table-using constructs (field lists, citations, ...).
+
+* docutils/writers/newlatex2e/__init__.py:
+
+ - Apply [ 1612821 ] Double quotes in literal text in Italian/German
+
+* docutils/writers/latex2e/__init__.py (see also
+ `<docs/user/docutils-05-compat.sty.html>`__) :
+
+ - Add ``--embed-stylesheet`` option.
+ - Apply [ 1474017 ] image vertical alignment is reversed.
+ - Apply [ 2051599 ] multi-page tables in latex writer (from pabigot).
+ - Change: has_key for dictionaries (not Nodes) to in-operator.
+ - Merge adjacent citations into one latex cite command.
+ - Failsave implementation of custom roles. LaTeX compilation now ignores
+ unknown classes instead of aborting with an error.
+ - Support custom roles based on standard roles.
+ - LaTeX packages can be used as ``--stylesheet`` arguments without
+ restriction. (A style sheet is now referenced with the ``\usepackage``
+ command, if it ends with ``.sty`` or has no extension.)
+ - Add ``bp`` to lenghts without unit (prevents LaTex errors).
+ - Correctly write length unit ``pt`` as ``bp`` in LaTeX.
+ - Do not convert ``px`` to ``pt`` (``px`` is supported by pdfTeX since
+ 2005-02-04 as a configurable length unit).
+ - Do not use fontenc, nor the obsolete 'ae' and 'aeguill' packages
+ if font-encoding is set to ''. LaTeX defaults to OT1 then.
+ - Set sub- and superscript role argument in text mode not as math.
+ Use a custom role based on sub-/superscript if you want italic shape.
+ - Shorter preamble and less dependencies: Load packages and define macros
+ only if required in the document.
+ - Use the name prefix ``DU`` for all Docutils specific LaTeX macros.
+ - New custom environments and commands with optional "classes" argument.
+ - Simpler LaTeX encoding, e.g. "\%" instead of "{\%}".
+ - Better conformance to Docutils specifications with ``--use-latex-toc``.
+ Support for LaTeX generated ToC also with unnumbered sections.
+ - If 'sectnum_xform' is False, the 'sectnum' directive triggers
+ section numbering by LaTeX.
+ - Use default font in admonitions and sidebar.
+ - Align of image in a figure defaults to 'center'.
+ - Bugfix: Newlines around targets and references prevent run-together
+ paragraphs.
+ - Fix internal hyperlinks.
+ - Use class defaults for page margins ('typearea' now optional).
+ - Float placement made configurable, default changed to "here definitely".
+ - Typeset generic topic as "quote block with title".
+ - Use template (file and configuration option).
+ - In the default template, load cmap.sty (fix text extraction in PDF) and
+ fixltx2e.sty (LaTeX patches, \textsubscript).
+ - Render doctest blocks as literal blocks (fixes [ 1586058 ]).
+ - Use `translate` instead of repeated `replace` calls for text encoding.
+ - Hyperlinked footnotes and support for symbol footnotes and
+ ``--footnote-references=brackets`` with ``--use-latex-footnotes``.
+ - Complete pairs of binary options
+ (``--figure-footnotes, --figure-citations, --link-stylesheet``,
+ ``--use-docutils-toc, --use-docutils-docinfo, --topic-abstract``)
+ - New defaults:
+ - font-encoding: "T1" (formerly implicitely set by 'ae').
+ - use-latex-toc: true (ToC with page numbers).
+ - use-latex-footnotes: true (no mixup with figures).
+
+* docutils/writers/manpage.py
+
+ - Do not print version at document end, this is done by the viewer.
+ - Do not print date at document end, this is done by the viewer.
+ - Fix storage of docinfo fields for none standard fields.
+
+* docutils/tools/rst2man.py
+
+Release 0.5 (2008-06-25)
+========================
+
+* docutils/languages/he.py: Added to project: Hebrew mappings by
+ Meir Kriheli.
+
+* docutils/parsers/rst/languages/he.py: Added to project: Hebrew
+ mappings by Meir Kriheli.
+
+* docutils/frontend.py:
+
+ - Configuration files are now assumed and required to be
+ UTF-8-encoded.
+ - Paths of applied configuration files are now recorded in the
+ runtime setting ``_config_files`` (accessible via
+ ``--dump-settings``).
+ - Added ``--strip-elements-with-class`` and ``--strip-class``
+ options (``strip_elements_with_classes`` and ``strip_classes``
+ settings).
+
+* docutils/io.py:
+
+ - Added code to determine the input encoding from data: encoding
+ declarations or the presence of byte order marks (UTF-8 & UTF-16).
+ - Added support for IronPython 1.0.
+
+* docutils/nodes.py:
+
+ - Added ``document.__getstate__`` method, for pickling.
+
+* docutils/parsers/rst/states.py:
+
+ - Allow ``+`` and ``:`` in reference names.
+ - Unquoted targets beginning with an underscore (``.. __target:
+ URI``) are no longer accepted.
+ - Added support for multiple attributions in a physical block quote
+ (indented text block), dividing it into multiple logical block
+ quotes.
+ - Added support for unicode bullets in bullet lists: "•", "‣", and
+ "⁃".
+ - Added support for new object-oriented directive interface,
+ retaining compatibility to the old functional interface.
+ - Added support for throwing ``DirectiveError``'s from within
+ directive code.
+
+* docutils/parsers/rst/__init__.py:
+
+ - Added ``Directive`` base class.
+ - Added ``DirectiveError`` base class.
+ - Fixed ``file_insertion_enabled`` & ``raw_enabled`` setting
+ definitions.
+
+* docutils/parsers/directives/:
+
+ - Refactored all reStructuredText directives to use the new
+ object-oriented directive interface. Errors are now (mostly)
+ thrown using the new ``DirectiveError`` class.
+
+* docutils/parsers/directives/misc.py:
+
+ - Added ``start-after`` and ``end-before`` options to ``include``
+ directive; thanks to Stefan Rank.
+
+* docutils/transforms/universal.py:
+
+ - Added ``StripClassesAndElements`` transform to remove from the
+ document tree all elements with classes in
+ ``settings.strip_elements_with_classes`` and all "classes"
+ attribute values in ``self.document.settings.strip_classes``.
+
+* docutils/transforms/writer_aux.py:
+
+ - Added ``Admonitions`` transform to transform specific admonitions
+ (like ``note``, ``warning``, etc.) into generic admonitions with a
+ localized title.
+
+* docutils/writers/html4css1/__init__.py:
+
+ - Moved template functionality from the PEP/HTML writer here.
+ - Expanded the fragments available in the ``parts`` attribute.
+ - Moved ``id`` attributes from titles to surrounding ``div``
+ elements.
+ - Dropped all ``name`` attributes of ``a`` elements (``id`` is
+ universally supported now).
+ - ``template.txt`` is now opened in text mode instead of binary mode
+ (to ensure Windows compatibility).
+ - ``a`` elements now have an "internal" or "external" class,
+ depending on reference type.
+
+* docutils/writers/html4css1/template.txt: Added to project.
+
+* docutils/writers/pep_html/:
+
+ - Moved template functionality to the HTML writer.
+
+* docutils/writers/s5_html/__init__.py:
+
+ - Added ``view_mode`` & ``hidden_controls`` settings
+ (``--view-mode`` & ``--hidden-controls/--visible-controls``
+ options).
+
+* docutils/writers/latex2e/__init__.py:
+
+ - Add ``--literal-block-env``
+ - Fix: escaping ``%`` in href urls.
+ - Move usepackage hyperref after stylesheet inclusion.
+ - Fix: scrartcl does not have chapter but scrreprt.
+ - Add newline after ``\end{verbatim}``.
+ - Merge smaller differences from latex2e_adaptive_preamble.
+ - Add ``use-part-section``.
+ - Put leavevmode before longtable to avoid having it moved before sub/pargraph.
+ - Using leavemode option_list no longer needs to check if parent
+ is a definition list.
+ - Append ``\leavemode`` to definition list terms.
+ - No longer write visit\_/depart_definition_list_item comments to
+ output.
+ - Table column width with 3 decimal places.
+ - Add table stubs support (boldfont).
+ - Add assemble_parts to writer.
+ - Add simply support for nested tables.
+ - Fix verbatim in tables if use-verbatim-when-possible.
+ - Use section commands down to subparagraph.
+ - Put ensuremath around some latin1 chars.
+ - Set ``usepackage[utf8x]{inputenc}`` for utf-8.
+ - New option ``--use-bibtex=style,db1,db2``.
+ - New option ``--reference-label`` to allow usage of LaTeX ref for
+ labels in section references.
+ - Add a label after every section to support sectionnumbers as reference
+ labels.
+ - Fix: bug# 1605376 rst2latex: bad options group list
+ - Remove inactive code for use_optionlist_for_option_list.
+ - Remove latex comments from option_list output.
+ - Fix: bug# 1612270 double qoutes in italian literal.
+ - Fix: output ``hypertarget{ node.get(refid) }{}`` from visit_target.
+ - Add option --use-latex-abstract.
+ - Image width unit ``px`` is translated to ``pt``.
+ - Add image height support.
+ - Fix: image width ``70%`` is converted ``0.700\linewidth``.
+ bug #1457388
+ - Fix: Do not escape underscores in citation reference labels if
+ use-latex-citations is set.
+ - Use centering instead of center for figure contents, to avoid vertical
+ space.
+ - Recognize table class: borderless, nolines, booktabs, standard.
+ - Fix: Renaming contents section does not work with latex writer; SF
+ bug #1487405.
+ - Applied patch for custom roles with classes from Edward Loper.
+ - Fixed bug that caused crashes with more than 256 lists.
+
+* docutils/writers/pep_html/__init__.py:
+
+ - Changed to support new python.org website structure and
+ pep2pyramid.py.
+
+* docs/howto/security.txt: "Deploying Docutils Securely", added to
+ project.
+
+* tools/buildhtml.py:
+
+ -- Added ``ignore`` setting to exclude a list of shell patterns
+ (default: ``.svn:CVS``).
+
+* tools/editors/emacs/rst.el:
+
+ - Changed license to "GPL".
+ - Added ``rst-straighten-decorations`` function.
+ - The ``compile`` module is now always loaded.
+ - Added ``rst-toggle-line-block`` function.
+ - Headings consisting only of non-ASCII characters are now
+ recognized by ``rst-toc`` and ``rst-adjust``.
+ - Added font-lock support for multi-line comments where the first
+ comment line is empty.
+ - Added ``(require 'font-lock)``.
+
+* setup.py:
+
+ - Provide descriptive error message if distutils is missing.
+
+
+Release 0.4 (2006-01-09)
+========================
+
+* General:
+
+ - Updated the project policies for trunk/branch development &
+ version numbering.
+
+* docutils/__init__.py:
+
+ - Added ``__version_details__`` attribute to describe code source
+ (repository/snapshot/release).
+ - Replaced ``default_transforms`` attribute of TransformSpec with
+ ``get_transforms()`` method.
+
+* docutils/core.py:
+
+ - Added ``publish_doctree`` and ``publish_from_doctree`` convenience
+ functions, for document tree extraction and reprocessing.
+
+* docutils/io.py:
+
+ - Added ``DocTreeInput`` class, for reprocessing existing documents.
+ - Added support for non-Unicode (e.g. binary) writer output.
+
+* docutils/nodes.py:
+
+ - Re-introduced ``Targetable.indirect_reference_name``, for
+ MoinMoin/reST compatibility (removed in r3124/r3129).
+ - Added ``serial_escape`` function; escapes string values that are
+ elements of a list, for serialization. Modified Docutils-XML
+ writing (``Element._dom_node``) and pseudo-XML writing
+ (``Element.starttag``) to use ``serial_escape``.
+ - Added ``Node.deepcopy()`` method.
+ - Removed the internal lists ``document.substitution_refs``,
+ ``document.anonymous_refs``, and ``document.anonymous_targets``.
+ - Added a "container" element.
+ - Fixed bug where values of list-valued attributes of elements
+ originating from custom interpreted text roles (i.e., with custom
+ classes) were being shared between element instances. Reported by
+ Shmuel Zeigerman.
+
+* docutils/statemachine.py:
+
+ - Added trailing whitespace stripping to ``string2lines()``.
+ - Added ``StringList.pad_double_width()`` & ``.replace()`` for East
+ Asian double-width character support.
+
+* docutils/utils.py:
+
+ - Added ``east_asian_column_width()`` for double-width character
+ support.
+
+* docutils/languages/ja.py: Added to project: Japanese mappings by
+ Hisashi Morita.
+
+* docutils/languages/zh_cn.py: Added to project: Simplified Chinese
+ mappings by Panjunyong.
+
+* docutils/parsers/null.py: Added to project; a do-nothing parser.
+
+* docutils/parsers/rst/__init__.py:
+
+ - Added validator to tab_width setting, with test. Closes SF bug
+ #1212515, report from Wu Wei.
+
+* docutils/parsers/rst/states.py:
+
+ - Fixed bug with escaped colons indicating a literal block.
+ - Fixed bug with enumerated lists (SF#1254145).
+ - Backslash-escaped colons inside of field names are now allowed.
+ - Targets (implicit and explicit), anonymous hyperlink references
+ and auto-numbered footnote references inside of substitution
+ definitions are now disallowed.
+ - Fixed bug: list items with blank first lines.
+ - Fixed bug: block quote attributions with indented second lines.
+ - Added East Asian double-width character support (Python 2.4 only).
+
+* docutils/parsers/rst/tableparser.py:
+
+ - Added East Asian double-width character support (Python 2.4 only).
+
+* docutils/parsers/rst/directives/body.py:
+
+ - Added the "container" directive.
+
+* docutils/parsers/rst/directives/misc.py:
+
+ - Added the "default-role", "title", and "date" directives.
+ - Added standard data file syntax to the "include" directive.
+ - Added support for "class" directive content.
+
+* docutils/parsers/rst/directives/images.py:
+
+ - Added ``indirect_reference_name`` support for images with a target
+ option.
+ - Added support for image width and height units.
+ - Fixed bug with image "target" options.
+
+* docutils/parsers/rst/directives/references.py:
+
+ - Added "class" attribute to "target-notes" directive, for
+ footnote_reference classes.
+
+* docutils/parsers/rst/include/: Directory added to project; contains
+ standard data files for the "include" directive. Initial contents:
+ character entity substitution definition sets, and a set of
+ definitions for S5/HTML presentations.
+
+* docutils/parsers/rst/languages/ja.py: Added to project: Japanese
+ mappings by David Goodger.
+
+* docutils/parsers/rst/languages/zh_cn.py: Added to project:
+ Simplified Chinese mappings by Panjunyong.
+
+* docutils/readers/__init__.py:
+
+ - Added universal.Decorations and universal.ExposeInternals
+ transforms as default transforms for all readers.
+ - Added ``ReReader`` base class for readers that reread an existing
+ document tree.
+
+* docutils/readers/doctree.py: Added to project; a reader for existing
+ document trees.
+
+* docutils/transforms/frontmatter.py:
+
+ - Fixed the DocInfo transform to handle SVN-style expansion of the
+ "Date" keyword.
+ - In ``DocInfo.extract_authors``, treat the contents of "authors"
+ fields uniformly.
+
+* docutils/transforms/misc.py:
+
+ - Added misc.Transitions transform, extracted from
+ universal.FinalChecks.
+
+* docutils/transforms/references.py:
+
+ - Added references.DanglingReferences transform, extracted from
+ universal.FinalChecks.
+ - Fixed bug with doubly-indirect substitutions.
+ - Added footnote_reference classes attribute to "TargetNotes".
+ - Fixed bug with circular substitution definitions that put Docutils
+ into an infinite loop.
+
+* docutils/transforms/universal.py:
+
+ - Added universal.ExposeInternals transform, extracted from
+ universal.FinalChecks.
+ - Removed universal.FinalChecks transform (logic has been moved to
+ several new transforms).
+ - Fixed bug with the "expose_internals" setting and Text nodes
+ (exposed by the "rawsource" internal attribute).
+ - Added the universal.StripComments transform, implementation of the
+ "strip_comments" setting.
+
+* docutils/transforms/writer_aux.py: Added to project; auxiliary
+ transforms for writers.
+
+ - Added ``Compound`` transform, which flattens compound paragraphs.
+
+* docutils/writers/: Several writer modules (html4css1.py) were
+ converted into packages. Support modules and data files have been
+ moved into the packages. The stylesheets for the HTML writers are
+ now installed along with the code, the code knows where to find
+ them, and the default is to use them (actually, to embed them).
+ Some adjustments to configuration files may be necessary. The
+ easiest way to obtain the new default behavior is to remove all
+ settings whose name includes "stylesheet".
+
+* docutils/writers/__init__.py:
+
+ - Added universal.Messages and universal.FilterMessages transforms
+ as default transforms for all writers.
+ - Added ``UnfilteredWriter`` base class for writers that pass the
+ document tree on unchanged.
+
+* docutils/writers/docutils_xml.py:
+
+ - Made ``xmlcharrefreplace`` the default output encoding error
+ handler.
+
+* docutils/writers/html4css1/:
+
+ - Added support for image width and height units.
+ - Made ``xmlcharrefreplace`` the default output encoding error
+ handler.
+ - Made ``--embed-stylesheet`` the default rather than
+ ``--link-stylesheet``.
+ - Moved "id" attribute from container (section etc.) to title's <a>
+ tag, to be on the same tag as "name".
+ (!!! To be reverted in Docutils 0.5.)
+ - Added vertical space between fields of field lists.
+ - Added ``--compact-field-lists`` option to remove vertical space in
+ simple field lists.
+ - Made cloaking of email addresses with ``--cloak-email-addresses``
+ less obtrusive.
+ - Fixed support for centered images.
+ - Added support for class="compact" & class="open" lists.
+
+* docutils/writers/latex2e/:
+
+ - Underscores in citekeys are no longer escaped.
+
+* docutils/writers/newlatex2e/unicode_map.py: Added to project;
+ mapping of Unicode characters to LaTeX equivalents.
+
+* docutils/writers/s5_html/: Package added to project; writer for
+ S5/HTML slide shows.
+
+* docs/dev/distributing.txt: Added to project; guide for distributors
+ (package maintainers).
+
+* docs/dev/hacking.txt: Added to project; guide for developers.
+
+* docs/ref/doctree.txt:
+
+ - Updated for plural attributes "classes", "ids", "names",
+ "dupnames".
+ - Added the "container" element.
+
+* docs/ref/docutils.dtd:
+
+ - Updated for plural attributes "classes", "ids", "names",
+ "dupnames".
+
+* docs/user/emacs.txt: Added to project; a document about Emacs
+ support for reStructuredText and Docutils.
+
+* docs/user/links.txt: Added to project; lists of Docutils-related
+ links.
+
+* docs/user/mailing-lists.txt: Added to project; information about
+ Docutils-related mailing lists and how to access them.
+
+* docs/user/slide-shows.txt: Added to project; example of and docs for
+ the S5/HTML writer (``rst2s5.py`` front end).
+
+* docs/ref/rst/definitions.txt: "reStructuredText Standard Definition
+ Files", added to project.
+
+* test/coverage.sh: Added to project; test coverage script.
+
+* test/DocutilsTestSupport.py:
+
+ - Added support for specifying runtime settings at the suite level.
+
+* test/test_functional.py:
+
+ - Added the ``clear_output_directory`` function.
+ - Added support for ``_test_more`` functions in functional test
+ config files.
+
+* tools/rst2s5.py: Added to project; front end for the S5/HTML writer.
+
+* tools/rstpep2html.py: Renamed from pep.py.
+
+* tools/dev/create_unimap.py: Added to project; script to create the
+ docutils/writers/unimap_latex.py mapping file.
+
+* tools/dev/profile_docutils.py: Added to project; profiler script.
+
+* tools/dev/unicode2rstsubs.py: Moved from tools/unicode2rstsubs.py.
+
+* tools/editors/emacs/restructuredtext.el,
+ tools/editors/emacs/rst-html.el, tools/editors/emacs/rst-mode.el:
+ Removed from project; the functionality is now contained in rst.el.
+
+* tools/editors/emacs/rst.el: Added to project. Added many features
+ and fixed many bugs. See docs/user/emacs.txt for details.
+
+* tools/stylesheets: Removed from project. Stylesheets have been
+ renamed and moved into writer packages.
+
+
+Release 0.3.9 (2005-05-26)
+==========================
+
+* General:
+
+ - Eliminated and replaced all uses of the old string attributes
+ ``id``, ``name``, ``dupname`` and ``class`` with references to the
+ new list attributes ``ids``, ``names``, ``dupnames`` and
+ ``classes`` throughout the whole source tree.
+
+* docutils/core.py:
+
+ - Enabled ``--dump-*`` options when ``--traceback`` specified,
+ allowing for easier debugging.
+ - In ``Publisher.publish()``, expanded the generic top-level
+ exception catching.
+
+* docutils/examples.py:
+
+ - Added ``internals`` function for exploration.
+
+* docutils/io.py:
+
+ - Fixed ``Input.decode`` method to apply heuristics only if no
+ encoding is explicitly given, and to provide better reporting of
+ decoding errors.
+ - The ``Input.decode`` method now removes byte order marks (BOMs)
+ from input streams.
+
+* docutils/nodes.py:
+
+ - ``image`` element class changed to subclass of Element, not
+ TextElement (it's an empty element, and cannot contain text).
+ - Added ``attr_defaults`` dictionary for default attribute values.
+ - Added empty list as default value for the following attributes:
+ ``ids``, ``names``, ``dupnames``, ``classes``, and ``backrefs``.
+ - Added ``document.decoration`` attribute,
+ ``document.get_decoration`` method, and ``decoration.get_header``
+ & ``.get_footer`` methods.
+ - Added ``Element.update_basic_atts()`` and ``Element.substitute()``
+ methods.
+
+* docutils/utils.py:
+
+ - Removed ``docutils.utils.Reporter.categories``,
+ ``docutils.utils.ConditionSet``, and all references to them, to
+ simplify error reporting.
+
+* docutils/languages/nl.py: Added to project; Dutch mappings by
+ Martijn Pieters.
+
+* docutils/parsers/rst/__init__.py:
+
+ - Added settings: ``file_insertion_enabled`` & ``raw_enabled``.
+
+* docutils/parsers/rst/states.py:
+
+ - Added check for escaped at-mark to prevent email address recognition.
+ - Fixed option lists to allow spaces inside ``<angle-bracketed option
+ arguments>``.
+ - Allowed whitespace in paths and URLs.
+ - Added auto-enumerated list items.
+ - Fixed bug that assumed ``.. _`` and ``.. |`` were invariably
+ followed by text.
+ - Added support for table stub columns.
+
+* docutils/parsers/rst/directives/__init__.py:
+
+ - Allowed whitespace in paths (``path`` function).
+ - Added ``uri`` directive option conversion function.
+
+* docutils/parsers/rst/directives/body.py:
+
+ - Fixed illegal context bug with "topic" directive (allowed within
+ sidebars; not within body elements).
+
+* docutils/parsers/rst/directives/images.py:
+
+ - Allowed whitespace (stripped) in "image" & "figure" directive URLs.
+ - Added support for the ``file_insertion_enabled`` setting in the
+ "figure" directive (disables "figwidth" option).
+ - "image" directive: added checks for valid values of "align" option,
+ depending on context. "figure" directive: added specialized
+ "align" option and attribute on "figure" element.
+ - Made ":figwidth: image" option of "figure" directive work again.
+ - Fixed bug with reference names containing uppercase letters
+ (e.g. ``Name_``) in "target" option of "image" directive.
+
+* docutils/parsers/rst/directives/misc.py:
+
+ - Fixed "include" and "raw" directives to catch text decoding
+ errors.
+ - Allowed whitespace in "include" & "raw" directive paths.
+ - Added support for ``file_insertion_enabled`` & ``raw_enabled``
+ settings in "include" & "raw" directives.
+
+* docutils/parsers/rst/directives/parts.py:
+
+ - Added "header" & "footer" directives.
+ - Fixed illegal context bug with "contents" directive (topics
+ allowed within sidebars; not within body elements).
+
+* docutils/parsers/rst/directives/tables.py:
+
+ - Added "list-table" directive.
+ - Caught empty CSV table bug.
+ - Added support for the ``file_insertion_enabled`` setting in the
+ "csv-table" directive.
+ - Added ``stub-columns`` option to "csv-table" and "list-table"
+ directives.
+
+* docutils/parsers/rst/languages/nl.py: Added to project; Dutch
+ mappings by Martijn Pieters.
+
+* docutils/readers/standalone.py:
+
+ - Added ``--section-subtitles`` and ``--no-section-subtitles``
+ options to activate or deactivate the SectSubTitle transform.
+
+* docutils/transforms/frontmatter.py:
+
+ - Added SectSubTitle transform to promote titles of lone
+ subsections to subtitles.
+
+* docutils/transforms/references.py:
+
+ - Fixed mislocated internal targets bug, by propagating internal
+ targets to the next node, making use of the newly added support
+ for multiple names and IDs.
+ - Fixed duplicate footnote label bug.
+ - Replaced ``ChainedTargets`` with more generic ``PropagateTargets``
+ transform.
+
+* docutils/writers/html4css1.py:
+
+ - Fixed unencoded stylesheet reference bug (characters like "&" in
+ stylesheet references).
+ - ``target`` nodes now appear as ``span`` tags (instead of ``a``
+ tags).
+ - Added support for multiple IDs per node by creating empty ``span``
+ tags.
+ - Added the ``field_name_limit`` & ``option_limit`` settings &
+ support.
+ - Added support for table stub columns.
+ - Added support for the ``align`` attribute on ``figure`` elements.
+ - Added the ``cloak_email_addresses`` setting & support.
+ - Added ``html_prolog``, ``html_head``, ``html_body``,
+ ``html_title``, & ``html_subtitle`` to parts dictionary exposed by
+ ``docutils.core.publish_parts``.
+ - Added support for section subtitles.
+
+* docutils/writers/latex2e.py:
+
+ - Fixed tables starting with more than one multirow cell.
+ - Improved --use-latex-docinfo so that organization/contact/address
+ fields are lumped with the last author field and appear on the
+ titlepage.
+ - Made sure the titlepage is always shown with --use-latex-docinfo,
+ even if the document has no title.
+ - Made sure that latex doesn't fill in today's date if no date field
+ was given.
+ - Added support for section subtitles.
+
+* docutils/writers/newlatex2e.py: Added to project; a new LaTeX writer
+ (under development).
+
+* docutils/writers/null.py: Added to project; a do-nothing Writer.
+
+* docs/api/publisher.txt:
+
+ - Added "``publish_parts`` Details" section.
+
+* docutils/dev/repository.txt: Added to project; information about the
+ Docutils Subversion repository.
+
+* docs/ref/docutils.dtd:
+
+ - Added a ``stub`` attribute to the ``colspec`` element via the
+ ``tbl.colspec.att`` parameter entity.
+ - Allowed topic elements within sidebars
+ - Added an ``align`` attribute to the ``figure`` element.
+
+* tools/rst2newlatex.py: Added to project; front end for the new LaTeX
+ writer.
+
+
+Release 0.3.7 (2004-12-24)
+==========================
+
+* docutils/frontend.py:
+
+ - Added options: --input-encoding-error-handler,
+ --record-dependencies, --leave-footnote-reference-space,
+ --strict-visitor.
+ - Added command-line and config file support for "overrides" setting
+ parameter.
+
+* docutils/io.py:
+
+ - Added support for input encoding error handler.
+
+* docutils/nodes.py:
+
+ - Added dispatch_visit and dispatch_departure methods to
+ NodeVisitor; useful as a hook for Visitors.
+ - Changed structure of ``line_block``; added ``line``.
+ - Added ``compound`` node class.
+ - Added a mechanism for Visitors to transitionally ignore new node
+ classes.
+
+* docutils/utils.py:
+
+ - Moved ``escape2null`` and ``unescape`` functions from
+ docutils/parsers/rst/states.py.
+
+* docutils/parsers/rst/roles.py:
+
+ - Added "raw" role.
+ - Changed role function API: the "text" parameter now takes
+ null-escaped interpreted text content.
+
+* docutils/parsers/rst/states.py:
+
+ - Fixed bug where a "role" directive in a nested parse would crash
+ the parser; the state machine's "language" attribute was not being
+ copied over.
+ - Added support for line block syntax.
+ - Fixed directive parsing bug: argument-less directives didn't
+ notice that arguments were present.
+ - Removed error checking for transitions.
+ - Added support for multiple classifiers in definition list items.
+ - Moved ``escape2null`` and ``unescape`` functions to docutils/utils.py.
+ - Changed role function API: the "text" parameter now takes
+ null-escaped interpreted text content.
+ - Empty sections and documents are allowed now.
+
+* docutils/parsers/rst/directives/__init__.py:
+
+ - Added ``encoding`` directive option conversion function.
+ - Allow multiple class names in class_option conversion function.
+
+* docutils/parsers/rst/directives/body.py:
+
+ - Converted the line-block directive to use the new structure.
+ - Extracted the old line-block functionality to the ``block``
+ function (still used).
+ - Added ``compound`` directive (thanks to Lea Wiemann).
+
+* docutils/parsers/rst/directives/misc.py:
+
+ - Added "encoding" option to "include" and "raw" directives.
+ - Added "trim", "ltrim", and "rtrim" options to "unicode" directive.
+ - Allow multiple class names in the "class" directive.
+
+* docutils/parsers/rst/directives/parts.py:
+
+ - Directive "sectnum" now accepts "prefix", "suffix", and "start"
+ options. Thanks to Lele Gaifax.
+
+* docutils/parsers/rst/directives/tables.py:
+
+ - Added "encoding" directive to "csv-table" directive.
+ - Added workaround for lack of Unicode support in csv.py, for
+ non-ASCII CSV input.
+
+* docutils/transforms/misc.py:
+
+ - Fixed bug when multiple "class" directives are applied to a single
+ element.
+ - Enabled multiple format names for "raw" directive.
+
+* docutils/transforms/references.py:
+
+ - Added support for trimming whitespace from beside substitution
+ references.
+
+* docutils/transforms/universal.py:
+
+ - FinalChecks now checks for illegal transitions and moves
+ transitions between sections.
+
+* docutils/writers/html4css1.py:
+
+ - HTMLTranslator.encode now converts U+00A0 to " ".
+ - "stylesheet" and "stylesheet_path" settings are now mutually
+ exclusive.
+ - Added support for the new line_block/line structure.
+ - --footnote-references now overrides
+ --trim-footnote-reference-space, if applicable.
+ - Added support for ``compound`` elements.
+ - Enabled multiple format names for "raw" directive.
+ - ``<p>`` tags of a paragraph which is the only visible child of the
+ document node are no longer stripped.
+ - Moved paragraph-compacting logic (for stripping ``<p>`` tags) to
+ new method ``should_be_compact_paragraph()``.
+ - Added class="docutils" to ``dl``, ``hr``, ``table`` and ``tt``
+ elements.
+ - "raw" elements are now surrounded by ``span`` or ``div`` tags in
+ the output if they have their ``class`` attribute set.
+ - The whole document is now surrounded by a ``<div
+ class="document">`` element.
+ - Body-level images are now wrapped by their own ``<div>`` elements,
+ with image classes copied to the wrapper, and for images which
+ have the ``:align:`` option set, the surrounding ``<div>`` now
+ receives a class attribute (like ``class="align-left"``).
+
+* docutils/writers/latex2e.py:
+
+ - no newline after depart_term.
+ - Added translations for some Unicode quotes.
+ - Added option "font-encoding", made package AE the default.
+ - "stylesheet" and "stylesheet_path" settings are now mutually
+ exclusive.
+ - --footnote-references now overrides
+ --trim-footnote-reference-space, if applicable.
+ - The footnote label style now matches the footnote reference style
+ ("brackets" or "superscript").
+ - Added support for ``compound`` elements.
+ - Enabled multiple format names for "raw" directive.
+
+* docs/ref/docutils.dtd:
+
+ - Changed structure of the ``line_block`` element; added ``line``.
+ - Added ``compound`` element.
+ - Added "ltrim" and "rtrim" attributes to
+ ``substitution_definition`` element.
+ - Enabled multiple format names for ``raw`` element.
+ - Enabled multiple classifiers in ``definition_list_item`` elements.
+
+* docs/ref/rst/directives.txt
+
+ - Marked "line-block" as deprecated.
+ - "Class" directive now allows multiple class names.
+ - Added "Rationale for Class Attribute Value Conversion".
+ - Added warning about "raw" overuse/abuse.
+
+* docs/ref/rst/restructuredtext.txt:
+
+ - Added syntax for line blocks.
+ - Definition list items may have multiple classifiers.
+
+* docs/ref/rst/roles.txt:
+
+ - Added "raw" role.
+
+* tools/stylesheets/default.css:
+
+ - Added support for the new line_block structure.
+ - Added "docutils" class to ``dl``, ``hr``, ``table`` and ``tt``.
+
+
+Release 0.3.5 (2004-07-29)
+==========================
+
+General:
+
+* _`Documentation cleanup/reorganization`.
+
+ - Created new subdirectories of docs/:
+
+ * ``docs/user/``: introductory/tutorial material for end-users
+ * ``docs/dev/``: for core-developers (development notes, plans, etc.)
+ * ``docs/api/``: API reference material for client-developers
+ * ``docs/ref/``: reference material for all groups
+ * ``docs/howto/``: for component-developers and core-developers
+ * ``docs/peps/``: Python Enhancement Proposals
+
+ - Moved ``docs/*`` to ``docs/user/``.
+ - Moved ``pysource.dtd``, ``pysource.txt``, ``semantics.txt`` from
+ ``spec/`` to ``docs/dev``.
+ - Moved ``doctree.txt``, ``docutils.dtd``, ``soextblx.dtd``,
+ ``transforms.txt`` from ``spec/`` to ``docs/ref/``.
+ - Moved ``alternatives.txt``, and ``problems.txt`` from
+ ``spec/rst/`` to ``docs/dev/rst/``.
+ - Moved ``reStructuredText.txt``, ``directives.txt``,
+ ``interpreted.txt``, and ``introduction.txt`` from ``spec/rst/``
+ to ``docs/ref/rst/``. Renamed ``interpreted.txt`` to
+ ``roles.txt``, ``reStructuredText.txt`` to
+ ``restructuredtext.txt``.
+ - Moved ``spec/howto/`` to ``docs/howto``.
+
+ In order to keep the CVS history of moved files, we supplied
+ SourceForge with a `script for modifying the Docutils CVS
+ repository`__.
+
+ __ http://cvs.sourceforge.net/viewcvs.py/*checkout*/docutils/sandbox/davidg/infrastructure/cvs-reorg.sh?content-type=text/plain&rev=1.5
+
+ After running the cleanup script:
+
+ - Added ``docs/index.txt``.
+ - Added a ``.htaccess`` file to the ``web`` module, containing
+ redirects for all old paths to new paths. They'll preserve
+ fragments (the "#name" part of a URL), and won't clutter up the
+ file system, and will correct the URL in the user's browser.
+ - Added ``BUGS.txt``, ``docs/dev/policies.txt``,
+ ``docs/dev/website.txt``, ``docs/dev/release.txt`` from all but
+ the "To Do" list itself in ``docs/dev/todo.txt``.
+ - Moved "Future Plans" from ``HISTORY.txt`` to new "Priorities"
+ section of ``docs/dev/todo.txt``.
+ - Added ``THANKS.txt`` from "Acknowledgements" in ``HISTORY.txt``.
+ - Added "How To Report Bugs" to ``BUGS.txt``.
+ - Went through all the sources and docs (including under web/) and
+ updated links. Mostly done by Lea Wiemann; thanks Lea!
+ (Still need to update links in the sandboxes.)
+
+Specific:
+
+* BUGS.txt: Added to project.
+
+* THANKS.txt: Added to project.
+
+* docutils/__init__.py:
+
+ - 0.3.4: Post-release.
+
+* docutils/core.py:
+
+ - Added special error handling & advice for UnicodeEncodeError.
+ - Refactored Publisher.publish (simplified exception handling &
+ extracted debug dumps).
+ - Renamed "enable_exit" parameter of convenience functions to
+ "enable_exit_status".
+ - Enabled traceback (exception propagation) by default in
+ programmatic convenience functions.
+ - Now publish_file and publish_cmdline convenience functions return
+ the encoded string results in addition to their regular I/O.
+ - Extracted common code from publish_file, publish_string, and
+ publish_parts, into new publish_programmatically. Extracted
+ settings code to ``Publisher.process_programmatic_settings``.
+ - In Publisher.publish, disabled ``settings_overrides`` when
+ ``settings`` is supplied; redundant.
+
+* docutils/frontend.py:
+
+ - Added help text for "--output-encoding-error-handler" and
+ "--error-encoding-error-handler".
+ - Renamed "--exit" to "--exit-status".
+ - Simplified default-setting code.
+
+* docutils/parsers/rst/__init__.py:
+
+ - Added "--pep-base-url" and "--rfc-base-url" options.
+
+* docutils/parsers/rst/states.py:
+
+ - Made URI recognition more aggressive and intelligent.
+
+* docutils/parsers/rst/directives/__init__.py:
+
+ - Added several directive option conversion functions.
+
+* docutils/parsers/rst/directives/body.py:
+
+ - Moved "table" directive to tables.py.
+
+* docutils/parsers/rst/directives/tables.py: Table-related directives,
+ added to project.
+
+* docutils/writers/latex2e.py:
+
+ - Added "--table-style=(standard|booktabs|nolines)"
+ - figures get "here" option (LaTeX per default puts them at bottom),
+ and figure content is centered.
+ - Rowspan support for tables.
+ - Fix: admonition titles before first section.
+ - Replace ``--`` in literal by ``-{}-`` because fontencoding T1 has endash.
+ - Replave ``_`` in literal by an underlined blank, because it has the correct
+ width.
+ - Fix: encode pdfbookmark titles, ``#`` broke pdflatex.
+ - A few unicode replacements, if output_encoding != utf
+ - Add "--graphicx-option".
+ - Indent literal-blocks.
+ - Fix: omit ``\maketitle`` when there is no document title.
+
+* docs/index.txt: "Docutils Project Documentation Overview", added to
+ project.
+
+* docs/api/cmdline-tool.txt: "Inside A Docutils Command-Line Front-End
+ Tool", added to project.
+
+* docs/api/publisher.txt: "The Docutils Publisher", added to project.
+
+* docs/api/runtime-settings.txt: "Docutils Runtime Settings", added to project.
+
+* docs/dev/policies.txt: Added to project (extracted from
+ ``docs/dev/todo.txt``, formerly ``spec/notes.txt``).
+
+* docs/dev/release.txt: Added to project (extracted from
+ ``docs/dev/todo.txt``, formerly ``spec/notes.txt``).
+
+* docs/dev/testing.txt: Added to project.
+
+* docs/dev/website.txt: Added to project (extracted from
+ ``docs/dev/todo.txt``, formerly ``spec/notes.txt``).
+
+* docs/ref/rst/directives.txt:
+
+ - Added directives: "table", "csv-table".
+
+* docs/user/rst/cheatsheet.txt: "The reStructuredText Cheat Sheet"
+ added to project. 1 page for syntax, and a 1 page reference for
+ directives and roles. Source text to be used as-is; not meant to be
+ converted to HTML.
+
+* docs/user/rst/demo.txt: Added to project; moved from tools/test.txt
+ with a change of title.
+
+* test/functional/, contents, and test/test_functional.py: Added to
+ project.
+
+* tools/buildhtml.py: Fixed bug with config file handling.
+
+* tools/html.py: Removed from project (duplicate of rst2html.py).
+
+* tools/pep2html.py: Removed from project (duplicate of Python's
+ nondist/peps/pep2html.py; Docutils' tools/pep.py can be used for
+ Docutils-related PEPs in docs/peps/).
+
+* tools/rst2pseudoxml.py: Renamed from publish.py.
+
+* tools/rst2xml.py: Renamed from docutils-xml.py.
+
+* tools/test.txt: Removed from project; moved to
+ docs/user/rst/demo.txt.
+
+* setup.py: Now also installs ``rst2latex.py``.
+
+
+Release 0.3.3 (2004-05-09)
+==========================
+
+* docutils/__init__.py:
+
+ - 0.3.1: Reorganized config file format (multiple sections); see
+ docs/config.txt.
+ - Added unknown_reference_resolvers attribute to TransformSpec.
+ - 0.3.2: Interpreted text reorganization.
+ - 0.3.3: Released.
+
+* docutils/core.py:
+
+ - Catch system messages to stop tracebacks from parsing errors.
+ - Catch exceptions during processing report & exit without
+ tracebacks, except when "--traceback" used.
+ - Reordered components for OptionParser; application comes last.
+ - Added "config_section" parameter to several methods and functions,
+ allowing front ends to easily specify their config file sections.
+ - Added publish_parts convenience function to allow access to individual
+ parts of a document.
+
+* docutils/examples.py: Added to project; practical examples of
+ Docutils client code, to be used as-is or as models for variations.
+
+* docutils/frontend.py:
+
+ - Added "--traceback" & "--no-traceback" options ("traceback"
+ setting).
+ - Implemented support for config file reorganization:
+ ``standard_config_files`` moved from ``ConfigParser`` to
+ ``OptionParser``; added
+ ``OptionParser.get_config_file_settings()`` and
+ ``.get_standard_config_settings()``; support for old "[options]"
+ section (with deprecation warning) and mapping from old to new
+ settings.
+ - Reimplemented setting validation.
+ - Enabled flexible boolean values: yes/no, true/false, on/off.
+ - Added ``Values``, a subclass of ``optparse.Values``, with support
+ for list setting attributes.
+ - Added support for new ``DOCUTILSCONFIG`` environment variable;
+ thanks to Beni Cherniavsky.
+ - Added "--no-section-numbering" option.
+
+* docutils/io.py:
+
+ - Catch IOErrors when opening source & destination files, report &
+ exit without tracebacks. Added ``handle_io_errors`` parameter to
+ ``FileInput`` & ``FileOutput`` to enable caller error handling.
+
+* docutils/nodes.py:
+
+ - Changed ``SparseNodeVisitor`` and ``GenericNodeVisitor`` dynamic
+ method definitions (via ``exec``) to dynamic assignments (via
+ ``setattr``); thanks to Roman Suzi.
+ - Encapsulated visitor dynamic assignments in a function; thanks to
+ Ian Bicking.
+ - Added indirect_reference_name attribute to the Targetable
+ class. This attribute holds the whitespace_normalized_name
+ (contains mixed case) of a target.
+
+* docutils/statemachine.py:
+
+ - Renamed ``StringList.strip_indent`` to ``.trim_left``.
+ - Added ``StringList.get_2D_block``.
+
+* docutils/utils.py:
+
+ - Added "level" attribute to SystemMessage exceptions.
+
+* docutils/languages/af.py: Added to project; Afrikaans mappings by
+ Jannie Hofmeyr.
+
+* docutils/languages/cs.py: Added to project; Czech mappings by Marek
+ Blaha.
+
+* docutils/languages/eo.py: Added to project; Esperanto mappings by
+ Marcelo Huerta San Martin.
+
+* docutils/languages/pt_br.py: Added to project; Brazilian Portuguese
+ mappings by Lalo Martins.
+
+* docutils/languages/ru.py: Added to project; Russian mappings by
+ Roman Suzi.
+
+* docutils/parsers/rst/roles.py: Added to project. Contains
+ interpreted text role functions, a registry for interpreted text
+ roles, and an API for adding to and retrieving from the registry.
+ Contributed by Edward Loper.
+
+* docutils/parsers/rst/states.py:
+
+ - Updated ``RSTState.nested_parse`` for "include" in table cells.
+ - Allowed true em-dash character and "---" as block quote
+ attribution marker.
+ - Added support for <angle-bracketed> complex option arguments
+ (option lists).
+ - Fixed handling of backslashes in substitution definitions.
+ - Fixed off-by-1 error with extra whitespace after substitution
+ definition directive.
+ - Added inline markup parsing to field lists' field names.
+ - Added support for quoted (and unindented) literal blocks.
+ Driven in part by a bribe from Frank Siebenlist (thanks!).
+ - Parser now handles escapes in URIs correctly.
+ - Made embedded-URIs' reference text omittable. Idea from Beni
+ Cherniavsky.
+ - Refactored explicit target processing code.
+ - Added name attribute to references containing the reference name only
+ through whitespace_normalize_name (no case changes).
+ - parse_target no longer returns the refname after going through
+ normalize_name. This is now handled in make_target.
+ - Fixed bug relating to role-less interpreted text in non-English
+ contexts.
+ - Reorganized interpreted text processing; moved code into the new
+ roles.py module. Contributed by Edward Loper.
+ - Refactored ``Body.parse_directive`` into ``run_directive`` and
+ ``parse_directive_block``.
+
+* docutils/parsers/rst/tableparser.py:
+
+ - Reworked for ``StringList``, to support "include" directives in
+ table cells.
+
+* docutils/parsers/rst/directives/__init__.py:
+
+ - Renamed ``unchanged()`` directive option conversion function to
+ ``unchanged_required``, and added a new ``unchanged``.
+ - Catch unicode value too high error; fixes bug 781766.
+ - Beefed up directive error reporting.
+
+* docutils/parsers/rst/directives/body.py:
+
+ - Added basic "table" directive.
+
+* docutils/parsers/rst/directives/images.py:
+
+ - Added "target" option to "image" directive.
+ - Added name attribute to references containing the reference name only
+ through whitespace_normalize_name (no case changes).
+
+* docutils/parsers/rst/directives/misc.py:
+
+ - Isolated the import of the ``urllib2`` module; was causing
+ problems on SourceForge (``libssl.so.2`` unavailable?).
+ - Added the "role" directive for declaring custom interpreted text
+ roles.
+
+* docutils/parsers/rst/directives/parts.py:
+
+ - The "contents" directive does more work up-front, creating the
+ "topic" and "title", and leaving the "pending" node for the
+ transform. Allows earlier reference resolution; fixes subtle bug.
+
+* docutils/parsers/rst/languages/af.py: Added to project; Afrikaans
+ mappings by Jannie Hofmeyr.
+
+* docutils/parsers/rst/languages/cs.py: Added to project; Czech
+ mappings by Marek Blaha.
+
+* docutils/parsers/rst/languages/eo.py: Added to project; Esperanto
+ mappings by Marcelo Huerta San Martin.
+
+* docutils/parsers/rst/languages/pt_br.py: Added to project; Brazilian
+ Portuguese mappings by Lalo Martins.
+
+* docutils/parsers/rst/languages/ru.py: Added to project; Russian
+ mappings by Roman Suzi.
+
+* docutils/transforms/parts.py:
+
+ - The "contents" directive does more work up-front, creating the
+ "topic" and "title", and leaving the "pending" node for the
+ transform. Allows earlier reference resolution; fixes subtle bug.
+ - Added support for disabling of section numbering.
+
+* docutils/transforms/references.py:
+
+ - Verifying that external targets are truly targets and not indirect
+ references. This is because we are now adding a "name" attribute to
+ references in addition to targets. Note sure if this is correct!
+ - Added code to hook into the unknown_reference_resolvers list for a
+ transformer in resolve_indirect_target. This allows the
+ unknown_reference_resolvers to keep around indirect targets which
+ docutils doesn't know about.
+ - Added specific error message for duplicate targets.
+
+* docutils/transforms/universal.py:
+
+ - Added FilterMessages transform (removes system messages below the
+ verbosity threshold).
+ - Added hook (via docutils.TransformSpec.unknown_reference_resolvers)
+ to FinalCheckVisitor for application-specific handling of
+ unresolvable references.
+ - Added specific error message for duplicate targets.
+
+* docutils/writers/__init__.py:
+
+ - Added assemble_parts method to the Writer class to allow for
+ access to a documents individual parts.
+ - Documented & set default for ``Writer.output`` attribute.
+
+* docutils/writers/html4css1.py:
+
+ - Fixed unicode handling of attribute values (bug 760673).
+ - Prevent duplication of "class" attribute values (bug report from
+ Kirill Lapshin).
+ - Improved table grid/border handling (prompted by report from Bob
+ Marshall).
+ - Added support for table titles.
+ - Added "<title />" for untitled docs, for XHTML conformance; thanks
+ to Darek Suchojad.
+ - Added functionality to keep track of individual parts of a document
+ and store them in a dictionary as the "parts" attribute of the writer.
+ Contributed by Reggie Dugard at the Docutils sprint at PyCon DC 2004.
+ - Added proper support for the "scale" attribute of the "image"
+ element. Contributed by Brent Cook.
+ - Added ``--initial-header-level`` option.
+ - Fixed bug: the body_pre_docinfo segment depended on there being a
+ docinfo; if no docinfo, the document title was incorporated into
+ the body segment. Adversely affected the publish_parts interface.
+
+* docutils/writers/latex2e.py:
+
+ - Changed default stylesheet to "no stylesheet" to avoid latex complaining
+ about a missing file.
+ - Added options and support: ``--compound-enumerators``,
+ ``--section-prefix-for-enumerators``, and
+ ``--section-enumerator-separator``. By John F Meinel Jr (SF patch
+ 934322).
+ - Added option ``--use-verbatim-when-possible``, to avoid
+ problematic characters (eg, '~' in italian) in literal blocks.
+ - It's now possible to use four section levels in the `book` and
+ `report` LaTeX classes. The default `article` class still has
+ three levels limit.
+
+* docs/config.txt: "Docutils Configuration Files", added to project.
+ Moved config file entry descriptions from tools.txt.
+
+* docs/tools.txt:
+
+ - Moved config file entry descriptions to config.txt.
+
+* spec/notes.txt: Continual updates. Added "Setting Up For Docutils
+ Development".
+
+* spec/howto/rst-roles.txt: "Creating reStructuredText Interpreted
+ Text Roles", added to project.
+
+* spec/rst/reStructuredText.txt:
+
+ - Added description of support for <angle-bracketed> complex option
+ arguments to option lists.
+ - Added subsections for indented and quoted literal blocks.
+
+* test: Continually adding & updating tests.
+
+ - Added test/test_settings.py & test/data/config_*.txt support
+ files.
+ - Added test/test_writers/test_htmlfragment.py.
+
+* test/DocutilsTestSupport.py:
+
+ - Refactored LaTeX publisher test suite/case class names to make
+ testing other writers easier.
+ - Added HtmlWriterPublishTestCase and HtmlFragmentTestSuite classes
+ to test the processing of HTML fragments which use the new
+ publish_parts convenience function.
+
+* tools/buildhtml.py:
+
+ - Added support for the "--prune" option.
+ - Removed dependency on pep2html.py; plaintext PEPs no longer
+ supported.
+
+* tools/docutils.conf:
+
+ - Updated for configuration file reorganization.
+
+* tools/rst2html.py:
+
+ - copied from tools/html.py
+
+* setup.py:
+
+ - added a 'scripts' section to configuration
+ - added 'tools/rst2html.py' to the scripts section
+
+
+Release 0.3 (2003-06-24)
+========================
+
+General:
+
+* Renamed "attribute" to "option" for directives/extensions.
+
+* Renamed transform method "transform" to "apply".
+
+* Renamed "options" to "settings" for runtime settings (as set by
+ command-line options). Sometimes "option" (singular) became
+ "settings" (plural). Some variations below:
+
+ - document.options -> document.settings (stored in other objects as
+ well)
+ - option_spec -> settings_spec (not directives though)
+ - OptionSpec -> SettingsSpec
+ - cmdline_options -> settings_spec
+ - relative_path_options -> relative_path_settings
+ - option_default_overrides -> settings_default_overrides
+ - Publisher.set_options -> Publisher.get_settings
+
+Specific:
+
+* COPYING.txt: Added "Public Domain Dedication".
+
+* FAQ.txt: Frequently asked questions, added to project.
+
+* setup.py:
+
+ - Updated with PyPI Trove classifiers.
+ - Conditional installation of third-party modules.
+
+* docutils/__init__.py:
+
+ - Bumped version to 0.2.1 to reflect changes to I/O classes.
+ - Bumped version to 0.2.2 to reflect changes to stylesheet options.
+ - Factored ``SettingsSpec`` out of ``Component``; separately useful.
+ - Bumped version to 0.2.3 because of the new "--embed-stylesheet"
+ option and its effect on the PEP template & writer.
+ - Bumped version to 0.2.4 due to changes to the PEP template &
+ stylesheet.
+ - Bumped version to 0.2.5 to reflect changes to Reporter output.
+ - Added ``TransformSpec`` class for new transform system.
+ - Bumped version to 0.2.6 for API changes (renaming).
+ - Bumped version to 0.2.7 for new ``docutils.core.publish_*``
+ convenience functions.
+ - Added ``Component.component_type`` attribute.
+ - Bumped version to 0.2.8 because of the internal parser switch from
+ plain lists to the docutils.statemachine.StringList objects.
+ - Bumped version to 0.2.9 because of the frontend.py API changes.
+ - Bumped version to 0.2.10 due to changes to the project layout
+ (third-party modules removed from the "docutils" package), and
+ signature changes in ``io.Input``/``io.Output``.
+ - Changed version to 0.3.0 for release.
+
+* docutils/core.py:
+
+ - Made ``publish()`` a bit more convenient.
+ - Generalized ``Publisher.set_io``.
+ - Renamed ``publish()`` to ``publish_cmdline()``; rearranged its
+ parameters; improved its docstring.
+ - Added ``publish_file()`` and ``publish_string()``.
+ - Factored ``Publisher.set_source()`` and ``.set_destination()``
+ out of ``.set_io``.
+ - Added support for "--dump-pseudo-xml", "--dump-settings", and
+ "--dump-transforms" hidden options.
+ - Added ``Publisher.apply_transforms()`` method.
+ - Added ``Publisher.set_components()`` method; support for
+ ``publish_*()`` conveninece functions.
+ - Moved config file processing to docutils/frontend.py.
+ - Added support for exit status ("exit_level" setting &
+ ``enable_exit`` parameter for Publisher.publish() and convenience
+ functions).
+
+* docutils/frontend.py:
+
+ - Check for & exit on identical source & destination paths.
+ - Fixed bug with absolute paths & "--config".
+ - Set non-command-line defaults in ``OptionParser.__init__()``:
+ ``_source`` & ``_destination``.
+ - Distributed ``relative_path_settings`` to components; updated
+ ``OptionParser.populate_from_components()`` to combine it all.
+ - Require list of keys in ``make_paths_absolute`` (was implicit in
+ global ``relative_path_settings``).
+ - Added "--expose-internal-attribute", "--dump-pseudo-xml",
+ "--dump-settings", and "--dump-transforms" hidden options.
+ - Removed nasty internals-fiddling ``ConfigParser.get_section``
+ code, replaced with correct code.
+ - Added validation functionality for config files.
+ - Added "--error-encoding" option/setting, "_disable_config"
+ internal setting.
+ - Added encoding validation; updated "--input-encoding" and
+ "--output-encoding"; added "--error-encoding-error-handler" and
+ "--output-encoding-error-handler".
+ - Moved config file processing from docutils/core.py.
+ - Updated ``OptionParser.populate_from_components`` to handle new
+ ``SettingsSpec.settings_defaults`` dict.
+ - Added support for "-" => stdin/stdout.
+ - Added "exit_level" setting ("--exit" option).
+
+* docutils/io.py:
+
+ - Split ``IO`` classes into subclasses of ``Input`` and ``Output``.
+ - Added automatic closing to ``FileInput`` and ``FileOutput``.
+ - Delayed opening of ``FileOutput`` file until ``write()`` called.
+ - ``FileOutput.write()`` now returns the encoded output string.
+ - Try to get path/stream name automatically in ``FileInput`` &
+ ``FileOutput``.
+ - Added defaults for source & destination paths.
+ - Allow for Unicode I/O with an explicit "unicode" encoding.
+ - Added ``Output.encode()``.
+ - Removed dependency on runtime settings; pass encoding directly.
+ - Recognize Unicode strings in ``Input.decode()``.
+ - Added support for output encoding error handlers.
+
+* docutils/nodes.py:
+
+ - Added "Invisible" element category class.
+ - Changed ``Node.walk()`` & ``.walkabout()`` to permit more tree
+ modification during a traversal.
+ - Added element classes: ``line_block``, ``generated``, ``address``,
+ ``sidebar``, ``rubric``, ``attribution``, ``admonition``,
+ ``superscript``, ``subscript``, ``inline``
+ - Added support for lists of nodes to ``Element.insert()``.
+ - Fixed parent linking in ``Element.replace()``.
+ - Added new abstract superclass ``FixedTextElement``; adds
+ "xml:space" attribute.
+ - Added support for "line" attribute of ``system_message`` nodes.
+ - Added support for the observer pattern from ``utils.Reporter``.
+ Added ``parse_messages`` and ``transform_messages`` attributes to
+ ``document``, removed ``messages``. Added ``note_parse_message``
+ and ``note_transform_message`` methods.
+ - Added support for improved diagnostics:
+
+ - Added "document", "source", and "line" internal attributes to
+ ``Node``, set by ``Node.setup_child()``.
+ - Converted variations on ``node.parent = self`` to
+ ``self.setup_child(node)``.
+ - Added ``document.current_source`` & ``.current_line``
+ attributes, and ``.note_source`` observer method.
+ - Changed "system_message" output to GNU-Tools format.
+
+ - Added a "rawsource" attribute to the ``Text`` class, for text
+ before backslash-escape resolution.
+ - Support for new transform system.
+ - Reworked ``pending`` element.
+ - Fixed XML DOM bug (SF #660611).
+ - Removed the ``interpeted`` element class and added
+ ``title_reference``, ``abbreviation``, ``acronym``.
+ - Made substitutions case-sensitive-but-forgiving; moved some code
+ from the parser.
+ - Fixed Unicode bug on element attributes (report: William Dode).
+
+* docutils/optik.py: Removed from project; replaced with
+ extras/optparse.py and extras/textwrap.py. These will be installed
+ only if they're not already present in the Python installation.
+
+* docutils/roman.py: Moved to extras/roman.py; this will be installed
+ only if it's not already present in the Python installation.
+
+* docutils/statemachine.py:
+
+ - Factored out ``State.add_initial_transitions()`` so it can be
+ extended.
+ - Converted whitespace-specific "blank" and "indent" transitions
+ from special-case code to ordinary transitions: removed
+ ``StateMachineWS.check_line()`` & ``.check_whitespace()``, added
+ ``StateWS.add_initial_transitions()`` method, ``ws_patterns`` &
+ ``ws_initial_transitions`` attributes.
+ - Removed ``State.match_transition()`` after merging it into
+ ``.check_line()``.
+ - Added ``StateCorrection`` exception.
+ - Added support for ``StateCorrection`` in ``StateMachine.run()``
+ (moved ``TransitionCorrection`` support there too.)
+ - Changed ``StateMachine.next_line()`` and ``.goto_line()`` to raise
+ ``EOFError`` instead of ``IndexError``.
+ - Added ``State.no_match`` method.
+ - Added support for the Observer pattern, triggered by input line
+ changes.
+ - Added ``strip_top`` parameter to
+ ``StateMachineWS.get_first_known_indented``.
+ - Made ``context`` a parameter to ``StateMachine.run()``.
+ - Added ``ViewList`` & ``StringList`` classes;
+ ``extract_indented()`` becomes ``StringList.get_indented()``.
+ - Added ``StateMachine.insert_input()``.
+ - Fixed ViewList slice handling for Python 2.3. Patch from (and
+ thanks to) Fred Drake.
+
+* docutils/utils.py:
+
+ - Added a ``source`` attribute to Reporter instances and
+ ``system_message`` elements.
+ - Added an observer pattern to ``utils.Reporter`` to keep track of
+ system messages.
+ - Fixed bugs in ``relative_path()``.
+ - Added support for improved diagnostics.
+ - Moved ``normalize_name()`` to nodes.py (``fully_normalize_name``).
+ - Added support for encoding Reporter stderr output, and encoding
+ error handlers.
+ - Reporter keeps track of the highest level system message yet
+ generated.
+
+* docutils/languages: Fixed bibliographic field language lookups.
+
+* docutils/languages/es.py: Added to project; Spanish mappings by
+ Marcelo Huerta San Martin.
+
+* docutils/languages/fr.py: Added to project; French mappings by
+ Stefane Fermigier.
+
+* docutils/languages/it.py: Added to project; Italian mappings by
+ Nicola Larosa.
+
+* docutils/languages/sk.py: Added to project; Slovak mappings by
+ Miroslav Vasko.
+
+* docutils/parser/__init__.py:
+
+ - Added ``Parser.finish_parse()`` method.
+
+* docutils/parser/rst/__init__.py:
+
+ - Added options: "--pep-references", "--rfc-references",
+ "--tab-width", "--trim-footnote-reference-space".
+
+* docutils/parsers/rst/states.py:
+
+ - Changed "title under/overline too short" system messages from INFO
+ to WARNING, and fixed its insertion location.
+ - Fixed enumerated list item parsing to allow paragraphs & section
+ titles to begin with enumerators.
+ - Converted system messages to use the new "line" attribute.
+ - Fixed a substitution reference edge case.
+ - Added support for "--pep-references" and "--rfc-references"
+ options; reworked ``Inliner`` code to make customization easier.
+ - Removed field argument parsing.
+ - Added support for short section title over/underlines.
+ - Fixed "simple reference name" regexp to ignore text like
+ "object.__method__"; not an anonymous reference.
+ - Added support for improved diagnostics.
+ - Reworked directive API, based on Dethe Elza's contribution. Added
+ ``Body.parse_directive()``, ``.parse_directive_options()``,
+ ``.parse_directive_arguments()`` methods.
+ - Added ``ExtensionOptions`` class, to parse directive options
+ without parsing field bodies. Factored
+ ``Body.parse_field_body()`` out of ``Body.field()``, overridden in
+ ``ExtensionOptions``.
+ - Improved definition list term/classifier parsing.
+ - Added warnings for unknown directives.
+ - Renamed ``Stuff`` to ``Struct``.
+ - Now flagged as errors: transitions at the beginning or end of
+ sections, empty sections (except title), and empty documents.
+ - Updated for ``statemachine.StringList``.
+ - Enabled recognition of schemeless email addresses in targets.
+ - Added support for embedded URIs in hyperlink references.
+ - Added backslash-escapes to inline markup end-string suffix.
+ - Added support for correct interpreted text processing.
+ - Fixed nested title parsing (topic, sidebar directives).
+ - Added special processing of backslash-escaped whitespace (idea
+ from David Abrahams).
+ - Made substitutions case-sensitive-but-forgiving; moved some code
+ to ``docutils.nodes``.
+ - Added support for block quote attributions.
+ - Added a kludge to work-around a conflict between the bubble-up
+ parser strategy and short titles (<= 3 char-long over- &
+ underlines). Fixes SF bug #738803 "infinite loop with multiple
+ titles" submitted by Jason Diamond.
+ - Added explicit interpreted text roles for standard inline markup:
+ "emphasis", "strong", "literal".
+ - Implemented "superscript" and "subscript" interpreted text roles.
+ - Added initial support for "abbreviation" and "acronym" roles;
+ incomplete.
+ - Added support for "--trim-footnote-reference-space" option.
+ - Optional space before colons in directives & hyperlink targets.
+
+* docutils/parsers/rst/tableparser.py:
+
+ - Fixed a bug that was producing unwanted empty rows in "simple"
+ tables.
+ - Detect bad column spans in "simple" tables.
+
+* docutils/parsers/rst/directives: Updated all directive functions to
+ new API.
+
+* docutils/parsers/rst/directives/__init__.py:
+
+ - Added ``flag()``, ``unchanged()``, ``path()``,
+ ``nonnegative_int()``, ``choice()``, and ``class_option()``
+ directive option helper functions.
+ - Added warnings for unknown directives.
+ - Return ``None`` for missing directives.
+ - Added ``register_directive()``, thanks to William Dode and Paul
+ Moore.
+
+* docutils/parsers/rst/directives/admonitions.py:
+
+ - Added "admonition" directive.
+
+* docutils/parsers/rst/directives/body.py: Added to project. Contains
+ the "topic", "sidebar" (from Patrick O'Brien), "line-block",
+ "parsed-literal", "rubric", "epigraph", "highlights" and
+ "pull-quote" directives.
+
+* docutils/parsers/rst/directives/images.py:
+
+ - Added an "align" attribute to the "image" & "figure" directives
+ (by Adam Chodorowski).
+ - Added "class" option to "image", and "figclass" to "figure".
+
+* docutils/parsers/rst/directives/misc.py:
+
+ - Added "include", "raw", and "replace" directives, courtesy of
+ Dethe Elza.
+ - Added "unicode" and "class" directives.
+
+* docutils/parsers/rst/directives/parts.py:
+
+ - Added the "sectnum" directive; by Dmitry Jemerov.
+ - Added "class" option to "contents" directive.
+
+* docutils/parsers/rst/directives/references.py: Added to project.
+ Contains the "target-notes" directive.
+
+* docutils/parsers/rst/languages/__init__.py:
+
+ - Return ``None`` from get_language() for missing language modules.
+
+* docutils/parsers/rst/languages/de.py: Added to project; German
+ mappings by Engelbert Gruber.
+
+* docutils/parsers/rst/languages/en.py:
+
+ - Added interpreted text roles mapping.
+
+* docutils/parsers/rst/languages/es.py: Added to project; Spanish
+ mappings by Marcelo Huerta San Martin.
+
+* docutils/parsers/rst/languages/fr.py: Added to project; French
+ mappings by William Dode.
+
+* docutils/parsers/rst/languages/it.py: Added to project; Italian
+ mappings by Nicola Larosa.
+
+* docutils/parsers/rst/languages/sk.py: Added to project; Slovak
+ mappings by Miroslav Vasko.
+
+* docutils/readers/__init__.py:
+
+ - Added support for the observer pattern from ``utils.Reporter``, in
+ ``Reader.parse`` and ``Reader.transform``.
+ - Removed ``Reader.transform()`` method.
+ - Added default parameter values to ``Reader.__init__()`` to make
+ instantiation easier.
+ - Removed bogus aliases: "restructuredtext" is *not* a Reader.
+
+* docutils/readers/pep.py:
+
+ - Added the ``peps.TargetNotes`` transform to the Reader.
+ - Removed PEP & RFC reference detection code; moved to
+ parsers/rst/states.py as options (enabled here by default).
+ - Added support for pre-acceptance PEPs (no PEP number yet).
+ - Moved ``Inliner`` & made it a class attribute of ``Reader`` for
+ easy subclassing.
+
+* docutils/readers/python: Python Source Reader subpackage added to
+ project, including preliminary versions of:
+
+ - __init__.py
+ - moduleparser.py: Parser for Python modules.
+
+* docutils/transforms/__init__.py:
+
+ - Added ``Transformer`` class and completed transform reform.
+ - Added unknown_reference_resolvers list for each transformer. This list holds
+ the list of functions provided by each component of the transformer that
+ help resolve references.
+
+* docutils/transforms/frontmatter.py:
+
+ - Improved support for generic fields.
+ - Fixed bibliographic field language lookups.
+
+* docutils/transforms/misc.py: Added to project. Miscellaneous
+ transforms.
+
+* docutils/transforms/parts.py:
+
+ - Moved the "id" attribute from TOC list items to the references
+ (``Contents.build_contents()``).
+ - Added the ``SectNum`` transform; by Dmitry Jemerov.
+ - Added "class" attribute support to ``Contents``.
+
+* docutils/transforms/peps.py:
+
+ - Added ``mask_email()`` function, updating to pep2html.py's
+ functionality.
+ - Linked "Content-Type: text/x-rst" to PEP 12.
+ - Added the ``TargetNotes`` PEP-specific transform.
+ - Added ``TargetNotes.cleanup_callback``.
+ - Added title check to ``Headers``.
+
+* docutils/transforms/references.py:
+
+ - Added the ``TargetNotes`` generic transform.
+ - Split ``Hyperlinks`` into multiple transforms.
+ - Fixed bug with multiply-indirect references (report: Bruce Smith).
+ - Added check for circular indirect references.
+ - Made substitutions case-sensitive-but-forgiving.
+
+* docutils/transforms/universal.py:
+
+ - Added support for the "--expose-internal-attributes" option.
+ - Removed ``Pending`` transform classes & data.
+
+* docutils/writers/__init__.py:
+
+ - Removed ``Writer.transform()`` method.
+
+* docutils/writers/docutils-xml.py:
+
+ - Added XML and doctype declarations.
+ - Added "--no-doctype" and "--no-xml-declaration" options.
+
+* docutils/writers/html4css1.py:
+
+ - "name" attributes only on these tags: a, applet, form, frame,
+ iframe, img, map.
+ - Added "name" attribute to <a> in section titles for Netscape 4
+ support (bug report: Pearu Peterson).
+ - Fixed targets (names) on footnote, citation, topic title,
+ problematic, and system_message nodes (for Netscape 4).
+ - Changed field names from "<td>" to "<th>".
+ - Added "@" to "@" encoding to thwart address harvesters.
+ - Improved the vertical whitespace optimization; ignore "invisible"
+ nodes (targets, comments, etc.).
+ - Improved inline literals with ``<span class="pre">`` around chunks
+ of text and `` `` for runs of spaces.
+ - Improved modularity of output; added ``self.body_pre_docinfo`` and
+ ``self.docinfo`` segments.
+ - Added support for "line_block", "address" elements.
+ - Improved backlinks (footnotes & system_messages).
+ - Improved system_message output.
+ - Redefined "--stylesheet" as containing an invariant URL, used
+ verbatim. Added "--stylesheet-path", interpreted w.r.t. the
+ working directory.
+ - Added "--footnote-references" option (superscript or brackets).
+ - Added "--compact-lists" and "--no-compact-lists" options.
+ - Added "--embed-stylesheet" and "--link-stylesheet" options;
+ factored out ``HTMLTranslator.get_stylesheet_reference()``.
+ - Improved field list rendering.
+ - Added Docutils version to "generator" meta tag.
+ - Fixed a bug with images; they must be inline, so wrapped in <p>.
+ - Improved layout of <pre> HTML source.
+ - Fixed attribute typo on <colspec>.
+ - Refined XML prologue.
+ - Support for no stylesheet.
+ - Removed "interpreted" element support.
+ - Added support for "title_reference", "sidebar", "attribution",
+ "rubric", and generic "admonition" elements.
+ - Added "--attribution" option.
+ - Added support for "inline", "subscript", "superscript" elements.
+ - Added initial support for "abbreviation" and "acronym";
+ incomplete.
+
+* docutils/writers/latex2e.py: LaTeX Writer, added by Engelbert Gruber
+ (from the sandbox).
+
+ - Added french.
+ - Double quotes in literal blocks (special treatment for de/ngerman).
+ - Added '--hyperlink-color' option ('0' turns off coloring of links).
+ - Added "--attribution" option.
+ - Right align attributions.
+
+* docutils/writers/pep_html.py:
+
+ - Parameterized output encoding in PEP template.
+ - Reworked substitutions from ``locals()`` into ``subs`` dict.
+ - Redefined "--pep-stylesheet" as containing an invariant URL, used
+ verbatim. Added "--pep-stylesheet-path", interpreted w.r.t. the
+ working directory.
+ - Added an override on the "--footnote-references" option.
+ - Factored out ``HTMLTranslator.get_stylesheet_reference()``.
+ - Added Docutils version to "generator" meta tag.
+ - Added a "DO NOT EDIT THIS FILE" comment to generated HTML.
+
+* docs/tools.txt:
+
+ - Added a "silent" setting for ``buildhtml.py``.
+ - Added a "Getting Help" section.
+ - Rearranged the structure.
+ - Kept up to date, with new settings, command-line options etc.
+ - Added section for ``rst2latex.py`` (Engelbert Gruber).
+ - Converted settings table into a definition list.
+
+* docs/rst/quickstart.txt:
+
+ - Added a table of contents.
+ - Added feedback information.
+ - Added mention of minimum section title underline lengths.
+ - Removed the 4-character minimum for section title underlines.
+
+* docs/rst/quickref.html:
+
+ - Added a "Getting Help" section.
+ - Added a style to make section title backlinks more subtle.
+ - Added mention of minimum section title underline lengths.
+ - Removed the 4-character minimum for section title underlines.
+
+* extras: Directory added to project; contains third-party modules
+ that Docutils depends on (optparse, textwrap, roman). These are
+ only installed if they're not already present.
+
+* licenses: Directory added to project; contains copies of license
+ files for non-public-domain files.
+
+* spec/doctree.txt:
+
+ - Changed the focus. It's about DTD elements: structural
+ relationships, semantics, and external (public) attributes. Not
+ about the element class library.
+ - Moved some implementation-specific stuff into ``docutils.nodes``
+ docstrings.
+ - Wrote descriptions of all common attributes and parameter
+ entities. Filled in introductory material.
+ - Working through the element descriptions: 55 down, 37 to go.
+ - Removed "Representation of Horizontal Rules" to
+ spec/rst/alternatives.txt.
+
+* spec/docutils.dtd:
+
+ - Added "generated" inline element.
+ - Added "line_block" body element.
+ - Added "auto" attribute to "title".
+ - Changed content models of "literal_block" and "doctest_block" to
+ ``%text.model``.
+ - Added ``%number;`` attribute type parameter entity.
+ - Changed ``%structural.elements;`` to ``%section.elements``.
+ - Updated attribute types; made more specific.
+ - Added "address" bibliographic element.
+ - Added "line" attribute to ``system_message`` element.
+ - Removed "field_argument" element; "field_name" may contain
+ multiple words and whitespace.
+ - Changed public identifier to docutils.sf.net.
+ - Removed "interpreted" element; added "title_reference",
+ "abbreviation", "acronym".
+ - Removed "refuri" attribute from "footnote_reference" and
+ "citation_reference".
+ - Added "sidebar", "rubric", "attribution", "admonition",
+ "superscript", "subscript", and "inline" elements.
+
+* spec/pep-0256.txt: Converted to reStructuredText & updated.
+
+* spec/pep-0257.txt: Converted to reStructuredText & updated.
+
+* spec/pep-0258.txt: Converted to reStructuredText & updated.
+
+* spec/semantics.txt: Updated with text from a Doc-SIG response to
+ Dallas Mahrt.
+
+* spec/transforms.txt: Added to project.
+
+* spec/howto: Added subdirectory, for developer how-to docs.
+
+* spec/howto/rst-directives.txt: Added to project. Original by Dethe
+ Elza, edited & extended by David Goodger.
+
+* spec/howto/i18n.txt: Docutils Internationalization. Added to
+ project.
+
+* spec/rst/alternatives.txt:
+
+ - Added "Doctree Representation of Transitions" from
+ spec/doctree.txt.
+ - Updated "Inline External Targets" & closed the debate.
+ - Added ideas for interpreted text syntax extensions.
+ - Added "Nested Inline Markup" section.
+
+* spec/rst/directives.txt:
+
+ - Added directives: "topic", "sectnum", "target-notes",
+ "line-block", "parsed-literal", "include", "replace", "sidebar",
+ "admonition", "rubric", "epigraph", "highlights", "unicode" and
+ "class".
+ - Formalized descriptions of directive details.
+ - Added an "align" attribute to the "image" & "figure" directives
+ (by Adam Chodorowski).
+ - Added "class" options to "topic", "sidebar", "line-block",
+ "parsed-literal", "contents", and "image"; and "figclass" to
+ "figure".
+
+* spec/rst/interpreted.txt: Added to project. Descriptions of
+ interpreted text roles.
+
+* spec/rst/introduction.txt:
+
+ - Added pointers to material for new users.
+
+* spec/rst/reStructuredText.txt:
+
+ - Disambiguated comments (just add a newline after the "::").
+ - Updated enumerated list description; added a discussion of the
+ second-line validity checking.
+ - Updated directive description.
+ - Added a note redirecting newbies to the user docs.
+ - Expanded description of inline markup start-strings in non-markup
+ contexts.
+ - Removed field arguments and made field lists a generic construct.
+ - Removed the 4-character minimum for section title underlines.
+ - Clarified term/classifier delimiter & inline markup ambiguity
+ (definition lists).
+ - Added "Embedded URIs".
+ - Updated "Interpreted Text" section.
+ - Added "Character-Level Inline Markup" section.
+
+* test: Continually adding & updating tests.
+
+ - Moved test/test_rst/ to test/test_parsers/test_rst/.
+ - Moved test/test_pep/ to test/test_readers/test_pep/.
+ - Added test/test_readers/test_python/.
+ - Added test/test_writers/ (Engelbert Gruber).
+
+* tools:
+
+ - Made the ``locale.setlocale()`` calls in front ends
+ fault-tolerant.
+
+* tools/buildhtml.py:
+
+ - Added "--silent" option.
+ - Fixed bug with absolute paths & "--config".
+ - Updated for new I/O classes.
+ - Added some exception handling.
+ - Separated publishers' setting defaults; prevents interference.
+ - Updated for new ``publish_file()`` convenience function.
+
+* tools/pep-html-template:
+
+ - Allow for "--embed-stylesheet".
+ - Added Docutils version to "generator" meta tag.
+ - Added a "DO NOT EDIT THIS FILE" comment to generated HTML.
+ - Conform to XHTML spec.
+
+* tools/pep2html.py:
+
+ - Made ``argv`` a parameter to ``main()``.
+ - Added support for "Content-Type:" header & arbitrary PEP formats.
+ - Linked "Content-Type: text/plain" to PEP 9.
+ - Files skipped (due to an error) are not pushed onto the server.
+ - Updated for new I/O classes.
+ - Added ``check_requirements()`` & ``pep_type_error()``.
+ - Added some exception handling.
+ - Updated for new ``publish_string()`` convenience function.
+ - Added a "DO NOT EDIT THIS FILE" comment to generated HTML.
+
+* tools/quicktest.py:
+
+ - Added "-V"/"--version" option.
+
+* tools/rst2latex.py: LaTeX front end, added by Engelbert Gruber.
+
+* tools/unicode2rstsubs.py: Added to project. Produces character
+ entity files (reSructuredText substitutions) from the MathML master
+ unicode.xml file.
+
+* tools/editors: Support code for editors, added to project. Contains
+ ``emacs/restructuredtext.el``.
+
+* tools/stylesheets/default.css: Moved into the stylesheets directory.
+
+ - Added style for chunks of inline literals.
+ - Removed margin for first child of table cells.
+ - Right-aligned field list names.
+ - Support for auto-numbered section titles in TOCs.
+ - Increased the size of inline literals (<tt>) in titles.
+ - Restored the light gray background for inline literals.
+ - Added support for "line_block" elements.
+ - Added style for "address" elements.
+ - Removed "a.footnote-reference" style; doing it with ``<sup>`` now.
+ - Improved field list rendering.
+ - Vertical whitespace improvements.
+ - Removed "a.target" style.
+
+* tools/stylesheets/pep.css:
+
+ - Fixed nested section margins.
+ - Other changes parallel those of ``../default.css``.
+
+
+Release 0.2 (2002-07-31)
+========================
+
+General:
+
+- The word "component" was being used ambiguously. From now on,
+ "component" will be used to mean "Docutils component", as in Reader,
+ Writer, Parser, or Transform. Portions of documents (Table of
+ Contents, sections, etc.) will be called "document parts".
+- Did a grand renaming: a lot of ``verylongnames`` became
+ ``very_long_names``.
+- Cleaned up imports: no more relative package imports or
+ comma-separated lists of top-level modules.
+- Added support for an option values object which carries default
+ settings and overrides (from command-line options and library use).
+- Added internal Unicode support, and support for both input and
+ output encodings.
+- Added support for the ``docutils.io.IO`` class & subclasses.
+
+Specific:
+
+* docutils/__init__.py:
+
+ - Added ``ApplicationError`` and ``DataError``, for use throughout
+ the package.
+ - Added ``Component`` base class for Docutils components; implements
+ the ``supports`` method.
+ - Added ``__version__`` (thus, ``docutils.__version__``).
+
+* docutils/core.py:
+
+ - Removed many keyword parameters to ``Publisher.__init__()`` and
+ ``publish()``; bundled into an option values object. Added
+ "argv", "usage", "description", and "option_spec" parameters for
+ command-line support.
+ - Added ``Publisher.process_command_line()`` and ``.set_options()``
+ methods.
+ - Reworked I/O model for ``docutils.io`` wrappers.
+ - Updated ``Publisher.set_options()``; now returns option values
+ object.
+ - Added support for configuration files (/etc/docutils.conf,
+ ./docutils.conf, ~/.docutils).
+ - Added ``Publisher.setup_option_parser()``.
+ - Added default usage message and description.
+
+* docutils/frontend.py: Added to project; support for front-end
+ (command-line) scripts. Option specifications may be augmented by
+ components. Requires Optik (http://optik.sf.net/) for option
+ processing (installed locally as docutils/optik.py).
+
+* docutils/io.py: Added to project; uniform API for a variety of input
+ output mechanisms.
+
+* docutils/nodes.py:
+
+ - Added ``TreeCopyVisitor`` class.
+ - Added a ``copy`` method to ``Node`` and subclasses.
+ - Added a ``SkipDeparture`` exception for visitors.
+ - Renamed ``TreePruningException`` from ``VisitorException``.
+ - Added docstrings to ``TreePruningException``, subclasses, and
+ ``Nodes.walk()``.
+ - Improved docstrings.
+ - Added ``SparseNodeVisitor``, refined ``NodeVisitor``.
+ - Moved ``utils.id()`` to ``nodes.make_id()`` to avoid circular
+ imports.
+ - Added ``decoration``, ``header``, and ``footer`` node classes, and
+ ``PreDecorative`` mixin.
+ - Reworked the name/id bookkeeping; to ``document``, removed
+ ``explicit_targets`` and ``implicit_targets`` attributes, added
+ ``nametypes`` attribute and ``set_name_id_map`` method.
+ - Added ``NodeFound`` exception, for use with ``NodeVisitor``
+ traversals.
+ - Added ``document.has_name()`` method.
+ - Fixed DOM generation for list-attributes.
+ - Added category class ``Labeled`` (used by footnotes & citations).
+ - Added ``Element.set_class()`` method (sets "class" attribute).
+
+* docutils/optik.py: Added to project. Combined from the Optik
+ package, with added option groups and other modifications. The use
+ of this module is probably only temporary.
+
+* docutils/statemachine.py:
+
+ - Added ``runtime_init`` method to ``StateMachine`` and ``State``.
+ - Added underscores to improve many awkward names.
+ - In ``string2lines()``, changed whitespace normalizing translation
+ table to regexp; restores Python 2.0 compatibility with Unicode.
+
+* docutils/urischemes.py:
+
+ - Filled in some descriptions.
+ - Added "shttp" scheme.
+
+* docutils/utils.py:
+
+ - Added ``clean_rcs_keywords`` function (moved from
+ docutils/transforms/frontmatter.py
+ ``DocInfo.filter_rcs_keywords``).
+ - Added underscores to improve many awkward names.
+ - Changed names of Reporter's thresholds:
+ warning_level -> report_level; error_level -> halt_level.
+ - Moved ``utils.id()`` to ``nodes.make_id()``.
+ - Added ``relative_path(source, target)``.
+
+* docutils/languages/de.py: German mappings; added to project. Thanks
+ to Gunnar Schwant for the translations.
+
+* docutils/languages/en.py: Added "Dedication" bibliographic field
+ mappings.
+
+* docutils/languages/sv.py: Swedish mappings; added to project by Adam
+ Chodorowski.
+
+* docutils/parsers/rst/states.py:
+
+ - Added underscores to improve many awkward names.
+ - Added RFC-2822 header support.
+ - Extracted the inline parsing code from ``RSTState`` to a separate
+ class, ``Inliner``, which will allow easy subclassing.
+ - Made local bindings for ``memo`` container & often-used contents
+ (reduces code complexity a lot). See ``RSTState.runtime_init()``.
+ - ``RSTState.parent`` replaces ``RSTState.statemachine.node``.
+ - Added ``MarkupMismatch`` exception; for late corrections.
+ - Added ``-/:`` characters to inline markup's start string prefix,
+ ``/`` to end string suffix.
+ - Fixed a footnote bug.
+ - Fixed a bug with literal blocks.
+ - Applied patch from Simon Budig: simplified regexps with symbolic
+ names, removed ``Inliner.groups`` and ``Body.explicit.groups``.
+ - Converted regexps from ``'%s' % var`` to ``'%(var)s' % locals()``.
+ - Fixed a bug in ``Inliner.interpreted_or_phrase_ref()``.
+ - Allowed non-ASCII in "simple names" (directive names, field names,
+ references, etc.).
+ - Converted ``Inliner.patterns.initial`` to be dynamically built
+ from parts with ``build_regexp()`` function.
+ - Changed ``Inliner.inline_target`` to ``.inline_internal_target``.
+ - Updated docstrings.
+ - Changed "table" to "grid_table"; added "simple_table" support.
+
+* docutils/parsers/rst/tableparser.py:
+
+ - Changed ``TableParser`` to ``GridTableParser``.
+ - Added ``SimpleTableParser``.
+ - Refactored naming.
+
+* docutils/parsers/rst/directives/__init__.py: Added "en" (English) as
+ a fallback language for directive names.
+
+* docutils/parsers/rst/directives/html.py: Changed the ``meta``
+ directive to use a ``pending`` element, used only by HTML writers.
+
+* docutils/parsers/rst/directives/parts.py: Renamed from
+ components.py.
+
+ - Added "backlinks" attribute to "contents" directive.
+
+* docutils/parsers/rst/languages/sv.py: Swedish mappings; added to
+ project by Adam Chodorowski.
+
+* docutils/readers/__init__.py: Gave Readers more control over
+ choosing and instantiating Parsers.
+
+* docutils/readers/pep.py: Added to project; for PEP processing.
+
+* docutils/transforms/__init__.py: ``Transform.__init__()`` now
+ requires a ``component`` parameter.
+
+* docutils/transforms/components.py: Added to project; transforms
+ related to Docutils components.
+
+* docutils/transforms/frontmatter.py:
+
+ - In ``DocInfo.extract_authors``, check for a single "author" in an
+ "authors" group, and convert it to a single "author" element.
+ - Added support for "Dedication" and generic bibliographic fields.
+
+* docutils/transforms/peps.py: Added to project; PEP-specific.
+
+* docutils/transforms/parts.py: Renamed from old components.py.
+
+ - Added filter for `Contents`, to use alt-text for inline images,
+ and to remove inline markup that doesn't make sense in the ToC.
+ - Added "name" attribute to TOC topic depending on its title.
+ - Added support for optional TOC backlinks.
+
+* docutils/transforms/references.py: Fixed indirect target resolution
+ in ``Hyperlinks`` transform.
+
+* docutils/transforms/universal.py:
+
+ - Changed ``Messages`` transform to properly filter out system
+ messages below the warning threshold.
+ - Added ``Decorations`` transform (support for ``--generator``,
+ ``--date``, ``--time``, ``--source-link`` options).
+
+* docutils/writers/__init__.py: Added "pdf" alias in anticipation of
+ Engelbert Gruber's PDF writer.
+
+* docutils/writers/html4css1.py:
+
+ - Made XHTML-compatible (switched to lowercase element & attribute
+ names; empty tag format).
+ - Escape double-dashes in comment text.
+ - Improved boilerplate & modularity of output.
+ - Exposed modular output in Writer class.
+ - Added a "generator" meta tag to <head>.
+ - Added support for the ``--stylesheet`` option.
+ - Added support for ``decoration``, ``header``, and ``footer``
+ elements.
+ - In ``HTMLTranslator.attval()``, changed whitespace normalizing
+ translation table to regexp; restores Python 2.0 compatibility
+ with Unicode.
+ - Added the translator class as instance variable to the Writer, to
+ make it easily subclassable.
+ - Improved option list spacing (thanks to Richard Jones).
+ - Modified field list output.
+ - Added backlinks to footnotes & citations.
+ - Added percentage widths to "<col>" tags (from colspec).
+ - Option lists: "<code>" changed to "<kbd>", ``option_argument``
+ "<span>" changed to "<var>".
+ - Inline literals: "<code>" changed to "<tt>".
+ - Many changes to optimize vertical space: compact simple lists etc.
+ - Add a command-line options & directive attributes to control TOC
+ and footnote/citation backlinks.
+ - Added support for optional footnote/citation backlinks.
+ - Added support for generic bibliographic fields.
+ - Identify backrefs.
+ - Relative URLs for stylesheet links.
+
+* docutils/writers/pep_html.py: Added to project; HTML Writer for
+ PEPs (subclass of ``html4css1.Writer``).
+
+* docutils/writers/pseudoxml.py: Renamed from pprint.py.
+
+* docutils/writers/docutils_xml.py: Added to project; trivial writer
+ of the Docutils internal doctree in XML.
+
+* docs/tools.txt: "Docutils Front-End Tools", added to project.
+
+* spec/doctree.txt:
+
+ - Changed the title to "The Docutils Document Tree".
+ - Added "Hyperlink Bookkeeping" section.
+
+* spec/docutils.dtd:
+
+ - Added ``decoration``, ``header``, and ``footer`` elements.
+ - Brought ``interpreted`` element in line with the parser: changed
+ attribute "type" to "role", added "position".
+ - Added support for generic bibliographic fields.
+
+* spec/notes.txt: Continual updates. Added "Project Policies".
+
+* spec/pep-0256.txt: Updated. Added "Roadmap to the Doctring PEPs"
+ section.
+
+* spec/pep-0257.txt: Clarified prohibition of signature repetition.
+
+* spec/pep-0258.txt: Updated. Added text from pysource.txt and
+ mailing list discussions.
+
+* spec/pep-0287.txt:
+
+ - Renamed to "reStructuredText Docstring Format".
+ - Minor edits.
+ - Reworked Q&A as an enumerated list.
+ - Converted to reStructuredText format.
+
+* spec/pysource.dtd:
+
+ - Reworked structural elements, incorporating ideas from Tony Ibbs.
+
+* spec/pysource.txt: Removed from project. Moved much of its contents
+ to pep-0258.txt.
+
+* spec/rst/alternatives.txt:
+
+ - Expanded auto-enumerated list idea; thanks to Fred Bremmer.
+ - Added "Inline External Targets" section.
+
+* spec/rst/directives.txt:
+
+ - Added "backlinks" attribute to "contents" directive.
+
+* spec/rst/problems.txt:
+
+ - Updated the Enumerated List Markup discussion.
+ - Added new alternative table markup syntaxes.
+
+* spec/rst/reStructuredText.txt:
+
+ - Clarified field list usage.
+ - Updated enumerated list description.
+ - Clarified purpose of directives.
+ - Added ``-/:`` characters to inline markup's start string prefix,
+ ``/`` to end string suffix.
+ - Updated "Authors" bibliographic field behavior.
+ - Changed "inline hyperlink targets" to "inline internal targets".
+ - Added "simple table" syntax to supplement the existing but
+ newly-renamed "grid tables".
+ - Added cautions for anonymous hyperlink use.
+ - Added "Dedication" and generic bibliographic fields.
+
+* test: Made test modules standalone (subdirectories became packages).
+
+* test/DocutilsTestSupport.py:
+
+ - Added support for PEP extensions to reStructuredText.
+ - Added support for simple tables.
+ - Refactored naming.
+
+* test/package_unittest.py: Renamed from UnitTestFolder.py.
+
+ - Now supports true packages containing test modules
+ (``__init__.py`` files required); fixes duplicate module name bug.
+
+* test/test_pep/: Subpackage added to project; PEP testing.
+
+* test/test_rst/test_SimpleTableParser.py: Added to project.
+
+* tools:
+
+ - Updated html.py and publish.py front-end tools to use the new
+ command-line processing facilities of ``docutils.frontend``
+ (exposed in ``docutils.core.Publisher``), reducing each to just a
+ few lines of code.
+ - Added ``locale.setlocale()`` calls to front-end tools.
+
+* tools/buildhtml.py: Added to project; batch-generates .html from all
+ the .txt files in directories and subdirectories.
+
+* tools/default.css:
+
+ - Added support for ``header`` and ``footer`` elements.
+ - Added styles for "Dedication" topics (biblio fields).
+
+* tools/docutils.conf: A configuration file; added to project.
+
+* tools/docutils-xml.py: Added to project.
+
+* tools/pep.py: Added to project; PEP to HTML front-end tool.
+
+* tools/pep-html-template: Added to project.
+
+* tools/pep2html.py: Added to project from Python (nondist/peps).
+ Added support for Docutils (reStructuredText PEPs).
+
+* tools/quicktest.py:
+
+ - Added the ``--attributes`` option, hacked a bit.
+ - Added a second command-line argument (output file); cleaned up.
+
+* tools/stylesheets/: Subdirectory added to project.
+
+* tools/stylesheets/pep.css: Added to project; stylesheet for PEPs.
+
+
+Release 0.1 (2002-04-20)
+========================
+
+This is the first release of Docutils, merged from the now inactive
+reStructuredText__ and `Docstring Processing System`__ projects. For
+the pre-Docutils history, see the `reStructuredText HISTORY`__ and the
+`DPS HISTORY`__ files.
+
+__ http://structuredtext.sourceforge.net/
+__ http://docstring.sourceforge.net/
+__ http://structuredtext.sourceforge.net/HISTORY.html
+__ http://docstring.sourceforge.net/HISTORY.html
+
+General changes: renamed 'dps' package to 'docutils'; renamed
+'restructuredtext' subpackage to 'rst'; merged the codebases; merged
+the test suites (reStructuredText's test/test_states renamed to
+test/test_rst); and all modifications required to make it all work.
+
+* docutils/parsers/rst/states.py:
+
+ - Improved diagnostic system messages for missing blank lines.
+ - Fixed substitution_reference bug.
+
+\f
+..
+ Local Variables:
+ mode: indented-text
+ indent-tabs-mode: nil
+ sentence-end-double-space: t
+ fill-column: 70
+ End:
--- /dev/null
+# file GENERATED by distutils, do NOT edit
+BUGS.txt
+COPYING.txt
+FAQ.txt
+HISTORY.txt
+MANIFEST
+MANIFEST.in
+README.txt
+RELEASE-NOTES.txt
+THANKS.txt
+install.py
+setup.cfg
+setup.py
+docs/index.txt
+docs/api/cmdline-tool.txt
+docs/api/publisher.txt
+docs/api/runtime-settings.txt
+docs/dev/distributing.txt
+docs/dev/enthought-plan.txt
+docs/dev/enthought-rfp.txt
+docs/dev/hacking.txt
+docs/dev/policies.txt
+docs/dev/pysource.dtd
+docs/dev/pysource.txt
+docs/dev/release.txt
+docs/dev/repository.txt
+docs/dev/semantics.txt
+docs/dev/testing.txt
+docs/dev/todo.txt
+docs/dev/website.txt
+docs/dev/rst/alternatives.txt
+docs/dev/rst/problems.txt
+docs/howto/html-stylesheets.txt
+docs/howto/i18n.txt
+docs/howto/rst-directives.txt
+docs/howto/rst-roles.txt
+docs/howto/security.txt
+docs/peps/pep-0256.txt
+docs/peps/pep-0257.txt
+docs/peps/pep-0258.txt
+docs/peps/pep-0287.txt
+docs/ref/doctree.txt
+docs/ref/docutils.dtd
+docs/ref/soextblx.dtd
+docs/ref/transforms.txt
+docs/ref/rst/definitions.txt
+docs/ref/rst/directives.txt
+docs/ref/rst/introduction.txt
+docs/ref/rst/restructuredtext.txt
+docs/ref/rst/roles.txt
+docs/user/Makefile.docutils-update
+docs/user/config.txt
+docs/user/docutils-05-compat.sty.txt
+docs/user/emacs.txt
+docs/user/html.txt
+docs/user/latex.txt
+docs/user/links.txt
+docs/user/mailing-lists.txt
+docs/user/manpage.txt
+docs/user/odt.txt
+docs/user/slide-shows.txt
+docs/user/smartquotes.txt
+docs/user/tools.txt
+docs/user/images/big-black.png
+docs/user/images/big-white.png
+docs/user/images/default.png
+docs/user/images/happy_monkey.png
+docs/user/images/medium-black.png
+docs/user/images/medium-white.png
+docs/user/images/rsp-all.png
+docs/user/images/rsp-breaks.png
+docs/user/images/rsp-covers.png
+docs/user/images/rsp-cuts.png
+docs/user/images/rsp-empty.png
+docs/user/images/rsp-objects.png
+docs/user/images/rsp.svg
+docs/user/images/s5-files.png
+docs/user/images/s5-files.svg
+docs/user/images/small-black.png
+docs/user/images/small-white.png
+docs/user/rst/cheatsheet.txt
+docs/user/rst/demo.txt
+docs/user/rst/quickref.html
+docs/user/rst/quickstart.txt
+docs/user/rst/images/biohazard-bitmap-scaling.svg
+docs/user/rst/images/biohazard-bitmap.svg
+docs/user/rst/images/biohazard-scaling.svg
+docs/user/rst/images/biohazard.png
+docs/user/rst/images/biohazard.svg
+docs/user/rst/images/biohazard.swf
+docs/user/rst/images/title-scaling.svg
+docs/user/rst/images/title.png
+docs/user/rst/images/title.svg
+docutils/__init__.py
+docutils/core.py
+docutils/docutils.conf
+docutils/examples.py
+docutils/frontend.py
+docutils/io.py
+docutils/nodes.py
+docutils/statemachine.py
+docutils/languages/__init__.py
+docutils/languages/af.py
+docutils/languages/ca.py
+docutils/languages/cs.py
+docutils/languages/da.py
+docutils/languages/de.py
+docutils/languages/en.py
+docutils/languages/eo.py
+docutils/languages/es.py
+docutils/languages/fa.py
+docutils/languages/fi.py
+docutils/languages/fr.py
+docutils/languages/gl.py
+docutils/languages/he.py
+docutils/languages/it.py
+docutils/languages/ja.py
+docutils/languages/ko.py
+docutils/languages/lt.py
+docutils/languages/lv.py
+docutils/languages/nl.py
+docutils/languages/pl.py
+docutils/languages/pt_br.py
+docutils/languages/ru.py
+docutils/languages/sk.py
+docutils/languages/sv.py
+docutils/languages/zh_cn.py
+docutils/languages/zh_tw.py
+docutils/parsers/__init__.py
+docutils/parsers/null.py
+docutils/parsers/rst/__init__.py
+docutils/parsers/rst/roles.py
+docutils/parsers/rst/states.py
+docutils/parsers/rst/tableparser.py
+docutils/parsers/rst/directives/__init__.py
+docutils/parsers/rst/directives/admonitions.py
+docutils/parsers/rst/directives/body.py
+docutils/parsers/rst/directives/html.py
+docutils/parsers/rst/directives/images.py
+docutils/parsers/rst/directives/misc.py
+docutils/parsers/rst/directives/parts.py
+docutils/parsers/rst/directives/references.py
+docutils/parsers/rst/directives/tables.py
+docutils/parsers/rst/include/README.txt
+docutils/parsers/rst/include/isoamsa.txt
+docutils/parsers/rst/include/isoamsb.txt
+docutils/parsers/rst/include/isoamsc.txt
+docutils/parsers/rst/include/isoamsn.txt
+docutils/parsers/rst/include/isoamso.txt
+docutils/parsers/rst/include/isoamsr.txt
+docutils/parsers/rst/include/isobox.txt
+docutils/parsers/rst/include/isocyr1.txt
+docutils/parsers/rst/include/isocyr2.txt
+docutils/parsers/rst/include/isodia.txt
+docutils/parsers/rst/include/isogrk1.txt
+docutils/parsers/rst/include/isogrk2.txt
+docutils/parsers/rst/include/isogrk3.txt
+docutils/parsers/rst/include/isogrk4-wide.txt
+docutils/parsers/rst/include/isogrk4.txt
+docutils/parsers/rst/include/isolat1.txt
+docutils/parsers/rst/include/isolat2.txt
+docutils/parsers/rst/include/isomfrk-wide.txt
+docutils/parsers/rst/include/isomfrk.txt
+docutils/parsers/rst/include/isomopf-wide.txt
+docutils/parsers/rst/include/isomopf.txt
+docutils/parsers/rst/include/isomscr-wide.txt
+docutils/parsers/rst/include/isomscr.txt
+docutils/parsers/rst/include/isonum.txt
+docutils/parsers/rst/include/isopub.txt
+docutils/parsers/rst/include/isotech.txt
+docutils/parsers/rst/include/mmlalias.txt
+docutils/parsers/rst/include/mmlextra-wide.txt
+docutils/parsers/rst/include/mmlextra.txt
+docutils/parsers/rst/include/s5defs.txt
+docutils/parsers/rst/include/xhtml1-lat1.txt
+docutils/parsers/rst/include/xhtml1-special.txt
+docutils/parsers/rst/include/xhtml1-symbol.txt
+docutils/parsers/rst/languages/__init__.py
+docutils/parsers/rst/languages/af.py
+docutils/parsers/rst/languages/ca.py
+docutils/parsers/rst/languages/cs.py
+docutils/parsers/rst/languages/da.py
+docutils/parsers/rst/languages/de.py
+docutils/parsers/rst/languages/en.py
+docutils/parsers/rst/languages/eo.py
+docutils/parsers/rst/languages/es.py
+docutils/parsers/rst/languages/fa.py
+docutils/parsers/rst/languages/fi.py
+docutils/parsers/rst/languages/fr.py
+docutils/parsers/rst/languages/gl.py
+docutils/parsers/rst/languages/he.py
+docutils/parsers/rst/languages/it.py
+docutils/parsers/rst/languages/ja.py
+docutils/parsers/rst/languages/ko.py
+docutils/parsers/rst/languages/lt.py
+docutils/parsers/rst/languages/lv.py
+docutils/parsers/rst/languages/nl.py
+docutils/parsers/rst/languages/pl.py
+docutils/parsers/rst/languages/pt_br.py
+docutils/parsers/rst/languages/ru.py
+docutils/parsers/rst/languages/sk.py
+docutils/parsers/rst/languages/sv.py
+docutils/parsers/rst/languages/zh_cn.py
+docutils/parsers/rst/languages/zh_tw.py
+docutils/readers/__init__.py
+docutils/readers/doctree.py
+docutils/readers/pep.py
+docutils/readers/standalone.py
+docutils/transforms/__init__.py
+docutils/transforms/components.py
+docutils/transforms/frontmatter.py
+docutils/transforms/misc.py
+docutils/transforms/parts.py
+docutils/transforms/peps.py
+docutils/transforms/references.py
+docutils/transforms/universal.py
+docutils/transforms/writer_aux.py
+docutils/utils/__init__.py
+docutils/utils/code_analyzer.py
+docutils/utils/error_reporting.py
+docutils/utils/punctuation_chars.py
+docutils/utils/roman.py
+docutils/utils/smartquotes.py
+docutils/utils/urischemes.py
+docutils/utils/math/__init__.py
+docutils/utils/math/latex2mathml.py
+docutils/utils/math/math2html.py
+docutils/utils/math/tex2mathml_extern.py
+docutils/utils/math/tex2unichar.py
+docutils/utils/math/unichar2tex.py
+docutils/writers/__init__.py
+docutils/writers/_html_base.py
+docutils/writers/docutils_xml.py
+docutils/writers/manpage.py
+docutils/writers/null.py
+docutils/writers/pseudoxml.py
+docutils/writers/html4css1/__init__.py
+docutils/writers/html4css1/html4css1.css
+docutils/writers/html4css1/template.txt
+docutils/writers/html5_polyglot/__init__.py
+docutils/writers/html5_polyglot/math.css
+docutils/writers/html5_polyglot/minimal.css
+docutils/writers/html5_polyglot/plain.css
+docutils/writers/html5_polyglot/template.txt
+docutils/writers/latex2e/__init__.py
+docutils/writers/latex2e/default.tex
+docutils/writers/latex2e/docutils-05-compat.sty
+docutils/writers/latex2e/titlepage.tex
+docutils/writers/latex2e/xelatex.tex
+docutils/writers/odf_odt/__init__.py
+docutils/writers/odf_odt/pygmentsformatter.py
+docutils/writers/odf_odt/styles.odt
+docutils/writers/pep_html/__init__.py
+docutils/writers/pep_html/pep.css
+docutils/writers/pep_html/template.txt
+docutils/writers/s5_html/__init__.py
+docutils/writers/s5_html/themes/README.txt
+docutils/writers/s5_html/themes/big-black/__base__
+docutils/writers/s5_html/themes/big-black/framing.css
+docutils/writers/s5_html/themes/big-black/pretty.css
+docutils/writers/s5_html/themes/big-white/framing.css
+docutils/writers/s5_html/themes/big-white/pretty.css
+docutils/writers/s5_html/themes/default/blank.gif
+docutils/writers/s5_html/themes/default/framing.css
+docutils/writers/s5_html/themes/default/iepngfix.htc
+docutils/writers/s5_html/themes/default/opera.css
+docutils/writers/s5_html/themes/default/outline.css
+docutils/writers/s5_html/themes/default/pretty.css
+docutils/writers/s5_html/themes/default/print.css
+docutils/writers/s5_html/themes/default/s5-core.css
+docutils/writers/s5_html/themes/default/slides.css
+docutils/writers/s5_html/themes/default/slides.js
+docutils/writers/s5_html/themes/medium-black/__base__
+docutils/writers/s5_html/themes/medium-black/pretty.css
+docutils/writers/s5_html/themes/medium-white/framing.css
+docutils/writers/s5_html/themes/medium-white/pretty.css
+docutils/writers/s5_html/themes/small-black/__base__
+docutils/writers/s5_html/themes/small-black/pretty.css
+docutils/writers/s5_html/themes/small-white/framing.css
+docutils/writers/s5_html/themes/small-white/pretty.css
+docutils/writers/xetex/__init__.py
+licenses/BSD-2-Clause.txt
+licenses/docutils.conf
+licenses/gpl-3-0.txt
+licenses/python-2-1-1.txt
+test/DocutilsTestSupport.py
+test/alltests.out
+test/alltests.py
+test/coverage.sh
+test/docutils.conf
+test/local-parser.py
+test/local-reader.py
+test/local-writer.py
+test/local_dummy_lang.py
+test/package_unittest.py
+test/record.txt
+test/test__init__.py
+test/test_command_line.py
+test/test_dependencies.py
+test/test_error_reporting.py
+test/test_functional.py
+test/test_io.py
+test/test_language.py
+test/test_nodes.py
+test/test_pickle.py
+test/test_publisher.py
+test/test_settings.py
+test/test_statemachine.py
+test/test_traversals.py
+test/test_utils.py
+test/test_viewlist.py
+test/data/config_1.txt
+test/data/config_2.txt
+test/data/config_error_handler.txt
+test/data/config_list.txt
+test/data/config_list_2.txt
+test/data/config_old.txt
+test/data/csv_data.txt
+test/data/csv_dep.txt
+test/data/dependencies.txt
+test/data/full-template.txt
+test/data/ham.css
+test/data/ham.tex
+test/data/include.txt
+test/data/latin1.txt
+test/data/raw.txt
+test/data/stylesheet.txt
+test/functional/README.txt
+test/functional/expected/compact_lists.html
+test/functional/expected/cyrillic.tex
+test/functional/expected/dangerous.html
+test/functional/expected/field_name_limit.html
+test/functional/expected/footnotes_html5.html
+test/functional/expected/latex_babel.tex
+test/functional/expected/latex_cornercases.tex
+test/functional/expected/latex_docinfo.tex
+test/functional/expected/latex_literal_block.tex
+test/functional/expected/latex_literal_block_fancyvrb.tex
+test/functional/expected/latex_literal_block_listings.tex
+test/functional/expected/latex_literal_block_verbatim.tex
+test/functional/expected/latex_literal_block_verbatimtab.tex
+test/functional/expected/math_output_html.html
+test/functional/expected/math_output_latex.html
+test/functional/expected/math_output_mathjax.html
+test/functional/expected/math_output_mathml.xhtml
+test/functional/expected/misc_rst_html4css1.html
+test/functional/expected/odt_basic.odt
+test/functional/expected/odt_classifier.odt
+test/functional/expected/odt_contents.odt
+test/functional/expected/odt_custom_headfoot.odt
+test/functional/expected/odt_footnotes.odt
+test/functional/expected/odt_header_footer.odt
+test/functional/expected/odt_literal_block.odt
+test/functional/expected/odt_nested_class.odt
+test/functional/expected/odt_no_class.odt
+test/functional/expected/odt_raw.odt
+test/functional/expected/odt_tables1.odt
+test/functional/expected/odt_unnested_class.odt
+test/functional/expected/pep_html.html
+test/functional/expected/standalone_rst_docutils_xml.xml
+test/functional/expected/standalone_rst_html4css1.html
+test/functional/expected/standalone_rst_html5.html
+test/functional/expected/standalone_rst_latex.tex
+test/functional/expected/standalone_rst_manpage.man
+test/functional/expected/standalone_rst_pseudoxml.txt
+test/functional/expected/standalone_rst_s5_html_1.html
+test/functional/expected/standalone_rst_s5_html_2.html
+test/functional/expected/standalone_rst_xetex.tex
+test/functional/expected/xetex-cyrillic.tex
+test/functional/expected/ui/default/blank.gif
+test/functional/expected/ui/default/framing.css
+test/functional/expected/ui/default/iepngfix.htc
+test/functional/expected/ui/default/opera.css
+test/functional/expected/ui/default/outline.css
+test/functional/expected/ui/default/pretty.css
+test/functional/expected/ui/default/print.css
+test/functional/expected/ui/default/s5-core.css
+test/functional/expected/ui/default/slides.css
+test/functional/expected/ui/default/slides.js
+test/functional/expected/ui/small-black/blank.gif
+test/functional/expected/ui/small-black/framing.css
+test/functional/expected/ui/small-black/iepngfix.htc
+test/functional/expected/ui/small-black/opera.css
+test/functional/expected/ui/small-black/outline.css
+test/functional/expected/ui/small-black/pretty.css
+test/functional/expected/ui/small-black/print.css
+test/functional/expected/ui/small-black/s5-core.css
+test/functional/expected/ui/small-black/slides.css
+test/functional/expected/ui/small-black/slides.js
+test/functional/input/compact_lists.txt
+test/functional/input/cyrillic.txt
+test/functional/input/dangerous.txt
+test/functional/input/field_list.txt
+test/functional/input/footnotes.txt
+test/functional/input/html5-text-level-tags.txt
+test/functional/input/latex_babel.txt
+test/functional/input/latex_cornercases.txt
+test/functional/input/latex_docinfo.txt
+test/functional/input/latex_literal_block.txt
+test/functional/input/link_in_substitution.txt
+test/functional/input/odt_basic.txt
+test/functional/input/odt_classifier.txt
+test/functional/input/odt_contents.txt
+test/functional/input/odt_custom_headfoot.txt
+test/functional/input/odt_footnotes.txt
+test/functional/input/odt_header_footer.txt
+test/functional/input/odt_literal_block.txt
+test/functional/input/odt_nested_class.txt
+test/functional/input/odt_no_class.txt
+test/functional/input/odt_raw.txt
+test/functional/input/odt_tables1.txt
+test/functional/input/odt_unnested_class.txt
+test/functional/input/pep_html.txt
+test/functional/input/simple.txt
+test/functional/input/standalone_rst_docutils_xml.txt
+test/functional/input/standalone_rst_html4css1.txt
+test/functional/input/standalone_rst_html5.txt
+test/functional/input/standalone_rst_latex.txt
+test/functional/input/standalone_rst_manpage.txt
+test/functional/input/standalone_rst_pseudoxml.txt
+test/functional/input/standalone_rst_s5_html.txt
+test/functional/input/standalone_rst_xetex.txt
+test/functional/input/data/classes_latex.txt
+test/functional/input/data/custom_roles.txt
+test/functional/input/data/custom_roles_latex.txt
+test/functional/input/data/errors.txt
+test/functional/input/data/header_footer.txt
+test/functional/input/data/html4css1.css
+test/functional/input/data/hyperlinking.txt
+test/functional/input/data/latex-problematic.txt
+test/functional/input/data/latex_encoding.txt
+test/functional/input/data/list_table.txt
+test/functional/input/data/math.css
+test/functional/input/data/math.txt
+test/functional/input/data/minimal.css
+test/functional/input/data/nonalphanumeric.txt
+test/functional/input/data/option_lists.txt
+test/functional/input/data/plain.css
+test/functional/input/data/section_titles.txt
+test/functional/input/data/standard.txt
+test/functional/input/data/svg_images.txt
+test/functional/input/data/swf_images.txt
+test/functional/input/data/table_colspan.txt
+test/functional/input/data/table_complex.txt
+test/functional/input/data/table_rowspan.txt
+test/functional/input/data/tables_latex.txt
+test/functional/input/data/unicode.txt
+test/functional/input/data/urls.txt
+test/functional/output/README.txt
+test/functional/output/compact_lists.html
+test/functional/output/cyrillic.tex
+test/functional/output/dangerous.html
+test/functional/output/field_name_limit.html
+test/functional/output/footnotes_html5.html
+test/functional/output/latex_babel.tex
+test/functional/output/latex_cornercases.tex
+test/functional/output/latex_docinfo.tex
+test/functional/output/latex_literal_block.tex
+test/functional/output/latex_literal_block_fancyvrb.tex
+test/functional/output/latex_literal_block_listings.tex
+test/functional/output/latex_literal_block_verbatim.tex
+test/functional/output/latex_literal_block_verbatimtab.tex
+test/functional/output/math_output_html.html
+test/functional/output/math_output_latex.html
+test/functional/output/math_output_mathjax.html
+test/functional/output/math_output_mathml.xhtml
+test/functional/output/misc_rst_html4css1.html
+test/functional/output/odt_basic.odt
+test/functional/output/odt_custom_headfoot.odt
+test/functional/output/odt_footnotes.odt
+test/functional/output/odt_header_footer.odt
+test/functional/output/odt_nested_class.odt
+test/functional/output/odt_no_class.odt
+test/functional/output/odt_raw.odt
+test/functional/output/odt_tables1.odt
+test/functional/output/odt_unnested_class.odt
+test/functional/output/pep_html.html
+test/functional/output/standalone_rst_docutils_xml.xml
+test/functional/output/standalone_rst_html4css1.html
+test/functional/output/standalone_rst_html5.html
+test/functional/output/standalone_rst_latex.tex
+test/functional/output/standalone_rst_manpage.man
+test/functional/output/standalone_rst_pseudoxml.txt
+test/functional/output/standalone_rst_s5_html_1.html
+test/functional/output/standalone_rst_s5_html_2.html
+test/functional/output/standalone_rst_xetex.tex
+test/functional/output/xetex-cyrillic.tex
+test/functional/output/ui/default/blank.gif
+test/functional/output/ui/default/framing.css
+test/functional/output/ui/default/iepngfix.htc
+test/functional/output/ui/default/opera.css
+test/functional/output/ui/default/outline.css
+test/functional/output/ui/default/pretty.css
+test/functional/output/ui/default/print.css
+test/functional/output/ui/default/s5-core.css
+test/functional/output/ui/default/slides.css
+test/functional/output/ui/default/slides.js
+test/functional/output/ui/small-black/blank.gif
+test/functional/output/ui/small-black/framing.css
+test/functional/output/ui/small-black/iepngfix.htc
+test/functional/output/ui/small-black/opera.css
+test/functional/output/ui/small-black/outline.css
+test/functional/output/ui/small-black/pretty.css
+test/functional/output/ui/small-black/print.css
+test/functional/output/ui/small-black/s5-core.css
+test/functional/output/ui/small-black/slides.css
+test/functional/output/ui/small-black/slides.js
+test/functional/tests/_default.py
+test/functional/tests/_standalone_rst_defaults.py
+test/functional/tests/compact_lists.py
+test/functional/tests/dangerous.py
+test/functional/tests/field_name_limit.py
+test/functional/tests/footnotes_html5.py
+test/functional/tests/latex_babel.py
+test/functional/tests/latex_cornercases.py
+test/functional/tests/latex_cyrillic.py
+test/functional/tests/latex_docinfo.py
+test/functional/tests/latex_literal_block.py
+test/functional/tests/latex_literal_block_fancyvrb.py
+test/functional/tests/latex_literal_block_listings.py
+test/functional/tests/latex_literal_block_verbatim.py
+test/functional/tests/latex_literal_block_verbatimtab.py
+test/functional/tests/math_output_html.py
+test/functional/tests/math_output_latex.py
+test/functional/tests/math_output_mathjax.py
+test/functional/tests/math_output_mathml.py
+test/functional/tests/misc_rst_html4css1.py
+test/functional/tests/pep_html.py
+test/functional/tests/standalone_rst_docutils_xml.py
+test/functional/tests/standalone_rst_html4css1.py
+test/functional/tests/standalone_rst_html5.py
+test/functional/tests/standalone_rst_latex.py
+test/functional/tests/standalone_rst_manpage.py
+test/functional/tests/standalone_rst_pseudoxml.py
+test/functional/tests/standalone_rst_s5_html_1.py
+test/functional/tests/standalone_rst_s5_html_2.py
+test/functional/tests/standalone_rst_xetex.py
+test/functional/tests/xetex_cyrillic.py
+test/test_parsers/__init__.py
+test/test_parsers/test_get_parser_class.py
+test/test_parsers/test_parser.py
+test/test_parsers/test_rst/__init__.py
+test/test_parsers/test_rst/test_SimpleTableParser.py
+test/test_parsers/test_rst/test_TableParser.py
+test/test_parsers/test_rst/test_block_quotes.py
+test/test_parsers/test_rst/test_bullet_lists.py
+test/test_parsers/test_rst/test_character_level_inline_markup.py
+test/test_parsers/test_rst/test_citations.py
+test/test_parsers/test_rst/test_comments.py
+test/test_parsers/test_rst/test_definition_lists.py
+test/test_parsers/test_rst/test_doctest_blocks.py
+test/test_parsers/test_rst/test_east_asian_text.py
+test/test_parsers/test_rst/test_enumerated_lists.py
+test/test_parsers/test_rst/test_field_lists.py
+test/test_parsers/test_rst/test_footnotes.py
+test/test_parsers/test_rst/test_inline_markup.py
+test/test_parsers/test_rst/test_interpreted.py
+test/test_parsers/test_rst/test_interpreted_fr.py
+test/test_parsers/test_rst/test_line_blocks.py
+test/test_parsers/test_rst/test_literal_blocks.py
+test/test_parsers/test_rst/test_option_lists.py
+test/test_parsers/test_rst/test_outdenting.py
+test/test_parsers/test_rst/test_paragraphs.py
+test/test_parsers/test_rst/test_section_headers.py
+test/test_parsers/test_rst/test_substitutions.py
+test/test_parsers/test_rst/test_tables.py
+test/test_parsers/test_rst/test_targets.py
+test/test_parsers/test_rst/test_transitions.py
+test/test_parsers/test_rst/includes/include9.txt
+test/test_parsers/test_rst/test_directives/__init__.py
+test/test_parsers/test_rst/test_directives/empty.txt
+test/test_parsers/test_rst/test_directives/include 11.txt
+test/test_parsers/test_rst/test_directives/include1.txt
+test/test_parsers/test_rst/test_directives/include10.txt
+test/test_parsers/test_rst/test_directives/include12.txt
+test/test_parsers/test_rst/test_directives/include13.txt
+test/test_parsers/test_rst/test_directives/include2.txt
+test/test_parsers/test_rst/test_directives/include3.txt
+test/test_parsers/test_rst/test_directives/include8.txt
+test/test_parsers/test_rst/test_directives/include_literal.txt
+test/test_parsers/test_rst/test_directives/raw1.txt
+test/test_parsers/test_rst/test_directives/test_admonitions.py
+test/test_parsers/test_rst/test_directives/test_block_quotes.py
+test/test_parsers/test_rst/test_directives/test_class.py
+test/test_parsers/test_rst/test_directives/test_code.py
+test/test_parsers/test_rst/test_directives/test_code_long.py
+test/test_parsers/test_rst/test_directives/test_code_none.py
+test/test_parsers/test_rst/test_directives/test_compound.py
+test/test_parsers/test_rst/test_directives/test_container.py
+test/test_parsers/test_rst/test_directives/test_contents.py
+test/test_parsers/test_rst/test_directives/test_date.py
+test/test_parsers/test_rst/test_directives/test_decorations.py
+test/test_parsers/test_rst/test_directives/test_default_role.py
+test/test_parsers/test_rst/test_directives/test_figures.py
+test/test_parsers/test_rst/test_directives/test_images.py
+test/test_parsers/test_rst/test_directives/test_include.py
+test/test_parsers/test_rst/test_directives/test_line_blocks.py
+test/test_parsers/test_rst/test_directives/test_math.py
+test/test_parsers/test_rst/test_directives/test_meta.py
+test/test_parsers/test_rst/test_directives/test_parsed_literals.py
+test/test_parsers/test_rst/test_directives/test_raw.py
+test/test_parsers/test_rst/test_directives/test_replace.py
+test/test_parsers/test_rst/test_directives/test_replace_fr.py
+test/test_parsers/test_rst/test_directives/test_role.py
+test/test_parsers/test_rst/test_directives/test_rubrics.py
+test/test_parsers/test_rst/test_directives/test_sectnum.py
+test/test_parsers/test_rst/test_directives/test_sidebars.py
+test/test_parsers/test_rst/test_directives/test_tables.py
+test/test_parsers/test_rst/test_directives/test_target_notes.py
+test/test_parsers/test_rst/test_directives/test_test_directives.py
+test/test_parsers/test_rst/test_directives/test_title.py
+test/test_parsers/test_rst/test_directives/test_topics.py
+test/test_parsers/test_rst/test_directives/test_unicode.py
+test/test_parsers/test_rst/test_directives/test_unknown.py
+test/test_parsers/test_rst/test_directives/utf-16.csv
+test/test_parsers/test_rst/test_directives/includes/include14.txt
+test/test_parsers/test_rst/test_directives/includes/include4.txt
+test/test_parsers/test_rst/test_directives/includes/include5.txt
+test/test_parsers/test_rst/test_directives/includes/more/include6.txt
+test/test_parsers/test_rst/test_directives/includes/sibling/include7.txt
+test/test_readers/__init__.py
+test/test_readers/test_get_reader_class.py
+test/test_readers/test_pep/__init__.py
+test/test_readers/test_pep/test_inline_markup.py
+test/test_readers/test_pep/test_rfc2822.py
+test/test_transforms/__init__.py
+test/test_transforms/test___init__.py
+test/test_transforms/test_class.py
+test/test_transforms/test_contents.py
+test/test_transforms/test_docinfo.py
+test/test_transforms/test_doctitle.py
+test/test_transforms/test_expose_internals.py
+test/test_transforms/test_filter.py
+test/test_transforms/test_footnotes.py
+test/test_transforms/test_hyperlinks.py
+test/test_transforms/test_messages.py
+test/test_transforms/test_peps.py
+test/test_transforms/test_sectnum.py
+test/test_transforms/test_smartquotes.py
+test/test_transforms/test_strip_comments.py
+test/test_transforms/test_strip_elements_with_class.py
+test/test_transforms/test_substitutions.py
+test/test_transforms/test_target_notes.py
+test/test_transforms/test_transitions.py
+test/test_transforms/test_writer_aux.py
+test/test_writers/__init__.py
+test/test_writers/test_docutils_xml.py
+test/test_writers/test_get_writer_class.py
+test/test_writers/test_html4css1_misc.py
+test/test_writers/test_html4css1_parts.py
+test/test_writers/test_html4css1_template.py
+test/test_writers/test_html5_polyglot_misc.py
+test/test_writers/test_html5_polyglot_parts.py
+test/test_writers/test_latex2e.py
+test/test_writers/test_manpage.py
+test/test_writers/test_null.py
+test/test_writers/test_odt.py
+test/test_writers/test_pseudoxml.py
+test/test_writers/test_s5.py
+tools/buildhtml.py
+tools/docutils.conf
+tools/quicktest.py
+tools/rst2html.py
+tools/rst2html4.py
+tools/rst2html5.py
+tools/rst2latex.py
+tools/rst2man.py
+tools/rst2odt.py
+tools/rst2odt_prepstyles.py
+tools/rst2pseudoxml.py
+tools/rst2s5.py
+tools/rst2xetex.py
+tools/rst2xml.py
+tools/rstpep2html.py
+tools/dev/README.txt
+tools/dev/create_unimap.py
+tools/dev/generate_punctuation_chars.py
+tools/dev/profile_docutils.py
+tools/dev/unicode2rstsubs.py
+tools/editors/README.txt
+tools/editors/emacs/IDEAS.rst
+tools/editors/emacs/README.txt
+tools/editors/emacs/docutils.conf
+tools/editors/emacs/rst.el
+tools/editors/emacs/tests/Ado.el
+tools/editors/emacs/tests/Hdr.el
+tools/editors/emacs/tests/Makefile
+tools/editors/emacs/tests/README.txt
+tools/editors/emacs/tests/Stn.el
+tools/editors/emacs/tests/Ttl.el
+tools/editors/emacs/tests/adjust-section.el
+tools/editors/emacs/tests/adjust-uc.el
+tools/editors/emacs/tests/adjust-uc_doc.rst
+tools/editors/emacs/tests/adornment.el
+tools/editors/emacs/tests/apply-block.el
+tools/editors/emacs/tests/buffer.el
+tools/editors/emacs/tests/comment.el
+tools/editors/emacs/tests/ert-buffer.el
+tools/editors/emacs/tests/fill.el
+tools/editors/emacs/tests/font-lock.el
+tools/editors/emacs/tests/helpers.el
+tools/editors/emacs/tests/imenu.el
+tools/editors/emacs/tests/indent.el
+tools/editors/emacs/tests/init.el
+tools/editors/emacs/tests/items.el
+tools/editors/emacs/tests/movement.el
+tools/editors/emacs/tests/re.el
+tools/editors/emacs/tests/shift.el
+tools/editors/emacs/tests/toc.el
+tools/editors/emacs/tests/tree.el
+tools/test/test_buildhtml.py
--- /dev/null
+include *.txt
+include *.py
+include setup.cfg
+include MANIFEST
+include MANIFEST.in
+recursive-include docutils *
+recursive-include docs *
+recursive-include licenses *
+recursive-include test *
+recursive-include tools *
+recursive-exclude * *.pyc *~ .DS_Store
--- /dev/null
+Metadata-Version: 1.2
+Name: docutils
+Version: 0.16
+Summary: Docutils -- Python Documentation Utilities
+Home-page: http://docutils.sourceforge.net/
+Author: David Goodger
+Author-email: goodger@python.org
+Maintainer: docutils-develop list
+Maintainer-email: docutils-develop@lists.sourceforge.net
+License: public domain, Python, 2-Clause BSD, GPL 3 (see COPYING.txt)
+Description: Docutils is a modular system for processing documentation
+ into useful formats, such as HTML, XML, and LaTeX. For
+ input Docutils supports reStructuredText, an easy-to-read,
+ what-you-see-is-what-you-get plaintext markup syntax.
+Platform: OS-independent
+Classifier: Development Status :: 4 - Beta
+Classifier: Environment :: Console
+Classifier: Intended Audience :: End Users/Desktop
+Classifier: Intended Audience :: Other Audience
+Classifier: Intended Audience :: Developers
+Classifier: Intended Audience :: System Administrators
+Classifier: License :: Public Domain
+Classifier: License :: OSI Approved :: Python Software Foundation License
+Classifier: License :: OSI Approved :: BSD License
+Classifier: License :: OSI Approved :: GNU General Public License (GPL)
+Classifier: Operating System :: OS Independent
+Classifier: Programming Language :: Python :: 2
+Classifier: Programming Language :: Python :: 2.7
+Classifier: Programming Language :: Python :: 3
+Classifier: Programming Language :: Python :: 3.5
+Classifier: Programming Language :: Python :: 3.6
+Classifier: Programming Language :: Python :: 3.7
+Classifier: Topic :: Documentation
+Classifier: Topic :: Software Development :: Documentation
+Classifier: Topic :: Text Processing
+Classifier: Natural Language :: English
+Classifier: Natural Language :: Afrikaans
+Classifier: Natural Language :: Catalan
+Classifier: Natural Language :: Chinese (Simplified)
+Classifier: Natural Language :: Chinese (Traditional)
+Classifier: Natural Language :: Czech
+Classifier: Natural Language :: Danish
+Classifier: Natural Language :: Dutch
+Classifier: Natural Language :: Esperanto
+Classifier: Natural Language :: Finnish
+Classifier: Natural Language :: French
+Classifier: Natural Language :: Galician
+Classifier: Natural Language :: German
+Classifier: Natural Language :: Hebrew
+Classifier: Natural Language :: Italian
+Classifier: Natural Language :: Japanese
+Classifier: Natural Language :: Korean
+Classifier: Natural Language :: Latvian
+Classifier: Natural Language :: Lithuanian
+Classifier: Natural Language :: Persian
+Classifier: Natural Language :: Polish
+Classifier: Natural Language :: Portuguese (Brazilian)
+Classifier: Natural Language :: Russian
+Classifier: Natural Language :: Slovak
+Classifier: Natural Language :: Spanish
+Classifier: Natural Language :: Swedish
+Requires-Python: >=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*
--- /dev/null
+=======================
+ README: Docutils 0.16
+=======================
+
+:Author: David Goodger
+:Contact: goodger@python.org
+:Date: $Date: 2020-01-12 14:28:32 +0100 (So, 12. Jän 2020) $
+:Web site: http://docutils.sourceforge.net/
+:Copyright: This document has been placed in the public domain.
+
+.. contents::
+
+
+Quick-Start
+===========
+
+This is for those who want to get up & running quickly.
+
+1. Docutils requires Python, available from
+
+ http://www.python.org/
+
+ See Requirements_ below for details.
+
+2. Use the latest Docutils code. Get the code from the `Subversion
+ repository`_ or from the snapshot:
+
+ https://sourceforge.net/p/docutils/code/HEAD/tree/trunk/docutils/
+
+ See `Releases & Snapshots`_ below for details.
+
+3. Unpack the tarball in a temporary directory (**not** directly in
+ Python's ``site-packages``), go to the directory created by expanding
+ the archive, and run ``setup.py install``. On
+ Windows systems it may be sufficient to double-click ``install.py``.
+
+ See Installation_ below for details.
+
+4. Use the front-end scripts to convert reStructuredText documents.
+ Try for example::
+
+ rst2html.py FAQ.txt FAQ.html (Unix)
+ python tools/rst2html.py FAQ.txt FAQ.html (Windows)
+
+ See Usage_ below for details.
+
+
+Purpose
+=======
+
+The purpose of the Docutils project is to create a set of tools for
+processing plaintext documentation into useful formats, such as HTML,
+XML, and LaTeX. Support for the following sources has been
+implemented:
+
+* Standalone files.
+
+* `PEPs (Python Enhancement Proposals)`_.
+
+Support for the following sources is planned:
+
+* Inline documentation from Python modules and packages, extracted
+ with namespace context.
+
+* Email (RFC-822 headers, quoted excerpts, signatures, MIME parts).
+
+* Wikis, with global reference lookups of "wiki links".
+
+* Compound documents, such as multiple chapter files merged into a
+ book.
+
+* And others as discovered.
+
+.. _PEPs (Python Enhancement Proposals):
+ http://www.python.org/peps/pep-0012.html
+
+
+Releases & Snapshots
+====================
+
+While we are trying to follow a "release early & often" policy,
+features are added frequently. Since the code in the Subversion
+repository is usually in a bug-free state, we recommend that you use
+a current snapshot.
+
+To get a snapshot, go to the code page and click the download snapshot
+button:
+
+* Docutils code, documentation, front-end tools, and tests:
+ https://sourceforge.net/p/docutils/code/HEAD/tree/trunk/docutils/
+
+* Sandbox (experimental, contributed code):
+ https://sourceforge.net/p/docutils/code/HEAD/tree/trunk/sandbox/
+
+To keep up to date on the latest developments, download fresh copies of
+the snapshots regularly or use a working copy of the
+`Subversion repository`_.
+
+.. _Subversion repository: docs/dev/repository.html
+
+
+Requirements
+============
+
+To run the code, Python_ must be installed.
+Docutils is compatible with Python versions 2.7, and
+3.5 to 3.7 (cf. `Python 3 compatibility`_).
+
+Docutils uses the following packages for enhanced functionality,
+if they are installed:
+
+* The `Python Imaging Library`_, or PIL, is used for some image
+ manipulation operations.
+
+* The `Pygments`_ syntax highlighter is used for content of `code`
+ directives and roles.
+
+.. _Python: http://www.python.org/.
+.. _Python Imaging Library: http://www.pythonware.com/products/pil/
+.. _Pygments: http://pygments.org/
+
+
+Python 3 compatibility
+----------------------
+
+Up to version 0.15, the Docutils codebase was translated "on-demand" using
+the 2to3 tool. Starting with Docutils 0.16, the code base supports both
+Python 2.7 and 3.5+ natively.
+
+
+Project Files & Directories
+===========================
+
+* README.txt: You're reading it.
+
+* COPYING.txt: Public Domain Dedication and copyright details for
+ non-public-domain files (most are PD).
+
+* FAQ.txt: Frequently Asked Questions (with answers!).
+
+* RELEASE-NOTES.txt: Summary of the major changes in recent releases.
+
+* HISTORY.txt: A detailed change log, for the current and all previous
+ project releases.
+
+* BUGS.txt: Known bugs, and how to report a bug.
+
+* THANKS.txt: List of contributors.
+
+* setup.py: Installation script. See "Installation" below.
+
+* install.py: Quick & dirty installation script. Just run it. For
+ any kind of customization or help though, setup.py must be used.
+
+* docutils: The project source directory, installed as a Python
+ package.
+
+* docs: The project documentation directory. Read ``docs/index.txt``
+ for an overview.
+
+* docs/user: The project user documentation directory. Contains the
+ following documents, among others:
+
+ - docs/user/tools.txt: Docutils Front-End Tools
+ - docs/user/latex.txt: Docutils LaTeX Writer
+ - docs/user/rst/quickstart.txt: A ReStructuredText Primer
+ - docs/user/rst/quickref.html: Quick reStructuredText (HTML only)
+
+* docs/ref: The project reference directory.
+ ``docs/ref/rst/restructuredtext.txt`` is the reStructuredText
+ reference.
+
+* licenses: Directory containing copies of license files for
+ non-public-domain files.
+
+* tools: Directory for Docutils front-end tools. See
+ ``docs/user/tools.txt`` for documentation.
+
+* test: Unit tests. Not required to use the software, but very useful
+ if you're planning to modify it. See `Running the Test Suite`_
+ below.
+
+
+Installation
+============
+
+The first step is to expand the ``.tgz`` archive in a temporary
+directory (**not** directly in Python's ``site-packages``). It
+contains a distutils setup file "setup.py". OS-specific installation
+instructions follow.
+
+
+GNU/Linux, BSDs, Unix, Mac OS X, etc.
+-------------------------------------
+
+1. Open a shell.
+
+2. Go to the directory created by expanding the archive::
+
+ cd <archive_directory_path>
+
+3. Install the package (you may need root permissions to complete this
+ step)::
+
+ su
+ (enter admin password)
+ python setup.py install
+
+ If the python executable isn't on your path, you'll have to specify
+ the complete path, such as ``/usr/local/bin/python``.
+
+ To install for a specific Python version, use this version in the
+ setup call, e.g. ::
+
+ python3.7 setup.py install
+
+ To install for different Python versions, repeat step 3 for every
+ required version. The last installed version will be used in the
+ `shebang line`_ of the ``rst2*.py`` wrapper scripts.
+
+ .. _shebang line: http://en.wikipedia.org/wiki/Shebang_%28Unix%29
+
+Windows
+-------
+
+Just double-click ``install.py``. If this doesn't work, try the
+following:
+
+1. Open a DOS Box (Command Shell, MS-DOS Prompt, or whatever they're
+ calling it these days).
+
+2. Go to the directory created by expanding the archive::
+
+ cd <archive_directory_path>
+
+3. Install the package::
+
+ <path_to_python.exe>\python setup.py install
+
+ To install for a specific python version, specify the Python
+ executable for this version.
+
+ To install for different Python versions, repeat step 3 for every
+ required version.
+
+Optional steps:
+
+* `running the test suite`_
+
+* `converting the documentation`_
+
+
+Usage
+=====
+
+There are many front-end tools in the unpacked "tools" subdirectory.
+Installation under Unix places copies in the PATH.
+You may want to begin with the "rst2html.py" front-end tool. Most
+tools take up to two arguments, the source path and destination path,
+with STDIN and STDOUT being the defaults. Use the "--help" option to
+the front-end tools for details on options and arguments. See
+Docutils Front-End Tools (``docs/user/tools.txt``) for full documentation.
+
+The package modules are continually growing and evolving. The
+``docutils.statemachine`` module is usable independently. It contains
+extensive inline documentation (in reStructuredText format of course).
+
+Contributions are welcome!
+
+
+Converting the documentation
+============================
+
+After unpacking and installing the Docutils package, the following
+shell commands will generate HTML for all included documentation::
+
+ cd <archive_directory_path>/tools
+ ./buildhtml.py ../
+
+On Windows systems, type::
+
+ cd <archive_directory_path>\tools
+ python buildhtml.py ..
+
+The final directory name of the ``<archive_directory_path>`` is
+"docutils" for snapshots. For official releases, the directory may be
+called "docutils-X.Y.Z", where "X.Y.Z" is the release version.
+Alternatively::
+
+ cd <archive_directory_path>
+ tools/buildhtml.py --config=tools/docutils.conf (Unix)
+ python tools\buildhtml.py --config=tools\docutils.conf (Windows)
+
+Some files may generate system messages (warnings and errors). The
+``docs/user/rst/demo.txt`` file (under the archive directory) contains
+five intentional errors. (They test the error reporting mechanism!)
+
+
+Running the Test Suite
+======================
+
+The test suite is documented in `Docutils Testing`_ (docs/dev/testing.txt).
+
+To run the entire test suite, open a shell and use the following
+commands::
+
+ cd <archive_directory_path>/test
+ ./alltests.py
+
+Under Windows, type::
+
+ cd <archive_directory_path>\test
+ python alltests.py
+
+
+You should see a long line of periods, one for each test, and then a
+summary like this::
+
+ Ran 1111 tests in 24.653s
+
+ OK
+ Elapsed time: 26.189 seconds
+
+The number of tests will grow over time, and the times reported will
+depend on the computer running the tests. The difference between the
+two times represents the time required to set up the tests (import
+modules, create data structures, etc.).
+
+If any of the tests fail, please `open a bug report`_ or `send an email`_
+(see `Bugs <BUGS.html>`_).
+Please include all relevant output, information about your operating
+system, Python version, and Docutils version. To see the Docutils
+version, use one of the ``rst2*`` front ends or ``tools/quicktest.py``
+with the ``--version`` option, e.g.::
+
+ cd ../tools
+ ./quicktest.py --version
+
+Windows users type these commands::
+
+ cd ..\tools
+ python quicktest.py --version
+
+
+.. _Docutils Testing: http://docutils.sourceforge.net/docs/dev/testing.html
+.. _open a bug report:
+ http://sourceforge.net/p/docutils/bugs/
+.. _send an email: mailto:docutils-users@lists.sourceforge.net
+ ?subject=Test%20suite%20failure
+.. _web interface: https://sourceforge.net/p/docutils/mailman/
+
+
+Getting Help
+============
+
+If you have questions or need assistance with Docutils or
+reStructuredText, please post a message to the Docutils-users_ mailing
+list.
+
+.. _Docutils-users: docs/user/mailing-lists.html#docutils-users
+
+\f
+..
+ Local Variables:
+ mode: indented-text
+ indent-tabs-mode: nil
+ sentence-end-double-space: t
+ fill-column: 70
+ End:
--- /dev/null
+.. -*- coding: utf-8 -*-
+
+========================
+ Docutils Release Notes
+========================
+
+:Contact: grubert@users.sourceforge.net
+:Maintainer: docutils-develop@lists.sourceforge.net
+:Date: $Date: 2019-12-12 17:31:22 +0100 (Do, 12. Dez 2019) $
+:Revision: $Revision: 8438 $
+:Web site: http://docutils.sourceforge.net/
+:Copyright: This document has been placed in the public domain.
+
+
+This document summarizes the major changes in recent and upcoming releases.
+For a more detailed list of changes, please see the `Docutils History`_.
+
+.. _Docutils History: HISTORY.html
+
+.. contents::
+
+Future changes
+==============
+
+* Installing with ``setup.py`` will require setuptools_ in versions > 0.16.
+
+* HTML5 writer:
+ Use the new semantic tags <main>, <section>, <header>,
+ <footer>, <aside>, <figure>, and <figcaption>.
+ See ``minimal.css`` and ``plain.css`` for styling rule examples.
+
+ Use HTML text-level tags <small>, <s>, <q>, <dfn>, <var>, <samp>, <kbd>,
+ <i>, <b>, <u>, <mark>, and <bdi> if a matching class value
+ is found in `inline` and `literal` elements.
+
+ Use HTML tags <ins> and <del> if a matching class value
+ is found in `inline`, `literal`, or `container` elements.
+
+
+* LaTeX writer:
+ Wrap admonitions in a "DUclass" environment. Stylesheets modifying
+ "\DUadmonition" will need to adapt.
+
+ Styling commands using ``\docutilsrole`` prefix will be ignored in
+ versions > 0.16 (see `Generating LaTeX with Docutils`__).
+
+ __ docs/user/latex.html#classes
+
+* ``Node.traverse()`` will return an iterator instead of a list.
+
+* Remove ``utils.unique_combinations``
+ (obsoleted by ``itertools.combinations``).
+
+* If the id_prefix_ setting is non-empty, leading number and hyphen characters
+ will not be stripped from a `reference name`_ during `identifier
+ normalization`_. This may change generated `identifier keys`.
+
+ Example: with ``--id-prefix="DU-"``, a section with title "34. May"
+ currently gets the identifier key ``DU-may`` and after the change the
+ identifier key ``DU-34-may``.
+
+* The default value for auto_id_prefix_ will change to "%". This means
+ auto-generated IDs will use the tag name as prefix. Set auto_id_prefix_ to
+ "id" if you want unchanged auto-IDs or to "%" if you want descriptive IDs.
+
+* The default HTML writer "html" with frontend ``rst2html.py`` may change
+ from "html4css1" to "html5".
+
+ Use ``get_writer_by_name('html')`` or the rst2html.py_ front end, if you
+ want the output to be up-to-date automatically.
+
+ Use a specific writer name or front end, if you depend on stability of the
+ generated HTML code, e.g. because you use a custom style sheet or
+ post-processing that may break otherwise.
+
+.. _setuptools: https://setuptools.readthedocs.io/en/latest/
+.. _id_prefix: docs/user/config.html#id-prefix
+.. _auto_id_prefix: docs/user/config.html#auto-id-prefix
+.. _rst2html.py: docs/user/tools.html#rst2html-py
+.. _reference name: docs/ref/rst/restructuredtext.html#reference-names
+.. _identifier normalization: directives.html#identifier-normalization
+
+Release 0.16b (2019-12-01)
+==========================
+
+.. Note::
+
+ Docutils 0.15.x is the last version supporting Python 2.6, 3.3 and 3.4.
+
+ Docutils 0.16.x supports Python 2.7 and Python >= 3.5 natively,
+ without the use of the ``2to3`` tool.
+
+* reStructuredText:
+
+ - Keep `backslash escapes`__ in the document tree. This allows, e.g.,
+ escaping of author-separators in `bibliographic fields`__.
+
+ __ http://docutils.sourceforge.net/docs/ref/rst/restructuredtext.html#escaping-mechanism
+ __ docs/ref/rst/restructuredtext.html#bibliographic-fields
+
+* LaTeX writer:
+
+ - Informal titles of type "rubric" default to bold-italic and left aligned.
+ - Deprecate ``\docutilsrole`` prefix for styling commands:
+ use ``\DUrole`` instead.
+ - Fix topic subtitle.
+ - Add "latex writers" to the `config_section_dependencies`.
+ - Ignore classes for `rubric` elements
+ (class wrapper interferes with LaTeX formatting).
+
+* tools/buildhtml.py
+
+ - New option "--html-writer" allows to select "html__" (default),
+ "html4" or "html5".
+
+ __ html: docs/user/html.html#html
+
+* docutils/io.py
+
+ - Remove the `handle_io_errors` option from io.FileInput/Output.
+
+* docutils/nodes.py
+
+ - If `auto_id_prefix`_ ends with "%", this is replaced with the tag name.
+
+ .. _auto_id_prefix: docs/user/config.html#auto-id-prefix
+
+* Various bugfixes and improvements (see HISTORY_).
+
+
+Release 0.15 (2019-07-20)
+=========================
+
+.. Note::
+
+ Docutils 0.14.x is the last version supporting Python 2.4, 2.5,
+ 3.1, and 3.2.
+
+ Docutils 0.15.x is compatible with Python versions 2.6, 2.7 and 3.3 to 3.5
+ (cf. `Python 3 compatibility`_).
+
+* reStructuredText:
+
+ - Allow embedded colons in field list field names (before, tokens like
+ ``:this:example:`` were considered ordinary text).
+
+ - Fixed a bug with the "trim" options of the "unicode" directive.
+
+* languages: Added Korean localisation (ko).
+
+* Bugfixes (see HISTORY_).
+
+
+Release 0.14 (2017-08-03)
+=========================
+
+* docutils/docs/ref/docutils.dtd:
+
+ - Enable validation of Docutils XML documents against the DTD:
+
+* docutils/parsers/rst/:
+
+ - Added functionality: escaped whitespace in URI contexts.
+ - Consistent handling of all whitespace characters in inline markup
+ recognition. (May break documents that relied on some whitespace
+ characters (NBSP, ...) *not* to be recognized as whitespace.)
+
+* docutils/utils/smartquotes.py:
+
+ - Update quote definitions for et, fi, fr, ro, sv, tr, uk.
+ - Add quote definitions for hr, hsb, hu, lv, sh, sl, sr.
+ - Differentiate apostrophe from closing single quote (if possible).
+ - Add command line interface for stand-alone use (requires 2.7).
+
+* docutils/writers/_html_base:
+
+ - Provide default title in metadata.
+ - The MathJax CDN shut down on April 30, 2017. For security reasons, we
+ don't use a third party public installation as default but warn
+ if `math-output` is set to MathJax without specifying a URL.
+ See math-output_ for details.
+
+* docutils/writers/html4css1:
+
+ - Respect automatic table column sizing.
+
+* docutils/writers/latex2e/__init__.py
+
+ - Handle class arguments for block-level elements by wrapping them
+ in a "DUclass" environment. This replaces the special handling for
+ "epigraph" and "topic" elements.
+
+* docutils/writers/odf_odt:
+
+ - Language option sets ODF document's default language
+ - Image width, scale, ... set image size in generated ODF.
+
+* tools/
+
+ - New front-end ``rst2html4.py``.
+
+
+Release 0.13.1 (2016-12-09)
+===========================
+
+* docutils/writers/html5_polyglot
+
+ - New HTML writer generating `HTML 5`_.
+
+ .. _HTML 5: http://www.w3.org/TR/html5/
+
+* tools/
+
+ - New front-end ``rst2html5.py``.
+
+* languages: persian/farsi (fa) and latvian (la) mappings.
+
+* change default base url for :rfc: to http://tools.ietf.org/html/
+
+* tables accept widths, a list and align
+
+* latex2e: Fix admonition width, remove deprecated options,
+ better tablewidth auto, ...
+
+* rst.el: The problem with ``electric-indent-mode`` has been fixed.
+
+
+Release 0.12 (2014-07-06)
+=========================
+
+Small changes only, release current state
+
+
+Release 0.11 (2013-07-22)
+=========================
+
+* General
+
+ - Apply [ 2714873 ] Fix for the overwritting of document attributes.
+ - Support embedded aliases within hyperlink references.
+ - Fix [ 228 ] try local import of docutils components (reader, writer, parser,
+ language module) before global search.
+
+* docutils/parsers/rst/directives/tables.py
+
+ - Fix [ 210 ] Python 3.3 checks CVS syntax only if "strict" is True.
+
+* docutils/writers/html4css1/__init__.py
+ - Fix [ 3600051 ] for tables in a list, table cells are not compacted.
+ - New setting `stylesheet_dirs` (see above).
+
+ Now, it is easy to add a custom stylesheet to Docutils' default
+ stylesheet with, e.g., ``--stylesheet_path='html4css1.css, mystyle.css'``
+
+ Changed behaviour of the default settings:
+ if there is a file ``html4css1.css`` in the working directory of the
+ process at launch, it is used instead of the one provided by Docutils
+ in the writer source directory.
+
+ - New default for math-output_: ``HTML math.css``.
+ - Avoid repeated class declarations in html4css1 writer
+ (modified version of patch [ 104 ]).
+
+.. _math-output: docs/user/config.html#math-output
+
+* docutils/writers/latex2e/__init__.py
+
+ - Drop the simple algorithm replacing straight double quotes with
+ English typographic ones.
+ Activate the SmartQuotes_ transform if you want this feature.
+ - New setting `stylesheet_dirs`: Comma-separated list of directories
+ where stylesheets are found. Used by `stylesheet_path` when expanding
+ relative path arguments.
+
+.. _SmartQuotes: docs/user/config.html#smart-quotes
+
+* docutils/writers/manpage.py
+
+ - Fix [3607063] handle lines starting with a period.
+ - Fix option separating comma was bold (thanks to Bill Morris).
+
+Release 0.10 (2012-12-16)
+=========================
+
+.. Note::
+
+ Docutils 0.9.x is the last version supporting Python 2.3.
+
+ Docutils 0.10 is compatible with Python versions from 2.4 to 3.2
+ (cf. `Python 3 compatibility`_).
+
+* General:
+
+ - SmartQuotes transform for typographic quotes and dashes.
+
+ - ``docutils/math``, ``docutils/error_reporting.py``, and
+ ``docutils/urischemes.py`` moved to the utils package.
+ Code importing these modules needs to adapt, e.g.::
+
+ try:
+ import docutils.math as math
+ except ImportError:
+ import docutils.utils.math as math
+
+ - enhanced math and error handling.
+
+* docutils/io.py
+
+ - FileInput/FileOutput: no system-exit on IOError.
+ The `handle_io_errors` option is ignored.
+
+.. _Python 3 compatibility: README.html#python-3-compatibility
+
+* docutils/writers/html4css1/__init__.py
+
+ - Use ``<code>`` tag for inline "code",
+ do not drop nested inline nodes (syntax highlight tokens).
+ - Customizable MathJax URL (based on patch by Dmitry Shachnev).
+ - No line break after opening inline math tag.
+
+* docutils/writers/latex2e/__init__.py, docutils/writers/xetex/__init__.py
+
+ - Fix section numbering by LaTeX.
+
+* docutils/writers/s5_html/__init__.py
+
+ - Fix [ 3556388 ] Mathjax does not work with rst2s5.
+
+
+Release 0.9.1 (2012-06-17)
+==========================
+
+* General:
+
+ Several fixes for Python 3 usage.
+
+* docutils/setup.py
+
+ - Fix [ 3527842 ]. Under Python 3, converted tests and tools were
+ installed in the PYTHONPATH. Converted tests are now
+ stored in ``docutils/test3/``, tools no longer need conversion.
+
+ If you installed one of Docutils versions 0.7 ... 0.9 with
+ ``setup.py install`` under Python 3, remove the spurious
+ ``test/`` and ``tools/`` directories in the site library root.
+
+
+Release 0.9 (2012-05-02)
+=========================
+
+* General:
+
+ - reStructuredText "code" role and directive with syntax highlighting
+ by Pygments_.
+ - "code" option of the "include" directive.
+
+ .. _Pygments: http://pygments.org/
+
+ - Fix [ 3402314 ] allow non-ASCII whitespace, punctuation
+ characters and "international" quotes around inline markup.
+
+ - Fix handling of missing stylesheets.
+
+* setup.py
+
+ - Fix [ 2971827 ] and [ 3442827 ]
+ extras/roman.py moved to docutils/utils/roman.py
+
+* docutils/utils.py -> docutils/utils/__init__.py
+
+ - docutils.utils is now a package (providing a place for sub-modules)
+
+* docutils/writers/html4css1/__init__.py
+
+ - change default for `math-output` setting to MathJax
+
+* docutils/writers/latex2e/__init__.py
+
+ - Support the `abbreviation` and `acronym` standard roles.
+ - Record only files required to generate the LaTeX source as dependencies.
+ - Use ``\setcounter{secnumdepth}{0}`` instead of ``*``-versions
+ when suppressing LaTeX section numbering.
+
+
+Release 0.8.1 (2011-08-30)
+==========================
+
+* General:
+
+ - Fix [ 3364658 ] (Change last file with Apache license to BSD-2-Clause)
+ and [ 3395920 ] (correct copyright info for rst.el).
+
+* docutils/writers/latex2e/__init__.py
+
+ - Clean up Babel language setting. Restores Sphinx compatibility.
+
+
+Release 0.8 (2011-07-07)
+========================
+
+* COPYING:
+
+ - Some additions to the Docutils core are released under the 2-Clause BSD
+ license.
+
+* General:
+
+ - Handle language codes according to `BCP 47`_.
+ - If the specified langauage is not supported by Docutils,
+ warn and fall back to English.
+ - Math support: reStructuredText "math" role and directive,
+ ``math`` and ``math_block`` doctree elements.
+ - Orphaned "python" reader and "newlatex2e" writer moved to the sandbox.
+
+ .. _BCP 47: http://www.rfc-editor.org/rfc/bcp/bcp47.txt
+
+* reStructuredText:
+
+ - most directives now support a "name" option that attaches a
+ reference name. So you can write ::
+
+ .. figure:: image.png
+ :name: figure name
+
+ as a short form of ::
+
+ .. _figure name:
+
+ .. figure:: image.png
+
+Internationalization:
+
+* Added lithuanian mappings.
+
+Components:
+
+* HTML writer:
+
+ - New setting "math-output" with support for HTML, MathML, and LaTeX.
+
+* LaTeX2e writer:
+
+ - Convert image URI to a local file path.
+ - Apply [ 3148141 ] fix multicolumn support when a colspanning cell
+ has more than one paragraph (Wolfgang Scherer).
+
+* XeTeX writer:
+
+ - New writer generating LaTeX code for compiling with ``xelatex``.
+
+ XeTeX uses unicode and modern font technologies.
+
+* and fixes and enhancements here and there.
+
+
+Release 0.7 (2010-07-07)
+========================
+
+Components:
+
+* HTML writer:
+
+ - Support SVG and SWF images (thanks to Stefan Rank).
+ - Generate valid XHTML for centered images with targets.
+ Use CSS classes instead of "align" tags for image alignment.
+
+* LaTeX2e writer:
+
+ - Use the ``\url`` command for URLs (breaks long URLs instead of writing
+ into the margin).
+ - Preserve runs of spaces in 'inline literals'.
+ - Deprecate ``figure_footnotes`` setting.
+ - Rename ``use_latex_footnotes`` setting to `docutils_footnotes`__.
+ - New ``latex_preamble`` setting.
+ - Use PDF standard fonts (Times/Helvetica/Courier) as default.
+ - `hyperref` package called with ``unicode`` option (see the
+ `hyperref config tips`__ for how to override).
+ - Drop the special `output_encoding`__ default ("latin-1").
+ The Docutils wide default (usually "UTF-8") is used instead.
+
+__ docs/user/config.html#docutils-footnotes
+__ docs/user/latex.html#hyperlinks
+__ docs/user/latex.html#output-encoding
+
+* manpage writer:
+
+ - Titles level 1, that is ``.SH``, always uppercase.
+ - Apply patch from mg: literal text should be bold in man-pages.
+
+General:
+
+* io.FileInput opens files as text files with universal newline support
+ (mode "rU", configurable with the new optional argument "mode").
+
+* setup.py:
+
+ - Python 3 support: copy test/ and tools/ to the build-dir
+ and convert Python sources with 2to3.
+
+
+Release 0.6 (2009-10-11)
+========================
+
+.. Note::
+
+ Docutils 0.5 is the last version supporting Python 2.2.
+
+ Docutils 0.6 is compatible with Python versions from 2.3 up to 2.6
+ and convertible to 3.1 code.
+
+.. note::
+
+ The "newlatex" writer is orphaned.
+
+ The recommended way to generate PDF output is to use either the
+ LaTeX2e writer or one of the alternatives listed at
+ http://docutils.sourceforge.net/docs/user/links.html#pdf.
+
+* reStructuredText:
+
+ - Allow length units for all length specifications.
+ - Allow percent sign in "scale" argument of "figure" and "image" directives.
+ - Bugfix: The "figalign" argument of a figure now works as intended
+ (aligning the figure not its contents).
+ - Align images with class "align-[right|center|left]"
+ (allows setting the alignment of an image in a figure).
+ - Hard tabs in literal inclusions are replaced by spaces. This is
+ configurable via the new "tab-width" option of the "include" directive
+ (a negative tab-width prevents tab expansion).
+
+* HTML writer:
+
+ - ``--stylesheet`` and ``--stylesheet-path`` options now support a comma
+ separated list of stylesheets.
+
+* LaTeX2e writer:
+
+ - New defaults:
+ - font-encoding: "T1" (formerly implicitely set by 'ae').
+ - use-latex-toc: true (ToC with page numbers).
+ - use-latex-footnotes: true (no mixup with figures).
+ - Float placement defaults to "here definitely" (configurable).
+ - Align of image in a figure defaults to 'center'.
+ - Use class defaults for page margins ('typearea' now optional).
+ - Support LaTeX packages as ``--stylesheet`` arguments.
+ - Use ``bp`` for lengths without unit or unit ``pt``,
+ do not convert ``px`` to ``pt``.
+ - Do not use 'ae' and 'aeguill' packages if font-encoding is set to ''.
+ - Set sub- and superscript role argument as text not math.
+ - Support custom roles based on standard roles.
+ - Load packages and define macros only if required in the document.
+ - All Docutils specific LaTeX macros are prefixed with ``DU``.
+ - Better conformance to Docutils specifications with "use_latex_toc".
+ - If 'sectnum_xform' is False, the 'sectnum' directive triggers
+ section numbering by LaTeX.
+ - Use default font in admonitions and sidebar.
+ - Typeset generic topic as "quote with title".
+ - Use template (file and configuration option).
+ - Render doctest blocks as literal blocks (indented).
+
+* ODT writer:
+
+ - moved from sandbox to Doctutils core.
+
+* manpage writer:
+
+ - moved from sandbox to Doctutils core.
+
+
+Release 0.5 (2008-06-25)
+========================
+
+Components:
+
+* HTML writer.
+
+ - Dropped all ``name`` attributes of ``a`` elements (``id`` is
+ universally supported now).
+
+* LaTeX2e writer:
+
+ - Better bibTeX citation support.
+ - Add ``--literal-block-env``
+
+* PEP writer:
+
+ - Changed to support new python.org website structure and
+ pep2pyramid.py.
+
+reStructuredText:
+
+* Changed the directive API to a new object-oriented system.
+ (Compatibility for the old, functional-style directive interface is
+ retained.) See the updated `Creating reStructuredText Directives`__
+ how-to.
+
+ __ docs/howto/rst-directives.html
+
+* Allow ``+`` and ``:`` in reference names requested for citations.
+
+Documentation:
+
+* Added `Deploying Docutils Securely`__
+
+ __ docs/howto/security.txt
+
+Internationalization:
+
+* Added hebrew mappings.
+
+General:
+
+* Configuration files are now assumed and required to be
+ UTF-8-encoded.
+
+* Added docutils/writers/html4css1/template.txt.
+
+* Enhance emacs support.
+
+
+Release 0.4 (2006-01-09)
+========================
+
+.. Note::
+
+ Docutils 0.4.x is the last version that will support Python 2.1.
+ Docutils 0.5 will *not* be compatible with Python 2.1; Python 2.2
+ or later will be required.
+
+ Docutils 0.4.x is the last version that will make compromises in
+ its HTML output for Netscape Navigator 4. Docutils 0.5 will
+ require more up-to-date browsers (the exact definition is to be
+ determined).
+
+Components:
+
+* Added an `S5/HTML writer`__ and the rst2s5.py__ front end:
+ multi-platform, multi-browser HTML slide shows.
+
+ __ docs/user/slide-shows.html
+ __ docs/user/tools.html#rst2s5-py
+
+* The newlatex2e writer is nearing completion.
+
+* Added a DocTree reader, ``publish_doctree`` and
+ ``publish_from_doctree`` convenience functions, for document tree
+ extraction and reprocessing.
+
+reStructuredText:
+
+* Added directives: "container__" (generic block-level container),
+ "default-role__" (role used for \`backtick\` syntax), "title__"
+ (document title metadata), and "date__" (generate the current local
+ date, for substitution definitions).
+
+ __ docs/ref/rst/directives.html#container
+ __ docs/ref/rst/directives.html#default-role
+ __ docs/ref/rst/directives.html#title
+ __ docs/ref/rst/directives.html#date
+
+* Length units are now supported for image__ sizes.
+
+ __ docs/ref/rst/directives.html#image
+
+* Added `standard definition files`__ for special characters etc.
+
+ __ docs/ref/rst/definitions.html
+
+Internationalization:
+
+* Added Japanese and Simplified Chinese language mappings, and support
+ for double-width CJK-characters in tables and section titles.
+
+Documentation:
+
+* Added a `guide for distributors`__ (package maintainers) and a
+ `guide for developers`__.
+
+ __ docs/dev/distributing.html
+ __ docs/dev/hacking.html
+
+General:
+
+* Added significant `Emacs support for reST`__.
+
+ __ docs/user/emacs.html
+
+* Added a `--strip-comments`__ option.
+
+ __ docs/user/config.html#strip-comments
+
+* `--embed-stylesheet`__ is now the default for the HTML writer
+ (rather than --link-stylesheet).
+
+ __ docs/user/config.html#embed-stylesheet
+
+
+Release 0.3.9 (2005-05-26)
+==========================
+
+* Added "file_insertion_enabled__" and "raw_enabled__" settings.
+
+ __ docs/user/config.html#file-insertion-enabled
+ __ docs/user/config.html#raw-enabled
+
+* Added `auto-enumerated lists`__.
+
+ __ docs/ref/rst/restructuredtext.html#enumerated-lists
+
+* Added `"header" and "footer"`__ directives.
+
+ __ docs/ref/rst/directives.html#document-header-footer
+
+* Added "list-table__" directive.
+
+ __ docs/ref/rst/directives.html#list-table
+
+* Added support for `section subtitles`__.
+
+ __ docs/user/config.html#sectsubtitle-xform
+
+* Added "field_name_limit__" and "option_limit__" settings to HTML writer.
+
+ __ docs/user/config.html#field-name-limit
+ __ docs/user/config.html#option-limit
+
+* Added "cloak_email_addresses__" setting to HTML writer.
+
+ __ docs/user/config.html#cloak-email-addresses
+
+* UTF-8 BOMs are now removed from the input stream.
+
+
+Release 0.3.7 (2004-12-24)
+==========================
+
+* A special "`line block`__" syntax has been added. (Also see the
+ `quick reference`__.)
+
+ __ docs/ref/rst/restructuredtext.html#line-blocks
+ __ docs/user/rst/quickref.html#line-blocks
+
+* Empty sections are now allowed.
+
+* A "raw__" role has been added.
+
+ __ docs/ref/rst/roles.html#raw
+
+* The LaTeX writer now escapes consecutive dashes (like "--" or "---")
+ so that they are no longer transformed by LaTeX to en or em dashes.
+ (Please see the FAQ__ for how to represent such dashes.)
+
+ __ FAQ.html#how-can-i-represent-esoteric-characters-e-g-character-entities-in-a-document
+
+* A `dependency recorder`__ has been added.
+
+ __ docs/user/config.html#record-dependencies
+
+* A directive has been added for `compound paragraphs`__.
+
+ __ docs/ref/rst/directives.html#compound-paragraph
+
+
+Release 0.3.5 (2004-07-29)
+==========================
+
+* Improved, extended and reorganized the documentation__.
+
+ __ docs/index.html
+
+* Added "csv-table__" directive.
+
+ __ docs/ref/rst/directives.html#csv-table
+
+.. _HISTORY: HISTORY.html
--- /dev/null
+.. -*- coding: utf-8 -*-
+
+Acknowledgements
+================
+
+:Author: David Goodger
+:Contact: goodger@python.org
+:Date: $Date: 2015-02-09 00:21:18 +0100 (Mo, 09. Feb 2015) $
+:Revision: $Revision: 7784 $
+:Copyright: This document has been placed in the public domain.
+
+I would like to acknowledge the people who have made a direct impact
+on the Docutils project, knowingly or not, in terms of encouragement,
+suggestions, criticism, bug reports, code contributions, cash
+donations, tasty treats, and related projects:
+
+* Aahz
+* David Abrahams
+* Guy D. Alcos
+* David Ascher
+* Ned Batchelder
+* Heiko Baumann
+* Anthony Baxter
+* Eric Bellot
+* Frank Bennett
+* Ian Bicking
+* Marek Blaha
+* Martin Blais
+* Stephen Boulet
+* Fred Bremmer
+* Simon Budig
+* Bill Bumgarner
+* Brett Cannon
+* Greg Chapman
+* Nicolas Chauveau
+* Beni Cherniavsky
+* Adam Chodorowski
+* Brent Cook
+* Laura Creighton
+* Artur de Sousa Rocha
+* Stephan Deibel & `Wing IDE <http://wingide.com/>`__
+* Jason Diamond
+* William Dode
+* Fred Drake
+* Reggie Dugard
+* Dethe Elza
+* Marcus Ertl
+* Benja Fallenstein
+* fantasai
+* Stefane Fermigier
+* Michael Foord
+* Jim Fulton
+* Peter Funk
+* Lele Gaifax
+* Dinu C. Gherman
+* Matt Gilbert
+* Jorge Gonzalez
+* Engelbert Gruber
+* Jacob Hallen
+* Simon Hefti
+* Doug Hellmann
+* Marc Herbert
+* Juergen Hermann
+* Jannie Hofmeyr
+* Steve Holden
+* Michael Hudson
+* Marcelo Huerta San Martin
+* Ludger Humbert
+* Jeremy Hylton
+* Tony Ibbs
+* Alan G. Isaac
+* Alan Jaffray
+* Joe YS Jaw
+* Dmitry Jemerov
+* Richard Jones
+* Andreas Jung
+* Robert Kern
+* Garth Kidd
+* Philipp Knüsel
+* Axel Kollmorgen
+* Jeff Kowalczyk
+* Martin F. Krafft
+* Meir Kriheli
+* Dave Kuhlman
+* Lloyd Kvam
+* Kirill Lapshin
+* Nicola Larosa
+* Daniel Larsson
+* Marc-Andre Lemburg
+* Julien Letessier
+* Chris Liechti
+* Wolfgang Lipp
+* Edward Loper
+* Dallas Mahrt
+* Brecht Machiels
+* Mikolaj Machowski
+* Ken Manheimer
+* Bob Marshall
+* Mark McEahern
+* Vincent McIntyre
+* John F Meinel Jr
+* Ivan Mendez for Free Software Office of the University of A Coruña
+* Eric Meyer
+* Günter Milde
+* Skip Montanaro
+* Paul Moore
+* Nigel W. Moriarty
+* Hisashi Morita
+* Mark Nodine
+* Omidyar Network (Pierre Omidyar & Doug Solomon)
+* Panjunyong
+* Patrick K. O'Brien
+* Michel Pelletier
+* Toshio Kuratomi
+* Sam Penrose
+* Tim Peters
+* Pearu Peterson
+* Martijn Pieters
+* Mark Pilgrim
+* Brett g Porter
+* David Priest
+* Jens Quade
+* Stefan Rank
+* Edward K. Ream
+* Andy Robinson
+* Tavis Rudd
+* Tracy Ruggles
+* Oliver Rutherfurd
+* Luc Saffre
+* Seo Sanghyeon
+* Kenichi Sato
+* Ueli Schlaepfer
+* Gunnar Schwant
+* Bill Sconce
+* Frank Siebenlist
+* Bruce Smith
+* Nir Soffer
+* Asko Soukka
+* Darek Suchojad
+* Roman Suzi
+* Janet Swisher
+* tav
+* Kent Tenney
+* Bob Tolbert
+* Paul Tremblay
+* Laurence Tratt
+* Adrian van den Dries
+* Guido van Rossum
+* Miroslav Vasko
+* Paul Viren
+* Martin von Loewis
+* Greg Ward
+* Barry Warsaw
+* Wu Wei
+* Edward Welbourne
+* Lea Wiemann
+* Anthony Williams
+* Robert Wojciechowicz
+* Ka-Ping Yee
+* Moshe Zadka
+* Shmuel Zeigerman
+
+Thank you!
+
+Special thanks to `SourceForge <http://sourceforge.net>`__ and the
+`Python Software Foundation <http://www.python.org/psf/>`__.
+
+Hopefully I haven't forgotten anyone or misspelled any names;
+apologies (and please let me know!) if I have.
--- /dev/null
+===============================================
+ Inside A Docutils Command-Line Front-End Tool
+===============================================
+
+:Author: David Goodger
+:Contact: docutils-develop@lists.sourceforge.net
+:Date: $Date: 2012-01-03 20:23:53 +0100 (Di, 03. Jän 2012) $
+:Revision: $Revision: 7302 $
+:Copyright: This document has been placed in the public domain.
+
+`The Docutils Publisher`_ class was set up to make building
+command-line tools easy. All that's required is to choose components
+and supply settings for variations. Let's take a look at a typical
+command-line front-end tool, ``tools/rst2html.py``, from top to
+bottom.
+
+On Unixish systems, it's best to make the file executable (``chmod +x
+file``), and supply an interpreter on the first line, the "shebang" or
+"hash-bang" line::
+
+ #!/usr/bin/env python
+
+Windows systems can be set up to associate the Python interpreter with
+the ``.py`` extension.
+
+Next are some comments providing metadata::
+
+ # $Id: cmdline-tool.txt 7302 2012-01-03 19:23:53Z grubert $
+ # Author: David Goodger <goodger@python.org>
+ # Copyright: This module has been placed in the public domain.
+
+The module docstring describes the purpose of the tool::
+
+ """
+ A minimal front end to the Docutils Publisher, producing HTML.
+ """
+
+This next block attempts to invoke locale support for
+internationalization services, specifically text encoding. It's not
+supported on all platforms though, so it's forgiving::
+
+ try:
+ import locale
+ locale.setlocale(locale.LC_ALL, '')
+ except:
+ pass
+
+The real work will be done by the code that's imported here::
+
+ from docutils.core import publish_cmdline, default_description
+
+We construct a description of the tool, for command-line help::
+
+ description = ('Generates (X)HTML documents from standalone '
+ 'reStructuredText sources. ' + default_description)
+
+Now we call the Publisher convenience function, which takes over.
+Most of its defaults are used ("standalone" Reader,
+"reStructuredText" Parser, etc.). The HTML Writer is chosen by name,
+and a description for command-line help is passed in::
+
+ publish_cmdline(writer_name='html', description=description)
+
+That's it! `The Docutils Publisher`_ takes care of the rest.
+
+.. _The Docutils Publisher: ./publisher.html
--- /dev/null
+========================
+ The Docutils Publisher
+========================
+
+:Author: David Goodger
+:Contact: docutils-develop@lists.sourceforge.net
+:Date: $Date: 2012-01-03 20:23:53 +0100 (Di, 03. Jän 2012) $
+:Revision: $Revision: 7302 $
+:Copyright: This document has been placed in the public domain.
+
+.. contents::
+
+
+The ``docutils.core.Publisher`` class is the core of Docutils,
+managing all the processing and relationships between components. See
+`PEP 258`_ for an overview of Docutils components.
+
+The ``docutils.core.publish_*`` convenience functions are the normal
+entry points for using Docutils as a library.
+
+See `Inside A Docutils Command-Line Front-End Tool`_ for an overview
+of a typical Docutils front-end tool, including how the Publisher
+class is used.
+
+.. _PEP 258: ../peps/pep-0258.html
+.. _Inside A Docutils Command-Line Front-End Tool: ./cmdline-tool.html
+
+
+Publisher Convenience Functions
+===============================
+
+Each of these functions set up a ``docutils.core.Publisher`` object,
+then call its ``publish`` method. ``docutils.core.Publisher.publish``
+handles everything else. There are several convenience functions in
+the ``docutils.core`` module:
+
+:_`publish_cmdline`: for command-line front-end tools, like
+ ``rst2html.py``. There are several examples in the ``tools/``
+ directory. A detailed analysis of one such tool is in `Inside A
+ Docutils Command-Line Front-End Tool`_
+
+:_`publish_file`: for programmatic use with file-like I/O. In
+ addition to writing the encoded output to a file, also returns the
+ encoded output as a string.
+
+:_`publish_string`: for programmatic use with string I/O. Returns
+ the encoded output as a string.
+
+:_`publish_parts`: for programmatic use with string input; returns a
+ dictionary of document parts. Dictionary keys are the names of
+ parts, and values are Unicode strings; encoding is up to the client.
+ Useful when only portions of the processed document are desired.
+ See `publish_parts Details`_ below.
+
+ There are usage examples in the `docutils/examples.py`_ module.
+
+:_`publish_doctree`: for programmatic use with string input; returns a
+ Docutils document tree data structure (doctree). The doctree can be
+ modified, pickled & unpickled, etc., and then reprocessed with
+ `publish_from_doctree`_.
+
+:_`publish_from_doctree`: for programmatic use to render from an
+ existing document tree data structure (doctree); returns the encoded
+ output as a string.
+
+:_`publish_programmatically`: for custom programmatic use. This
+ function implements common code and is used by ``publish_file``,
+ ``publish_string``, and ``publish_parts``. It returns a 2-tuple:
+ the encoded string output and the Publisher object.
+
+.. _Inside A Docutils Command-Line Front-End Tool: ./cmdline-tool.html
+.. _docutils/examples.py: ../../docutils/examples.py
+
+
+Configuration
+-------------
+
+To pass application-specific setting defaults to the Publisher
+convenience functions, use the ``settings_overrides`` parameter. Pass
+a dictionary of setting names & values, like this::
+
+ overrides = {'input_encoding': 'ascii',
+ 'output_encoding': 'latin-1'}
+ output = publish_string(..., settings_overrides=overrides)
+
+Settings from command-line options override configuration file
+settings, and they override application defaults. For details, see
+`Docutils Runtime Settings`_. See `Docutils Configuration Files`_ for
+details about individual settings.
+
+.. _Docutils Runtime Settings: ./runtime-settings.html
+.. _Docutils Configuration Files: ../user/tools.html
+
+
+Encodings
+---------
+
+The default output encoding of Docutils is UTF-8. If you have any
+non-ASCII in your input text, you may have to do a bit more setup.
+Docutils may introduce some non-ASCII text if you use
+`auto-symbol footnotes`_ or the `"contents" directive`_.
+
+.. _auto-symbol footnotes:
+ ../ref/rst/restructuredtext.html#auto-symbol-footnotes
+.. _"contents" directive:
+ ../ref/rst/directives.html#table-of-contents
+
+
+``publish_parts`` Details
+=========================
+
+The ``docutils.core.publish_parts`` convenience function returns a
+dictionary of document parts. Dictionary keys are the names of parts,
+and values are Unicode strings.
+
+Each Writer component may publish a different set of document parts,
+described below. Not all writers implement all parts.
+
+
+Parts Provided By All Writers
+-----------------------------
+
+_`encoding`
+ The output encoding setting.
+
+_`version`
+ The version of Docutils used.
+
+_`whole`
+ ``parts['whole']`` contains the entire formatted document.
+
+
+.. _HTML writer:
+
+Parts Provided By the HTML Writer
+---------------------------------
+
+_`body`
+ ``parts['body']`` is equivalent to parts['fragment_']. It is
+ *not* equivalent to parts['html_body_'].
+
+_`body_prefix`
+ ``parts['body_prefix']`` contains::
+
+ </head>
+ <body>
+ <div class="document" ...>
+
+ and, if applicable::
+
+ <div class="header">
+ ...
+ </div>
+
+_`body_pre_docinfo`
+ ``parts['body_pre_docinfo]`` contains (as applicable)::
+
+ <h1 class="title">...</h1>
+ <h2 class="subtitle" id="...">...</h2>
+
+_`body_suffix`
+ ``parts['body_suffix']`` contains::
+
+ </div>
+
+ (the end-tag for ``<div class="document">``), the footer division
+ if applicable::
+
+ <div class="footer">
+ ...
+ </div>
+
+ and::
+
+ </body>
+ </html>
+
+_`docinfo`
+ ``parts['docinfo']`` contains the document bibliographic data, the
+ docinfo field list rendered as a table.
+
+_`footer`
+ ``parts['footer']`` contains the document footer content, meant to
+ appear at the bottom of a web page, or repeated at the bottom of
+ every printed page.
+
+_`fragment`
+ ``parts['fragment']`` contains the document body (*not* the HTML
+ ``<body>``). In other words, it contains the entire document,
+ less the document title, subtitle, docinfo, header, and footer.
+
+_`head`
+ ``parts['head']`` contains ``<meta ... />`` tags and the document
+ ``<title>...</title>``.
+
+_`head_prefix`
+ ``parts['head_prefix']`` contains the XML declaration, the DOCTYPE
+ declaration, the ``<html ...>`` start tag and the ``<head>`` start
+ tag.
+
+_`header`
+ ``parts['header']`` contains the document header content, meant to
+ appear at the top of a web page, or repeated at the top of every
+ printed page.
+
+_`html_body`
+ ``parts['html_body']`` contains the HTML ``<body>`` content, less
+ the ``<body>`` and ``</body>`` tags themselves.
+
+_`html_head`
+ ``parts['html_head']`` contains the HTML ``<head>`` content, less
+ the stylesheet link and the ``<head>`` and ``</head>`` tags
+ themselves. Since ``publish_parts`` returns Unicode strings and
+ does not know about the output encoding, the "Content-Type" meta
+ tag's "charset" value is left unresolved, as "%s"::
+
+ <meta http-equiv="Content-Type" content="text/html; charset=%s" />
+
+ The interpolation should be done by client code.
+
+_`html_prolog`
+ ``parts['html_prolog]`` contains the XML declaration and the
+ doctype declaration. The XML declaration's "encoding" attribute's
+ value is left unresolved, as "%s"::
+
+ <?xml version="1.0" encoding="%s" ?>
+
+ The interpolation should be done by client code.
+
+_`html_subtitle`
+ ``parts['html_subtitle']`` contains the document subtitle,
+ including the enclosing ``<h2 class="subtitle">`` & ``</h2>``
+ tags.
+
+_`html_title`
+ ``parts['html_title']`` contains the document title, including the
+ enclosing ``<h1 class="title">`` & ``</h1>`` tags.
+
+_`meta`
+ ``parts['meta']`` contains all ``<meta ... />`` tags.
+
+_`stylesheet`
+ ``parts['stylesheet']`` contains the embedded stylesheet or
+ stylesheet link.
+
+_`subtitle`
+ ``parts['subtitle']`` contains the document subtitle text and any
+ inline markup. It does not include the enclosing ``<h2>`` &
+ ``</h2>`` tags.
+
+_`title`
+ ``parts['title']`` contains the document title text and any inline
+ markup. It does not include the enclosing ``<h1>`` & ``</h1>``
+ tags.
+
+
+Parts Provided by the PEP/HTML Writer
+`````````````````````````````````````
+
+The PEP/HTML writer provides the same parts as the `HTML writer`_,
+plus the following:
+
+_`pepnum`
+ ``parts['pepnum']`` contains
+
+
+Parts Provided by the S5/HTML Writer
+````````````````````````````````````
+
+The S5/HTML writer provides the same parts as the `HTML writer`_.
+
+
+Parts Provided by the LaTeX2e Writer
+------------------------------------
+
+See the template files for examples how these parts can be combined
+into a valid LaTeX document.
+
+abstract
+ ``parts['abstract']`` contains the formatted content of the
+ 'abstract' docinfo field.
+
+body
+ ``parts['body']`` contains the document's content. In other words, it
+ contains the entire document, except the document title, subtitle, and
+ docinfo.
+
+ This part can be included into another LaTeX document body using the
+ ``\input{}`` command.
+
+body_pre_docinfo
+ ``parts['body_pre_docinfo]`` contains the ``\maketitle`` command.
+
+dedication
+ ``parts['dedication']`` contains the formatted content of the
+ 'dedication' docinfo field.
+
+docinfo
+ ``parts['docinfo']`` contains the document bibliographic data, the
+ docinfo field list rendered as a table.
+
+ With ``--use-latex-docinfo`` 'author', 'organization', 'contact',
+ 'address' and 'date' info is moved to titledata.
+
+ 'dedication' and 'abstract' are always moved to separate parts.
+
+fallbacks
+ ``parts['fallbacks']`` contains fallback definitions for
+ Docutils-specific commands and environments.
+
+head_prefix
+ ``parts['head_prefix']`` contains the declaration of
+ documentclass and document options.
+
+latex_preamble
+ ``parts['latex_preamble']`` contains the argument of the
+ ``--latex-preamble`` option.
+
+pdfsetup
+ ``parts['pdfsetup']`` contains the PDF properties
+ ("hyperref" package setup).
+
+requirements
+ ``parts['requirements']`` contains required packages and setup
+ before the stylesheet inclusion.
+
+stylesheet
+ ``parts['stylesheet']`` contains the embedded stylesheet(s) or
+ stylesheet loading command(s).
+
+subtitle
+ ``parts['subtitle']`` contains the document subtitle text and any
+ inline markup.
+
+title
+ ``parts['title']`` contains the document title text and any inline
+ markup.
+
+titledata
+ ``parts['titledata]`` contains the combined title data in
+ ``\title``, ``\author``, and ``\data`` macros.
+
+ With ``--use-latex-docinfo``, this includes the 'author',
+ 'organization', 'contact', 'address' and 'date' docinfo items.
--- /dev/null
+===========================
+ Docutils Runtime Settings
+===========================
+
+:Author: David Goodger
+:Contact: docutils-develop@lists.sourceforge.net
+:Date: $Date: 2012-01-03 20:23:53 +0100 (Di, 03. Jän 2012) $
+:Revision: $Revision: 7302 $
+:Copyright: This document has been placed in the public domain.
+
+.. contents::
+
+
+Introduction
+============
+
+Docutils runtime settings are assembled from several sources:
+component settings specifications, application settings
+specifications, configuration files, and command-line options.
+Docutils overlays default and explicitly specified values from these
+sources such that settings behave the way we want and expect them to
+behave.
+
+To understand how Docutils deals with runtime settings, the attributes
+and parameters involved must first be understood. Begin with the the
+docstrings of the attributes of the ``docutils.SettingsSpec`` base
+class (in the ``docutils/__init__.py`` module):
+
+* ``settings_spec``
+* ``settings_defaults``
+* ``settings_default_overrides``
+* ``relative_path_settings``
+* ``config_section``
+* ``config_section_dependencies``
+
+Next, several _`convenience function parameters` are also significant
+(described in the ``docutils.core.publish_programmatically`` function
+docstring):
+
+* The ``settings`` parameter is a runtime settings
+ (``docutils.frontend.Values``) object which, if present, is assumed
+ to be complete (it must include all runtime settings). Also, if the
+ ``settings`` parameter is present, no further runtime settings
+ processing is done. In other words, the other parameters, described
+ below, will have no effect.
+
+* ``settings_spec``, a `docutils.SettingsSpec` subclass or object, is
+ treated like a fourth component (after the Parser, Reader, and
+ Writer). In other words, it's the settings specification for the
+ "Application" itself.
+
+* ``settings_overrides`` is a dictionary which will override the
+ defaults of the components (from their settings specs).
+
+* ``config_section`` specifies the name of an application-specific
+ configuration file section.
+
+
+.. _command-line tools:
+
+Runtime Settings Processing for Command-Line Tools
+==================================================
+
+Following along with the actual code is recommended. The
+``docutils/__init__.py``, ``docutils/core.py``, and
+``docutils.frontend.py`` modules are described.
+
+1. A command-line front-end tool imports and calls
+ ``docutils.core.publish_cmdline``. The relevant `convenience
+ function parameters`_ are described above.
+
+2. ``docutils.core.publish_cmdline`` initializes a
+ ``docutils.core.Publisher`` object, then calls its ``publish``
+ method.
+
+3. The ``docutils.core.Publisher`` object's ``publish`` method checks
+ its ``settings`` attribute to see if it's defined. If it is, no
+ further runtime settings processing is done.
+
+ If ``settings`` is not defined, ``self.process_command_line`` is
+ called with the following relevant arguments:
+
+ * ``settings_spec``
+ * ``config_section``
+ * ``settings_overrides`` (in the form of excess keyword
+ arguments, collected in the ``defaults`` parameter)
+
+4. ``self.process_command_line`` calls ``self.setup_option_parser``,
+ passing ``settings_spec``, ``config_section``, and ``defaults``.
+
+5. ``self.setup_option_parser`` checks its ``config_section``
+ parameter; if defined, it adds that config file section to
+ ``settings_spec`` (or to a new, empty ``docutils.SettingsSpec``
+ object), replacing anything defined earlier. (See `Docutils
+ Configuration Files`_ for details.) Then it instantiates a new
+ ``docutils.frontend.OptionParser`` object, passing the following
+ relevant arguments:
+
+ * ``components``: A tuple of ``docutils.SettingsSpec`` objects,
+ ``(self.parser, self.reader, self.writer, settings_spec)``
+ * ``defaults`` (originally from ``settings_overrides``)
+
+6. The ``docutils.frontend.OptionParser`` object's ``__init__`` method
+ calls ``self.populate_from_components`` with ``self.components``,
+ which consists of ``self`` prepended to the ``components`` tuple it
+ received. ``self`` (``docutils.frontend.OptionParser``) defines
+ general Docutils settings.
+
+7. In ``self.populate_from_components``, for each component passed,
+ ``component.settings_spec`` is processed and
+ ``component.settings_defaults`` is applied. Then, for each
+ component, ``component.settings_default_overrides`` is applied.
+ This two-loop process ensures that
+ ``component.settings_default_overrides`` can override the default
+ settings of any other component.
+
+8. Back in ``docutils.frontend.OptionParser.__init__``, the
+ ``defaults`` parameter (derived from the ``settings_overrides``
+ parameter of ``docutils.core.Publisher.publish``) is overlaid over
+ ``self.defaults``. So ``settings_overrides`` has priority over all
+ ``SettingsSpec`` data.
+
+9. Next, ``docutils.frontend.OptionParser.__init__`` checks if
+ configuration files are enabled (its ``read_config_files``
+ parameter is true, and ``self.defaults['_disable_config']`` is
+ false). If they are enabled (and normally, they are),
+ ``self.get_standard_config_settings`` is called. This reads the
+ `docutils configuration files`_, and returns a dictionary of
+ settings. This is then overlaid on ``self.defaults``. So
+ configuration file settings have priority over all software-defined
+ defaults.
+
+10. Back in the ``docutils.core.Publisher`` object,
+ ``self.setup_option_parser`` returns the ``option_parser`` object
+ to its caller, ``self.process_command_line``.
+
+11. ``self.process_command_line`` calls ``option_parser.parse_args``,
+ which parses all command line options and returns a
+ ``docutils.frontend.Values`` object. This is assigned to the
+ ``docutils.core.Publisher`` object's ``self.settings``. So
+ command-line options have priority over configuration file
+ settings.
+
+ When ``option_parser.parse_args`` is called, the source and
+ destination command-line arguments are also parsed, and assigned
+ to the ``_source`` and ``_destination`` attributes of what becomes
+ the ``docutils.core.Publisher`` object's ``self.settings``.
+
+12. From ``docutils.core.Publisher.publish``, ``self.set_io`` is
+ called with no arguments. If either ``self.source`` or
+ ``self.destination`` are not set, the corresponding
+ ``self.set_source`` and ``self.set_destination`` are called,
+ effectively with no arguments.
+
+13. ``self.set_source`` checks for a ``source_path`` parameter, and if
+ there is none (which is the case for command-line use), it is
+ taken from ``self.settings._source``. ``self.source`` is set by
+ instantiating a ``self.source_class`` object. For command-line
+ front-end tools, the default ``self.source_class`` is used,
+ ``docutils.io.FileInput``.
+
+14. ``self.set_destination`` does the same job for the destination
+ that ``self.set_source`` does for the source (the default
+ ``self.destination_class`` is ``docutils.io.FileOutput``).
+
+.. _Docutils Configuration Files: ../user/config.html
+
+
+Runtime Settings Processing From Applications
+=============================================
+
+Applications process runtime settings in a different way than
+`command-line tools`_ do. Instead of calling ``publish_cmdline``, the
+application calls one of ``publish_file``, ``publish_string``, or
+``publish_parts``. These in turn call ``publish_programmatically``,
+which implements a generic programmatic interface. Although an
+application may also call ``publish_programmatically`` directly, it is
+not recommended (if it does seem to be necessary, please write to the
+Docutils-develop_ mailing list).
+
+``publish_programmatically`` accepts the same `convenience function
+parameters`_ as ``publish_cmdline``. Where things differ is that
+programmatic use does no command-line processing. Instead of calling
+``docutils.Publisher.process_command_line`` (as ``publish_cmdline``
+does, via ``docutils.Publisher.publish``),
+``docutils.Publisher.process_programmatic_settings`` is called to set
+up the runtime settings.
+
+.. copy & modify the list from command-line tools?
+
+
+.. _Docutils-develop: ../user/mailing-lists.html#docutils-develop
--- /dev/null
+===============================
+ Docutils_ Distributor's Guide
+===============================
+
+:Author: Lea Wiemann
+:Contact: docutils-develop@lists.sourceforge.net
+:Revision: $Revision: 8338 $
+:Date: $Date: 2019-08-26 14:09:42 +0200 (Mo, 26. Aug 2019) $
+:Copyright: This document has been placed in the public domain.
+
+.. _Docutils: http://docutils.sourceforge.net/
+
+.. contents::
+
+This document describes how to create packages of Docutils (e.g. for
+shipping with a Linux distribution). If you have any questions,
+please direct them to the Docutils-develop_ mailing list.
+
+First, please download the most current `release tarball`_ and unpack
+it.
+
+.. _Docutils-develop: ../user/mailing-lists.html#docutils-develop
+.. _release tarball: http://docutils.sourceforge.net/#download
+
+
+Dependencies
+============
+
+Docutils has the following dependencies:
+
+* Python 2.7 or later is required. Use ">= Python 2.7" in the
+ dependencies.
+
+* Docutils may optionally make use of the PIL (`Python Imaging
+ Library`_). If PIL is present, it is automatically detected by
+ Docutils.
+
+* Docutils recommends the `Pygments`_ syntax hightlighter. If available, it
+ is used for highlighting the content of `code directives`_ and roles as
+ well as included source code files (with the "code" option to the include_
+ directive).
+
+.. _Python Imaging Library: http://www.pythonware.com/products/pil/
+.. _Pygments: http://pygments.org/
+.. _code directives: ../ref/rst/directives.html#code
+.. _include: ../ref/rst/directives.html#include
+
+
+Python Files
+============
+
+The Docutils Python files must be installed into the
+``site-packages/`` directory of Python. Running ``python setup.py
+install`` should do the trick, but if you want to place the files
+yourself, you can just install the ``docutils/`` directory of the
+Docutils tarball to ``/usr/lib/python/site-packages/docutils/``. In
+this case you should also compile the Python files to ``.pyc`` and/or
+``.pyo`` files so that Docutils doesn't need to be recompiled every
+time it's executed.
+
+
+Executables
+===========
+
+The executable front-end tools are located in the ``tools/`` directory
+of the Docutils tarball.
+
+The ``rst2*.py`` tools (except ``rst2newlatex.py``) are intended for
+end-users. You should install them to ``/usr/bin/``. You do not need
+to change the names (e.g. to ``docutils-rst2html.py``) because the
+``rst2`` prefix is unique.
+
+
+Documentation
+=============
+
+The documentation should be generated using ``buildhtml.py``. To
+generate HTML for all documentation files, go to the ``tools/``
+directory and run::
+
+ # Place html4css1.css in base directory.
+ cp ../docutils/writers/html4css1/html4css1.css ..
+ ./buildhtml.py --stylesheet-path=../html4css1.css ..
+
+Then install the following files to ``/usr/share/doc/docutils/`` (or
+wherever you install documentation):
+
+* All ``.html`` and ``.txt`` files in the base directory.
+
+* The ``docs/`` directory.
+
+ Do not install the contents of the ``docs/`` directory directly to
+ ``/usr/share/doc/docutils/``; it's incomplete and would contain
+ invalid references!
+
+* The ``licenses/`` directory.
+
+* ``html4css1.css`` in the base directory.
+
+
+Removing the ``.txt`` Files
+---------------------------
+
+If you are tight with disk space, you can remove all ``.txt`` files in
+the tree except for:
+
+* those in the ``licenses/`` directory because they have not been
+ processed to HTML and
+
+* ``user/rst/cheatsheet.txt`` and ``user/rst/demo.txt``, which should
+ be readable in source form.
+
+Before you remove the ``.txt`` files you should rerun ``buildhtml.py``
+with the ``--no-source-link`` switch to avoid broken references to the
+source files.
+
+
+Other Files
+===========
+
+You may want to install the Emacs-Lisp files
+``tools/editors/emacs/*.el`` into the appropriate directory.
+
+
+Configuration File
+==================
+
+It is possible to have a system-wide configuration file at
+``/etc/docutils.conf``. However, this is usually not necessary. You
+should *not* install ``tools/docutils.conf`` into ``/etc/``.
+
+
+Tests
+=====
+
+While you probably do not need to ship the tests with your
+distribution, you can test your package by installing it and then
+running ``alltests.py`` from the ``tests/`` directory of the Docutils
+tarball.
+
+For more information on testing, view the `Docutils Testing`_ page.
+
+.. _Docutils Testing: http://docutils.sourceforge.net/docs/dev/testing.html
--- /dev/null
+===========================================
+ Plan for Enthought API Documentation Tool
+===========================================
+
+:Author: David Goodger
+:Contact: docutils-develop@lists.sourceforge.net
+:Date: $Date: 2012-01-03 20:23:53 +0100 (Di, 03. Jän 2012) $
+:Revision: $Revision: 7302 $
+:Copyright: 2004 by `Enthought, Inc. <http://www.enthought.com>`_
+:License: `Enthought License`_ (BSD-style)
+
+.. _Enthought License: http://docutils.sf.net/licenses/enthought.txt
+
+This document should be read in conjunction with the `Enthought API
+Documentation Tool RFP`__ prepared by Janet Swisher.
+
+__ enthought-rfp.html
+
+.. contents::
+.. sectnum::
+
+
+Introduction
+============
+
+In March 2004 at I met Eric Jones, president and CTO of `Enthought,
+Inc.`_, at `PyCon 2004`_ in Washington DC. He told me that Enthought
+was using reStructuredText_ for source code documentation, but they
+had some issues. He asked if I'd be interested in doing some work on
+a customized API documentation tool. Shortly after PyCon, Janet
+Swisher, Enthought's senior technical writer, contacted me to work out
+details. Some email, a trip to Austin in May, and plenty of Texas
+hospitality later, we had a project. This document will record the
+details, milestones, and evolution of the project.
+
+In a nutshell, Enthought is sponsoring the implementation of an open
+source API documentation tool that meets their needs. Fortuitously,
+their needs coincide well with the "Python Source Reader" description
+in `PEP 258`_. In other words, Enthought is funding some significant
+improvements to Docutils, improvements that were planned but never
+implemented due to time and other constraints. The implementation
+will take place gradually over several months, on a part-time basis.
+
+This is an ideal example of cooperation between a corporation and an
+open-source project. The corporation, the project, I personally, and
+the community all benefit. Enthought, whose commitment to open source
+is also evidenced by their sponsorship of SciPy_, benefits by
+obtaining a useful piece of software, much more quickly than would
+have been possible without their support. Docutils benefits directly
+from the implementation of one of its core subsystems. I benefit from
+the funding, which allows me to justify the long hours to my wife and
+family. All the corporations, projects, and individuals that make up
+the community will benefit from the end result, which will be great.
+
+All that's left now is to actually do the work!
+
+.. _PyCon 2004: http://pycon.org/dc2004/
+.. _reStructuredText: http://docutils.sf.net/rst.html
+.. _SciPy: http://www.scipy.org/
+
+
+Development Plan
+================
+
+1. Analyze prior art, most notably Epydoc_ and HappyDoc_, to see how
+ they do what they do. I have no desire to reinvent wheels
+ unnecessarily. I want to take the best ideas from each tool,
+ combined with the outline in `PEP 258`_ (which will evolve), and
+ build at least the foundation of the definitive Python
+ auto-documentation tool.
+
+ .. _Epydoc: http://epydoc.sourceforge.net/
+ .. _HappyDoc: http://happydoc.sourceforge.net/
+ .. _PEP 258:
+ http://docutils.sf.net/docs/peps/pep-0258.html#python-source-reader
+
+2. Decide on a base platform. The best way to achieve Enthought's
+ goals in a reasonable time frame may be to extend Epydoc or
+ HappyDoc. Or it may be necessary to start fresh.
+
+3. Extend the reStructuredText parser. See `Proposed Changes to
+ reStructuredText`_ below.
+
+4. Depending on the base platform chosen, build or extend the
+ docstring & doc comment extraction tool. This may be the biggest
+ part of the project, but I won't be able to break it down into
+ details until more is known.
+
+
+Repository
+==========
+
+If possible, all software and documentation files will be stored in
+the Subversion repository of Docutils and/or the base project, which
+are all publicly-available via anonymous pserver access.
+
+The Docutils project is very open about granting Subversion write
+access; so far, everyone who asked has been given access. Any
+Enthought staff member who would like Subversion write access will get
+it.
+
+If either Epydoc or HappyDoc is chosen as the base platform, I will
+ask the project's administrator for CVS access for myself and any
+Enthought staff member who wants it. If sufficient access is not
+granted -- although I doubt that there would be any problem -- we may
+have to begin a fork, which could be hosted on SourceForge, on
+Enthought's Subversion server, or anywhere else deemed appropriate.
+
+
+Copyright & License
+===================
+
+Most existing Docutils files have been placed in the public domain, as
+follows::
+
+ :Copyright: This document has been placed in the public domain.
+
+This is in conjunction with the "Public Domain Dedication" section of
+COPYING.txt__.
+
+__ http://docutils.sourceforge.net/COPYING.html
+
+The code and documentation originating from Enthought funding will
+have Enthought's copyright and license declaration. While I will try
+to keep Enthought-specific code and documentation separate from the
+existing files, there will inevitably be cases where it makes the most
+sense to extend existing files.
+
+I propose the following:
+
+1. New files related to this Enthought-funded work will be identified
+ with the following field-list headers::
+
+ :Copyright: 2004 by Enthought, Inc.
+ :License: Enthought License (BSD Style)
+
+ The license field text will be linked to the license file itself.
+
+2. For significant or major changes to an existing file (more than 10%
+ change), the headers shall change as follows (for example)::
+
+ :Copyright: 2001-2004 by David Goodger
+ :Copyright: 2004 by Enthought, Inc.
+ :License: BSD-style
+
+ If the Enthought-funded portion becomes greater than the previously
+ existing portion, Enthought's copyright line will be shown first.
+
+3. In cases of insignificant or minor changes to an existing file
+ (less than 10% change), the public domain status shall remain
+ unchanged.
+
+A section describing all of this will be added to the Docutils
+`COPYING`__ instructions file.
+
+If another project is chosen as the base project, similar changes
+would be made to their files, subject to negotiation.
+
+__ http://docutils.sf.net/COPYING.html
+
+
+Proposed Changes to reStructuredText
+====================================
+
+Doc Comment Syntax
+------------------
+
+The "traits" construct is implemented as dictionaries, where
+standalone strings would be Python syntax errors. Therefore traits
+require documentation in comments. We also need a way to
+differentiate between ordinary "internal" comments and documentation
+comments (doc comments).
+
+Javadoc uses the following syntax for doc comments::
+
+ /**
+ * The first line of a multi-line doc comment begins with a slash
+ * and *two* asterisks. The doc comment ends normally.
+ */
+
+Python doesn't have multi-line comments; only single-line. A similar
+convention in Python might look like this::
+
+ ##
+ # The first line of a doc comment begins with *two* hash marks.
+ # The doc comment ends with the first non-comment line.
+ 'data' : AnyValue,
+
+ ## The double-hash-marks could occur on the first line of text,
+ # saving a line in the source.
+ 'data' : AnyValue,
+
+How to indicate the end of the doc comment? ::
+
+ ##
+ # The first line of a doc comment begins with *two* hash marks.
+ # The doc comment ends with the first non-comment line, or another
+ # double-hash-mark.
+ ##
+ # This is an ordinary, internal, non-doc comment.
+ 'data' : AnyValue,
+
+ ## First line of a doc comment, terse syntax.
+ # Second (and last) line. Ends here: ##
+ # This is an ordinary, internal, non-doc comment.
+ 'data' : AnyValue,
+
+Or do we even need to worry about this case? A simple blank line
+could be used::
+
+ ## First line of a doc comment, terse syntax.
+ # Second (and last) line. Ends with a blank line.
+
+ # This is an ordinary, internal, non-doc comment.
+ 'data' : AnyValue,
+
+Other possibilities::
+
+ #" Instead of double-hash-marks, we could use a hash mark and a
+ # quotation mark to begin the doc comment.
+ 'data' : AnyValue,
+
+ ## We could require double-hash-marks on every line. This has the
+ ## added benefit of delimiting the *end* of the doc comment, as
+ ## well as working well with line wrapping in Emacs
+ ## ("fill-paragraph" command).
+ # Ordinary non-doc comment.
+ 'data' : AnyValue,
+
+ #" A hash mark and a quotation mark on each line looks funny, and
+ #" it doesn't work well with line wrapping in Emacs.
+ 'data' : AnyValue,
+
+These styles (repeated on each line) work well with line wrapping in
+Emacs::
+
+ ## #> #| #- #% #! #*
+
+These styles do *not* work well with line wrapping in Emacs::
+
+ #" #' #: #) #. #/ #@ #$ #^ #= #+ #_ #~
+
+The style of doc comment indicator used could be a runtime, global
+and/or per-module setting. That may add more complexity than it's
+worth though.
+
+
+Recommendation
+``````````````
+
+I recommend adopting "#*" on every line::
+
+ # This is an ordinary non-doc comment.
+
+ #* This is a documentation comment, with an asterisk after the
+ #* hash marks on every line.
+ 'data' : AnyValue,
+
+I initially recommended adopting double-hash-marks::
+
+ # This is an ordinary non-doc comment.
+
+ ## This is a documentation comment, with double-hash-marks on
+ ## every line.
+ 'data' : AnyValue,
+
+But Janet Swisher rightly pointed out that this could collide with
+ordinary comments that are then block-commented. This applies to
+double-hash-marks on the first line only as well. So they're out.
+
+On the other hand, the JavaDoc-comment style ("##" on the first line
+only, "#" after that) is used in Fredrik Lundh's PythonDoc_. It may
+be worthwhile to conform to this syntax, reinforcing it as a standard.
+PythonDoc does not support terse doc comments (text after "##" on the
+first line).
+
+.. _PythonDoc: http://effbot.org/zone/pythondoc.htm
+
+
+Update
+``````
+
+Enthought's Traits system has switched to a metaclass base, and traits
+are now defined via ordinary attributes. Therefore doc comments are
+no longer absolutely necessary; attribute docstrings will suffice.
+Doc comments may still be desirable though, since they allow
+documentation to precede the thing being documented.
+
+
+Docstring Density & Whitespace Minimization
+-------------------------------------------
+
+One problem with extensively documented classes & functions, is that
+there is a lot of screen space wasted on whitespace. Here's some
+current Enthought code (from lib/cp/fluids/gassmann.py)::
+
+ def max_gas(temperature, pressure, api, specific_gravity=.56):
+ """
+ Computes the maximum dissolved gas in oil using Batzle and
+ Wang (1992).
+
+ Parameters
+ ----------
+ temperature : sequence
+ Temperature in degrees Celsius
+ pressure : sequence
+ Pressure in MPa
+ api : sequence
+ Stock tank oil API
+ specific_gravity : sequence
+ Specific gravity of gas at STP, default is .56
+
+ Returns
+ -------
+ max_gor : sequence
+ Maximum dissolved gas in liters/liter
+
+ Description
+ -----------
+ This estimate is based on equations given by Mavko, Mukerji,
+ and Dvorkin, (1998, pp. 218-219, or 2003, p. 236) obtained
+ originally from Batzle and Wang (1992).
+ """
+ code...
+
+The docstring is 24 lines long.
+
+Rather than using subsections, field lists (which exist now) can save
+6 lines::
+
+ def max_gas(temperature, pressure, api, specific_gravity=.56):
+ """
+ Computes the maximum dissolved gas in oil using Batzle and
+ Wang (1992).
+
+ :Parameters:
+ temperature : sequence
+ Temperature in degrees Celsius
+ pressure : sequence
+ Pressure in MPa
+ api : sequence
+ Stock tank oil API
+ specific_gravity : sequence
+ Specific gravity of gas at STP, default is .56
+ :Returns:
+ max_gor : sequence
+ Maximum dissolved gas in liters/liter
+ :Description: This estimate is based on equations given by
+ Mavko, Mukerji, and Dvorkin, (1998, pp. 218-219, or 2003,
+ p. 236) obtained originally from Batzle and Wang (1992).
+ """
+ code...
+
+As with the "Description" field above, field bodies may begin on the
+same line as the field name, which also saves space.
+
+The output for field lists is typically a table structure. For
+example:
+
+ :Parameters:
+ temperature : sequence
+ Temperature in degrees Celsius
+ pressure : sequence
+ Pressure in MPa
+ api : sequence
+ Stock tank oil API
+ specific_gravity : sequence
+ Specific gravity of gas at STP, default is .56
+ :Returns:
+ max_gor : sequence
+ Maximum dissolved gas in liters/liter
+ :Description:
+ This estimate is based on equations given by Mavko,
+ Mukerji, and Dvorkin, (1998, pp. 218-219, or 2003, p. 236)
+ obtained originally from Batzle and Wang (1992).
+
+But the definition lists describing the parameters and return values
+are still wasteful of space. There are a lot of half-filled lines.
+
+Definition lists are currently defined as::
+
+ term : classifier
+ definition
+
+Where the classifier part is optional. Ideas for improvements:
+
+1. We could allow multiple classifiers::
+
+ term : classifier one : two : three ...
+ definition
+
+2. We could allow the definition on the same line as the term, using
+ some embedded/inline markup:
+
+ * "--" could be used, but only in limited and well-known contexts::
+
+ term -- definition
+
+ This is the syntax used by StructuredText (one of
+ reStructuredText's predecessors). It was not adopted for
+ reStructuredText because it is ambiguous -- people often use "--"
+ in their text, as I just did. But given a constrained context,
+ the ambiguity would be acceptable (or would it?). That context
+ would be: in docstrings, within a field list, perhaps only with
+ certain well-defined field names (parameters, returns).
+
+ * The "constrained context" above isn't really enough to make the
+ ambiguity acceptable. Instead, a slightly more verbose but far
+ less ambiguous syntax is possible::
+
+ term === definition
+
+ This syntax has advantages. Equals signs lend themselves to the
+ connotation of "definition". And whereas one or two equals signs
+ are commonly used in program code, three equals signs in a row
+ have no conflicting meanings that I know of. (Update: there
+ *are* uses out there.)
+
+ The problem with this approach is that using inline markup for
+ structure is inherently ambiguous in reStructuredText. For
+ example, writing *about* definition lists would be difficult::
+
+ ``term === definition`` is an example of a compact definition list item
+
+ The parser checks for structural markup before it does inline
+ markup processing. But the "===" should be protected by its inline
+ literal context.
+
+3. We could allow the definition on the same line as the term, using
+ structural markup. A variation on bullet lists would work well::
+
+ : term :: definition
+ : another term :: and a definition that
+ wraps across lines
+
+ Some ambiguity remains::
+
+ : term ``containing :: double colons`` :: definition
+
+ But the likelihood of such cases is negligible, and they can be
+ covered in the documentation.
+
+ Other possibilities for the definition delimiter include::
+
+ : term : classifier -- definition
+ : term : classifier --- definition
+ : term : classifier : : definition
+ : term : classifier === definition
+
+The third idea currently has the best chance of being adopted and
+implemented.
+
+
+Recommendation
+``````````````
+
+Combining these ideas, the function definition becomes::
+
+ def max_gas(temperature, pressure, api, specific_gravity=.56):
+ """
+ Computes the maximum dissolved gas in oil using Batzle and
+ Wang (1992).
+
+ :Parameters:
+ : temperature : sequence :: Temperature in degrees Celsius
+ : pressure : sequence :: Pressure in MPa
+ : api : sequence :: Stock tank oil API
+ : specific_gravity : sequence :: Specific gravity of gas at
+ STP, default is .56
+ :Returns:
+ : max_gor : sequence :: Maximum dissolved gas in liters/liter
+ :Description: This estimate is based on equations given by
+ Mavko, Mukerji, and Dvorkin, (1998, pp. 218-219, or 2003,
+ p. 236) obtained originally from Batzle and Wang (1992).
+ """
+ code...
+
+The docstring is reduced to 14 lines, from the original 24. For
+longer docstrings with many parameters and return values, the
+difference would be more significant.
--- /dev/null
+==================================
+ Enthought API Documentation Tool
+==================================
+-----------------------
+ Request for Proposals
+-----------------------
+
+:Author: Janet Swisher, Senior Technical Writer
+:Organization: `Enthought, Inc. <http://www.enthought.com>`_
+:Copyright: 2004 by Enthought, Inc.
+:License: `Enthought License`_ (BSD Style)
+
+.. _Enthought License: http://docutils.sf.net/licenses/enthought.txt
+
+The following is excerpted from the full RFP, and is published here
+with permission from `Enthought, Inc.`_ See the `Plan for Enthought
+API Documentation Tool`__.
+
+__ enthought-plan.html
+
+.. contents::
+.. sectnum::
+
+
+Requirements
+============
+
+The documentation tool will address the following high-level goals:
+
+
+Documentation Extraction
+------------------------
+
+1. Documentation will be generated directly from Python source code,
+ drawing from the code structure, docstrings, and possibly other
+ comments.
+
+2. The tool will extract logical constructs as appropriate, minimizing
+ the need for comments that are redundant with the code structure.
+ The output should reflect both documented and undocumented
+ elements.
+
+
+Source Format
+-------------
+
+1. The docstrings will be formatted in as terse syntax as possible.
+ Required tags, syntax, and white space should be minimized.
+
+2. The tool must support the use of Traits. Special comment syntax
+ for Traits may be necessary. Information about the Traits package
+ is available at http://code.enthought.com/traits/. In the
+ following example, each trait definition is prefaced by a plain
+ comment::
+
+ __traits__ = {
+
+ # The current selection within the frame.
+ 'selection' : Trait([], TraitInstance(list)),
+
+ # The frame has been activated or deactivated.
+ 'activated' : TraitEvent(),
+
+ 'closing' : TraitEvent(),
+
+ # The frame is closed.
+ 'closed' : TraitEvent(),
+ }
+
+3. Support for ReStructuredText (ReST) format is desirable, because
+ much of the existing docstrings uses ReST. However, the complete
+ ReST specification need not be supported, if a subset can achieve
+ the project goals. If the tool does not support ReST, the
+ contractor should also provide a tool or path to convert existing
+ docstrings.
+
+
+Output Format
+-------------
+
+1. Documentation will be output as a navigable suite of HTML
+ files.
+
+2. The style of the HTML files will be customizable by a cascading
+ style sheet and/or a customizable template.
+
+3. Page elements such as headers and footer should be customizable, to
+ support differing requirements from one documentation project to
+ the next.
+
+
+Output Structure and Navigation
+-------------------------------
+
+1. The navigation scheme for the HTML files should not rely on frames,
+ and should harmonize with conversion to Microsoft HTML Help (.chm)
+ format.
+
+2. The output should be structured to make navigable the architecture
+ of the Python code. Packages, modules, classes, traits, and
+ functions should be presented in clear, logical hierarchies.
+ Diagrams or trees for inheritance, collaboration, sub-packaging,
+ etc. are desirable but not required.
+
+3. The output must include indexes that provide a comprehensive view
+ of all packages, modules, and classes. These indexes will provide
+ readers with a clear and exhaustive view of the code base. These
+ indexes should be presented in a way that is easily accessible and
+ allows easy navigation.
+
+4. Cross-references to other documented elements will be used
+ throughout the documentation, to enable the reader to move quickly
+ relevant information. For example, where type information for an
+ element is available, the type definition should be
+ cross-referenced.
+
+5. The HTML suite should provide consistent navigation back to the
+ home page, which will include the following information:
+
+ * Bibliographic information
+
+ - Author
+ - Copyright
+ - Release date
+ - Version number
+
+ * Abstract
+
+ * References
+
+ - Links to related internal docs (i.e., other docs for the same
+ product)
+
+ - Links to related external docs (e.g., supporting development
+ docs, Python support docs, docs for included packages)
+
+ It should be possible to specify similar information at the top
+ level of each package, so that packages can be included as
+ appropriate for a given application.
+
+
+License
+=======
+
+Enthought intends to release the software under an open-source
+("BSD-style") license.
--- /dev/null
+==========================
+ Docutils_ Hacker's Guide
+==========================
+
+:Author: Lea Wiemann
+:Contact: docutils-develop@lists.sourceforge.net
+:Revision: $Revision: 7302 $
+:Date: $Date: 2012-01-03 20:23:53 +0100 (Di, 03. Jän 2012) $
+:Copyright: This document has been placed in the public domain.
+
+:Abstract: This is the introduction to Docutils for all persons who
+ want to extend Docutils in some way.
+:Prerequisites: You have used reStructuredText_ and played around with
+ the `Docutils front-end tools`_ before. Some (basic) Python
+ knowledge is certainly helpful (though not necessary, strictly
+ speaking).
+
+.. _Docutils: http://docutils.sourceforge.net/
+.. _reStructuredText: http://docutils.sourceforge.net/rst.html
+.. _Docutils front-end tools: ../user/tools.html
+
+.. contents::
+
+
+Overview of the Docutils Architecture
+=====================================
+
+To give you an understanding of the Docutils architecture, we'll dive
+right into the internals using a practical example.
+
+Consider the following reStructuredText file::
+
+ My *favorite* language is Python_.
+
+ .. _Python: http://www.python.org/
+
+Using the ``rst2html.py`` front-end tool, you would get an HTML output
+which looks like this::
+
+ [uninteresting HTML code removed]
+ <body>
+ <div class="document">
+ <p>My <em>favorite</em> language is <a class="reference" href="http://www.python.org/">Python</a>.</p>
+ </div>
+ </body>
+ </html>
+
+While this looks very simple, it's enough to illustrate all internal
+processing stages of Docutils. Let's see how this document is
+processed from the reStructuredText source to the final HTML output:
+
+
+Reading the Document
+--------------------
+
+The **Reader** reads the document from the source file and passes it
+to the parser (see below). The default reader is the standalone
+reader (``docutils/readers/standalone.py``) which just reads the input
+data from a single text file. Unless you want to do really fancy
+things, there is no need to change that.
+
+Since you probably won't need to touch readers, we will just move on
+to the next stage:
+
+
+Parsing the Document
+--------------------
+
+The **Parser** analyzes the the input document and creates a **node
+tree** representation. In this case we are using the
+**reStructuredText parser** (``docutils/parsers/rst/__init__.py``).
+To see what that node tree looks like, we call ``quicktest.py`` (which
+can be found in the ``tools/`` directory of the Docutils distribution)
+with our example file (``test.txt``) as first parameter (Windows users
+might need to type ``python quicktest.py test.txt``)::
+
+ $ quicktest.py test.txt
+ <document source="test.txt">
+ <paragraph>
+ My
+ <emphasis>
+ favorite
+ language is
+ <reference name="Python" refname="python">
+ Python
+ .
+ <target ids="python" names="python" refuri="http://www.python.org/">
+
+Let us now examine the node tree:
+
+The top-level node is ``document``. It has a ``source`` attribute
+whose value is ``text.txt``. There are two children: A ``paragraph``
+node and a ``target`` node. The ``paragraph`` in turn has children: A
+text node ("My "), an ``emphasis`` node, a text node (" language is "),
+a ``reference`` node, and again a ``Text`` node (".").
+
+These node types (``document``, ``paragraph``, ``emphasis``, etc.) are
+all defined in ``docutils/nodes.py``. The node types are internally
+arranged as a class hierarchy (for example, both ``emphasis`` and
+``reference`` have the common superclass ``Inline``). To get an
+overview of the node class hierarchy, use epydoc (type ``epydoc
+nodes.py``) and look at the class hierarchy tree.
+
+
+Transforming the Document
+-------------------------
+
+In the node tree above, the ``reference`` node does not contain the
+target URI (``http://www.python.org/``) yet.
+
+Assigning the target URI (from the ``target`` node) to the
+``reference`` node is *not* done by the parser (the parser only
+translates the input document into a node tree).
+
+Instead, it's done by a **Transform**. In this case (resolving a
+reference), it's done by the ``ExternalTargets`` transform in
+``docutils/transforms/references.py``.
+
+In fact, there are quite a lot of Transforms, which do various useful
+things like creating the table of contents, applying substitution
+references or resolving auto-numbered footnotes.
+
+The Transforms are applied after parsing. To see how the node tree
+has changed after applying the Transforms, we use the
+``rst2pseudoxml.py`` tool:
+
+.. parsed-literal::
+
+ $ rst2pseudoxml.py test.txt
+ <document source="test.txt">
+ <paragraph>
+ My
+ <emphasis>
+ favorite
+ language is
+ <reference name="Python" **refuri="http://www.python.org/"**>
+ Python
+ .
+ <target ids="python" names="python" ``refuri="http://www.python.org/"``>
+
+For our small test document, the only change is that the ``refname``
+attribute of the reference has been replaced by a ``refuri``
+attribute |---| the reference has been resolved.
+
+While this does not look very exciting, transforms are a powerful tool
+to apply any kind of transformation on the node tree.
+
+By the way, you can also get a "real" XML representation of the node
+tree by using ``rst2xml.py`` instead of ``rst2pseudoxml.py``.
+
+
+Writing the Document
+--------------------
+
+To get an HTML document out of the node tree, we use a **Writer**, the
+HTML writer in this case (``docutils/writers/html4css1.py``).
+
+The writer receives the node tree and returns the output document.
+For HTML output, we can test this using the ``rst2html.py`` tool::
+
+ $ rst2html.py --link-stylesheet test.txt
+ <?xml version="1.0" encoding="utf-8" ?>
+ <!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">
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+ <meta name="generator" content="Docutils 0.3.10: http://docutils.sourceforge.net/" />
+ <title></title>
+ <link rel="stylesheet" href="../docutils/writers/html4css1/html4css1.css" type="text/css" />
+ </head>
+ <body>
+ <div class="document">
+ <p>My <em>favorite</em> language is <a class="reference" href="http://www.python.org/">Python</a>.</p>
+ </div>
+ </body>
+ </html>
+
+So here we finally have our HTML output. The actual document contents
+are in the fourth-last line. Note, by the way, that the HTML writer
+did not render the (invisible) ``target`` node |---| only the
+``paragraph`` node and its children appear in the HTML output.
+
+
+Extending Docutils
+==================
+
+Now you'll ask, "how do I actually extend Docutils?"
+
+First of all, once you are clear about *what* you want to achieve, you
+have to decide *where* to implement it |---| in the Parser (e.g. by
+adding a directive or role to the reStructuredText parser), as a
+Transform, or in the Writer. There is often one obvious choice among
+those three (Parser, Transform, Writer). If you are unsure, ask on
+the Docutils-develop_ mailing list.
+
+In order to find out how to start, it is often helpful to look at
+similar features which are already implemented. For example, if you
+want to add a new directive to the reStructuredText parser, look at
+the implementation of a similar directive in
+``docutils/parsers/rst/directives/``.
+
+
+Modifying the Document Tree Before It Is Written
+------------------------------------------------
+
+You can modify the document tree right before the writer is called.
+One possibility is to use the publish_doctree_ and
+publish_from_doctree_ functions.
+
+To retrieve the document tree, call::
+
+ document = docutils.core.publish_doctree(...)
+
+Please see the docstring of publish_doctree for a list of parameters.
+
+.. XXX Need to write a well-readable list of (commonly used) options
+ of the publish_* functions. Probably in api/publisher.txt.
+
+``document`` is the root node of the document tree. You can now
+change the document by accessing the ``document`` node and its
+children |---| see `The Node Interface`_ below.
+
+When you're done with modifying the document tree, you can write it
+out by calling::
+
+ output = docutils.core.publish_from_doctree(document, ...)
+
+.. _publish_doctree: ../api/publisher.html#publish_doctree
+.. _publish_from_doctree: ../api/publisher.html#publish_from_doctree
+
+
+The Node Interface
+------------------
+
+As described in the overview above, Docutils' internal representation
+of a document is a tree of nodes. We'll now have a look at the
+interface of these nodes.
+
+(To be completed.)
+
+
+What Now?
+=========
+
+This document is not complete. Many topics could (and should) be
+covered here. To find out with which topics we should write about
+first, we are awaiting *your* feedback. So please ask your questions
+on the Docutils-develop_ mailing list.
+
+
+.. _Docutils-develop: ../user/mailing-lists.html#docutils-develop
+
+
+.. |---| unicode:: 8212 .. em-dash
+ :trim:
+
+\f
+..
+ Local Variables:
+ mode: indented-text
+ indent-tabs-mode: nil
+ sentence-end-double-space: t
+ fill-column: 70
+ End:
--- /dev/null
+===========================
+ Docutils Project Policies
+===========================
+
+:Author: David Goodger; open to all Docutils developers
+:Contact: docutils-develop@lists.sourceforge.net
+:Date: $Date: 2017-08-18 18:44:27 +0200 (Fr, 18. Aug 2017) $
+:Revision: $Revision: 8173 $
+:Copyright: This document has been placed in the public domain.
+
+.. contents::
+
+The Docutils project group is a meritocracy based on code contribution
+and lots of discussion [#bcs]_. A few quotes sum up the policies of
+the Docutils project. The IETF's classic credo (by MIT professor Dave
+Clark) is an ideal we can aspire to:
+
+ We reject: kings, presidents, and voting. We believe in: rough
+ consensus and running code.
+
+As architect, chief cook and bottle-washer, David Goodger currently
+functions as BDFN (Benevolent Dictator For Now). (But he would
+happily abdicate the throne given a suitable candidate. Any takers?)
+
+Eric S. Raymond, anthropologist of the hacker subculture, writes in
+his essay `The Magic Cauldron`_:
+
+ The number of contributors [to] projects is strongly and inversely
+ correlated with the number of hoops each project makes a user go
+ through to contribute.
+
+We will endeavour to keep the barrier to entry as low as possible.
+The policies below should not be thought of as barriers, but merely as
+a codification of experience to date. These are "best practices";
+guidelines, not absolutes. Exceptions are expected, tolerated, and
+used as a source of improvement. Feedback and criticism is welcome.
+
+As for control issues, Emmett Plant (CEO of the Xiph.org Foundation,
+originators of Ogg Vorbis) put it well when he said:
+
+ Open source dictates that you lose a certain amount of control
+ over your codebase, and that's okay with us.
+
+.. [#bcs] Phrase borrowed from `Ben Collins-Sussman of the Subversion
+ project <http://www.red-bean.com/sussman/svn-anti-fud.html>`__.
+
+.. _The Magic Cauldron:
+ http://www.catb.org/~esr/writings/magic-cauldron/
+
+
+How to get a new feature into Docutils
+========================================
+
+Question:
+ I would very much like to have this new feature in the Docutils core.
+ What exactly do I have to do to make this possible?
+
+* Present your idea at the Docutils-develop_ mailing list,
+
+ +1 usually triggers a fast response,
+ -1 may be forgotten later,
+
+ and/or file a ticket at Docutils' `feature request tracker`_.
+
+ +1 there is a permanent record,
+ -1 it may stay forgotten among all the other feature requests.
+
+* Convince a Docutils developer that this is a valuable addition worth the
+ effort.
+
+* Contribute. The developers will make sure that the contribution fits
+ nicely into Docutils (cf. the `review criteria`_). This might involve
+ discussing (and compromising on) design and implementation details. It
+ might also lead to the conclusion that the addition fits better in the
+ `extensions and related projects`_.
+
+* Be patient, and be persistent. None of us are paid to do this,
+ it's all in our spare time -- which is precious and rare.
+
+How to make code contributions that are easily accepted:
+
+* Have a look at the `Python coding conventions`_ and `documentation
+ conventions`_ below.
+
+* **Prepare test cases.** This vastly helps when integrating new code. Test
+ cases are also examples and showcases for new features. See `Docutils
+ Testing`_ for a description of the test suite in ``docutils/test/``.
+
+ Ensure the addition works with all `supported Python versions`__.
+
+ __ ../../README.html#requirements
+
+* Look at the Docutils sources to see how similar features are implemented,
+ learn to do it "the Docutils way".
+
+* Prepare the a patch or an addition to the existing documentation.
+ Include links.
+
+* If you are familiar with version control, consider creating a `feature
+ branch`_ in a Docutils repository_ checkout. (Working with branches is
+ *much* easier with git_. You can get a git clone of the repository from
+ http://repo.or.cz/w/docutils.git or with git-svn.)
+
+.. _docutils-develop: ../user/mailing-lists.html#docutils-develop
+.. _feature request tracker:
+ http://sourceforge.net/p/docutils/feature-requests/
+
+.. _git: http://git-scm.com/
+.. _Docutils testing: testing.html
+
+
+Python Coding Conventions
+=========================
+
+Contributed code will not be refused merely because it does not
+strictly adhere to these conditions; as long as it's internally
+consistent, clean, and correct, it probably will be accepted. But
+don't be surprised if the "offending" code gets fiddled over time to
+conform to these conventions.
+
+The Docutils project shall follow the generic coding conventions as
+specified in the `Style Guide for Python Code`_ and `Docstring
+Conventions`_ PEPs, summarized, clarified, and extended as follows:
+
+* 4 spaces per indentation level. No hard tabs.
+
+* Use only 7-bit ASCII, no 8-bit strings. See `Docutils
+ Internationalization`_.
+
+* No one-liner compound statements (i.e., no ``if x: return``: use two
+ lines & indentation), except for degenerate class or method
+ definitions (i.e., ``class X: pass`` is OK.).
+
+* Lines should be no more than 78 characters long.
+
+* Use "StudlyCaps" for class names (except for element classes in
+ docutils.nodes).
+
+* Use "lowercase" or "lowercase_with_underscores" for function,
+ method, and variable names. For short names, maximum two words,
+ joined lowercase may be used (e.g. "tagname"). For long names with
+ three or more words, or where it's hard to parse the split between
+ two words, use lowercase_with_underscores (e.g.,
+ "note_explicit_target", "explicit_target"). If in doubt, use
+ underscores.
+
+* Avoid lambda expressions, which are inherently difficult to
+ understand. Named functions are preferable and superior: they're
+ faster (no run-time compilation), and well-chosen names serve to
+ document and aid understanding.
+
+* Avoid functional constructs (filter, map, etc.). Use list
+ comprehensions instead.
+
+* Avoid ``from __future__ import`` constructs. They are inappropriate
+ for production code.
+
+* Use 'single quotes' for string literals, and """triple double
+ quotes""" for docstrings.
+
+.. _Style Guide for Python Code:
+ http://www.python.org/peps/pep-0008.html
+.. _Docstring Conventions: http://www.python.org/peps/pep-0257.html
+.. _Docutils Internationalization: ../howto/i18n.html#python-code
+
+
+Documentation Conventions
+=========================
+
+* Docutils documentation is written using reStructuredText, of course.
+
+* Use 7-bit ASCII if at all possible, and Unicode substitutions when
+ necessary.
+
+* Use the following section title adornment styles::
+
+ ================
+ Document Title
+ ================
+
+ --------------------------------------------
+ Document Subtitle, or Major Division Title
+ --------------------------------------------
+
+ Section
+ =======
+
+ Subsection
+ ----------
+
+ Sub-Subsection
+ ``````````````
+
+ Sub-Sub-Subsection
+ ..................
+
+* Use two blank lines before each section/subsection/etc. title. One
+ blank line is sufficient between immediately adjacent titles.
+
+* Add a bibliographic field list immediately after the document
+ title/subtitle. See the beginning of this document for an example.
+
+* Add an Emacs "local variables" block in a comment at the end of the
+ document. See the end of this document for an example.
+
+
+Copyrights and Licensing
+========================
+
+The majority of the Docutils project code and documentation has been
+placed in the public domain. Unless clearly and explicitly indicated
+otherwise, any patches (modifications to existing files) submitted to
+the project for inclusion (via Subversion, SourceForge trackers,
+mailing lists, or private email) are assumed to be in the public
+domain as well.
+
+Any new files contributed to the project should clearly state their
+intentions regarding copyright, in one of the following ways:
+
+* Public domain (preferred): include the statement "This
+ module/document has been placed in the public domain."
+
+* Copyright & open source license: include a copyright notice, along
+ with either an embedded license statement, a reference to an
+ accompanying license file, or a license URL.
+
+ The license should be well known, simple and compatible with other
+ open source software licenses. To keep the number of different
+ licenses at a minimum, using the `2-Clause BSD license`_
+ is recommended.
+
+2-Clause BSD license
+--------------------
+
+(also known as "Simplified" or `FreeBSD license`)
+
+ If you want a simple, permissive non-copyleft free software license, the
+ FreeBSD license is a reasonable choice. However, please don't call it a
+ “BSD” or “BSD-style” license, because that is likely to cause confusion
+ which could lead to use of the flawed original BSD license.
+
+ -- `Various Licenses and Comments about Them`_
+
+Pros:
+ * clear wording, structured text
+ * license used by the closely related Sphinx project
+ * "2-Clause BSD license" is a non-ambiguous name, used by both, OSI and
+ GNU.
+
+References:
+ * http://www.freebsd.org/copyright/freebsd-license.html
+ * http://www.opensource.org/licenses/BSD-2-Clause
+ * http://www.spdx.org/licenses/BSD-2-Clause
+
+.. _Various Licenses and Comments about Them:
+ http://www.gnu.org/licenses/license-list.html
+.. _OSI Approved Licenses: http://www.opensource.org/licenses/category
+.. _SPDX Open Source License Registry: http://www.spdx.org/licenses/
+
+
+.. _Subversion Repository:
+
+Repository
+==========
+
+Please see the `repository documentation`_ for details on how to
+access Docutils' Subversion repository. Anyone can access the
+repository anonymously. Only project developers can make changes.
+(If you would like to become a project developer, just ask!) Also see
+`Setting Up For Docutils Development`_ below for some useful info.
+
+Unless you really *really* know what you're doing, please do *not* use
+``svn import``. It's quite easy to mess up the repository with an
+import.
+
+.. _repository documentation: repository.html
+
+
+Branches
+--------
+
+(These branch policies go into effect with Docutils 0.4.)
+
+The "docutils" directory of the **trunk** (a.k.a. the **Docutils
+core**) is used for active -- but stable, fully tested, and reviewed
+-- development.
+
+If we need to cut a bugfix release, we'll create a **maintenance branch**
+based on the latest feature release. For example, when Docutils 0.5 is
+released, this would be ``branches/docutils-0.5``, and any existing 0.4.x
+maintenance branches may be retired. Maintenance branches will receive bug
+fixes only; no new features will be allowed here.
+
+Obvious and uncontroversial bug fixes *with tests* can be checked in
+directly to the core and to the maintenance branches. Don't forget to
+add test cases! Many (but not all) bug fixes will be applicable both
+to the core and to the maintenance branches; these should be applied
+to both. No patches or dedicated branches are required for bug fixes,
+but they may be used. It is up to the discretion of project
+developers to decide which mechanism to use for each case.
+
+.. _feature branches:
+.. _feature branch:
+
+Feature additions and API changes will be done in **feature
+branches**. Feature branches will not be managed in any way.
+Frequent small checkins are encouraged here. Feature branches must be
+discussed on the `docutils-develop mailing list`_ and reviewed before
+being merged into the core.
+
+.. _docutils-develop mailing list:
+ http://lists.sourceforge.net/lists/listinfo/docutils-develop
+
+
+Review Criteria
+```````````````
+
+Before a new feature, an API change, or a complex, disruptive, or
+controversial bug fix can be checked in to the core or into a
+maintenance branch, it must undergo review. These are the criteria:
+
+* The branch must be complete, and include full documentation and
+ tests.
+
+* There should ideally be one branch merge commit per feature or
+ change. In other words, each branch merge should represent a
+ coherent change set.
+
+* The code must be stable and uncontroversial. Moving targets and
+ features under debate are not ready to be merged.
+
+* The code must work. The test suite must complete with no failures.
+ See `Docutils Testing`_.
+
+The review process will ensure that at least one other set of eyeballs
+& brains sees the code before it enters the core. In addition to the
+above, the general `Check-ins`_ policy (below) also applies.
+
+
+Check-ins
+---------
+
+Changes or additions to the Docutils core and maintenance branches
+carry a commitment to the Docutils user community. Developers must be
+prepared to fix and maintain any code they have committed.
+
+The Docutils core (``trunk/docutils`` directory) and maintenance
+branches should always be kept in a stable state (usable and as
+problem-free as possible). All changes to the Docutils core or
+maintenance branches must be in `good shape`_, usable_, documented_,
+tested_, and `reasonably complete`_.
+
+* _`Good shape` means that the code is clean, readable, and free of
+ junk code (unused legacy code; by analogy to "junk DNA").
+
+* _`Usable` means that the code does what it claims to do. An "XYZ
+ Writer" should produce reasonable XYZ output.
+
+* _`Documented`: The more complete the documentation the better.
+ Modules & files must be at least minimally documented internally.
+ `Docutils Front-End Tools`_ should have a new section for any
+ front-end tool that is added. `Docutils Configuration Files`_
+ should be modified with any settings/options defined. For any
+ non-trivial change, the HISTORY.txt_ file should be updated.
+
+* _`Tested` means that unit and/or functional tests, that catch all
+ bugs fixed and/or cover all new functionality, have been added to
+ the test suite. These tests must be checked by running the test
+ suite under all supported Python versions, and the entire test suite
+ must pass. See `Docutils Testing`_.
+
+* _`Reasonably complete` means that the code must handle all input.
+ Here "handle" means that no input can cause the code to fail (cause
+ an exception, or silently and incorrectly produce nothing).
+ "Reasonably complete" does not mean "finished" (no work left to be
+ done). For example, a writer must handle every standard element
+ from the Docutils document model; for unimplemented elements, it
+ must *at the very least* warn that "Output for element X is not yet
+ implemented in writer Y".
+
+If you really want to check code directly into the Docutils core,
+you can, but you must ensure that it fulfills the above criteria
+first. People will start to use it and they will expect it to work!
+If there are any issues with your code, or if you only have time for
+gradual development, you should put it on a branch or in the sandbox
+first. It's easy to move code over to the Docutils core once it's
+complete.
+
+It is the responsibility and obligation of all developers to keep the
+Docutils core and maintenance branches stable. If a commit is made to
+the core or maintenance branch which breaks any test, the solution is
+simply to revert the change. This is not vindictive; it's practical.
+We revert first, and discuss later.
+
+Docutils will pursue an open and trusting policy for as long as
+possible, and deal with any aberrations if (and hopefully not when)
+they happen. We'd rather see a torrent of loose contributions than
+just a trickle of perfect-as-they-stand changes. The occasional
+mistake is easy to fix. That's what version control is for!
+
+.. _Docutils Front-End Tools: ../user/tools.html
+.. _Docutils Configuration Files: ../user/config.html
+.. _HISTORY.txt: ../../HISTORY.txt
+
+
+.. _`Version Numbering`:
+
+Version Identification
+======================
+
+The state of development of the current Docutils codebase is stored in
+two forms: a `docutils.__version_info__`_ namedtuple, and a
+`docutils.__version__`_ text string.
+
+See also the `Docutils Release Procedure`_, and
+``docutils.__version__`` & ``docutils.__version_info__`` in
+docutils/__init__.py.
+
+.. _Docutils Release Procedure: release.html#version-numbers
+
+
+``docutils.__version_info__``
+-----------------------------
+
+Detailed version information is available in
+``docutils.__version_info__``, an instance of the namedtuple_
+``docutils.VersionInfo``. It is modelled on `sys.version_info`_ and
+has the following attributes:
+
+major : non-negative integer
+ **Major releases** (x.0, e.g. 1.0) will be rare, and will
+ represent major changes in API, functionality, or commitment. The
+ major number will be bumped to 1 when the project is
+ feature-complete, and may be incremented later if there is a major
+ change in the design or API. When Docutils reaches version 1.0,
+ the major APIs will be considered frozen and backward
+ compatibility will become of paramount importance.
+
+minor : non-negative integer
+ Releases that change the minor number (x.y, e.g. 0.5) will be
+ **feature releases**; new features from the `Docutils core`_ will
+ be included.
+
+micro : non-negative integer
+ Releases that change the micro number (x.y.z, e.g. 0.4.1) will be
+ **bug-fix releases**. No new features will be introduced in these
+ releases; only bug fixes will be included. The micro number is
+ omitted from ``docutils.__version__`` when micro=0.
+
+releaselevel : text string
+ The release level indicates the `development status`_ (or phase)
+ of the project's codebase:
+
+ ============= ======= ============================================
+ Release Level Label Description
+ ============= ======= ============================================
+ alpha ``a`` Reserved for use after major experimental
+ changes, to indicate an unstable codebase.
+
+ beta ``b`` Indicates active development, between releases.
+ Used with serial = 0.
+
+ candidate ``rcN`` Release candidate: indicates that the
+ codebase is ready to release unless
+ significant bugs emerge.
+ Serial N starts at 1.
+
+ final Indicates an official project release.
+ There is no pre-release segment for final
+ releases (no label).
+ ============= ======= ============================================
+
+ The abbreviations in the "Label" column are used in the
+ `docutils.__version__`_ identifier text.
+
+ .. _development status:
+ https://en.wikipedia.org/wiki/Software_release_life_cycle
+
+serial : non-negative integer
+ The serial number is incremented whenever a new pre-release is
+ begun.
+
+release : boolean
+ True for official releases and pre-releases, False during
+ development.
+
+One of *{major, minor, micro}* is incremented after each official
+release, and the lower-order numbers are reset to 0.
+
+The default state of the repository during active development and
+between releases is: release level "beta", serial = 0, release =
+False.
+
+``docutils.__version_info__`` can be used to test for a minimally
+required version, e.g.::
+
+ comparison_version = docutils.VersionInfo(
+ major=0, minor=13, micro=0,
+ releaselevel='candidate', serial=2, release=True)
+ if docutils.__version_info__ >= comparison_version:
+ ...
+
+For practical purposes it may suffice to test against a truncated tuple,
+e.g.::
+
+ if docutils.__version_info__ >= (0, 13)
+
+is True for all versions "larger" than ``"0.13"``.
+
+Mind, however, that a test like ::
+
+ if docutils.__version_info__ > (0, 14)
+
+is True also for development versions and pre-releases of the 0.14 series
+although, according to PEP 440, these must be sorted before 0.14.
+
+.. _namedtuple: https://docs.python.org/3/library/collections.html#collections.namedtuple
+.. _sys.version_info: https://docs.python.org/3/library/sys.html#version-info
+
+
+``docutils.__version__``
+------------------------
+
+``docutils.__version__`` contains the version identifier as a text
+string: a concise, `PEP 440`_-conforming representation of
+``docutils.__version_info__``.
+
+For version comparison operations, use `docutils.__version_info__`_.
+Do not parse the text of ``docutils.__version__``.
+
+``docutils.__version__`` takes the following form::
+
+ <major>.<minor>[.<micro>][<releaselevel>[<serial>]][.dev]
+ <--- release segment ---><-- pre-release segment -><- development ->
+
+.. _PEP 440: https://www.python.org/dev/peps/pep-0440/
+
+* The abbreviated forms of each release level, found in the "Label"
+ column in the table above ("a" or "b" or "rc"), are used in the
+ pre-release segment.
+
+* When the serial number is 0, it is omitted from the pre-release
+ segment.
+
+* The development segment is present during active development (as
+ "``.dev``", when ``docutils.__version_info__.release`` is False),
+ and absent for official releases and pre-releases (when
+ ``docutils.__version_info__.release`` is True).
+
+Examples of ``docutils.__version__`` identifiers, over the course of
+normal development (without branches), in ascending order:
+
+====================== ============================
+Release Level Version Identifier
+====================== ============================
+final (release) 0.14
+beta (development) 0.15b.dev [2]_
+beta (release) 0.15b [1]_
+candidate 1 (dev.) 0.15rc1.dev
+candidate 1 (release) 0.15rc1
+candidate 2 (dev.) 0.15rc2.dev [1]_
+candidate 2 (release) 0.15rc2 [1]_
+... candidate N 0.15rcN.dev [1]_, 0.15rcN [1]_
+final (release) 0.15
+beta (dev.) 0.16b.dev [2]_
+====================== ============================
+
+.. [1] These steps may be skipped.
+
+.. [2] Default active development state between releases.
+
+
+Policy History
+--------------
+
+* Prior to version 0.4, Docutils didn't have an official version
+ numbering policy, and micro releases contained both bug fixes and
+ new features.
+
+* An earlier version of this policy was adopted in October 2005, and
+ took effect with Docutils version 0.4.
+
+* This policy was updated in June 2017 for Docutils version 0.14. See
+ `Feature Request #50`_ and the `discussion on docutils-devel`__ from
+ May 28 to June 20 2017.
+
+ .. _Feature Request #50:
+ https://sourceforge.net/p/docutils/feature-requests/50/
+ __ https://sourceforge.net/p/docutils/mailman/message/35903816/
+
+
+Snapshots
+=========
+
+Snapshot tarballs can be downloaded from the repository (see the "download
+snapshot" button in the head of the code listing table).
+
+* the `Docutils core`_, representing the current cutting-edge state of
+ development;
+
+* the `sandbox directory`_ with contributed projects and extensions from
+ `the Sandbox`_;
+
+.. * maintenance branches, for bug fixes;
+
+ TODO: do we have active maintenance branches?
+ (the only branch looking like a maintenance branch is
+ http://sourceforge.net/p/docutils/code/HEAD/tree/branches/docutils-0.4)
+
+* `development branches`_, representing ongoing development efforts to bring
+ new features into Docutils.
+
+.. _Docutils core:
+ http://sourceforge.net/p/docutils/code/HEAD/tree/trunk/docutils
+.. _development branches:
+ http://sourceforge.net/p/docutils/code/HEAD/tree/branches/
+
+
+Setting Up For Docutils Development
+===================================
+
+When making changes to the code, testing is a must. The code should
+be run to verify that it produces the expected results, and the entire
+test suite should be run too. The modified Docutils code has to be
+accessible to Python for the tests to have any meaning. There are two
+ways to keep the Docutils code accessible during development:
+
+1. Update your ``PYTHONPATH`` environment variable so that Python
+ picks up your local working copy of the code. This is the
+ recommended method.
+
+ We'll assume that the Docutils trunk is checked out under your
+ ~/projects/ directory as follows::
+
+ svn co https://<user>@docutils.svn.sourceforge.net/svnroot/docutils/trunk \
+ docutils
+
+ For the bash shell, add this to your ``~/.profile``::
+
+ PYTHONPATH=$HOME/projects/docutils/docutils
+ PYTHONPATH=$PYTHONPATH:$HOME/projects/docutils/docutils/extras
+ export PYTHONPATH
+
+ The first line points to the directory containing the ``docutils``
+ package. The second line adds the directory containing the
+ third-party modules Docutils depends on. The third line exports
+ this environment variable. You may also wish to add the ``tools``
+ directory to your ``PATH``::
+
+ PATH=$PATH:$HOME/projects/docutils/docutils/tools
+ export PATH
+
+2. Before you run anything, every time you make a change, reinstall
+ Docutils::
+
+ python setup.py install
+
+ .. CAUTION::
+
+ This method is **not** recommended for day-to-day development;
+ it's too easy to forget. Confusion inevitably ensues.
+
+ If you install Docutils this way, Python will always pick up the
+ last-installed copy of the code. If you ever forget to
+ reinstall the "docutils" package, Python won't see your latest
+ changes.
+
+A useful addition to the ``docutils`` top-level directory in branches
+and alternate copies of the code is a ``set-PATHS`` file
+containing the following lines::
+
+ # source this file
+ export PYTHONPATH=$PWD:$PWD/extras
+ export PATH=$PWD/tools:$PATH
+
+Open a shell for this branch, ``cd`` to the ``docutils`` top-level
+directory, and "source" this file. For example, using the bash
+shell::
+
+ $ cd some-branch/docutils
+ $ . set-PATHS
+
+
+Mailing Lists
+=============
+
+Developers are recommended to subscribe to all `Docutils mailing
+lists`_.
+
+.. _Docutils mailing lists: ../user/mailing-lists.html
+
+
+The Wiki
+========
+
+There is a development wiki at http://docutils.python-hosting.com/ as
+a scratchpad for transient notes. Please use the repository for
+permament document storage.
+
+Extensions and Related Projects
+===============================
+
+The Sandbox
+-----------
+
+The `sandbox directory`_ is a place to play around, to try out and
+share ideas. It's a part of the Subversion repository but it isn't
+distributed as part of Docutils releases. Feel free to check in code
+to the sandbox; that way people can try it out but you won't have to
+worry about it working 100% error-free, as is the goal of the Docutils
+core. A project-specific subdirectory should be created for each new
+project. Any developer who wants to play in the sandbox may do so,
+but project directories are recommended over personal directories,
+which discourage collaboration. It's OK to make a mess in the
+sandbox! But please, play nice.
+
+Please update the `sandbox README`_ file with links and a brief
+description of your work.
+
+In order to minimize the work necessary for others to install and try
+out new, experimental components, the following sandbox directory
+structure is recommended::
+
+ sandbox/
+ project_name/ # For a collaborative project.
+ README.txt # Describe the requirements, purpose/goals, usage,
+ # and list the maintainers.
+ docs/
+ ...
+ component.py # The component is a single module.
+ # *OR* (but *not* both)
+ component/ # The component is a package.
+ __init__.py # Contains the Reader/Writer class.
+ other1.py # Other modules and data files used
+ data.txt # by this component.
+ ...
+ test/ # Test suite.
+ ...
+ tools/ # For front ends etc.
+ ...
+ setup.py # Use Distutils to install the component
+ # code and tools/ files into the right
+ # places in Docutils.
+ userid/ # For *temporary* personal space.
+
+Some sandbox projects are destined to move to the Docutils core once
+completed. Others, such as add-ons to Docutils or applications of
+Docutils, may graduate to become `parallel projects`_.
+
+.. _sandbox README: http://docutils.sf.net/sandbox/README.html
+.. _sandbox directory:
+ http://sourceforge.net/p/docutils/code/HEAD/tree/trunk/sandbox/
+
+
+.. _parallel project:
+
+Parallel Projects
+-----------------
+
+Parallel projects contain useful code that is not central to the
+functioning of Docutils. Examples are specialized add-ons or
+plug-ins, and applications of Docutils. They use Docutils, but
+Docutils does not require their presence to function.
+
+An official parallel project will have its own directory beside (or
+parallel to) the main ``docutils`` directory in the Subversion
+repository. It can have its own web page in the
+docutils.sourceforge.net domain, its own file releases and
+downloadable snapshots, and even a mailing list if that proves useful.
+However, an official parallel project has implications: it is expected
+to be maintained and continue to work with changes to the core
+Docutils.
+
+A parallel project requires a project leader, who must commit to
+coordinate and maintain the implementation:
+
+* Answer questions from users and developers.
+* Review suggestions, bug reports, and patches.
+* Monitor changes and ensure the quality of the code and
+ documentation.
+* Coordinate with Docutils to ensure interoperability.
+* Put together official project releases.
+
+Of course, related projects may be created independently of Docutils.
+The advantage of a parallel project is that the SourceForge
+environment and the developer and user communities are already
+established. Core Docutils developers are available for consultation
+and may contribute to the parallel project. It's easier to keep the
+projects in sync when there are changes made to the core Docutils
+code.
+
+Other related projects
+----------------------
+
+Many related but independent projects are listed in the Docutils
+`link list`_. If you want your project to appear there, drop a note at
+the Docutils-develop_ mailing list.
+
+.. _link list: http://docutils.sourceforge.net/docs/user/links.html
+
+
+\f
+..
+ Local Variables:
+ mode: indented-text
+ indent-tabs-mode: nil
+ sentence-end-double-space: t
+ fill-column: 70
+ End:
--- /dev/null
+<!--
+======================================================================
+ Docutils Python Source DTD
+======================================================================
+:Author: David Goodger
+:Contact: docutils-develop@lists.sourceforge.net
+:Revision: $Revision: 7302 $
+:Date: $Date: 2012-01-03 20:23:53 +0100 (Di, 03. Jän 2012) $
+:Copyright: This DTD has been placed in the public domain.
+:Filename: pysource.dtd
+
+This DTD (document type definition) extends the Generic DTD (see
+below).
+
+More information about this DTD and the Docutils project can be found
+at http://docutils.sourceforge.net/. The latest version of this DTD
+is available from
+http://docutils.sourceforge.net/docs/dev/pysource.dtd.
+
+The formal public identifier for this DTD is::
+
+ +//IDN docutils.sourceforge.net//DTD Docutils Python Source//EN//XML
+-->
+
+<!--
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ Parameter Entity Overrides
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+-->
+
+<!ENTITY % additional.section.elements
+ " | package_section | module_section | class_section
+ | method_section | function_section
+ | module_attribute_section | function_attribute_section
+ | class_attribute_section | instance_attribute_section ">
+
+<!ENTITY % additional.inline.elements
+ " | package | module | class | method | function
+ | variable | parameter | type | attribute
+ | module_attribute | class_attribute | instance_attribute
+ | exception_class | warning_class ">
+
+<!--
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ Generic DTD
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+This DTD extends the Docutils Generic DTD, available from
+http://docutils.sourceforge.net/docs/ref/docutils.dtd.
+-->
+
+<!ENTITY % docutils PUBLIC
+ "+//IDN python.org//DTD Docutils Generic//EN//XML"
+ "docutils.dtd">
+%docutils;
+
+<!--
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ Additional Section Elements
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+-->
+
+<!-- package's namespace == __init__.py module's namespace -->
+<!ELEMENT package_section
+ (package, fullname?, import_list?, %structure.model;)>
+<!ATTLIST package_section %basic.atts;>
+
+<!ELEMENT module_section
+ (module, fullname?, import_list?, %structure.model;)>
+<!ATTLIST module_section %basic.atts;>
+
+<!ELEMENT class_section
+ (class, inheritance_list?, fullname?, subclasses?,
+ %structure.model;)>
+<!ATTLIST class_section %basic.atts;>
+
+<!ELEMENT method_section
+ (method, parameter_list?, fullname?, overrides?,
+ %structure.model;)>
+<!ATTLIST method_section %basic.atts;>
+
+<!ELEMENT function_section
+ (function, parameter_list?, fullname?, %structure.model;)>
+<!ATTLIST function_section %basic.atts;>
+
+<!ELEMENT module_attribute_section
+ (attribute, initial_value?, fullname?, %structure.model;)>
+<!ATTLIST module_attribute_section %basic.atts;>
+
+<!ELEMENT function_attribute_section
+ (attribute, initial_value?, fullname?, %structure.model;)>
+<!ATTLIST function_attribute_section %basic.atts;>
+
+<!ELEMENT class_attribute_section
+ (attribute, initial_value?, fullname?, overrides?,
+ %structure.model;)>
+<!ATTLIST class_attribute_section %basic.atts;>
+
+<!ELEMENT instance_attribute_section
+ (attribute, initial_value?, fullname?, overrides?,
+ %structure.model;)>
+<!ATTLIST instance_attribute_section %basic.atts;>
+
+<!--
+ Section Subelements
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+-->
+
+<!ELEMENT fullname
+ (package | module | class | method | function | attribute)+>
+<!ATTLIST fullname %basic.atts;>
+
+<!ELEMENT import_list (import_item+)>
+<!ATTLIST import_list %basic.atts;>
+
+<!--
+Support ``import module``, ``import module as alias``, ``from module
+import identifier``, and ``from module import identifier as alias``.
+-->
+<!ELEMENT import_item (fullname, identifier?, alias?)>
+<!ATTLIST import_item %basic.atts;>
+
+<!ELEMENT inheritance_list (class+)>
+<!ATTLIST inheritance_list %basic.atts;>
+
+<!ELEMENT subclasses (class+)>
+<!ATTLIST subclasses %basic.atts;>
+
+<!ELEMENT parameter_list
+ ((parameter_item+, optional_parameters*) | optional_parameters+)>
+<!ATTLIST parameter_list %basic.atts;>
+
+<!ELEMENT parameter_item
+ ((parameter | parameter_tuple), parameter_default?)>
+<!ATTLIST parameter_item %basic.atts;>
+
+<!ELEMENT optional_parameters (parameter_item+, optional_parameters*)>
+<!ATTLIST optional_parameters %basic.atts;>
+
+<!ELEMENT parameter_tuple (parameter | parameter_tuple)+>
+<!ATTLIST parameter_tuple %basic.atts;>
+
+<!ELEMENT parameter_default (#PCDATA)>
+<!ATTLIST parameter_default %basic.atts;>
+
+<!ELEMENT overrides (fullname+)>
+<!ATTLIST overrides %basic.atts;>
+
+<!ELEMENT initial_value (#PCDATA)>
+<!ATTLIST initial_value %basic.atts;>
+
+<!--
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ Additional Inline Elements
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+-->
+
+<!-- Also used as the `package_section` identifier/title. -->
+<!ELEMENT package (#PCDATA)>
+<!ATTLIST package
+ %basic.atts;
+ %reference.atts;>
+
+<!-- Also used as the `module_section` identifier/title. -->
+<!ELEMENT module (#PCDATA)>
+<!ATTLIST module
+ %basic.atts;
+ %reference.atts;>
+
+<!--
+Also used as the `class_section` identifier/title, and in the
+`inheritance` element.
+-->
+<!ELEMENT class (#PCDATA)>
+<!ATTLIST class
+ %basic.atts;
+ %reference.atts;>
+
+<!-- Also used as the `method_section` identifier/title. -->
+<!ELEMENT method (#PCDATA)>
+<!ATTLIST method
+ %basic.atts;
+ %reference.atts;>
+
+<!-- Also used as the `function_section` identifier/title. -->
+<!ELEMENT function (#PCDATA)>
+<!ATTLIST function
+ %basic.atts;
+ %reference.atts;>
+
+<!--
+??? Use this instead of the ``*_attribute`` elements below? Add a
+"type" attribute to differentiate?
+
+Also used as the identifier/title for `module_attribute_section`,
+`class_attribute_section`, and `instance_attribute_section`.
+-->
+<!ELEMENT attribute (#PCDATA)>
+<!ATTLIST attribute
+ %basic.atts;
+ %reference.atts;>
+
+<!--
+Also used as the `module_attribute_section` identifier/title. A module
+attribute is an exported module-level global variable.
+-->
+<!ELEMENT module_attribute (#PCDATA)>
+<!ATTLIST module_attribute
+ %basic.atts;
+ %reference.atts;>
+
+<!-- Also used as the `class_attribute_section` identifier/title. -->
+<!ELEMENT class_attribute (#PCDATA)>
+<!ATTLIST class_attribute
+ %basic.atts;
+ %reference.atts;>
+
+<!--
+Also used as the `instance_attribute_section` identifier/title.
+-->
+<!ELEMENT instance_attribute (#PCDATA)>
+<!ATTLIST instance_attribute
+ %basic.atts;
+ %reference.atts;>
+
+<!ELEMENT variable (#PCDATA)>
+<!ATTLIST variable
+ %basic.atts;
+ %reference.atts;>
+
+<!-- Also used in `parameter_list`. -->
+<!ELEMENT parameter (#PCDATA)>
+<!ATTLIST parameter
+ %basic.atts;
+ %reference.atts;
+ excess_positional %yesorno; #IMPLIED
+ excess_keyword %yesorno; #IMPLIED>
+
+<!ELEMENT type (#PCDATA)>
+<!ATTLIST type
+ %basic.atts;
+ %reference.atts;>
+
+<!ELEMENT exception_class (#PCDATA)>
+<!ATTLIST exception_class
+ %basic.atts;
+ %reference.atts;>
+
+<!ELEMENT warning_class (#PCDATA)>
+<!ATTLIST warning_class
+ %basic.atts;
+ %reference.atts;>
+
+<!--
+Local Variables:
+mode: sgml
+indent-tabs-mode: nil
+fill-column: 70
+End:
+-->
--- /dev/null
+======================
+ Python Source Reader
+======================
+:Author: David Goodger
+:Contact: docutils-develop@lists.sourceforge.net
+:Revision: $Revision: 7302 $
+:Date: $Date: 2012-01-03 20:23:53 +0100 (Di, 03. Jän 2012) $
+:Copyright: This document has been placed in the public domain.
+
+This document explores issues around extracting and processing
+docstrings from Python modules.
+
+For definitive element hierarchy details, see the "Python Plaintext
+Document Interface DTD" XML document type definition, pysource.dtd_
+(which modifies the generic docutils.dtd_). Descriptions below list
+'DTD elements' (XML 'generic identifiers' or tag names) corresponding
+to syntax constructs.
+
+
+.. contents::
+
+
+Model
+=====
+
+The Python Source Reader ("PySource") model that's evolving in my mind
+goes something like this:
+
+1. Extract the docstring/namespace [#]_ tree from the module(s) and/or
+ package(s).
+
+ .. [#] See `Docstring Extractor`_ below.
+
+2. Run the parser on each docstring in turn, producing a forest of
+ doctrees (per nodes.py).
+
+3. Join the docstring trees together into a single tree, running
+ transforms:
+
+ - merge hyperlinks
+ - merge namespaces
+ - create various sections like "Module Attributes", "Functions",
+ "Classes", "Class Attributes", etc.; see pysource.dtd_
+ - convert the above special sections to ordinary doctree nodes
+
+4. Run transforms on the combined doctree. Examples: resolving
+ cross-references/hyperlinks (including interpreted text on Python
+ identifiers); footnote auto-numbering; first field list ->
+ bibliographic elements.
+
+ (Or should step 4's transforms come before step 3?)
+
+5. Pass the resulting unified tree to the writer/builder.
+
+I've had trouble reconciling the roles of input parser and output
+writer with the idea of modes ("readers" or "directors"). Does the
+mode govern the tranformation of the input, the output, or both?
+Perhaps the mode should be split into two.
+
+For example, say the source of our input is a Python module. Our
+"input mode" should be the "Python Source Reader". It discovers (from
+``__docformat__``) that the input parser is "reStructuredText". If we
+want HTML, we'll specify the "HTML" output formatter. But there's a
+piece missing. What *kind* or *style* of HTML output do we want?
+PyDoc-style, LibRefMan style, etc. (many people will want to specify
+and control their own style). Is the output style specific to a
+particular output format (XML, HTML, etc.)? Is the style specific to
+the input mode? Or can/should they be independent?
+
+I envision interaction between the input parser, an "input mode" , and
+the output formatter. The same intermediate data format would be used
+between each of these, being transformed as it progresses.
+
+
+Docstring Extractor
+===================
+
+We need code that scans a parsed Python module, and returns an ordered
+tree containing the names, docstrings (including attribute and
+additional docstrings), and additional info (in parentheses below) of
+all of the following objects:
+
+- packages
+- modules
+- module attributes (+ values)
+- classes (+ inheritance)
+- class attributes (+ values)
+- instance attributes (+ values)
+- methods (+ formal parameters & defaults)
+- functions (+ formal parameters & defaults)
+
+(Extract comments too? For example, comments at the start of a module
+would be a good place for bibliographic field lists.)
+
+In order to evaluate interpreted text cross-references, namespaces for
+each of the above will also be required.
+
+See python-dev/docstring-develop thread "AST mining", started on
+2001-08-14.
+
+
+Interpreted Text
+================
+
+DTD elements: package, module, class, method, function,
+module_attribute, class_attribute, instance_attribute, variable,
+parameter, type, exception_class, warning_class.
+
+To classify identifiers explicitly, the role is given along with the
+identifier in either prefix or suffix form::
+
+ Use :method:`Keeper.storedata` to store the object's data in
+ `Keeper.data`:instance_attribute:.
+
+The role may be one of 'package', 'module', 'class', 'method',
+'function', 'module_attribute', 'class_attribute',
+'instance_attribute', 'variable', 'parameter', 'type',
+'exception_class', 'exception', 'warning_class', or 'warning'. Other
+roles may be defined.
+
+.. _pysource.dtd: pysource.dtd
+.. _docutils.dtd: ../ref/docutils.dtd
+
+\f
+..
+ Local Variables:
+ mode: indented-text
+ indent-tabs-mode: nil
+ fill-column: 70
+ End:
--- /dev/null
+=============================
+ Docutils_ Release Procedure
+=============================
+
+:Authors: David Goodger; Lea Wiemann; open to all Docutils developers
+:Contact: docutils-develop@lists.sourceforge.net
+:Date: $Date: 2019-12-12 14:05:17 +0100 (Do, 12. Dez 2019) $
+:Revision: $Revision: 8436 $
+:Copyright: This document has been placed in the public domain.
+
+.. _Docutils: http://docutils.sourceforge.net/
+
+Releasing
+---------
+
+Version identifier
+~~~~~~~~~~~~~~~~~~
+
+For details, see `Version Numbering in Docutils Project Policies`__.
+
+__ policies.html#version-numbering
+
+
+How to change the version identifier
+""""""""""""""""""""""""""""""""""""
+
+The *version identifier* ``docutils.__version__`` is defined in
+``docutils/docutils/__init__.py`` and used in in the following files::
+
+ docutils/setup.py
+ docutils/test/functional/expected/* ("Generator: Docutils X.Y[.Z]")
+ docutils/README.txt
+ web/index.txt
+
+You can use the script ``set_version.sh`` to change the version
+identifier:
+
+#. ``cd`` to the "docutils" subdirectory in the repository checkout,
+
+#. call ::
+
+ ../sandbox/infrastructure/set_release.sh <new_version>
+
+ where ``<new_version>`` is major.minor[.micro][<pre>][.dev].
+
+ This also changes ``__version_info__`` in
+ ``docutils/docutils/__init__.py``.
+
+Run the test suite after changing the codebase version to ensure
+accuracy and consistency.
+
+
+Release steps
+~~~~~~~~~~~~~
+
+REWORK FOR SOURCEFORGE REPO
+
+
+.. WARNING:: Steps in boldface text are *not* covered by the release script
+ at sandbox/infrastructure/release.sh. "Not covered" means that you
+ aren't even reminded of them.
+
+.. Note:: This document does not cover branching and tagging, but the
+ release script does.
+
+* **Announce**
+
+ On the Docutils-develop mailing list, announce that the release is
+ going to be made, update the release notes (consult HISTORY.TXT for
+ important changes) and ask for additions.
+
+ Announce the upcoming release at the Sphinx-devel mailing list
+ and ask for testing with Sphinx.
+ (This step can be skipped for bugfix releases and pre-releases.)
+
+ Announce the date of the feature freeze – at least a week ahead!
+
+* **Feature freeze** From now on, only bug-fix commits are allowed.
+
+ Update the `pre-release segment` of the `version identifier`_
+ (``b``, ``rcN`` or empty) to match the level of the upcoming release
+ (beta, candidate or final). Ensure ``docutils.__version_info__`` matches
+ the version identifier. (See also `How to change the version
+ identifier`_.)
+
+* **Announce** the check-in freeze date on Docutils-develop – at least a
+ week ahead.
+
+* **Check-in freeze**
+
+ for example it was 0.14b.dev and is changed to 0.15
+
+ **Update the version identifier**:
+ Remove the `development release segment` (``.dev``) from the `version
+ identifier`_ and set ``docutils.__version_info__.release`` to True.
+
+ Check the `version identifier` in the following files (should be
+ already correct if set according to `How to change the version
+ identifier`_):
+
+ + docutils/setup.py
+ + docutils/docutils/__init__.py
+ + docutils/test/functional/expected/* ("Generator: Docutils X.Y[.Z]")
+ + docutils/README.txt
+ + web/index.txt
+
+* See what ``sandbox/infrastructure/release.sh`` can aid
+
+ .. Note:: *BUG* test tarball requires root password, but it is possible to
+ skip this stage interactively, and testing should be done before
+ release.
+
+
+* Close the "Changes Since ..." section in docutils/HISTORY.txt.
+
+* Clear/unset the PYTHONPATH environment variable.
+
+* Create the release tarball:
+
+ (a) Create a new empty directory and ``cd`` into it.
+
+ (b) Get a clean snapshot of the main tree::
+
+ svn export svn://svn.code.sf.net/p/docutils/code/trunk/docutils
+
+ or via the [Download Snapshot] button at
+ http://sourceforge.net/p/docutils/code/HEAD/tree/trunk/docutils/
+
+ (c) Use Distutils to create the release tarball::
+
+ cd docutils
+ python setup.py sdist
+
+* Expand and _`install` the release tarball in isolation:
+
+ (a) Expand the tarball in a new location, not over any existing
+ files.
+
+ (b) Remove the old installation from site-packages (including
+ roman.py, and optparse.py, textwrap.py).
+
+ "remove" might fail, see _`Assumptions and their failure`
+
+ Install from expanded directory::
+
+ cd docutils-X.Y.Z
+ python setup.py install
+
+ The "install" command may require root permissions.
+
+ (c) Repeat step b) for all supported Python versions.
+
+* Run the _`test suite` from the expanded archive directory with all
+ supported Python versions on all available platforms (GNU/Linux, Mac
+ OS X, Windows)::
+
+ cd test ; python -u alltests.py
+
+* Add a directory X.Y.Z (where X.Y.Z is the current version number
+ of Docutils) in the webroot (i.e. the ``htdocs/`` directory).
+ Put all documentation files into it::
+
+ cd docutils-X.Y.Z
+ rm -rf build
+ cd tools/
+ ./buildhtml.py ..
+ cd ..
+ find -name test -type d -prune -o -name \*.css -print0 \
+ -o -name \*.html -print0 -o -name \*.txt -print0 \
+ | tar -cjvf docutils-docs.tar.bz2 -T - --null
+ scp docutils-docs.tar.bz2 <username>@shell.sourceforge.net:
+
+ Now log in to shell.sourceforge.net and::
+
+ cd /home/groups/d/do/docutils/htdocs/
+ mkdir -m g+rwxs X.Y.Z
+ cd X.Y.Z
+ tar -xjvf ~/docutils-docs.tar.bz2
+ rm ~/docutils-docs.tar.bz2
+
+* Upload the release tarball, release.sh tries with scp.
+
+* Access the _`file release system` on SourceForge (Admin
+ interface).
+
+ ``https://sourceforge.net/projects/docutils/files/docutils/``
+
+ * change into the released version's directory
+ * click ``(i)`` button of the tar.gz-file
+ * select as default download for all operating systems.
+
+* Submit a notification on project news.
+
+* For verifying the integrity of the release, download the release
+ tarball (you may need to wait up to 30 minutes), install_ it, and
+ re-run the `test suite`_.
+
+* Register with PyPI (``python setup.py register``).
+
+ (2019-07-21 still ?) Set the download-url so eggs can access older releases.
+
+* **build wheels**::
+
+ python setup.py bdist_wheel
+
+ This builds wheels_ by downloading the new release from pypi.
+
+ Upload the wheels to PyPI::
+
+ twine upload dist/*
+
+* **Lift the freeze**
+
+ Set the `version identifier`_ and ``__version_info__.releaselevel`` in
+ docutils/docutils/__init__.py to mark the repository version as
+ "in development", usually ``<major>.<minor+1>b.dev`` (cf. `How to change
+ the version identifier`_).
+
+* After a final release, add a new empty section "Changes Since ..." in
+ HISTORY.txt.
+
+* Update the web page (web/index.txt)::
+
+ cd sandbox/infrastructure/
+ ./docutils-update.local
+
+ Running on sf-server no longer works.
+
+* set svn version e.g. 0.16b.dev
+
+* **Run alltests.py with svn version**
+
+* **Send announcement email to:**
+
+ * docutils-develop@lists.sourceforge.net (also announcing the end of
+ the check-in freeze)
+ * docutils-users@lists.sourceforge.net
+ * doc-sig@python.org
+ * python-announce@python.org
+
+* **Add a** `SourceForge News item`__, **with title "Docutils X.Y.Z released"**
+
+ __ https://sourceforge.net/p/docutils/news
+
+ **Mark as default download for all platforms.**
+
+.. _wheels: https://packaging.python.org/en/latest/distributing.html#wheels
+.. _pure Python wheels:
+ https://packaging.python.org/en/latest/distributing.html#pure-python-wheels
+
+\f
+..
+ Local Variables:
+ mode: indented-text
+ indent-tabs-mode: nil
+ sentence-end-double-space: t
+ fill-column: 70
+ End:
--- /dev/null
+=====================================
+ The Docutils_ Subversion Repository
+=====================================
+
+:Author: Lea Wiemann
+:Contact: docutils-develop@lists.sourceforge.net
+:Revision: $Revision: 7800 $
+:Date: $Date: 2015-02-24 14:01:43 +0100 (Di, 24. Feb 2015) $
+:Copyright: This document has been placed in the public domain.
+
+.. _Docutils: http://docutils.sourceforge.net/
+
+.. admonition:: Quick Instructions
+
+ To get a checkout of the Docutils source tree (with the
+ sandboxes), type ::
+
+ svn checkout http://svn.code.sf.net/p/docutils/code/trunk docutils-code
+
+
+ If you are going to commit changes to the repository, please read
+ the **whole document**, especially the section "`Information for
+ Developers`_"!
+
+.. important::
+ As of 2013-03-13 the subversion urls have changed.
+
+Docutils uses a Subversion_ repository located at
+``docutils.svn.sourceforge.net``.
+Subversion is exhaustively documented in the `Subversion Book`_ (svnbook).
+
+While Unix and Mac OS X users will probably prefer the standard
+Subversion command line interface, Windows user may want to try
+TortoiseSVN_, a convenient explorer extension. The instructions apply
+analogously.
+
+There is a git_ mirror at http://repo.or.cz/docutils.git providing
+`web access`_ and the base for `creating a local git clone`_.
+
+For the project policy on repository use (check-in requirements,
+branching, etc.), please see the `Docutils Project Policies`__.
+
+__ policies.html#subversion-repository
+
+.. _Subversion: http://subversion.tigris.org/
+.. _Subversion Book: http://svnbook.red-bean.com/
+.. _TortoiseSVN: http://tortoisesvn.tigris.org/
+.. _SourceForge.net: http://sourceforge.net/
+.. _git: http://git-scm.com/
+
+.. contents::
+
+
+Accessing the Repository
+========================
+
+General Information
+-------------------
+
+Web Access
+~~~~~~~~~~
+
+The repository can be browsed and examined via the web at
+http://sourceforge.net/p/docutils/code
+
+Alternatively, use the web interface of the git mirror at
+http://repo.or.cz/w/docutils.git.
+
+
+Repository Access Methods
+~~~~~~~~~~~~~~~~~~~~~~~~~
+
+To get a checkout of the Docutils repository, first determine the root
+of the repository depending on your preferred protocol:
+
+anonymous access: (read only)
+ ``http://svn.code.sf.net/p/docutils/code``
+
+`developer access`_: (read and write)
+ ``svn+ssh://<USERNAME>@svn.code.sf.net/p/docutils/code``
+
+.. git clone: (read only)
+ ``git clone git://repo.or.cz/docutils.git``
+
+Checking Out the Repository
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+To check out only the current main source tree of Docutils, type ::
+
+ svn checkout ROOT/trunk/docutils
+
+(Substitute your preferred repository root for ROOT.) To check out
+everything (main tree, sandboxes, web site, and parallel projects),
+type ::
+
+ svn checkout ROOT/trunk docutils
+
+This will create a working copy of the whole trunk in a new directory
+called ``docutils``.
+
+Note that you probably do *not* want to check out the ROOT itself
+(without "/trunk"), because then you'd end up fetching the whole
+Docutils tree for every branch and tag over and over again.
+
+To update your working copy later on, ``cd`` into the working copy and
+type ::
+
+ svn update
+
+Creating a local git clone
+~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Users of git_ can clone a mirror of the docutils repository with ::
+
+ git clone git://repo.or.cz/docutils.git
+
+and proceed according to the `git documentation`_.
+
+.. _git documentation: http://git-scm.com/documentation
+
+Switching the Repository Root
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+If you changed your mind and want to use a different repository root,
+``cd`` into your working copy and type::
+
+ svn switch --relocate OLDROOT NEWROOT
+
+.. _developer access:
+
+Information for Developers
+--------------------------
+
+If you would like to have write access to the repository, register
+with SourceForge.net_ and send your SourceForge.net
+user names to docutils-develop@lists.sourceforge.net.
+(Note that there may be a delay of several hours until you can commit
+changes to the repository.)
+
+Sourceforge subversion access is documented `here`__
+
+__ http://sourceforge.net/p/forge/documentation/svn/
+
+
+Setting Up Your Subversion Client For Development
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Before commiting changes to the repository, please ensure that the
+following lines are contained (and uncommented) in your local
+~/.subversion/config file, so that new files are added with the
+correct properties set::
+
+ [miscellany]
+ # For your convenience:
+ global-ignores = ... *.pyc ...
+ # For correct properties:
+ enable-auto-props = yes
+
+ [auto-props]
+ *.py = svn:eol-style=native;svn:keywords=Author Date Id Revision
+ *.txt = svn:eol-style=native;svn:keywords=Author Date Id Revision
+ *.html = svn:eol-style=native;svn:keywords=Author Date Id Revision
+ *.xml = svn:eol-style=native;svn:keywords=Author Date Id Revision
+ *.tex = svn:eol-style=native;svn:keywords=Author Date Id Revision
+ *.css = svn:eol-style=native;svn:keywords=Author Date Id Revision
+ *.patch = svn:eol-style=native
+ *.sh = svn:eol-style=native;svn:executable;svn:keywords=Author Date Id Revision
+ *.png = svn:mime-type=image/png
+ *.jpg = svn:mime-type=image/jpeg
+ *.gif = svn:mime-type=image/gif
+
+
+Repository Layout
+=================
+
+The following tree shows the repository layout::
+
+ docutils/
+ |-- branches/
+ | |-- branch1/
+ | | |-- docutils/
+ | | |-- sandbox/
+ | | `-- web/
+ | `-- branch2/
+ | |-- docutils/
+ | |-- sandbox/
+ | `-- web/
+ |-- tags/
+ | |-- tag1/
+ | | |-- docutils/
+ | | |-- sandbox/
+ | | `-- web/
+ | `-- tag2/
+ | |-- docutils/
+ | |-- sandbox/
+ | `-- web/
+ `-- trunk/
+ |-- docutils/
+ |-- sandbox/
+ `-- web/
+
+The main source tree lives at ``docutils/trunk/docutils/``, next to
+the sandboxes (``docutils/trunk/sandbox/``) and the web site files
+(``docutils/trunk/web/``).
+
+``docutils/branches/`` and ``docutils/tags/`` contain (shallow) copies
+of either the whole trunk or only the main source tree
+(``docutils/trunk/docutils``).
--- /dev/null
+==================================================
+ A Record of reStructuredText Syntax Alternatives
+==================================================
+
+:Author: David Goodger
+:Contact: docutils-develop@lists.sourceforge.net
+:Revision: $Revision: 7383 $
+:Date: $Date: 2012-03-19 18:04:49 +0100 (Mo, 19. Mär 2012) $
+:Copyright: This document has been placed in the public domain.
+
+The following are ideas, alternatives, and justifications that were
+considered for reStructuredText syntax, which did not originate with
+Setext_ or StructuredText_. For an analysis of constructs which *did*
+originate with StructuredText or Setext, please see `Problems With
+StructuredText`_. See the `reStructuredText Markup Specification`_
+for full details of the established syntax.
+
+The ideas are divided into sections:
+
+* Implemented_: already done. The issues and alternatives are
+ recorded here for posterity.
+
+* `Not Implemented`_: these ideas won't be implemented.
+
+* Tabled_: these ideas should be revisited in the future.
+
+* `To Do`_: these ideas should be implemented. They're just waiting
+ for a champion to resolve issues and get them done.
+
+* `... Or Not To Do?`_: possible but questionable. These probably
+ won't be implemented, but you never know.
+
+.. _Setext: http://docutils.sourceforge.net/mirror/setext.html
+.. _StructuredText:
+ http://www.zope.org/DevHome/Members/jim/StructuredTextWiki/FrontPage
+.. _Problems with StructuredText: problems.html
+.. _reStructuredText Markup Specification:
+ ../../ref/rst/restructuredtext.html
+
+
+.. contents::
+
+-------------
+ Implemented
+-------------
+
+Field Lists
+===========
+
+Prior to the syntax for field lists being finalized, several
+alternatives were proposed.
+
+1. Unadorned RFC822_ everywhere::
+
+ Author: Me
+ Version: 1
+
+ Advantages: clean, precedent (RFC822-compliant). Disadvantage:
+ ambiguous (these paragraphs are a prime example).
+
+ Conclusion: rejected.
+
+2. Special case: use unadorned RFC822_ for the very first or very last
+ text block of a document::
+
+ """
+ Author: Me
+ Version: 1
+
+ The rest of the document...
+ """
+
+ Advantages: clean, precedent (RFC822-compliant). Disadvantages:
+ special case, flat (unnested) field lists only, still ambiguous::
+
+ """
+ Usage: cmdname [options] arg1 arg2 ...
+
+ We obviously *don't* want the like above to be interpreted as a
+ field list item. Or do we?
+ """
+
+ Conclusion: rejected for the general case, accepted for specific
+ contexts (PEPs, email).
+
+3. Use a directive::
+
+ .. fields::
+
+ Author: Me
+ Version: 1
+
+ Advantages: explicit and unambiguous, RFC822-compliant.
+ Disadvantage: cumbersome.
+
+ Conclusion: rejected for the general case (but such a directive
+ could certainly be written).
+
+4. Use Javadoc-style::
+
+ @Author: Me
+ @Version: 1
+ @param a: integer
+
+ Advantages: unambiguous, precedent, flexible. Disadvantages:
+ non-intuitive, ugly, not RFC822-compliant.
+
+ Conclusion: rejected.
+
+5. Use leading colons::
+
+ :Author: Me
+ :Version: 1
+
+ Advantages: unambiguous, obvious (*almost* RFC822-compliant),
+ flexible, perhaps even elegant. Disadvantages: no precedent, not
+ quite RFC822-compliant.
+
+ Conclusion: accepted!
+
+6. Use double colons::
+
+ Author:: Me
+ Version:: 1
+
+ Advantages: unambiguous, obvious? (*almost* RFC822-compliant),
+ flexible, similar to syntax already used for literal blocks and
+ directives. Disadvantages: no precedent, not quite
+ RFC822-compliant, similar to syntax already used for literal blocks
+ and directives.
+
+ Conclusion: rejected because of the syntax similarity & conflicts.
+
+Why is RFC822 compliance important? It's a universal Internet
+standard, and super obvious. Also, I'd like to support the PEP format
+(ulterior motive: get PEPs to use reStructuredText as their standard).
+But it *would* be easy to get used to an alternative (easy even to
+convert PEPs; probably harder to convert python-deviants ;-).
+
+Unfortunately, without well-defined context (such as in email headers:
+RFC822 only applies before any blank lines), the RFC822 format is
+ambiguous. It is very common in ordinary text. To implement field
+lists unambiguously, we need explicit syntax.
+
+The following question was posed in a footnote:
+
+ Should "bibliographic field lists" be defined at the parser level,
+ or at the DPS transformation level? In other words, are they
+ reStructuredText-specific, or would they also be applicable to
+ another (many/every other?) syntax?
+
+The answer is that bibliographic fields are a
+reStructuredText-specific markup convention. Other syntaxes may
+implement the bibliographic elements explicitly. For example, there
+would be no need for such a transformation for an XML-based markup
+syntax.
+
+.. _RFC822: http://www.rfc-editor.org/rfc/rfc822.txt
+
+
+Interpreted Text "Roles"
+========================
+
+The original purpose of interpreted text was as a mechanism for
+descriptive markup, to describe the nature or role of a word or
+phrase. For example, in XML we could say "<function>len</function>"
+to mark up "len" as a function. It is envisaged that within Python
+docstrings (inline documentation in Python module source files, the
+primary market for reStructuredText) the role of a piece of
+interpreted text can be inferred implicitly from the context of the
+docstring within the program source. For other applications, however,
+the role may have to be indicated explicitly.
+
+Interpreted text is enclosed in single backquotes (`).
+
+1. Initially, it was proposed that an explicit role could be indicated
+ as a word or phrase within the enclosing backquotes:
+
+ - As a prefix, separated by a colon and whitespace::
+
+ `role: interpreted text`
+
+ - As a suffix, separated by whitespace and a colon::
+
+ `interpreted text :role`
+
+ There are problems with the initial approach:
+
+ - There could be ambiguity with interpreted text containing colons.
+ For example, an index entry of "Mission: Impossible" would
+ require a backslash-escaped colon.
+
+ - The explicit role is descriptive markup, not content, and will
+ not be visible in the processed output. Putting it inside the
+ backquotes doesn't feel right; the *role* isn't being quoted.
+
+2. Tony Ibbs suggested that the role be placed outside the
+ backquotes::
+
+ role:`prefix` or `suffix`:role
+
+ This removes the embedded-colons ambiguity, but limits the role
+ identifier to be a single word (whitespace would be illegal).
+ Since roles are not meant to be visible after processing, the lack
+ of whitespace support is not important.
+
+ The suggested syntax remains ambiguous with respect to ratios and
+ some writing styles. For example, suppose there is a "signal"
+ identifier, and we write::
+
+ ...calculate the `signal`:noise ratio.
+
+ "noise" looks like a role.
+
+3. As an improvement on #2, we can bracket the role with colons::
+
+ :role:`prefix` or `suffix`:role:
+
+ This syntax is similar to that of field lists, which is fine since
+ both are doing similar things: describing.
+
+ This is the syntax chosen for reStructuredText.
+
+4. Another alternative is two colons instead of one::
+
+ role::`prefix` or `suffix`::role
+
+ But this is used for analogies ("A:B::C:D": "A is to B as C is to
+ D").
+
+ Both alternative #2 and #4 lack delimiters on both sides of the
+ role, making it difficult to parse (by the reader).
+
+5. Some kind of bracketing could be used:
+
+ - Parentheses::
+
+ (role)`prefix` or `suffix`(role)
+
+ - Braces::
+
+ {role}`prefix` or `suffix`{role}
+
+ - Square brackets::
+
+ [role]`prefix` or `suffix`[role]
+
+ - Angle brackets::
+
+ <role>`prefix` or `suffix`<role>
+
+ (The overlap of \*ML tags with angle brackets would be too
+ confusing and precludes their use.)
+
+Syntax #3 was chosen for reStructuredText.
+
+
+Comments
+========
+
+A problem with comments (actually, with all indented constructs) is
+that they cannot be followed by an indented block -- a block quote --
+without swallowing it up.
+
+I thought that perhaps comments should be one-liners only. But would
+this mean that footnotes, hyperlink targets, and directives must then
+also be one-liners? Not a good solution.
+
+Tony Ibbs suggested a "comment" directive. I added that we could
+limit a comment to a single text block, and that a "multi-block
+comment" could use "comment-start" and "comment-end" directives. This
+would remove the indentation incompatibility. A "comment" directive
+automatically suggests "footnote" and (hyperlink) "target" directives
+as well. This could go on forever! Bad choice.
+
+Garth Kidd suggested that an "empty comment", a ".." explicit markup
+start with nothing on the first line (except possibly whitespace) and
+a blank line immediately following, could serve as an "unindent". An
+empty comment does **not** swallow up indented blocks following it,
+so block quotes are safe. "A tiny but practical wart." Accepted.
+
+
+Anonymous Hyperlinks
+====================
+
+Alan Jaffray came up with this idea, along with the following syntax::
+
+ Search the `Python DOC-SIG mailing list archives`{}_.
+
+ .. _: http://mail.python.org/pipermail/doc-sig/
+
+The idea is sound and useful. I suggested a "double underscore"
+syntax::
+
+ Search the `Python DOC-SIG mailing list archives`__.
+
+ .. __: http://mail.python.org/pipermail/doc-sig/
+
+But perhaps single underscores are okay? The syntax looks better, but
+the hyperlink itself doesn't explicitly say "anonymous"::
+
+ Search the `Python DOC-SIG mailing list archives`_.
+
+ .. _: http://mail.python.org/pipermail/doc-sig/
+
+Mixing anonymous and named hyperlinks becomes confusing. The order of
+targets is not significant for named hyperlinks, but it is for
+anonymous hyperlinks::
+
+ Hyperlinks: anonymous_, named_, and another anonymous_.
+
+ .. _named: named
+ .. _: anonymous1
+ .. _: anonymous2
+
+Without the extra syntax of double underscores, determining which
+hyperlink references are anonymous may be difficult. We'd have to
+check which references don't have corresponding targets, and match
+those up with anonymous targets. Keeping to a simple consistent
+ordering (as with auto-numbered footnotes) seems simplest.
+
+reStructuredText will use the explicit double-underscore syntax for
+anonymous hyperlinks. An alternative (see `Reworking Explicit Markup
+(Round 1)`_ below) for the somewhat awkward ".. __:" syntax is "__"::
+
+ An anonymous__ reference.
+
+ __ http://anonymous
+
+
+Reworking Explicit Markup (Round 1)
+===================================
+
+Alan Jaffray came up with the idea of `anonymous hyperlinks`_, added
+to reStructuredText. Subsequently it was asserted that hyperlinks
+(especially anonymous hyperlinks) would play an increasingly important
+role in reStructuredText documents, and therefore they require a
+simpler and more concise syntax. This prompted a review of the
+current and proposed explicit markup syntaxes with regards to
+improving usability.
+
+1. Original syntax::
+
+ .. _blah: internal hyperlink target
+ .. _blah: http://somewhere external hyperlink target
+ .. _blah: blahblah_ indirect hyperlink target
+ .. __: anonymous internal target
+ .. __: http://somewhere anonymous external target
+ .. __: blahblah_ anonymous indirect target
+ .. [blah] http://somewhere footnote
+ .. blah:: http://somewhere directive
+ .. blah: http://somewhere comment
+
+ .. Note::
+
+ The comment text was intentionally made to look like a hyperlink
+ target.
+
+ Origins:
+
+ * Except for the colon (a delimiter necessary to allow for
+ phrase-links), hyperlink target ``.. _blah:`` comes from Setext.
+ * Comment syntax from Setext.
+ * Footnote syntax from StructuredText ("named links").
+ * Directives and anonymous hyperlinks original to reStructuredText.
+
+ Advantages:
+
+ + Consistent explicit markup indicator: "..".
+ + Consistent hyperlink syntax: ".. _" & ":".
+
+ Disadvantages:
+
+ - Anonymous target markup is awkward: ".. __:".
+ - The explicit markup indicator ("..") is excessively overloaded?
+ - Comment text is limited (can't look like a footnote, hyperlink,
+ or directive). But this is probably not important.
+
+2. Alan Jaffray's proposed syntax #1::
+
+ __ _blah internal hyperlink target
+ __ blah: http://somewhere external hyperlink target
+ __ blah: blahblah_ indirect hyperlink target
+ __ anonymous internal target
+ __ http://somewhere anonymous external target
+ __ blahblah_ anonymous indirect target
+ __ [blah] http://somewhere footnote
+ .. blah:: http://somewhere directive
+ .. blah: http://somewhere comment
+
+ The hyperlink-connoted underscores have become first-level syntax.
+
+ Advantages:
+
+ + Anonymous targets are simpler.
+ + All hyperlink targets are one character shorter.
+
+ Disadvantages:
+
+ - Inconsistent internal hyperlink targets. Unlike all other named
+ hyperlink targets, there's no colon. There's an extra leading
+ underscore, but we can't drop it because without it, "blah" looks
+ like a relative URI. Unless we restore the colon::
+
+ __ blah: internal hyperlink target
+
+ - Obtrusive markup?
+
+3. Alan Jaffray's proposed syntax #2::
+
+ .. _blah internal hyperlink target
+ .. blah: http://somewhere external hyperlink target
+ .. blah: blahblah_ indirect hyperlink target
+ .. anonymous internal target
+ .. http://somewhere anonymous external target
+ .. blahblah_ anonymous indirect target
+ .. [blah] http://somewhere footnote
+ !! blah: http://somewhere directive
+ ## blah: http://somewhere comment
+
+ Leading underscores have been (almost) replaced by "..", while
+ comments and directives have gained their own syntax.
+
+ Advantages:
+
+ + Anonymous hyperlinks are simpler.
+ + Unique syntax for comments. Connotation of "comment" from
+ some programming languages (including our favorite).
+ + Unique syntax for directives. Connotation of "action!".
+
+ Disadvantages:
+
+ - Inconsistent internal hyperlink targets. Again, unlike all other
+ named hyperlink targets, there's no colon. There's a leading
+ underscore, matching the trailing underscores of references,
+ which no other hyperlink targets have. We can't drop that one
+ leading underscore though: without it, "blah" looks like a
+ relative URI. Again, unless we restore the colon::
+
+ .. blah: internal hyperlink target
+
+ - All (except for internal) hyperlink targets lack their leading
+ underscores, losing the "hyperlink" connotation.
+
+ - Obtrusive syntax for comments. Alternatives::
+
+ ;; blah: http://somewhere
+ (also comment syntax in Lisp & others)
+ ,, blah: http://somewhere
+ ("comma comma": sounds like "comment"!)
+
+ - Iffy syntax for directives. Alternatives?
+
+4. Tony Ibbs' proposed syntax::
+
+ .. _blah: internal hyperlink target
+ .. _blah: http://somewhere external hyperlink target
+ .. _blah: blahblah_ indirect hyperlink target
+ .. anonymous internal target
+ .. http://somewhere anonymous external target
+ .. blahblah_ anonymous indirect target
+ .. [blah] http://somewhere footnote
+ .. blah:: http://somewhere directive
+ .. blah: http://somewhere comment
+
+ This is the same as the current syntax, except for anonymous
+ targets which drop their "__: ".
+
+ Advantage:
+
+ + Anonymous targets are simpler.
+
+ Disadvantages:
+
+ - Anonymous targets lack their leading underscores, losing the
+ "hyperlink" connotation.
+ - Anonymous targets are almost indistinguishable from comments.
+ (Better to know "up front".)
+
+5. David Goodger's proposed syntax: Perhaps going back to one of
+ Alan's earlier suggestions might be the best solution. How about
+ simply adding "__ " as a synonym for ".. __: " in the original
+ syntax? These would become equivalent::
+
+ .. __: anonymous internal target
+ .. __: http://somewhere anonymous external target
+ .. __: blahblah_ anonymous indirect target
+
+ __ anonymous internal target
+ __ http://somewhere anonymous external target
+ __ blahblah_ anonymous indirect target
+
+Alternative 5 has been adopted.
+
+
+Backquotes in Phrase-Links
+==========================
+
+[From a 2001-06-05 Doc-SIG post in reply to questions from Doug
+Hellmann.]
+
+The first draft of the spec, posted to the Doc-SIG in November 2000,
+used square brackets for phrase-links. I changed my mind because:
+
+1. In the first draft, I had already decided on single-backquotes for
+ inline literal text.
+
+2. However, I wanted to minimize the necessity for backslash escapes,
+ for example when quoting Python repr-equivalent syntax that uses
+ backquotes.
+
+3. The processing of identifiers (function/method/attribute/module
+ etc. names) into hyperlinks is a useful feature. PyDoc recognizes
+ identifiers heuristically, but it doesn't take much imagination to
+ come up with counter-examples where PyDoc's heuristics would result
+ in embarassing failure. I wanted to do it deterministically, and
+ that called for syntax. I called this construct "interpreted
+ text".
+
+4. Leveraging off the ``*emphasis*/**strong**`` syntax, lead to the
+ idea of using double-backquotes as syntax.
+
+5. I worked out some rules for inline markup recognition.
+
+6. In combination with #5, double backquotes lent themselves to inline
+ literals, neatly satisfying #2, minimizing backslash escapes. In
+ fact, the spec says that no interpretation of any kind is done
+ within double-backquote inline literal text; backslashes do *no*
+ escaping within literal text.
+
+7. Single backquotes are then freed up for interpreted text.
+
+8. I already had square brackets required for footnote references.
+
+9. Since interpreted text will typically turn into hyperlinks, it was
+ a natural fit to use backquotes as the phrase-quoting syntax for
+ trailing-underscore hyperlinks.
+
+The original inspiration for the trailing underscore hyperlink syntax
+was Setext. But for phrases Setext used a very cumbersome
+``underscores_between_words_like_this_`` syntax.
+
+The underscores can be viewed as if they were right-pointing arrows:
+``-->``. So ``hyperlink_`` points away from the reference, and
+``.. _hyperlink:`` points toward the target.
+
+
+Substitution Mechanism
+======================
+
+Substitutions arose out of a Doc-SIG thread begun on 2001-10-28 by
+Alan Jaffray, "reStructuredText inline markup". It reminded me of a
+missing piece of the reStructuredText puzzle, first referred to in my
+contribution to "Documentation markup & processing / PEPs" (Doc-SIG
+2001-06-21).
+
+Substitutions allow the power and flexibility of directives to be
+shared by inline text. They are a way to allow arbitrarily complex
+inline objects, while keeping the details out of the flow of text.
+They are the equivalent of SGML/XML's named entities. For example, an
+inline image (using reference syntax alternative 4d (vertical bars)
+and definition alternative 3, the alternatives chosen for inclusion in
+the spec)::
+
+ The |biohazard| symbol must be used on containers used to dispose
+ of medical waste.
+
+ .. |biohazard| image:: biohazard.png
+ [height=20 width=20]
+
+The ``|biohazard|`` substitution reference will be replaced in-line by
+whatever the ``.. |biohazard|`` substitution definition generates (in
+this case, an image). A substitution definition contains the
+substitution text bracketed with vertical bars, followed by a an
+embedded inline-compatible directive, such as "image". A transform is
+required to complete the substitution.
+
+Syntax alternatives for the reference:
+
+1. Use the existing interpreted text syntax, with a predefined role
+ such as "sub"::
+
+ The `biohazard`:sub: symbol...
+
+ Advantages: existing syntax, explicit. Disadvantages: verbose,
+ obtrusive.
+
+2. Use a variant of the interpreted text syntax, with a new suffix
+ akin to the underscore in phrase-link references::
+
+ (a) `name`@
+ (b) `name`#
+ (c) `name`&
+ (d) `name`/
+ (e) `name`<
+ (f) `name`::
+ (g) `name`:
+
+
+ Due to incompatibility with other constructs and ordinary text
+ usage, (f) and (g) are not possible.
+
+3. Use interpreted text syntax with a fixed internal format::
+
+ (a) `:name:`
+ (b) `name:`
+ (c) `name::`
+ (d) `::name::`
+ (e) `%name%`
+ (f) `#name#`
+ (g) `/name/`
+ (h) `&name&`
+ (i) `|name|`
+ (j) `[name]`
+ (k) `<name>`
+ (l) `&name;`
+ (m) `'name'`
+
+ To avoid ML confusion (k) and (l) are definitely out. Square
+ brackets (j) won't work in the target (the substitution definition
+ would be indistinguishable from a footnote).
+
+ The ```/name/``` syntax (g) is reminiscent of "s/find/sub"
+ substitution syntax in ed-like languages. However, it may have a
+ misleading association with regexps, and looks like an absolute
+ POSIX path. (i) is visually equivalent and lacking the
+ connotations.
+
+ A disadvantage of all of these is that they limit interpreted text,
+ albeit only slightly.
+
+4. Use specialized syntax, something new::
+
+ (a) #name#
+ (b) @name@
+ (c) /name/
+ (d) |name|
+ (e) <<name>>
+ (f) //name//
+ (g) ||name||
+ (h) ^name^
+ (i) [[name]]
+ (j) ~name~
+ (k) !name!
+ (l) =name=
+ (m) ?name?
+ (n) >name<
+
+ "#" (a) and "@" (b) are obtrusive. "/" (c) without backquotes
+ looks just like a POSIX path; it is likely for such usage to appear
+ in text.
+
+ "|" (d) and "^" (h) are feasible.
+
+5. Redefine the trailing underscore syntax. See definition syntax
+ alternative 4, below.
+
+Syntax alternatives for the definition:
+
+1. Use the existing directive syntax, with a predefined directive such
+ as "sub". It contains a further embedded directive resolving to an
+ inline-compatible object::
+
+ .. sub:: biohazard
+ .. image:: biohazard.png
+ [height=20 width=20]
+
+ .. sub:: parrot
+ That bird wouldn't *voom* if you put 10,000,000 volts
+ through it!
+
+ The advantages and disadvantages are the same as in inline
+ alternative 1.
+
+2. Use syntax as in #1, but with an embedded directivecompressed::
+
+ .. sub:: biohazard image:: biohazard.png
+ [height=20 width=20]
+
+ This is a bit better than alternative 1, but still too much.
+
+3. Use a variant of directive syntax, incorporating the substitution
+ text, obviating the need for a special "sub" directive name. If we
+ assume reference alternative 4d (vertical bars), the matching
+ definition would look like this::
+
+ .. |biohazard| image:: biohazard.png
+ [height=20 width=20]
+
+4. (Suggested by Alan Jaffray on Doc-SIG from 2001-11-06.)
+
+ Instead of adding new syntax, redefine the trailing underscore
+ syntax to mean "substitution reference" instead of "hyperlink
+ reference". Alan's example::
+
+ I had lunch with Jonathan_ today. We talked about Zope_.
+
+ .. _Jonathan: lj [user=jhl]
+ .. _Zope: http://www.zope.org/
+
+ A problem with the proposed syntax is that URIs which look like
+ simple reference names (alphanum plus ".", "-", "_") would be
+ indistinguishable from substitution directive names. A more
+ consistent syntax would be::
+
+ I had lunch with Jonathan_ today. We talked about Zope_.
+
+ .. _Jonathan: lj:: user=jhl
+ .. _Zope: http://www.zope.org/
+
+ (``::`` after ``.. _Jonathan: lj``.)
+
+ The "Zope" target is a simple external hyperlink, but the
+ "Jonathan" target contains a directive. Alan proposed is that the
+ reference text be replaced by whatever the referenced directive
+ (the "directive target") produces. A directive reference becomes a
+ hyperlink reference if the contents of the directive target resolve
+ to a hyperlink. If the directive target resolves to an icon, the
+ reference is replaced by an inline icon. If the directive target
+ resolves to a hyperlink, the directive reference becomes a
+ hyperlink reference.
+
+ This seems too indirect and complicated for easy comprehension.
+
+ The reference in the text will sometimes become a link, sometimes
+ not. Sometimes the reference text will remain, sometimes not. We
+ don't know *at the reference*::
+
+ This is a `hyperlink reference`_; its text will remain.
+ This is an `inline icon`_; its text will disappear.
+
+ That's a problem.
+
+The syntax that has been incorporated into the spec and parser is
+reference alternative 4d with definition alternative 3::
+
+ The |biohazard| symbol...
+
+ .. |biohazard| image:: biohazard.png
+ [height=20 width=20]
+
+We can also combine substitution references with hyperlink references,
+by appending a "_" (named hyperlink reference) or "__" (anonymous
+hyperlink reference) suffix to the substitution reference. This
+allows us to click on an image-link::
+
+ The |biohazard|_ symbol...
+
+ .. |biohazard| image:: biohazard.png
+ [height=20 width=20]
+ .. _biohazard: http://www.cdc.gov/
+
+There have been several suggestions for the naming of these
+constructs, originally called "substitution references" and
+"substitutions".
+
+1. Candidate names for the reference construct:
+
+ (a) substitution reference
+ (b) tagging reference
+ (c) inline directive reference
+ (d) directive reference
+ (e) indirect inline directive reference
+ (f) inline directive placeholder
+ (g) inline directive insertion reference
+ (h) directive insertion reference
+ (i) insertion reference
+ (j) directive macro reference
+ (k) macro reference
+ (l) substitution directive reference
+
+2. Candidate names for the definition construct:
+
+ (a) substitution
+ (b) substitution directive
+ (c) tag
+ (d) tagged directive
+ (e) directive target
+ (f) inline directive
+ (g) inline directive definition
+ (h) referenced directive
+ (i) indirect directive
+ (j) indirect directive definition
+ (k) directive definition
+ (l) indirect inline directive
+ (m) named directive definition
+ (n) inline directive insertion definition
+ (o) directive insertion definition
+ (p) insertion definition
+ (q) insertion directive
+ (r) substitution definition
+ (s) directive macro definition
+ (t) macro definition
+ (u) substitution directive definition
+ (v) substitution definition
+
+"Inline directive reference" (1c) seems to be an appropriate term at
+first, but the term "inline" is redundant in the case of the
+reference. Its counterpart "inline directive definition" (2g) is
+awkward, because the directive definition itself is not inline.
+
+"Directive reference" (1d) and "directive definition" (2k) are too
+vague. "Directive definition" could be used to refer to any
+directive, not just those used for inline substitutions.
+
+One meaning of the term "macro" (1k, 2s, 2t) is too
+programming-language-specific. Also, macros are typically simple text
+substitution mechanisms: the text is substituted first and evaluated
+later. reStructuredText substitution definitions are evaluated in
+place at parse time and substituted afterwards.
+
+"Insertion" (1h, 1i, 2n-2q) is almost right, but it implies that
+something new is getting added rather than one construct being
+replaced by another.
+
+Which brings us back to "substitution". The overall best names are
+"substitution reference" (1a) and "substitution definition" (2v). A
+long way to go to add one word!
+
+
+Inline External Targets
+=======================
+
+Currently reStructuredText has two hyperlink syntax variations:
+
+* Named hyperlinks::
+
+ This is a named reference_ of one word ("reference"). Here is
+ a `phrase reference`_. Phrase references may even cross `line
+ boundaries`_.
+
+ .. _reference: http://www.example.org/reference/
+ .. _phrase reference: http://www.example.org/phrase_reference/
+ .. _line boundaries: http://www.example.org/line_boundaries/
+
+ + Advantages:
+
+ - The plaintext is readable.
+ - Each target may be reused multiple times (e.g., just write
+ ``"reference_"`` again).
+ - No syncronized ordering of references and targets is necessary.
+
+ + Disadvantages:
+
+ - The reference text must be repeated as target names; could lead
+ to mistakes.
+ - The target URLs may be located far from the references, and hard
+ to find in the plaintext.
+
+* Anonymous hyperlinks (in current reStructuredText)::
+
+ This is an anonymous reference__. Here is an anonymous
+ `phrase reference`__. Phrase references may even cross `line
+ boundaries`__.
+
+ __ http://www.example.org/reference/
+ __ http://www.example.org/phrase_reference/
+ __ http://www.example.org/line_boundaries/
+
+ + Advantages:
+
+ - The plaintext is readable.
+ - The reference text does not have to be repeated.
+
+ + Disadvantages:
+
+ - References and targets must be kept in sync.
+ - Targets cannot be reused.
+ - The target URLs may be located far from the references.
+
+For comparison and historical background, StructuredText also has two
+syntaxes for hyperlinks:
+
+* First, ``"reference text":URL``::
+
+ This is a "reference":http://www.example.org/reference/
+ of one word ("reference"). Here is a "phrase
+ reference":http://www.example.org/phrase_reference/.
+
+* Second, ``"reference text", http://example.com/absolute_URL``::
+
+ This is a "reference", http://www.example.org/reference/
+ of one word ("reference"). Here is a "phrase reference",
+ http://www.example.org/phrase_reference/.
+
+Both syntaxes share advantages and disadvantages:
+
++ Advantages:
+
+ - The target is specified immediately adjacent to the reference.
+
++ Disadvantages:
+
+ - Poor plaintext readability.
+ - Targets cannot be reused.
+ - Both syntaxes use double quotes, common in ordinary text.
+ - In the first syntax, the URL and the last word are stuck
+ together, exacerbating the line wrap problem.
+ - The second syntax is too magical; text could easily be written
+ that way by accident (although only absolute URLs are recognized
+ here, perhaps because of the potential for ambiguity).
+
+A new type of "inline external hyperlink" has been proposed.
+
+1. On 2002-06-28, Simon Budig proposed__ a new syntax for
+ reStructuredText hyperlinks::
+
+ This is a reference_(http://www.example.org/reference/) of one
+ word ("reference"). Here is a `phrase
+ reference`_(http://www.example.org/phrase_reference/). Are
+ these examples, (single-underscore), named? If so, `anonymous
+ references`__(http://www.example.org/anonymous/) using two
+ underscores would probably be preferable.
+
+ __ http://mail.python.org/pipermail/doc-sig/2002-June/002648.html
+
+ The syntax, advantages, and disadvantages are similar to those of
+ StructuredText.
+
+ + Advantages:
+
+ - The target is specified immediately adjacent to the reference.
+
+ + Disadvantages:
+
+ - Poor plaintext readability.
+ - Targets cannot be reused (unless named, but the semantics are
+ unclear).
+
+ + Problems:
+
+ - The ``"`ref`_(URL)"`` syntax forces the last word of the
+ reference text to be joined to the URL, making a potentially
+ very long word that can't be wrapped (URLs can be very long).
+ The reference and the URL should be separate. This is a
+ symptom of the following point:
+
+ - The syntax produces a single compound construct made up of two
+ equally important parts, *with syntax in the middle*, *between*
+ the reference and the target. This is unprecedented in
+ reStructuredText.
+
+ - The "inline hyperlink" text is *not* a named reference (there's
+ no lookup by name), so it shouldn't look like one.
+
+ - According to the IETF standards RFC 2396 and RFC 2732,
+ parentheses are legal URI characters and curly braces are legal
+ email characters, making their use prohibitively difficult.
+
+ - The named/anonymous semantics are unclear.
+
+2. After an analysis__ of the syntax of (1) above, we came up with the
+ following compromise syntax::
+
+ This is an anonymous reference__
+ __<http://www.example.org/reference/> of one word
+ ("reference"). Here is a `phrase reference`__
+ __<http://www.example.org/phrase_reference/>. `Named
+ references`_ _<http://www.example.org/anonymous/> use single
+ underscores.
+
+ __ http://mail.python.org/pipermail/doc-sig/2002-July/002670.html
+
+ The syntax builds on that of the existing "inline internal
+ targets": ``an _`inline internal target`.``
+
+ + Advantages:
+
+ - The target is specified immediately adjacent to the reference,
+ improving maintainability:
+
+ - References and targets are easily kept in sync.
+ - The reference text does not have to be repeated.
+
+ - The construct is executed in two parts: references identical to
+ existing references, and targets that are new but not too big a
+ stretch from current syntax.
+
+ - There's overwhelming precedent for quoting URLs with angle
+ brackets [#]_.
+
+ + Disadvantages:
+
+ - Poor plaintext readability.
+ - Lots of "line noise".
+ - Targets cannot be reused (unless named; see below).
+
+ To alleviate the readability issue slightly, we could allow the
+ target to appear later, such as after the end of the sentence::
+
+ This is a named reference__ of one word ("reference").
+ __<http://www.example.org/reference/> Here is a `phrase
+ reference`__. __<http://www.example.org/phrase_reference/>
+
+ Problem: this could only work for one reference at a time
+ (reference/target pairs must be proximate [refA trgA refB trgB],
+ not interleaved [refA refB trgA trgB] or nested [refA refB trgB
+ trgA]). This variation is too problematic; references and inline
+ external targets will have to be kept imediately adjacent (see (3)
+ below).
+
+ The ``"reference__ __<target>"`` syntax is actually for "anonymous
+ inline external targets", emphasized by the double underscores. It
+ follows that single trailing and leading underscores would lead to
+ *implicitly named* inline external targets. This would allow the
+ reuse of targets by name. So after ``"reference_ _<target>"``,
+ another ``"reference_"`` would point to the same target.
+
+ .. [#]
+ From RFC 2396 (URI syntax):
+
+ The angle-bracket "<" and ">" and double-quote (")
+ characters are excluded [from URIs] because they are often
+ used as the delimiters around URI in text documents and
+ protocol fields.
+
+ Using <> angle brackets around each URI is especially
+ recommended as a delimiting style for URI that contain
+ whitespace.
+
+ From RFC 822 (email headers):
+
+ Angle brackets ("<" and ">") are generally used to indicate
+ the presence of a one machine-usable reference (e.g.,
+ delimiting mailboxes), possibly including source-routing to
+ the machine.
+
+3. If it is best for references and inline external targets to be
+ immediately adjacent, then they might as well be integrated.
+ Here's an alternative syntax embedding the target URL in the
+ reference::
+
+ This is an anonymous `reference <http://www.example.org
+ /reference/>`__ of one word ("reference"). Here is a `phrase
+ reference <http://www.example.org/phrase_reference/>`__.
+
+ Advantages and disadvantages are similar to those in (2).
+ Readability is still an issue, but the syntax is a bit less
+ heavyweight (reduced line noise). Backquotes are required, even
+ for one-word references; the target URL is included within the
+ reference text, forcing a phrase context.
+
+ We'll call this variant "embedded URIs".
+
+ Problem: how to refer to a title like "HTML Anchors: <a>" (which
+ ends with an HTML/SGML/XML tag)? We could either require more
+ syntax on the target (like ``"`reference text
+ __<http://example.com/>`__"``), or require the odd conflicting
+ title to be escaped (like ``"`HTML Anchors: \<a>`__"``). The
+ latter seems preferable, and not too onerous.
+
+ Similarly to (2) above, a single trailing underscore would convert
+ the reference & inline external target from anonymous to implicitly
+ named, allowing reuse of targets by name.
+
+ I think this is the least objectionable of the syntax alternatives.
+
+Other syntax variations have been proposed (by Brett Cannon and Benja
+Fallenstein)::
+
+ `phrase reference`->http://www.example.com
+
+ `phrase reference`@http://www.example.com
+
+ `phrase reference`__ ->http://www.example.com
+
+ `phrase reference` [-> http://www.example.com]
+
+ `phrase reference`__ [-> http://www.example.com]
+
+ `phrase reference` <http://www.example.com>_
+
+None of these variations are clearly superior to #3 above. Some have
+problems that exclude their use.
+
+With any kind of inline external target syntax it comes down to the
+conflict between maintainability and plaintext readability. I don't
+see a major problem with reStructuredText's maintainability, and I
+don't want to sacrifice plaintext readability to "improve" it.
+
+The proponents of inline external targets want them for easily
+maintainable web pages. The arguments go something like this:
+
+- Named hyperlinks are difficult to maintain because the reference
+ text is duplicated as the target name.
+
+ To which I said, "So use anonymous hyperlinks."
+
+- Anonymous hyperlinks are difficult to maintain becuase the
+ references and targets have to be kept in sync.
+
+ "So keep the targets close to the references, grouped after each
+ paragraph. Maintenance is trivial."
+
+- But targets grouped after paragraphs break the flow of text.
+
+ "Surely less than URLs embedded in the text! And if the intent is
+ to produce web pages, not readable plaintext, then who cares about
+ the flow of text?"
+
+Many participants have voiced their objections to the proposed syntax:
+
+ Garth Kidd: "I strongly prefer the current way of doing it.
+ Inline is spectactularly messy, IMHO."
+
+ Tony Ibbs: "I vehemently agree... that the inline alternatives
+ being suggested look messy - there are/were good reasons they've
+ been taken out... I don't believe I would gain from the new
+ syntaxes."
+
+ Paul Moore: "I agree as well. The proposed syntax is far too
+ punctuation-heavy, and any of the alternatives discussed are
+ ambiguous or too subtle."
+
+Others have voiced their support:
+
+ fantasai: "I agree with Simon. In many cases, though certainly
+ not in all, I find parenthesizing the url in plain text flows
+ better than relegating it to a footnote."
+
+ Ken Manheimer: "I'd like to weigh in requesting some kind of easy,
+ direct inline reference link."
+
+(Interesting that those *against* the proposal have been using
+reStructuredText for a while, and those *for* the proposal are either
+new to the list ["fantasai", background unknown] or longtime
+StructuredText users [Ken Manheimer].)
+
+I was initially ambivalent/against the proposed "inline external
+targets". I value reStructuredText's readability very highly, and
+although the proposed syntax offers convenience, I don't know if the
+convenience is worth the cost in ugliness. Does the proposed syntax
+compromise readability too much, or should the choice be left up to
+the author? Perhaps if the syntax is *allowed* but its use strongly
+*discouraged*, for aesthetic/readability reasons?
+
+After a great deal of thought and much input from users, I've decided
+that there are reasonable use cases for this construct. The
+documentation should strongly caution against its use in most
+situations, recommending independent block-level targets instead.
+Syntax #3 above ("embedded URIs") will be used.
+
+
+Doctree Representation of Transitions
+=====================================
+
+(Although not reStructuredText-specific, this section fits best in
+this document.)
+
+Having added the "horizontal rule" construct to the `reStructuredText
+Markup Specification`_, a decision had to be made as to how to reflect
+the construct in the implementation of the document tree. Given this
+source::
+
+ Document
+ ========
+
+ Paragraph 1
+
+ --------
+
+ Paragraph 2
+
+The horizontal rule indicates a "transition" (in prose terms) or the
+start of a new "division". Before implementation, the parsed document
+tree would be::
+
+ <document>
+ <section names="document">
+ <title>
+ Document
+ <paragraph>
+ Paragraph 1
+ -------- <--- error here
+ <paragraph>
+ Paragraph 2
+
+There are several possibilities for the implementation:
+
+1. Implement horizontal rules as "divisions" or segments. A
+ "division" is a title-less, non-hierarchical section. The first
+ try at an implementation looked like this::
+
+ <document>
+ <section names="document">
+ <title>
+ Document
+ <paragraph>
+ Paragraph 1
+ <division>
+ <paragraph>
+ Paragraph 2
+
+ But the two paragraphs are really at the same level; they shouldn't
+ appear to be at different levels. There's really an invisible
+ "first division". The horizontal rule splits the document body
+ into two segments, which should be treated uniformly.
+
+2. Treating "divisions" uniformly brings us to the second
+ possibility::
+
+ <document>
+ <section names="document">
+ <title>
+ Document
+ <division>
+ <paragraph>
+ Paragraph 1
+ <division>
+ <paragraph>
+ Paragraph 2
+
+ With this change, documents and sections will directly contain
+ divisions and sections, but not body elements. Only divisions will
+ directly contain body elements. Even without a horizontal rule
+ anywhere, the body elements of a document or section would be
+ contained within a division element. This makes the document tree
+ deeper. This is similar to the way HTML_ treats document contents:
+ grouped within a ``<body>`` element.
+
+3. Implement them as "transitions", empty elements::
+
+ <document>
+ <section names="document">
+ <title>
+ Document
+ <paragraph>
+ Paragraph 1
+ <transition>
+ <paragraph>
+ Paragraph 2
+
+ A transition would be a "point element", not containing anything,
+ only identifying a point within the document structure. This keeps
+ the document tree flatter, but the idea of a "point element" like
+ "transition" smells bad. A transition isn't a thing itself, it's
+ the space between two divisions. However, transitions are a
+ practical solution.
+
+Solution 3 was chosen for incorporation into the document tree model.
+
+.. _HTML: http://www.w3.org/MarkUp/
+
+
+Syntax for Line Blocks
+======================
+
+* An early idea: How about a literal-block-like prefix, perhaps
+ "``;;``"? (It is, after all, a *semi-literal* literal block, no?)
+ Example::
+
+ Take it away, Eric the Orchestra Leader! ;;
+
+ A one, two, a one two three four
+
+ Half a bee, philosophically,
+ must, *ipso facto*, half not be.
+ But half the bee has got to be,
+ *vis a vis* its entity. D'you see?
+
+ But can a bee be said to be
+ or not to be an entire bee,
+ when half the bee is not a bee,
+ due to some ancient injury?
+
+ Singing...
+
+ Kinda lame.
+
+* Another idea: in an ordinary paragraph, if the first line ends with
+ a backslash (escaping the newline), interpret the entire paragraph
+ as a verse block? For example::
+
+ Add just one backslash\
+ And this paragraph becomes
+ An awful haiku
+
+ (Awful, and arguably invalid, since in Japanese the word "haiku"
+ contains three syllables not two.)
+
+ This idea was superceded by the rules for escaped whitespace, useful
+ for `character-level inline markup`_.
+
+* In a `2004-02-22 docutils-develop message`__, Jarno Elonen proposed
+ a "plain list" syntax (and also provided a patch)::
+
+ | John Doe
+ | President, SuperDuper Corp.
+ | jdoe@example.org
+
+ __ http://thread.gmane.org/gmane.text.docutils.devel/1187
+
+ This syntax is very natural. However, these "plain lists" seem very
+ similar to line blocks, and I see so little intrinsic "list-ness"
+ that I'm loathe to add a new object. I used the term "blurbs" to
+ remove the "list" connotation from the originally proposed name.
+ Perhaps line blocks could be refined to add the two properties they
+ currently lack:
+
+ A) long lines wrap nicely
+ B) HTML output doesn't look like program code in non-CSS web
+ browsers
+
+ (A) is an issue of all 3 aspects of Docutils: syntax (construct
+ behaviour), internal representation, and output. (B) is partly an
+ issue of internal representation but mostly of output.
+
+ReStructuredText will redefine line blocks with the "|"-quoting
+syntax. The following is my current thinking.
+
+
+Syntax
+------
+
+Perhaps line block syntax like this would do::
+
+ | M6: James Bond
+ | MIB: Mr. J.
+ | IMF: not decided yet, but probably one of the following:
+ | Ethan Hunt
+ | Jim Phelps
+ | Claire Phelps
+ | CIA: Lea Leiter
+
+Note that the "nested" list does not have nested syntax (the "|" are
+not further indented); the leading whitespace would still be
+significant somehow (more below). As for long lines in the input,
+this could suffice::
+
+ | John Doe
+ | Founder, President, Chief Executive Officer, Cook, Bottle
+ Washer, and All-Round Great Guy
+ | SuperDuper Corp.
+ | jdoe@example.org
+
+The lack of "|" on the third line indicates that it's a continuation
+of the second line, wrapped.
+
+I don't see much point in allowing arbitrary nested content. Multiple
+paragraphs or bullet lists inside a "blurb" doesn't make sense to me.
+Simple nested line blocks should suffice.
+
+
+Internal Representation
+-----------------------
+
+Line blocks are currently represented as text blobs as follows::
+
+ <!ELEMENT line_block %text.model;>
+ <!ATTLIST line_block
+ %basic.atts;
+ %fixedspace.att;>
+
+Instead, we could represent each line by a separate element::
+
+ <!ELEMENT line_block (line+)>
+ <!ATTLIST line_block %basic.atts;>
+
+ <!ELEMENT line %text.model;>
+ <!ATTLIST line %basic.atts;>
+
+We'd keep the significance of the leading whitespace of each line
+either by converting it to non-breaking spaces at output, or with a
+per-line margin. Non-breaking spaces are simpler (for HTML, anyway)
+but kludgey, and wouldn't support indented long lines that wrap. But
+should inter-word whitespace (i.e., not leading whitespace) be
+preserved? Currently it is preserved in line blocks.
+
+Representing a more complex line block may be tricky::
+
+ | But can a bee be said to be
+ | or not to be an entire bee,
+ | when half the bee is not a bee,
+ | due to some ancient injury?
+
+Perhaps the representation could allow for nested line blocks::
+
+ <!ELEMENT line_block (line | line_block)+>
+
+With this model, leading whitespace would no longer be significant.
+Instead, left margins are implied by the nesting. The example above
+could be represented as follows::
+
+ <line_block>
+ <line>
+ But can a bee be said to be
+ <line_block>
+ <line>
+ or not to be an entire bee,
+ <line_block>
+ <line>
+ when half the bee is not a bee,
+ <line_block>
+ <line>
+ due to some ancient injury?
+
+I wasn't sure what to do about even more complex line blocks::
+
+ | Indented
+ | Not indented
+ | Indented a bit
+ | A bit more
+ | Only one space
+
+How should that be parsed and nested? Should the first line have
+the same nesting level (== indentation in the output) as the fourth
+line, or the same as the last line? Mark Nodine suggested that such
+line blocks be parsed similarly to complexly-nested block quotes,
+which seems reasonable. In the example above, this would result in
+the nesting of first line matching the last line's nesting. In
+other words, the nesting would be relative to neighboring lines
+only.
+
+
+Output
+------
+
+In HTML, line blocks are currently output as "<pre>" blocks, which
+gives us significant whitespace and line breaks, but doesn't allow
+long lines to wrap and causes monospaced output without stylesheets.
+Instead, we could output "<div>" elements parallelling the
+representation above, where each nested <div class="line_block"> would
+have an increased left margin (specified in the stylesheet).
+
+Jarno suggested the following HTML output::
+
+ <div class="line_block">
+ <span class="line">First, top level line</span><br class="hidden"/>
+ <div class="line_block"><span class="hidden"> </span>
+ <span class="line">Second, once nested</span><br class="hidden"/>
+ <span class="line">Third, once nested</span><br class="hidden"/>
+ ...
+ </div>
+ ...
+ </div>
+
+The ``<br class="hidden" />`` and ``<span
+class="hidden"> </span>`` are meant to support non-CSS and
+non-graphical browsers. I understand the case for "br", but I'm not
+so sure about hidden " ". I question how much effort should be
+put toward supporting non-graphical and especially non-CSS browsers,
+at least for html4css1.py output.
+
+Should the lines themselves be ``<span>`` or ``<div>``? I don't like
+mixing inline and block-level elements.
+
+
+Implementation Plan
+-------------------
+
+We'll leave the old implementation in place (via the "line-block"
+directive only) until all Writers have been updated to support the new
+syntax & implementation. The "line-block" directive can then be
+updated to use the new internal representation, and its documentation
+will be updated to recommend the new syntax.
+
+
+List-Driven Tables
+==================
+
+The original idea came from Dylan Jay:
+
+ ... to use a two level bulleted list with something to
+ indicate it should be rendered as a table ...
+
+It's an interesting idea. It could be implemented in as a directive
+which transforms a uniform two-level list into a table. Using a
+directive would allow the author to explicitly set the table's
+orientation (by column or by row), the presence of row headers, etc.
+
+Alternatives:
+
+1. (Implemented in Docutils 0.3.8).
+
+ Bullet-list-tables might look like this::
+
+ .. list-table::
+
+ * - Treat
+ - Quantity
+ - Description
+ * - Albatross!
+ - 299
+ - On a stick!
+ * - Crunchy Frog!
+ - 1499
+ - If we took the bones out, it wouldn't be crunchy,
+ now would it?
+ * - Gannet Ripple!
+ - 199
+ - On a stick!
+
+ This list must be written in two levels. This wouldn't work::
+
+ .. list-table::
+
+ * Treat
+ * Albatross!
+ * Gannet!
+ * Crunchy Frog!
+
+ * Quantity
+ * 299
+ * 199
+ * 1499
+
+ * Description
+ * On a stick!
+ * On a stick!
+ * If we took the bones out...
+
+ The above is a single list of 12 items. The blank lines are not
+ significant to the markup. We'd have to explicitly specify how
+ many columns or rows to use, which isn't a good idea.
+
+2. Beni Cherniavsky suggested a field list alternative. It could look
+ like this::
+
+ .. field-list-table::
+ :headrows: 1
+
+ - :treat: Treat
+ :quantity: Quantity
+ :descr: Description
+
+ - :treat: Albatross!
+ :quantity: 299
+ :descr: On a stick!
+
+ - :treat: Crunchy Frog!
+ :quantity: 1499
+ :descr: If we took the bones out, it wouldn't be
+ crunchy, now would it?
+
+ Column order is determined from the order of fields in the first
+ row. Field order in all other rows is ignored. As a side-effect,
+ this allows trivial re-arrangement of columns. By using named
+ fields, it becomes possible to omit fields in some rows without
+ losing track of things, which is important for spans.
+
+3. An alternative to two-level bullet lists would be to use enumerated
+ lists for the table cells::
+
+ .. list-table::
+
+ * 1. Treat
+ 2. Quantity
+ 3. Description
+ * 1. Albatross!
+ 2. 299
+ 3. On a stick!
+ * 1. Crunchy Frog!
+ 2. 1499
+ 3. If we took the bones out, it wouldn't be crunchy,
+ now would it?
+
+ That provides better correspondence between cells in the same
+ column than does bullet-list syntax, but not as good as field list
+ syntax. I think that were only field-list-tables available, a lot
+ of users would use the equivalent degenerate case::
+
+ .. field-list-table::
+ - :1: Treat
+ :2: Quantity
+ :3: Description
+ ...
+
+4. Another natural variant is to allow a description list with field
+ lists as descriptions::
+
+ .. list-table::
+ :headrows: 1
+
+ Treat
+ :quantity: Quantity
+ :descr: Description
+ Albatross!
+ :quantity: 299
+ :descr: On a stick!
+ Crunchy Frog!
+ :quantity: 1499
+ :descr: If we took the bones out, it wouldn't be
+ crunchy, now would it?
+
+ This would make the whole first column a header column ("stub").
+ It's limited to a single column and a single paragraph fitting on
+ one source line. Also it wouldn't allow for empty cells or row
+ spans in the first column. But these are limitations that we could
+ live with, like those of simple tables.
+
+The List-driven table feature could be done in many ways. Each user
+will have their preferred usage. Perhaps a single "list-table"
+directive could handle them all, depending on which options and
+content are present.
+
+Issues:
+
+* How to indicate that there's 1 header row? Perhaps two lists? ::
+
+ .. list-table::
+
+ + - Treat
+ - Quantity
+ - Description
+
+ * - Albatross!
+ - 299
+ - On a stick!
+
+ This is probably too subtle though. Better would be a directive
+ option, like ``:headrows: 1``. An early suggestion for the header
+ row(s) was to use a directive option::
+
+ .. field-list-table::
+ :header:
+ - :treat: Treat
+ :quantity: Quantity
+ :descr: Description
+ - :treat: Albatross!
+ :quantity: 299
+ :descr: On a stick!
+
+ But the table data is at two levels and looks inconsistent.
+
+ In general, we cannot extract the header row from field lists' field
+ names because field names cannot contain everything one might put in
+ a table cell. A separate header row also allows shorter field names
+ and doesn't force one to rewrite the whole table when the header
+ text changes. But for simpler cases, we can offer a ":header:
+ fields" option, which does extract header cells from field names::
+
+ .. field-list-table::
+ :header: fields
+
+ - :Treat: Albatross!
+ :Quantity: 299
+ :Description: On a stick!
+
+* How to indicate the column widths? A directive option? ::
+
+ .. list-table::
+ :widths: 15 10 35
+
+ Automatic defaults from the text used?
+
+* How to handle row and/or column spans?
+
+ In a field list, column-spans can be indicated by specifying the
+ first and last fields, separated by space-dash-space or ellipsis::
+
+ - :foo - baz: quuux
+ - :foo ... baz: quuux
+
+ Commas were proposed for column spans::
+
+ - :foo, bar: quux
+
+ But non-adjacent columns become problematic. Should we report an
+ error, or duplicate the value into each span of adjacent columns (as
+ was suggested)? The latter suggestion is appealing but may be too
+ clever. Best perhaps to simply specify the two ends.
+
+ It was suggested that comma syntax should be allowed, too, in order
+ to allow the user to avoid trouble when changing the column order.
+ But changing the column order of a table with spans is not trivial;
+ we shouldn't make it easier to mess up.
+
+ One possible syntax for row-spans is to simply treat any row where a
+ field is missing as a row-span from the last row where it appeared.
+ Leaving a field empty would still be possible by writing a field
+ with empty content. But this is too implicit.
+
+ Another way would be to require an explicit continuation marker
+ (``...``/``-"-``/``"``?) in all but the first row of a spanned
+ field. Empty comments could work (".."). If implemented, the same
+ marker could also be supported in simple tables, which lack
+ row-spanning abilities.
+
+ Explicit markup like ":rowspan:" and ":colspan:" was also suggested.
+
+ Sometimes in a table, the first header row contains spans. It may
+ be necessary to provide a way to specify the column field names
+ independently of data rows. A directive option would do it.
+
+* We could specify "column-wise" or "row-wise" ordering, with the same
+ markup structure. For example, with definition data::
+
+ .. list-table::
+ :column-wise:
+
+ Treat
+ - Albatross!
+ - Crunchy Frog!
+ Quantity
+ - 299
+ - 1499
+ Description
+ - On a stick!
+ - If we took the bones out, it wouldn't be
+ crunchy, now would it?
+
+* A syntax for _`stubs in grid tables` is easy to imagine::
+
+ +------------------------++------------+----------+
+ | Header row, column 1 || Header 2 | Header 3 |
+ +========================++============+==========+
+ | body row 1, column 1 || column 2 | column 3 |
+ +------------------------++------------+----------+
+
+ Or this idea from Nick Moffitt::
+
+ +-----+---+---+
+ | XOR # T | F |
+ +=====+===+===+
+ | T # F | T |
+ +-----+---+---+
+ | F # T | F |
+ +-----+---+---+
+
+
+Auto-Enumerated Lists
+=====================
+
+Implemented 2005-03-24: combination of variation 1 & 2.
+
+The advantage of auto-numbered enumerated lists would be similar to
+that of auto-numbered footnotes: lists could be written and rearranged
+without having to manually renumber them. The disadvantages are also
+the same: input and output wouldn't match exactly; the markup may be
+ugly or confusing (depending on which alternative is chosen).
+
+1. Use the "#" symbol. Example::
+
+ #. Item 1.
+ #. Item 2.
+ #. Item 3.
+
+ Advantages: simple, explicit. Disadvantage: enumeration sequence
+ cannot be specified (limited to arabic numerals); ugly.
+
+2. As a variation on #1, first initialize the enumeration sequence?
+ For example::
+
+ a) Item a.
+ #) Item b.
+ #) Item c.
+
+ Advantages: simple, explicit, any enumeration sequence possible.
+ Disadvantages: ugly; perhaps confusing with mixed concrete/abstract
+ enumerators.
+
+3. Alternative suggested by Fred Bremmer, from experience with MoinMoin::
+
+ 1. Item 1.
+ 1. Item 2.
+ 1. Item 3.
+
+ Advantages: enumeration sequence is explicit (could be multiple
+ "a." or "(I)" tokens). Disadvantages: perhaps confusing; otherwise
+ erroneous input (e.g., a duplicate item "1.") would pass silently,
+ either causing a problem later in the list (if no blank lines
+ between items) or creating two lists (with blanks).
+
+ Take this input for example::
+
+ 1. Item 1.
+
+ 1. Unintentional duplicate of item 1.
+
+ 2. Item 2.
+
+ Currently the parser will produce two list, "1" and "1,2" (no
+ warnings, because of the presence of blank lines). Using Fred's
+ notation, the current behavior is "1,1,2 -> 1 1,2" (without blank
+ lines between items, it would be "1,1,2 -> 1 [WARNING] 1,2"). What
+ should the behavior be with auto-numbering?
+
+ Fred has produced a patch__, whose initial behavior is as follows::
+
+ 1,1,1 -> 1,2,3
+ 1,2,2 -> 1,2,3
+ 3,3,3 -> 3,4,5
+ 1,2,2,3 -> 1,2,3 [WARNING] 3
+ 1,1,2 -> 1,2 [WARNING] 2
+
+ (After the "[WARNING]", the "3" would begin a new list.)
+
+ I have mixed feelings about adding this functionality to the spec &
+ parser. It would certainly be useful to some users (myself
+ included; I often have to renumber lists). Perhaps it's too
+ clever, asking the parser to guess too much. What if you *do* want
+ three one-item lists in a row, each beginning with "1."? You'd
+ have to use empty comments to force breaks. Also, I question
+ whether "1,2,2 -> 1,2,3" is optimal behavior.
+
+ In response, Fred came up with "a stricter and more explicit rule
+ [which] would be to only auto-number silently if *all* the
+ enumerators of a list were identical". In that case::
+
+ 1,1,1 -> 1,2,3
+ 1,2,2 -> 1,2 [WARNING] 2
+ 3,3,3 -> 3,4,5
+ 1,2,2,3 -> 1,2 [WARNING] 2,3
+ 1,1,2 -> 1,2 [WARNING] 2
+
+ Should any start-value be allowed ("3,3,3"), or should
+ auto-numbered lists be limited to begin with ordinal-1 ("1", "A",
+ "a", "I", or "i")?
+
+ __ http://sourceforge.net/tracker/index.php?func=detail&aid=548802
+ &group_id=38414&atid=422032
+
+4. Alternative proposed by Tony Ibbs::
+
+ #1. First item.
+ #3. Aha - I edited this in later.
+ #2. Second item.
+
+ The initial proposal required unique enumerators within a list, but
+ this limits the convenience of a feature of already limited
+ applicability and convenience. Not a useful requirement; dropped.
+
+ Instead, simply prepend a "#" to a standard list enumerator to
+ indicate auto-enumeration. The numbers (or letters) of the
+ enumerators themselves are not significant, except:
+
+ - as a sequence indicator (arabic, roman, alphabetic; upper/lower),
+
+ - and perhaps as a start value (first list item).
+
+ Advantages: explicit, any enumeration sequence possible.
+ Disadvantages: a bit ugly.
+
+
+Adjacent citation references
+============================
+
+A special case for inline markup was proposed and implemented:
+multiple citation references could be joined into one::
+
+ [cite1]_[cite2]_ instead of requiring [cite1]_ [cite2]_
+
+However, this was rejected as an unwarranted exception to the rules
+for inline markup.
+(The main motivation for the proposal, grouping citations in the latex writer,
+was implemented by recognising the second group in the example above and
+transforming it into ``\cite{cite1,cite2}``.)
+
+
+Inline markup recognition
+=========================
+
+Implemented 2011-12-05 (version 0.9):
+Extended `inline markup recognition rules`_.
+
+Non-ASCII whitespace, punctuation characters and "international" quotes are
+allowed around inline markup (based on `Unicode categories`_). The rules for
+ASCII characters were not changed.
+
+Rejected alternatives:
+
+a) Use `Unicode categories`_ for all chars (ASCII or not)
+
+ +1 comprehensible, standards based,
+ -1 many "false positives" need escaping,
+ -1 not backwards compatible.
+
+b) full backwards compatibility
+
+ :Pi: only before start-string
+ :Pf: only behind end-string
+ :Po: "conservative" sorting of other punctuation:
+
+ :``.,;!?\\``: Close
+ :``¡¿``: Open
+
+ +1 backwards compatible,
+ +1 logical extension of the existing rules,
+ -1 exception list for "other" punctuation needed,
+ -1 rules even more complicated,
+ -1 not clear how to sort "other" punctuation that is currently not
+ recognized,
+ -2 international quoting convention like
+ »German ›angular‹ quotes« not recognized.
+
+.. _Inline markup recognition rules:
+ ../../ref/rst/restructuredtext.html#inline-markup-recognition-rules
+.. _Unicode categories:
+ http://www.unicode.org/Public/5.1.0/ucd/UCD.html#General_Category_Values
+
+
+-----------------
+ Not Implemented
+-----------------
+
+Reworking Footnotes
+===================
+
+As a further wrinkle (see `Reworking Explicit Markup (Round 1)`_
+above), in the wee hours of 2002-02-28 I posted several ideas for
+changes to footnote syntax:
+
+ - Change footnote syntax from ``.. [1]`` to ``_[1]``? ...
+ - Differentiate (with new DTD elements) author-date "citations"
+ (``[GVR2002]``) from numbered footnotes? ...
+ - Render footnote references as superscripts without "[]"? ...
+
+These ideas are all related, and suggest changes in the
+reStructuredText syntax as well as the docutils tree model.
+
+The footnote has been used for both true footnotes (asides expanding
+on points or defining terms) and for citations (references to external
+works). Rather than dealing with one amalgam construct, we could
+separate the current footnote concept into strict footnotes and
+citations. Citations could be interpreted and treated differently
+from footnotes. Footnotes would be limited to numerical labels:
+manual ("1") and auto-numbered (anonymous "#", named "#label").
+
+The footnote is the only explicit markup construct (starts with ".. ")
+that directly translates to a visible body element. I've always been
+a little bit uncomfortable with the ".. " marker for footnotes because
+of this; ".. " has a connotation of "special", but footnotes aren't
+especially "special". Printed texts often put footnotes at the bottom
+of the page where the reference occurs (thus "foot note"). Some HTML
+designs would leave footnotes to be rendered the same positions where
+they're defined. Other online and printed designs will gather
+footnotes into a section near the end of the document, converting them
+to "endnotes" (perhaps using a directive in our case); but this
+"special processing" is not an intrinsic property of the footnote
+itself, but a decision made by the document author or processing
+system.
+
+Citations are almost invariably collected in a section at the end of a
+document or section. Citations "disappear" from where they are
+defined and are magically reinserted at some well-defined point.
+There's more of a connection to the "special" connotation of the ".. "
+syntax. The point at which the list of citations is inserted could be
+defined manually by a directive (e.g., ".. citations::"), and/or have
+default behavior (e.g., a section automatically inserted at the end of
+the document) that might be influenced by options to the Writer.
+
+Syntax proposals:
+
++ Footnotes:
+
+ - Current syntax::
+
+ .. [1] Footnote 1
+ .. [#] Auto-numbered footnote.
+ .. [#label] Auto-labeled footnote.
+
+ - The syntax proposed in the original 2002-02-28 Doc-SIG post:
+ remove the ".. ", prefix a "_"::
+
+ _[1] Footnote 1
+ _[#] Auto-numbered footnote.
+ _[#label] Auto-labeled footnote.
+
+ The leading underscore syntax (earlier dropped because
+ ``.. _[1]:`` was too verbose) is a useful reminder that footnotes
+ are hyperlink targets.
+
+ - Minimal syntax: remove the ".. [" and "]", prefix a "_", and
+ suffix a "."::
+
+ _1. Footnote 1.
+ _#. Auto-numbered footnote.
+ _#label. Auto-labeled footnote.
+
+ ``_1.``, ``_#.``, and ``_#label.`` are markers,
+ like list markers.
+
+ Footnotes could be rendered something like this in HTML
+
+ | 1. This is a footnote. The brackets could be dropped
+ | from the label, and a vertical bar could set them
+ | off from the rest of the document in the HTML.
+
+ Two-way hyperlinks on the footnote marker ("1." above) would also
+ help to differentiate footnotes from enumerated lists.
+
+ If converted to endnotes (by a directive/transform), a horizontal
+ half-line might be used instead. Page-oriented output formats
+ would typically use the horizontal line for true footnotes.
+
++ Footnote references:
+
+ - Current syntax::
+
+ [1]_, [#]_, [#label]_
+
+ - Minimal syntax to match the minimal footnote syntax above::
+
+ 1_, #_, #label_
+
+ As a consequence, pure-numeric hyperlink references would not be
+ possible; they'd be interpreted as footnote references.
+
++ Citation references: no change is proposed from the current footnote
+ reference syntax::
+
+ [GVR2001]_
+
++ Citations:
+
+ - Current syntax (footnote syntax)::
+
+ .. [GVR2001] Python Documentation; van Rossum, Drake, et al.;
+ http://www.python.org/doc/
+
+ - Possible new syntax::
+
+ _[GVR2001] Python Documentation; van Rossum, Drake, et al.;
+ http://www.python.org/doc/
+
+ _[DJG2002]
+ Docutils: Python Documentation Utilities project; Goodger
+ et al.; http://docutils.sourceforge.net/
+
+ Without the ".. " marker, subsequent lines would either have to
+ align as in one of the above, or we'd have to allow loose
+ alignment (I'd rather not)::
+
+ _[GVR2001] Python Documentation; van Rossum, Drake, et al.;
+ http://www.python.org/doc/
+
+I proposed adopting the "minimal" syntax for footnotes and footnote
+references, and adding citations and citation references to
+reStructuredText's repertoire. The current footnote syntax for
+citations is better than the alternatives given.
+
+From a reply by Tony Ibbs on 2002-03-01:
+
+ However, I think easier with examples, so let's create one::
+
+ Fans of Terry Pratchett are perhaps more likely to use
+ footnotes [1]_ in their own writings than other people
+ [2]_. Of course, in *general*, one only sees footnotes
+ in academic or technical writing - it's use in fiction
+ and letter writing is not normally considered good
+ style [4]_, particularly in emails (not a medium that
+ lends itself to footnotes).
+
+ .. [1] That is, little bits of referenced text at the
+ bottom of the page.
+ .. [2] Because Terry himself does, of course [3]_.
+ .. [3] Although he has the distinction of being
+ *funny* when he does it, and his fans don't always
+ achieve that aim.
+ .. [4] Presumably because it detracts from linear
+ reading of the text - this is, of course, the point.
+
+ and look at it with the second syntax proposal::
+
+ Fans of Terry Pratchett are perhaps more likely to use
+ footnotes [1]_ in their own writings than other people
+ [2]_. Of course, in *general*, one only sees footnotes
+ in academic or technical writing - it's use in fiction
+ and letter writing is not normally considered good
+ style [4]_, particularly in emails (not a medium that
+ lends itself to footnotes).
+
+ _[1] That is, little bits of referenced text at the
+ bottom of the page.
+ _[2] Because Terry himself does, of course [3]_.
+ _[3] Although he has the distinction of being
+ *funny* when he does it, and his fans don't always
+ achieve that aim.
+ _[4] Presumably because it detracts from linear
+ reading of the text - this is, of course, the point.
+
+ (I note here that if I have gotten the indentation of the
+ footnotes themselves correct, this is clearly not as nice. And if
+ the indentation should be to the left margin instead, I like that
+ even less).
+
+ and the third (new) proposal::
+
+ Fans of Terry Pratchett are perhaps more likely to use
+ footnotes 1_ in their own writings than other people
+ 2_. Of course, in *general*, one only sees footnotes
+ in academic or technical writing - it's use in fiction
+ and letter writing is not normally considered good
+ style 4_, particularly in emails (not a medium that
+ lends itself to footnotes).
+
+ _1. That is, little bits of referenced text at the
+ bottom of the page.
+ _2. Because Terry himself does, of course 3_.
+ _3. Although he has the distinction of being
+ *funny* when he does it, and his fans don't always
+ achieve that aim.
+ _4. Presumably because it detracts from linear
+ reading of the text - this is, of course, the point.
+
+ I think I don't, in practice, mind the targets too much (the use
+ of a dot after the number helps a lot here), but I do have a
+ problem with the body text, in that I don't naturally separate out
+ the footnotes as different than the rest of the text - instead I
+ keep wondering why there are numbers interspered in the text. The
+ use of brackets around the numbers ([ and ]) made me somehow parse
+ the footnote references as "odd" - i.e., not part of the body text
+ - and thus both easier to skip, and also (paradoxically) easier to
+ pick out so that I could follow them.
+
+ Thus, for the moment (and as always susceptable to argument), I'd
+ say -1 on the new form of footnote reference (i.e., I much prefer
+ the existing ``[1]_`` over the proposed ``1_``), and ambivalent
+ over the proposed target change.
+
+ That leaves David's problem of wanting to distinguish footnotes
+ and citations - and the only thing I can propose there is that
+ footnotes are numeric or # and citations are not (which, as a
+ human being, I can probably cope with!).
+
+From a reply by Paul Moore on 2002-03-01:
+
+ I think the current footnote syntax ``[1]_`` is *exactly* the
+ right balance of distinctness vs unobtrusiveness. I very
+ definitely don't think this should change.
+
+ On the target change, it doesn't matter much to me.
+
+From a further reply by Tony Ibbs on 2002-03-01, referring to the
+"[1]" form and actual usage in email:
+
+ Clearly this is a form people are used to, and thus we should
+ consider it strongly (in the same way that the usage of ``*..*``
+ to mean emphasis was taken partly from email practise).
+
+ Equally clearly, there is something "magical" for people in the
+ use of a similar form (i.e., ``[1]``) for both footnote reference
+ and footnote target - it seems natural to keep them similar.
+
+ ...
+
+ I think that this established plaintext usage leads me to strongly
+ believe we should retain square brackets at both ends of a
+ footnote. The markup of the reference end (a single trailing
+ underscore) seems about as minimal as we can get away with. The
+ markup of the target end depends on how one envisages the thing -
+ if ".." means "I am a target" (as I tend to see it), then that's
+ good, but one can also argue that the "_[1]" syntax has a neat
+ symmetry with the footnote reference itself, if one wishes (in
+ which case ".." presumably means "hidden/special" as David seems
+ to think, which is why one needs a ".." *and* a leading underline
+ for hyperlink targets.
+
+Given the persuading arguments voiced, we'll leave footnote & footnote
+reference syntax alone. Except that these discussions gave rise to
+the "auto-symbol footnote" concept, which has been added. Citations
+and citation references have also been added.
+
+
+Syntax for Questions & Answers
+==============================
+
+Implement as a generic two-column marked list? As a standalone
+(non-directive) construct? (Is the markup ambiguous?) Add support to
+parts.contents?
+
+New elements would be required. Perhaps::
+
+ <!ELEMENT question_list (question_list_item+)>
+ <!ATTLIST question_list
+ numbering (none | local | global)
+ #IMPLIED
+ start NUMBER #IMPLIED>
+ <!ELEMENT question_list_item (question, answer*)>
+ <!ELEMENT question %text.model;>
+ <!ELEMENT answer (%body.elements;)+>
+
+Originally I thought of implementing a Q&A list with special syntax::
+
+ Q: What am I?
+
+ A: You are a question-and-answer
+ list.
+
+ Q: What are you?
+
+ A: I am the omniscient "we".
+
+Where each "Q" and "A" could also be numbered (e.g., "Q1"). However,
+a simple enumerated or bulleted list will do just fine for syntax. A
+directive could treat the list specially; e.g. the first paragraph
+could be treated as a question, the remainder as the answer (multiple
+answers could be represented by nested lists). Without special
+syntax, this directive becomes low priority.
+
+As described in the FAQ__, no special syntax or directive is needed
+for this application.
+
+__ http://docutils.sf.net/FAQ.html
+ #how-can-i-mark-up-a-faq-or-other-list-of-questions-answers
+
+
+--------
+ Tabled
+--------
+
+Reworking Explicit Markup (Round 2)
+===================================
+
+See `Reworking Explicit Markup (Round 1)`_ for an earlier discussion.
+
+In April 2004, a new thread becan on docutils-develop: `Inconsistency
+in RST markup`__. Several arguments were made; the first argument
+begat later arguments. Below, the arguments are paraphrased "in
+quotes", with responses.
+
+__ http://thread.gmane.org/gmane.text.docutils.devel/1386
+
+1. References and targets take this form::
+
+ targetname_
+
+ .. _targetname: stuff
+
+ But footnotes, "which generate links just like targets do", are
+ written as::
+
+ [1]_
+
+ .. [1] stuff
+
+ "Footnotes should be written as"::
+
+ [1]_
+
+ .. _[1]: stuff
+
+ But they're not the same type of animal. That's not a "footnote
+ target", it's a *footnote*. Being a target is not a footnote's
+ primary purpose (an arguable point). It just happens to grow a
+ target automatically, for convenience. Just as a section title::
+
+ Title
+ =====
+
+ isn't a "title target", it's a *title*, which happens to grow a
+ target automatically. The consistency is there, it's just deeper
+ than at first glance.
+
+ Also, ".. [1]" was chosen for footnote syntax because it closely
+ resembles one form of actual footnote rendering. ".. _[1]:" is too
+ verbose; excessive punctuation is required to get the job done.
+
+ For more of the reasoning behind the syntax, see `Problems With
+ StructuredText (Hyperlinks) <problems.html#hyperlinks>`__ and
+ `Reworking Footnotes`_.
+
+2. "I expect directives to also look like ``.. this:`` [one colon]
+ because that also closely parallels the link and footnote target
+ markup."
+
+ There are good reasons for the two-colon syntax:
+
+ Two colons are used after the directive type for these reasons:
+
+ - Two colons are distinctive, and unlikely to be used in common
+ text.
+
+ - Two colons avoids clashes with common comment text like::
+
+ .. Danger: modify at your own risk!
+
+ - If an implementation of reStructuredText does not recognize a
+ directive (i.e., the directive-handler is not installed), a
+ level-3 (error) system message is generated, and the entire
+ directive block (including the directive itself) will be
+ included as a literal block. Thus "::" is a natural choice.
+
+ -- `restructuredtext.html#directives
+ <../../ref/rst/restructuredtext.html#directives>`__
+
+ The last reason is not particularly compelling; it's more of a
+ convenient coincidence or mnemonic.
+
+3. "Comments always seemed too easy. I almost never write comments.
+ I'd have no problem writing '.. comment:' in front of my comments.
+ In fact, it would probably be more readable, as comments *should*
+ be set off strongly, because they are very different from normal
+ text."
+
+ Many people do use comments though, and some applications of
+ reStructuredText require it. For example, all reStructuredText
+ PEPs (and this document!) have an Emacs stanza at the bottom, in a
+ comment. Having to write ".. comment::" would be very obtrusive.
+
+ Comments *should* be dirt-easy to do. It should be easy to
+ "comment out" a block of text. Comments in programming languages
+ and other markup languages are invariably easy.
+
+ Any author is welcome to preface their comments with "Comment:" or
+ "Do Not Print" or "Note to Editor" or anything they like. A
+ "comment" directive could easily be implemented. It might be
+ confused with admonition directives, like "note" and "caution"
+ though. In unrelated (and unpublished and unfinished) work, adding
+ a "comment" directive as a true document element was considered::
+
+ If structure is necessary, we could use a "comment" directive
+ (to avoid nonsensical DTD changes, the "comment" directive
+ could produce an untitled topic element).
+
+4. "One of the goals of reStructuredText is to be *readable* by people
+ who don't know it. This construction violates that: it is not at
+ all obvious to the uninitiated that text marked by '..' is a
+ comment. On the other hand, '.. comment:' would be totally
+ transparent."
+
+ Totally transparent, perhaps, but also very obtrusive. Another of
+ `reStructuredText's goals`_ is to be unobtrusive, and
+ ".. comment::" would violate that. The goals of reStructuredText
+ are many, and they conflict. Determining the right set of goals
+ and finding solutions that best fit is done on a case-by-case
+ basis.
+
+ Even readability is has two aspects. Being readable without any
+ prior knowledge is one. Being as easily read in raw form as in
+ processed form is the other. ".." may not contribute to the former
+ aspect, but ".. comment::" would certainly detract from the latter.
+
+ .. _author's note:
+ .. _reStructuredText's goals: ../../ref/rst/introduction.html#goals
+
+5. "Recently I sent someone an rst document, and they got confused; I
+ had to explain to them that '..' marks comments, *unless* it's a
+ directive, etc..."
+
+ The explanation of directives *is* roundabout, defining comments in
+ terms of not being other things. That's definitely a wart.
+
+6. "Under the current system, a mistyped directive (with ':' instead
+ of '::') will be silently ignored. This is an error that could
+ easily go unnoticed."
+
+ A parser option/setting like "--comments-on-stderr" would help.
+
+7. "I'd prefer to see double-dot-space / command / double-colon as the
+ standard Docutils markup-marker. It's unusual enough to avoid
+ being accidently used. Everything that starts with a double-dot
+ should end with a double-colon."
+
+ That would increase the punctuation verbosity of some constructs
+ considerably.
+
+8. Edward Loper proposed the following plan for backwards
+ compatibility:
+
+ 1. ".. foo" will generate a deprecation warning to stderr, and
+ nothing in the output (no system messages).
+ 2. ".. foo: bar" will be treated as a directive foo. If there
+ is no foo directive, then do the normal error output.
+ 3. ".. foo:: bar" will generate a deprecation warning to
+ stderr, and be treated as a directive. Or leave it valid?
+
+ So some existing documents might start printing deprecation
+ warnings, but the only existing documents that would *break*
+ would be ones that say something like::
+
+ .. warning: this should be a comment
+
+ instead of::
+
+ .. warning:: this should be a comment
+
+ Here, we're trading fairly common a silent error (directive
+ falsely treated as a comment) for a fairly uncommon explicitly
+ flagged error (comment falsely treated as directive). To make
+ things even easier, we could add a sentence to the
+ unknown-directive error. Something like "If you intended to
+ create a comment, please use '.. comment:' instead".
+
+On one hand, I understand and sympathize with the points raised. On
+the other hand, I think the current syntax strikes the right balance
+(but I acknowledge a possible lack of objectivity). On the gripping
+hand, the comment and directive syntax has become well established, so
+even if it's a wart, it may be a wart we have to live with.
+
+Making any of these changes would cause a lot of breakage or at least
+deprecation warnings. I'm not sure the benefit is worth the cost.
+
+For now, we'll treat this as an unresolved legacy issue.
+
+
+-------
+ To Do
+-------
+
+Nested Inline Markup
+====================
+
+These are collected notes on a long-discussed issue. The original
+mailing list messages should be referred to for details.
+
+* In a 2001-10-31 discussion I wrote:
+
+ Try, for example, `Ed Loper's 2001-03-21 post`_, which details
+ some rules for nested inline markup. I think the complexity is
+ prohibitive for the marginal benefit. (And if you can understand
+ that tree without going mad, you're a better man than I. ;-)
+
+ Inline markup is already fragile. Allowing nested inline markup
+ would only be asking for trouble IMHO. If it proves absolutely
+ necessary, it can be added later. The rules for what can appear
+ inside what must be well thought out first though.
+
+ .. _Ed Loper's 2001-03-21 post:
+ http://mail.python.org/pipermail/doc-sig/2001-March/001487.html
+
+ -- http://mail.python.org/pipermail/doc-sig/2001-October/002354.html
+
+* In a 2001-11-09 Doc-SIG post, I wrote:
+
+ The problem is that in the
+ what-you-see-is-more-or-less-what-you-get markup language that
+ is reStructuredText, the symbols used for inline markup ("*",
+ "**", "`", "``", etc.) may preclude nesting.
+
+ I've rethought this position. Nested markup is not precluded, just
+ tricky. People and software parse "double and 'single' quotes" all
+ the time. Continuing,
+
+ I've thought over how we might implement nested inline
+ markup. The first algorithm ("first identify the outer inline
+ markup as we do now, then recursively scan for nested inline
+ markup") won't work; counterexamples were given in my `last post
+ <http://mail.python.org/pipermail/doc-sig/2001-November/002363.html>`__.
+
+ The second algorithm makes my head hurt::
+
+ while 1:
+ scan for start-string
+ if found:
+ push on stack
+ scan for start or end string
+ if new start string found:
+ recurse
+ elif matching end string found:
+ pop stack
+ elif non-matching end string found:
+ if its a markup error:
+ generate warning
+ elif the initial start-string was misinterpreted:
+ # e.g. in this case: ***strong** in emphasis*
+ restart with the other interpretation
+ # but it might be several layers back ...
+ ...
+
+ This is similar to how the parser does section title
+ recognition, but sections are much more regular and
+ deterministic.
+
+ Bottom line is, I don't think the benefits are worth the effort,
+ even if it is possible. I'm not going to try to write the code,
+ at least not now. If somebody codes up a consistent, working,
+ general solution, I'll be happy to consider it.
+
+ -- http://mail.python.org/pipermail/doc-sig/2001-November/002388.html
+
+* In a `2003-05-06 Docutils-Users post`__ Paul Tremblay proposed a new
+ syntax to allow for easier nesting. It eventually evolved into
+ this::
+
+ :role:[inline text]
+
+ The duplication with the existing interpreted text syntax is
+ problematic though.
+
+ __ http://article.gmane.org/gmane.text.docutils.user/317
+
+* Could the parser be extended to parse nested interpreted text? ::
+
+ :emphasis:`Some emphasized text with :strong:`some more
+ emphasized text` in it and **perhaps** :reference:`a link``
+
+* In a `2003-06-18 Docutils-Develop post`__, Mark Nodine reported on
+ his implementation of a form of nested inline markup in his
+ Perl-based parser (unpublished). He brought up some interesting
+ ideas. The implementation was flawed, however, by the change in
+ semantics required for backslash escapes.
+
+ __ http://article.gmane.org/gmane.text.docutils.devel/795
+
+* Docutils-develop threads between David Abrahams, David Goodger, and
+ Mark Nodine (beginning 2004-01-16__ and 2004-01-19__) hashed out
+ many of the details of a potentially successful implementation, as
+ described below. David Abrahams checked in code to the "nesting"
+ branch of CVS, awaiting thorough review.
+
+ __ http://thread.gmane.org/gmane.text.docutils.devel/1102
+ __ http://thread.gmane.org/gmane.text.docutils.devel/1125
+
+It may be possible to accomplish nested inline markup in general with
+a more powerful inline markup parser. There may be some issues, but
+I'm not averse to the idea of nested inline markup in general. I just
+don't have the time or inclination to write a new parser now. Of
+course, a good patch would be welcome!
+
+I envisage something like this. Explicit-role interpreted text must
+be nestable. Prefix-based is probably preferred, since suffix-based
+will look like inline literals::
+
+ ``text`:role1:`:role2:
+
+But it can be disambiguated, so it ought to be left up to the author::
+
+ `\ `text`:role1:`:role2:
+
+In addition, other forms of inline markup may be nested if
+unambiguous::
+
+ *emphasized ``literal`` and |substitution ref| and link_*
+
+IOW, the parser ought to be as permissive as possible.
+
+
+Index Entries & Indexes
+=======================
+
+Were I writing a book with an index, I guess I'd need two
+different kinds of index targets: inline/implicit and
+out-of-line/explicit. For example::
+
+ In this `paragraph`:index:, several words are being
+ `marked`:index: inline as implicit `index`:index:
+ entries.
+
+ .. index:: markup
+ .. index:: syntax
+
+ The explicit index directives above would refer to
+ this paragraph. It might also make sense to allow multiple
+ entries in an ``index`` directive:
+
+ .. index::
+ markup
+ syntax
+
+The words "paragraph", "marked", and "index" would become index
+entries pointing at the words in the first paragraph. The index
+entry words appear verbatim in the text. (Don't worry about the
+ugly ":index:" part; if indexing is the only/main application of
+interpreted text in your documents, it can be implicit and
+omitted.) The two directives provide manual indexing, where the
+index entry words ("markup" and "syntax") do not appear in the
+main text. We could combine the two directives into one::
+
+ .. index:: markup; syntax
+
+Semicolons instead of commas because commas could *be* part of the
+index target, like::
+
+ .. index:: van Rossum, Guido
+
+Another reason for index directives is because other inline markup
+wouldn't be possible within inline index targets.
+
+Sometimes index entries have multiple levels. Given::
+
+ .. index:: statement syntax: expression statements
+
+In a hypothetical index, combined with other entries, it might
+look like this::
+
+ statement syntax
+ expression statements ..... 56
+ assignment ................ 57
+ simple statements ......... 58
+ compound statements ....... 60
+
+Inline multi-level index targets could be done too. Perhaps
+something like::
+
+ When dealing with `expression statements <statement syntax:>`,
+ we must remember ...
+
+The opposite sense could also be possible::
+
+ When dealing with `index entries <:multi-level>`, there are
+ many permutations to consider.
+
+Also "see / see also" index entries.
+
+Given::
+
+ Here's a paragraph.
+
+ .. index:: paragraph
+
+(The "index" directive above actually targets the *preceding*
+object.) The directive should produce something like this XML::
+
+ <paragraph>
+ <index_entry text="paragraph"/>
+ Here's a paragraph.
+ </paragraph>
+
+This kind of content model would also allow true inline
+index-entries::
+
+ Here's a `paragraph`:index:.
+
+If the "index" role were the default for the application, it could be
+dropped::
+
+ Here's a `paragraph`.
+
+Both of these would result in this XML::
+
+ <paragraph>
+ Here's a <index_entry>paragraph</index_entry>.
+ </paragraph>
+
+
+from 2002-06-24 docutils-develop posts
+--------------------------------------
+
+ If all of your index entries will appear verbatim in the text,
+ this should be sufficient. If not (e.g., if you want "Van Rossum,
+ Guido" in the index but "Guido van Rossum" in the text), we'll
+ have to figure out a supplemental mechanism, perhaps using
+ substitutions.
+
+I've thought a bit more on this, and I came up with two possibilities:
+
+1. Using interpreted text, embed the index entry text within the
+ interpreted text::
+
+ ... by `Guido van Rossum [Van Rossum, Guido]` ...
+
+ The problem with this is obvious: the text becomes cluttered and
+ hard to read. The processed output would drop the text in
+ brackets, which goes against the spirit of interpreted text.
+
+2. Use substitutions::
+
+ ... by |Guido van Rossum| ...
+
+ .. |Guido van Rossum| index:: Van Rossum, Guido
+
+ A problem with this is that each substitution definition must have
+ a unique name. A subsequent ``.. |Guido van Rossum| index:: BDFL``
+ would be illegal. Some kind of anonymous substitution definition
+ mechanism would be required, but I think that's going too far.
+
+Both of these alternatives are flawed. Any other ideas?
+
+
+-------------------
+ ... Or Not To Do?
+-------------------
+
+This is the realm of the possible but questionably probable. These
+ideas are kept here as a record of what has been proposed, for
+posterity and in case any of them prove to be useful.
+
+
+Compound Enumerated Lists
+=========================
+
+Allow for compound enumerators, such as "1.1." or "1.a." or "1(a)", to
+allow for nested enumerated lists without indentation?
+
+
+Indented Lists
+==============
+
+Allow for variant styles by interpreting indented lists as if they
+weren't indented? For example, currently the list below will be
+parsed as a list within a block quote::
+
+ paragraph
+
+ * list item 1
+ * list item 2
+
+But a lot of people seem to write that way, and HTML browsers make it
+look as if that's the way it should be. The parser could check the
+contents of block quotes, and if they contain only a single list,
+remove the block quote wrapper. There would be two problems:
+
+1. What if we actually *do* want a list inside a block quote?
+
+2. What if such a list comes immediately after an indented construct,
+ such as a literal block?
+
+Both could be solved using empty comments (problem 2 already exists
+for a block quote after a literal block). But that's a hack.
+
+Perhaps a runtime setting, allowing or disabling this convenience,
+would be appropriate. But that raises issues too:
+
+ User A, who writes lists indented (and their config file is set up
+ to allow it), sends a file to user B, who doesn't (and their
+ config file disables indented lists). The result of processing by
+ the two users will be different.
+
+It may seem minor, but it adds ambiguity to the parser, which is bad.
+
+See the `Doc-SIG discussion starting 2001-04-18`__ with Ed Loper's
+"Structuring: a summary; and an attempt at EBNF", item 4 (and
+follow-ups, here__ and here__). Also `docutils-users, 2003-02-17`__
+and `beginning 2003-08-04`__.
+
+__ http://mail.python.org/pipermail/doc-sig/2001-April/001776.html
+__ http://mail.python.org/pipermail/doc-sig/2001-April/001789.html
+__ http://mail.python.org/pipermail/doc-sig/2001-April/001793.html
+__ http://sourceforge.net/mailarchive/message.php?msg_id=3838913
+__ http://sf.net/mailarchive/forum.php?thread_id=2957175&forum_id=11444
+
+
+Sloppy Indentation of List Items
+================================
+
+Perhaps the indentation shouldn't be so strict. Currently, this is
+required::
+
+ 1. First line,
+ second line.
+
+Anything wrong with this? ::
+
+ 1. First line,
+ second line.
+
+Problem? ::
+
+ 1. First para.
+
+ Block quote. (no good: requires some indent relative to first
+ para)
+
+ Second Para.
+
+ 2. Have to carefully define where the literal block ends::
+
+ Literal block
+
+ Literal block?
+
+Hmm... Non-strict indentation isn't such a good idea.
+
+
+Lazy Indentation of List Items
+==============================
+
+Another approach: Going back to the first draft of reStructuredText
+(2000-11-27 post to Doc-SIG)::
+
+ - This is the fourth item of the main list (no blank line above).
+ The second line of this item is not indented relative to the
+ bullet, which precludes it from having a second paragraph.
+
+Change that to *require* a blank line above and below, to reduce
+ambiguity. This "loosening" may be added later, once the parser's
+been nailed down. However, a serious drawback of this approach is to
+limit the content of each list item to a single paragraph.
+
+
+David's Idea for Lazy Indentation
+---------------------------------
+
+Consider a paragraph in a word processor. It is a single logical line
+of text which ends with a newline, soft-wrapped arbitrarily at the
+right edge of the page or screen. We can think of a plaintext
+paragraph in the same way, as a single logical line of text, ending
+with two newlines (a blank line) instead of one, and which may contain
+arbitrary line breaks (newlines) where it was accidentally
+hard-wrapped by an application. We can compensate for the accidental
+hard-wrapping by "unwrapping" every unindented second and subsequent
+line. The indentation of the first line of a paragraph or list item
+would determine the indentation for the entire element. Blank lines
+would be required between list items when using lazy indentation.
+
+The following example shows the lazy indentation of multiple body
+elements::
+
+ - This is the first paragraph
+ of the first list item.
+
+ Here is the second paragraph
+ of the first list item.
+
+ - This is the first paragraph
+ of the second list item.
+
+ Here is the second paragraph
+ of the second list item.
+
+A more complex example shows the limitations of lazy indentation::
+
+ - This is the first paragraph
+ of the first list item.
+
+ Next is a definition list item:
+
+ Term
+ Definition. The indentation of the term is
+ required, as is the indentation of the definition's
+ first line.
+
+ When the definition extends to more than
+ one line, lazy indentation may occur. (This is the second
+ paragraph of the definition.)
+
+ - This is the first paragraph
+ of the second list item.
+
+ - Here is the first paragraph of
+ the first item of a nested list.
+
+ So this paragraph would be outside of the nested list,
+ but inside the second list item of the outer list.
+
+ But this paragraph is not part of the list at all.
+
+And the ambiguity remains::
+
+ - Look at the hyphen at the beginning of the next line
+ - is it a second list item marker, or a dash in the text?
+
+ Similarly, we may want to refer to numbers inside enumerated
+ lists:
+
+ 1. How many socks in a pair? There are
+ 2. How many pants in a pair? Exactly
+ 1. Go figure.
+
+Literal blocks and block quotes would still require consistent
+indentation for all their lines. For block quotes, we might be able
+to get away with only requiring that the first line of each contained
+element be indented. For example::
+
+ Here's a paragraph.
+
+ This is a paragraph inside a block quote.
+ Second and subsequent lines need not be indented at all.
+
+ - A bullet list inside
+ the block quote.
+
+ Second paragraph of the
+ bullet list inside the block quote.
+
+Although feasible, this form of lazy indentation has problems. The
+document structure and hierarchy is not obvious from the indentation,
+making the source plaintext difficult to read. This will also make
+keeping track of the indentation while writing difficult and
+error-prone. However, these problems may be acceptable for Wikis and
+email mode, where we may be able to rely on less complex structure
+(few nested lists, for example).
+
+
+Multiple Roles in Interpreted Text
+==================================
+
+In reStructuredText, inline markup cannot be nested (yet; `see
+above`__). This also applies to interpreted text. In order to
+simultaneously combine multiple roles for a single piece of text, a
+syntax extension would be necessary. Ideas:
+
+1. Initial idea::
+
+ `interpreted text`:role1,role2:
+
+2. Suggested by Jason Diamond::
+
+ `interpreted text`:role1:role2:
+
+If a document is so complex as to require nested inline markup,
+perhaps another markup system should be considered. By design,
+reStructuredText does not have the flexibility of XML.
+
+__ `Nested Inline Markup`_
+
+
+Parameterized Interpreted Text
+==============================
+
+In some cases it may be expedient to pass parameters to interpreted
+text, analogous to function calls. Ideas:
+
+1. Parameterize the interpreted text role itself (suggested by Jason
+ Diamond)::
+
+ `interpreted text`:role1(foo=bar):
+
+ Positional parameters could also be supported::
+
+ `CSS`:acronym(Cascading Style Sheets): is used for HTML, and
+ `CSS`:acronym(Content Scrambling System): is used for DVDs.
+
+ Technical problem: current interpreted text syntax does not
+ recognize roles containing whitespace. Design problem: this smells
+ like programming language syntax, but reStructuredText is not a
+ programming language.
+
+2. Put the parameters inside the interpreted text::
+
+ `CSS (Cascading Style Sheets)`:acronym: is used for HTML, and
+ `CSS (Content Scrambling System)`:acronym: is used for DVDs.
+
+ Although this could be defined on an individual basis (per role),
+ we ought to have a standard. Hyperlinks with embedded URIs already
+ use angle brackets; perhaps they could be used here too::
+
+ `CSS <Cascading Style Sheets>`:acronym: is used for HTML, and
+ `CSS <Content Scrambling System>`:acronym: is used for DVDs.
+
+ Do angle brackets connote URLs too much for this to be acceptable?
+ How about the "tag" connotation -- does it save them or doom them?
+
+3. `Nested inline markup`_ could prove useful here::
+
+ `CSS :def:`Cascading Style Sheets``:acronym: is used for HTML,
+ and `CSS :def:`Content Scrambling System``:acronym: is used for
+ DVDs.
+
+ Inline markup roles could even define the default roles of nested
+ inline markup, allowing this cleaner syntax::
+
+ `CSS `Cascading Style Sheets``:acronym: is used for HTML, and
+ `CSS `Content Scrambling System``:acronym: is used for DVDs.
+
+Does this push inline markup too far? Readability becomes a serious
+issue. Substitutions may provide a better alternative (at the expense
+of verbosity and duplication) by pulling the details out of the text
+flow::
+
+ |CSS| is used for HTML, and |CSS-DVD| is used for DVDs.
+
+ .. |CSS| acronym:: Cascading Style Sheets
+ .. |CSS-DVD| acronym:: Content Scrambling System
+ :text: CSS
+
+----------------------------------------------------------------------
+
+This whole idea may be going beyond the scope of reStructuredText.
+Documents requiring this functionality may be better off using XML or
+another markup system.
+
+This argument comes up regularly when pushing the envelope of
+reStructuredText syntax. I think it's a useful argument in that it
+provides a check on creeping featurism. In many cases, the resulting
+verbosity produces such unreadable plaintext that there's a natural
+desire *not* to use it unless absolutely necessary. It's a matter of
+finding the right balance.
+
+
+Syntax for Interpreted Text Role Bindings
+=========================================
+
+The following syntax (idea from Jeffrey C. Jacobs) could be used to
+associate directives with roles::
+
+ .. :rewrite: class:: rewrite
+
+ `She wore ribbons in her hair and it lay with streaks of
+ grey`:rewrite:
+
+The syntax is similar to that of substitution declarations, and the
+directive/role association may resolve implementation issues. The
+semantics, ramifications, and implementation details would need to be
+worked out.
+
+The example above would implement the "rewrite" role as adding a
+``class="rewrite"`` attribute to the interpreted text ("inline"
+element). The stylesheet would then pick up on the "class" attribute
+to do the actual formatting.
+
+The advantage of the new syntax would be flexibility. Uses other than
+"class" may present themselves. The disadvantage is complexity:
+having to implement new syntax for a relatively specialized operation,
+and having new semantics in existing directives ("class::" would do
+something different).
+
+The `"role" directive`__ has been implemented.
+
+__ ../../ref/rst/directives.html#role
+
+
+Character Processing
+====================
+
+Several people have suggested adding some form of character processing
+to reStructuredText:
+
+* Some sort of automated replacement of ASCII sequences:
+
+ - ``--`` to em-dash (or ``--`` to en-dash, and ``---`` to em-dash).
+ - Convert quotes to curly quote entities. (Essentially impossible
+ for HTML? Unnecessary for TeX.)
+ - Various forms of ``:-)`` to smiley icons.
+ - ``"\ "`` to . Problem with line-wrapping though: it could
+ end up escaping the newline.
+ - Escaped newlines to <BR>.
+ - Escaped period or quote or dash as a disappearing catalyst to
+ allow character-level inline markup?
+
+* XML-style character entities, such as "©" for the copyright
+ symbol.
+
+Docutils has no need of a character entity subsystem. Supporting
+Unicode and text encodings, character entities should be directly
+represented in the text: a copyright symbol should be represented by
+the copyright symbol character. If this is not possible in an
+authoring environment, a pre-processing stage can be added, or a table
+of substitution definitions can be devised.
+
+A "unicode" directive has been implemented to allow direct
+specification of esoteric characters. In combination with the
+substitution construct, "include" files defining common sets of
+character entities can be defined and used. `A set of character
+entity set definition files have been defined`__ (`tarball`__).
+There's also `a description and instructions for use`__.
+
+__ http://docutils.sf.net/tmp/charents/
+__ http://docutils.sf.net/tmp/charents.tgz
+__ http://docutils.sf.net/tmp/charents/README.html
+
+To allow for `character-level inline markup`_, a limited form of
+character processing has been added to the spec and parser: escaped
+whitespace characters are removed from the processed document. Any
+further character processing will be of this functional type, rather
+than of the character-encoding type.
+
+.. _character-level inline markup:
+ ../../ref/rst/restructuredtext.html#character-level-inline-markup
+
+* Directive idea::
+
+ .. text-replace:: "pattern" "replacement"
+
+ - Support Unicode "U+XXXX" codes.
+ - Support regexps, perhaps with alternative "regexp-replace"
+ directive.
+ - Flags for regexps; ":flags:" option, or individuals.
+ - Specifically, should the default be case-sensistive or
+ -insensitive?
+
+
+Page Or Line Breaks
+===================
+
+* Should ^L (or something else in reST) be defined to mean
+ force/suggest page breaks in whatever output we have?
+
+ A "break" or "page-break" directive would be easy to add. A new
+ doctree element would be required though (perhaps "break"). The
+ final behavior would be up to the Writer. The directive argument
+ could be one of page/column/recto/verso for added flexibility.
+
+ Currently ^L (Python's ``\f``) characters are treated as whitespace.
+ They're converted to single spaces, actually, as are vertical tabs
+ (^K, Python's ``\v``). It would be possible to recognize form feeds
+ as markup, but it requires some thought and discussion first. Are
+ there any downsides? Many editing environments do not allow the
+ insertion of control characters. Will it cause any harm? It would
+ be useful as a shorthand for the directive.
+
+ It's common practice to use ^L before Emacs "Local Variables"
+ lists::
+
+ ^L
+ ..
+ Local Variables:
+ mode: indented-text
+ indent-tabs-mode: nil
+ sentence-end-double-space: t
+ fill-column: 70
+ End:
+
+ These are already present in many PEPs and Docutils project
+ documents. From the Emacs manual (info):
+
+ A "local variables list" goes near the end of the file, in the
+ last page. (It is often best to put it on a page by itself.)
+
+ It would be unfortunate if this construct caused a final blank page
+ to be generated (for those Writers that recognize the page breaks).
+ We'll have to add a transform that looks for a "break" plus zero or
+ more comments at the end of a document, and removes them.
+
+ Probably a bad idea because there is no such thing as a page in a
+ generic document format.
+
+* Could the "break" concept above be extended to inline forms?
+ E.g. "^L" in the middle of a sentence could cause a line break.
+ Only recognize it at the end of a line (i.e., ``\f\n``)?
+
+ Or is formfeed inappropriate? Perhaps vertical tab (``\v``), but
+ even that's a stretch. Can't use carriage returns, since they're
+ commonly used for line endings.
+
+ Probably a bad idea as well because we do not want to use control
+ characters for well-readable and well-writable markup, and after all
+ we have the line block syntax for line breaks.
+
+
+Superscript Markup
+==================
+
+Add ``^superscript^`` inline markup? The only common non-markup uses
+of "^" I can think of are as short hand for "superscript" itself and
+for describing control characters ("^C to cancel"). The former
+supports the proposed syntax, and it could be argued that the latter
+ought to be literal text anyhow (e.g. "``^C`` to cancel").
+
+However, superscripts are seldom needed, and new syntax would break
+existing documents. When it's needed, the ``:superscript:``
+(``:sup:``) role can we used as well.
+
+
+Code Execution
+==============
+
+Add the following directives?
+
+- "exec": Execute Python code & insert the results. Call it
+ "python" to allow for other languages?
+
+- "system": Execute an ``os.system()`` call, and insert the results
+ (possibly as a literal block). Definitely dangerous! How to make
+ it safe? Perhaps such processing should be left outside of the
+ document, in the user's production system (a makefile or a script or
+ whatever). Or, the directive could be disabled by default and only
+ enabled with an explicit command-line option or config file setting.
+ Even then, an interactive prompt may be useful, such as:
+
+ The file.txt document you are processing contains a "system"
+ directive requesting that the ``sudo rm -rf /`` command be
+ executed. Allow it to execute? (y/N)
+
+- "eval": Evaluate an expression & insert the text. At parse
+ time or at substitution time? Dangerous? Perhaps limit to canned
+ macros; see text.date_.
+
+ .. _text.date: ../todo.html#text-date
+
+It's too dangerous (or too complicated in the case of "eval"). We do
+not want to have such things in the core.
+
+
+``encoding`` Directive
+======================
+
+Add an "encoding" directive to specify the character encoding of the
+input data? Not a good idea for the following reasons:
+
+- When it sees the directive, the parser will already have read the
+ input data, and encoding determination will already have been done.
+
+- If a file with an "encoding" directive is edited and saved with
+ a different encoding, the directive may cause data corruption.
+
+
+Support for Annotations
+=======================
+
+Add an "annotation" role, as the equivalent of the HTML "title"
+attribute? This is secondary information that may "pop up" when the
+pointer hovers over the main text. A corresponding directive would be
+required to associate annotations with the original text (by name, or
+positionally as in anonymous targets?).
+
+There have not been many requests for such feature, though. Also,
+cluttering WYSIWYG plaintext with annotations may not seem like a good
+idea, and there is no "tool tip" in formats other than HTML.
+
+
+``term`` Role
+=============
+
+Add a "term" role for unfamiliar or specialized terminology? Probably
+not; there is no real use case, and emphasis is enough for most cases.
+
+
+Object references
+=================
+
+We need syntax for `object references`_.
+
+ - Parameterized substitutions? For example::
+
+ See |figure (figure name)| on |page (figure name)|.
+
+ .. |figure (name)| figure-ref:: (name)
+ .. |page (name)| page-ref:: (name)
+
+ The result would be::
+
+ See figure 3.11 on page 157.
+
+ But this would require substitution directives to be processed at
+ reference-time, not at definition-time as they are now. Or,
+ perhaps the directives could just leave ``pending`` elements
+ behind, and the transforms do the work? How to pass the data
+ through? Too complicated. Use interpreted text roles.
+
+.. _object references:
+ ../todo.html#object-numbering-and-object-references
+
+
+\f
+..
+ Local Variables:
+ mode: indented-text
+ indent-tabs-mode: nil
+ sentence-end-double-space: t
+ fill-column: 70
+ End:
--- /dev/null
+==============================
+ Problems With StructuredText
+==============================
+:Author: David Goodger
+:Contact: docutils-develop@lists.sourceforge.net
+:Revision: $Revision: 7302 $
+:Date: $Date: 2012-01-03 20:23:53 +0100 (Di, 03. Jän 2012) $
+:Copyright: This document has been placed in the public domain.
+
+There are several problems, unresolved issues, and areas of
+controversy within StructuredText_ (Classic and Next Generation). In
+order to resolve all these issues, this analysis brings all of the
+issues out into the open, enumerates all the alternatives, and
+proposes solutions to be incorporated into the reStructuredText_
+specification.
+
+
+.. contents::
+
+
+Formal Specification
+====================
+
+The description in the original StructuredText.py has been criticized
+for being vague. For practical purposes, "the code *is* the spec."
+Tony Ibbs has been working on deducing a `detailed description`_ from
+the documentation and code of StructuredTextNG_. Edward Loper's
+STMinus_ is another attempt to formalize a spec.
+
+For this kind of a project, the specification should always precede
+the code. Otherwise, the markup is a moving target which can never be
+adopted as a standard. Of course, a specification may be revised
+during lifetime of the code, but without a spec there is no visible
+control and thus no confidence.
+
+
+Understanding and Extending the Code
+====================================
+
+The original StructuredText_ is a dense mass of sparsely commented
+code and inscrutable regular expressions. It was not designed to be
+extended and is very difficult to understand. StructuredTextNG_ has
+been designed to allow input (syntax) and output extensions, but its
+documentation (both internal [comments & docstrings], and external) is
+inadequate for the complexity of the code itself.
+
+For reStructuredText to become truly useful, perhaps even part of
+Python's standard library, it must have clear, understandable
+documentation and implementation code. For the implementation of
+reStructuredText to be taken seriously, it must be a sterling example
+of the potential of docstrings; the implementation must practice what
+the specification preaches.
+
+
+Section Structure via Indentation
+=================================
+
+Setext_ required that body text be indented by 2 spaces. The original
+StructuredText_ and StructuredTextNG_ require that section structure
+be indicated through indentation, as "inspired by Python". For
+certain structures with a very limited, local extent (such as lists,
+block quotes, and literal blocks), indentation naturally indicates
+structure or hierarchy. For sections (which may have a very large
+extent), structure via indentation is unnecessary, unnatural and
+ambiguous. Rather, the syntax of the section title *itself* should
+indicate that it is a section title.
+
+The original StructuredText states that "A single-line paragraph whose
+immediately succeeding paragraphs are lower level is treated as a
+header." Requiring indentation in this way is:
+
+- Unnecessary. The vast majority of docstrings and standalone
+ documents will have no more than one level of section structure.
+ Requiring indentation for such docstrings is unnecessary and
+ irritating.
+
+- Unnatural. Most published works use title style (type size, face,
+ weight, and position) and/or section/subsection numbering rather
+ than indentation to indicate hierarchy. This is a tradition with a
+ very long history.
+
+- Ambiguous. A StructuredText header is indistinguishable from a
+ one-line paragraph followed by a block quote (precluding the use of
+ block quotes). Enumerated section titles are ambiguous (is it a
+ header? is it a list item?). Some additional adornment must be
+ required to confirm the line's role as a title, both to a parser and
+ to the human reader of the source text.
+
+Python's use of significant whitespace is a wonderful (if not
+original) innovation, however requiring indentation in ordinary
+written text is hypergeneralization.
+
+reStructuredText_ indicates section structure through title adornment
+style (as exemplified by this document). This is far more natural.
+In fact, it is already in widespread use in plain text documents,
+including in Python's standard distribution (such as the toplevel
+README_ file).
+
+
+Character Escaping Mechanism
+============================
+
+No matter what characters are chosen for markup, some day someone will
+want to write documentation *about* that markup or using markup
+characters in a non-markup context. Therefore, any complete markup
+language must have an escaping or encoding mechanism. For a
+lightweight markup system, encoding mechanisms like SGML/XML's '*'
+are out. So an escaping mechanism is in. However, with carefully
+chosen markup, it should be necessary to use the escaping mechanism
+only infrequently.
+
+reStructuredText_ needs an escaping mechanism: a way to treat
+markup-significant characters as the characters themselves. Currently
+there is no such mechanism (although ZWiki uses '!'). What are the
+candidates?
+
+1. ``!``
+ (http://www.zope.org/DevHome/Members/jim/StructuredTextWiki/NGEscaping)
+2. ``\``
+3. ``~``
+4. doubling of characters
+
+The best choice for this is the backslash (``\``). It's "the single
+most popular escaping character in the world!", therefore familiar and
+unsurprising. Since characters only need to be escaped under special
+circumstances, which are typically those explaining technical
+programming issues, the use of the backslash is natural and
+understandable. Python docstrings can be raw (prefixed with an 'r',
+as in 'r""'), which would obviate the need for gratuitous doubling-up
+of backslashes.
+
+(On 2001-03-29 on the Doc-SIG mailing list, GvR endorsed backslash
+escapes, saying, "'nuff said. Backslash it is." Although neither
+legally binding nor irrevocable nor any kind of guarantee of anything,
+it is a good sign.)
+
+The rule would be: An unescaped backslash followed by any markup
+character escapes the character. The escaped character represents the
+character itself, and is prevented from playing a role in any markup
+interpretation. The backslash is removed from the output. A literal
+backslash is represented by an "escaped backslash," two backslashes in
+a row.
+
+A carefully constructed set of recognition rules for inline markup
+will obviate the need for backslash-escapes in almost all cases; see
+`Delimitation of Inline Markup`_ below.
+
+When an expression (requiring backslashes and other characters used
+for markup) becomes too complicated and therefore unreadable, a
+literal block may be used instead. Inside literal blocks, no markup
+is recognized, therefore backslashes (for the purpose of escaping
+markup) become unnecessary.
+
+We could allow backslashes preceding non-markup characters to remain
+in the output. This would make describing regular expressions and
+other uses of backslashes easier. However, this would complicate the
+markup rules and would be confusing.
+
+
+Blank Lines in Lists
+====================
+
+Oft-requested in Doc-SIG (the earliest reference is dated 1996-08-13)
+is the ability to write lists without requiring blank lines between
+items. In docstrings, space is at a premium. Authors want to convey
+their API or usage information in as compact a form as possible.
+StructuredText_ requires blank lines between all body elements,
+including list items, even when boundaries are obvious from the markup
+itself.
+
+In reStructuredText, blank lines are optional between list items.
+However, in order to eliminate ambiguity, a blank line is required
+before the first list item and after the last. Nested lists also
+require blank lines before the list start and after the list end.
+
+
+Bullet List Markup
+==================
+
+StructuredText_ includes 'o' as a bullet character. This is dangerous
+and counter to the language-independent nature of the markup. There
+are many languages in which 'o' is a word. For example, in Spanish::
+
+ Llamame a la casa
+ o al trabajo.
+
+ (Call me at home or at work.)
+
+And in Japanese (when romanized)::
+
+ Senshuu no doyoubi ni tegami
+ o kakimashita.
+
+ ([I] wrote a letter on Saturday last week.)
+
+If a paragraph containing an 'o' word wraps such that the 'o' is the
+first text on a line, or if a paragraph begins with such a word, it
+could be misinterpreted as a bullet list.
+
+In reStructuredText_, 'o' is not used as a bullet character. '-',
+'*', and '+' are the possible bullet characters.
+
+
+Enumerated List Markup
+======================
+
+StructuredText enumerated lists are allowed to begin with numbers and
+letters followed by a period or right-parenthesis, then whitespace.
+This has surprising consequences for writing styles. For example,
+this is recognized as an enumerated list item by StructuredText::
+
+ Mr. Creosote.
+
+People will write enumerated lists in all different ways. It is folly
+to try to come up with the "perfect" format for an enumerated list,
+and limit the docstring parser's recognition to that one format only.
+
+Rather, the parser should recognize a variety of enumerator styles.
+It is also recommended that the enumerator of the first list item be
+ordinal-1 ('1', 'A', 'a', 'I', or 'i'), as output formats may not be
+able to begin a list at an arbitrary enumeration.
+
+An initial idea was to require two or more consistent enumerated list
+items in a row. This idea proved impractical and was dropped. In
+practice, the presence of a proper enumerator is enough to reliably
+recognize an enumerated list item; any ambiguities are reported by the
+parser. Here's the original idea for posterity:
+
+ The parser should recognize a variety of enumerator styles, mark
+ each block as a potential enumerated list item (PELI), and
+ interpret the enumerators of adjacent PELIs to decide whether they
+ make up a consistent enumerated list.
+
+ If a PELI is labeled with a "1.", and is immediately followed by a
+ PELI labeled with a "2.", we've got an enumerated list. Or "(A)"
+ followed by "(B)". Or "i)" followed by "ii)", etc. The chances
+ of accidentally recognizing two adjacent and consistently labeled
+ PELIs, are acceptably small.
+
+ For an enumerated list to be recognized, the following must be
+ true:
+
+ - the list must consist of multiple adjacent list items (2 or
+ more)
+ - the enumerators must all have the same format
+ - the enumerators must be sequential
+
+
+Definition List Markup
+======================
+
+StructuredText uses ' -- ' (whitespace, two hyphens, whitespace) on
+the first line of a paragraph to indicate a definition list item. The
+' -- ' serves to separate the term (on the left) from the definition
+(on the right).
+
+Many people use ' -- ' as an em-dash in their text, conflicting with
+the StructuredText usage. Although the Chicago Manual of Style says
+that spaces should not be used around an em-dash, Peter Funk pointed
+out that this is standard usage in German (according to the Duden, the
+official German reference), and possibly in other languages as well.
+The widespread use of ' -- ' precludes its use for definition lists;
+it would violate the "unsurprising" criterion.
+
+A simpler, and at least equally visually distinctive construct
+(proposed by Guido van Rossum, who incidentally is a frequent user of
+' -- ') would do just as well::
+
+ term 1
+ Definition.
+
+ term 2
+ Definition 2, paragraph 1.
+
+ Definition 2, paragraph 2.
+
+A reStructuredText definition list item consists of a term and a
+definition. A term is a simple one-line paragraph. A definition is a
+block indented relative to the term, and may contain multiple
+paragraphs and other body elements. No blank line precedes a
+definition (this distinguishes definition lists from block quotes).
+
+
+Literal Blocks
+==============
+
+The StructuredText_ specification has literal blocks indicated by
+'example', 'examples', or '::' ending the preceding paragraph. STNG
+only recognizes '::'; 'example'/'examples' are not implemented. This
+is good; it fixes an unnecessary language dependency. The problem is
+what to do with the sometimes- unwanted '::'.
+
+In reStructuredText_ '::' at the end of a paragraph indicates that
+subsequent *indented* blocks are treated as literal text. No further
+markup interpretation is done within literal blocks (not even
+backslash-escapes). If the '::' is preceded by whitespace, '::' is
+omitted from the output; if '::' was the sole content of a paragraph,
+the entire paragraph is removed (no 'empty' paragraph remains). If
+'::' is preceded by a non-whitespace character, '::' is replaced by
+':' (i.e., the extra colon is removed).
+
+Thus, a section could begin with a literal block as follows::
+
+ Section Title
+ -------------
+
+ ::
+
+ print "this is example literal"
+
+
+Tables
+======
+
+The table markup scheme in classic StructuredText was horrible. Its
+omission from StructuredTextNG is welcome, and its markup will not be
+repeated here. However, tables themselves are useful in
+documentation. Alternatives:
+
+1. This format is the most natural and obvious. It was independently
+ invented (no great feat of creation!), and later found to be the
+ format supported by the `Emacs table mode`_::
+
+ +------------+------------+------------+--------------+
+ | Header 1 | Header 2 | Header 3 | Header 4 |
+ +============+============+============+==============+
+ | Column 1 | Column 2 | Column 3 & 4 span (Row 1) |
+ +------------+------------+------------+--------------+
+ | Column 1 & 2 span | Column 3 | - Column 4 |
+ +------------+------------+------------+ - Row 2 & 3 |
+ | 1 | 2 | 3 | - span |
+ +------------+------------+------------+--------------+
+
+ Tables are described with a visual outline made up of the
+ characters '-', '=', '|', and '+':
+
+ - The hyphen ('-') is used for horizontal lines (row separators).
+ - The equals sign ('=') is optionally used as a header separator
+ (as of version 1.5.24, this is not supported by the Emacs table
+ mode).
+ - The vertical bar ('|') is used for for vertical lines (column
+ separators).
+ - The plus sign ('+') is used for intersections of horizontal and
+ vertical lines.
+
+ Row and column spans are possible simply by omitting the column or
+ row separators, respectively. The header row separator must be
+ complete; in other words, a header cell may not span into the table
+ body. Each cell contains body elements, and may have multiple
+ paragraphs, lists, etc. Initial spaces for a left margin are
+ allowed; the first line of text in a cell determines its left
+ margin.
+
+2. Below is a simpler table structure. It may be better suited to
+ manual input than alternative #1, but there is no Emacs editing
+ mode available. One disadvantage is that it resembles section
+ titles; a one-column table would look exactly like section &
+ subsection titles. ::
+
+ ============ ============ ============ ==============
+ Header 1 Header 2 Header 3 Header 4
+ ============ ============ ============ ==============
+ Column 1 Column 2 Column 3 & 4 span (Row 1)
+ ------------ ------------ ---------------------------
+ Column 1 & 2 span Column 3 - Column 4
+ ------------------------- ------------ - Row 2 & 3
+ 1 2 3 - span
+ ============ ============ ============ ==============
+
+ The table begins with a top border of equals signs with a space at
+ each column boundary (regardless of spans). Each row is
+ underlined. Internal row separators are underlines of '-', with
+ spaces at column boundaries. The last of the optional head rows is
+ underlined with '=', again with spaces at column boundaries.
+ Column spans have no spaces in their underline. Row spans simply
+ lack an underline at the row boundary. The bottom boundary of the
+ table consists of '=' underlines. A blank line is required
+ following a table.
+
+3. A minimalist alternative is as follows::
+
+ ==== ===== ======== ======== ======= ==== ===== =====
+ Old State Input Action New State Notes
+ ----------- -------- ----------------- -----------
+ ids types new type sys.msg. dupname ids types
+ ==== ===== ======== ======== ======= ==== ===== =====
+ -- -- explicit -- -- new True
+ -- -- implicit -- -- new False
+ None False explicit -- -- new True
+ old False explicit implicit old new True
+ None True explicit explicit new None True
+ old True explicit explicit new,old None True [1]
+ None False implicit implicit new None False
+ old False implicit implicit new,old None False
+ None True implicit implicit new None True
+ old True implicit implicit new old True
+ ==== ===== ======== ======== ======= ==== ===== =====
+
+ The table begins with a top border of equals signs with one or more
+ spaces at each column boundary (regardless of spans). There must
+ be at least two columns in the table (to differentiate it from
+ section headers). Each line starts a new row. The rightmost
+ column is unbounded; text may continue past the edge of the table.
+ Each row/line must contain spaces at column boundaries, except for
+ explicit column spans. Underlines of '-' can be used to indicate
+ column spans, but should be used sparingly if at all. Lines
+ containing column span underlines may not contain any other text.
+ The last of the optional head rows is underlined with '=', again
+ with spaces at column boundaries. The bottom boundary of the table
+ consists of '=' underlines. A blank line is required following a
+ table.
+
+ This table sums up the features. Using all the features in such a
+ small space is not pretty though::
+
+ ======== ======== ========
+ Header 2 & 3 Span
+ ------------------
+ Header 1 Header 2 Header 3
+ ======== ======== ========
+ Each line is a new row.
+ Each row consists of one line only.
+ Row spans are not possible.
+ The last column may spill over to the right.
+ Column spans are possible with an underline joining columns.
+ ----------------------------
+ The span is limited to the row above the underline.
+ ======== ======== ========
+
+4. As a variation of alternative 3, bullet list syntax in the first
+ column could be used to indicate row starts. Multi-line rows are
+ possible, but row spans are not. For example::
+
+ ===== =====
+ col 1 col 2
+ ===== =====
+ - 1 Second column of row 1.
+ - 2 Second column of row 2.
+ Second line of paragraph.
+ - 3 Second column of row 3.
+
+ Second paragraph of row 3,
+ column 2
+ ===== =====
+
+ Column spans would be indicated on the line after the last line of
+ the row. To indicate a real bullet list within a first-column
+ cell, simply nest the bullets.
+
+5. In a further variation, we could simply assume that whitespace in
+ the first column implies a multi-line row; the text in other
+ columns is continuation text. For example::
+
+ ===== =====
+ col 1 col 2
+ ===== =====
+ 1 Second column of row 1.
+ 2 Second column of row 2.
+ Second line of paragraph.
+ 3 Second column of row 3.
+
+ Second paragraph of row 3,
+ column 2
+ ===== =====
+
+ Limitations of this approach:
+
+ - Cells in the first column are limited to one line of text.
+
+ - Cells in the first column *must* contain some text; blank cells
+ would lead to a misinterpretation. An empty comment ("..") is
+ sufficient.
+
+6. Combining alternative 3 and 4, a bullet list in the first column
+ could mean multi-line rows, and no bullet list means single-line
+ rows only.
+
+Alternatives 1 and 5 has been adopted by reStructuredText.
+
+
+Delimitation of Inline Markup
+=============================
+
+StructuredText specifies that inline markup must begin with
+whitespace, precluding such constructs as parenthesized or quoted
+emphatic text::
+
+ "**What?**" she cried. (*exit stage left*)
+
+The `reStructuredText markup specification`_ allows for such
+constructs and disambiguates inline markup through a set of
+recognition rules. These recognition rules define the context of
+markup start-strings and end-strings, allowing markup characters to be
+used in most non-markup contexts without a problem (or a backslash).
+So we can say, "Use asterisks (*) around words or phrases to
+*emphasisze* them." The '(*)' will not be recognized as markup. This
+reduces the need for markup escaping to the point where an escape
+character is *almost* (but not quite!) unnecessary.
+
+
+Underlining
+===========
+
+StructuredText uses '_text_' to indicate underlining. To quote David
+Ascher in his 2000-01-21 Doc-SIG mailing list post, "Docstring
+grammar: a very revised proposal":
+
+ The tagging of underlined text with _'s is suboptimal. Underlines
+ shouldn't be used from a typographic perspective (underlines were
+ designed to be used in manuscripts to communicate to the
+ typesetter that the text should be italicized -- no well-typeset
+ book ever uses underlines), and conflict with double-underscored
+ Python variable names (__init__ and the like), which would get
+ truncated and underlined when that effect is not desired. Note
+ that while *complete* markup would prevent that truncation
+ ('__init__'), I think of docstring markups much like I think of
+ type annotations -- they should be optional and above all do no
+ harm. In this case the underline markup does harm.
+
+Underlining is not part of the reStructuredText specification.
+
+
+Inline Literals
+===============
+
+StructuredText's markup for inline literals (text left as-is,
+verbatim, usually in a monospaced font; as in HTML <TT>) is single
+quotes ('literals'). The problem with single quotes is that they are
+too often used for other purposes:
+
+- Apostrophes: "Don't blame me, 'cause it ain't mine, it's Chris'.";
+
+- Quoting text:
+
+ First Bruce: "Well Bruce, I heard the prime minister use it.
+ 'S'hot enough to boil a monkey's bum in 'ere your Majesty,' he
+ said, and she smiled quietly to herself."
+
+ In the UK, single quotes are used for dialogue in published works.
+
+- String literals: s = ''
+
+Alternatives::
+
+ 'text' \'text\' ''text'' "text" \"text\" ""text""
+ #text# @text@ `text` ^text^ ``text'' ``text``
+
+The examples below contain inline literals, quoted text, and
+apostrophes. Each example should evaluate to the following HTML::
+
+ Some <TT>code</TT>, with a 'quote', "double", ain't it grand?
+ Does <TT>a[b] = 'c' + "d" + `2^3`</TT> work?
+
+ 0. Some code, with a quote, double, ain't it grand?
+ Does a[b] = 'c' + "d" + `2^3` work?
+ 1. Some 'code', with a \'quote\', "double", ain\'t it grand?
+ Does 'a[b] = \'c\' + "d" + `2^3`' work?
+ 2. Some \'code\', with a 'quote', "double", ain't it grand?
+ Does \'a[b] = 'c' + "d" + `2^3`\' work?
+ 3. Some ''code'', with a 'quote', "double", ain't it grand?
+ Does ''a[b] = 'c' + "d" + `2^3`'' work?
+ 4. Some "code", with a 'quote', \"double\", ain't it grand?
+ Does "a[b] = 'c' + "d" + `2^3`" work?
+ 5. Some \"code\", with a 'quote', "double", ain't it grand?
+ Does \"a[b] = 'c' + "d" + `2^3`\" work?
+ 6. Some ""code"", with a 'quote', "double", ain't it grand?
+ Does ""a[b] = 'c' + "d" + `2^3`"" work?
+ 7. Some #code#, with a 'quote', "double", ain't it grand?
+ Does #a[b] = 'c' + "d" + `2^3`# work?
+ 8. Some @code@, with a 'quote', "double", ain't it grand?
+ Does @a[b] = 'c' + "d" + `2^3`@ work?
+ 9. Some `code`, with a 'quote', "double", ain't it grand?
+ Does `a[b] = 'c' + "d" + \`2^3\`` work?
+ 10. Some ^code^, with a 'quote', "double", ain't it grand?
+ Does ^a[b] = 'c' + "d" + `2\^3`^ work?
+ 11. Some ``code'', with a 'quote', "double", ain't it grand?
+ Does ``a[b] = 'c' + "d" + `2^3`'' work?
+ 12. Some ``code``, with a 'quote', "double", ain't it grand?
+ Does ``a[b] = 'c' + "d" + `2^3\``` work?
+
+Backquotes (#9 & #12) are the best choice. They are unobtrusive and
+relatviely rarely used (more rarely than ' or ", anyhow). Backquotes
+have the connotation of 'quotes', which other options (like carets,
+#10) don't.
+
+Analogously with ``*emph*`` & ``**strong**``, double-backquotes (#12)
+could be used for inline literals. If single-backquotes are used for
+'interpreted text' (context-sensitive domain-specific descriptive
+markup) such as function name hyperlinks in Python docstrings, then
+double-backquotes could be used for absolute-literals, wherein no
+processing whatsoever takes place. An advantage of double-backquotes
+would be that backslash-escaping would no longer be necessary for
+embedded single-backquotes; however, embedded double-backquotes (in an
+end-string context) would be illegal. See `Backquotes in
+Phrase-Links`__ in `Record of reStructuredText Syntax Alternatives`__.
+
+__ alternatives.html#backquotes-in-phrase-links
+__ alternatives.html
+
+Alternative choices are carets (#10) and TeX-style quotes (#11). For
+examples of TeX-style quoting, see
+http://www.zope.org/Members/jim/StructuredTextWiki/CustomizingTheDocumentProcessor.
+
+Some existing uses of backquotes:
+
+1. As a synonym for repr() in Python.
+2. For command-interpolation in shell scripts.
+3. Used as open-quotes in TeX code (and carried over into plaintext
+ by TeXies).
+
+The inline markup start-string and end-string recognition rules
+defined by the `reStructuredText markup specification`_ would allow
+all of these cases inside inline literals, with very few exceptions.
+As a fallback, literal blocks could handle all cases.
+
+Outside of inline literals, the above uses of backquotes would require
+backslash-escaping. However, these are all prime examples of text
+that should be marked up with inline literals.
+
+If either backquotes or straight single-quotes are used as markup,
+TeX-quotes are too troublesome to support, so no special-casing of
+TeX-quotes should be done (at least at first). If TeX-quotes have to
+be used outside of literals, a single backslash-escaped would suffice:
+\``TeX quote''. Ugly, true, but very infrequently used.
+
+Using literal blocks is a fallback option which removes the need for
+backslash-escaping::
+
+ like this::
+
+ Here, we can do ``absolutely'' anything `'`'\|/|\ we like!
+
+No mechanism for inline literals is perfect, just as no escaping
+mechanism is perfect. No matter what we use, complicated inline
+expressions involving the inline literal quote and/or the backslash
+will end up looking ugly. We can only choose the least often ugly
+option.
+
+reStructuredText will use double backquotes for inline literals, and
+single backqoutes for interpreted text.
+
+
+Hyperlinks
+==========
+
+There are three forms of hyperlink currently in StructuredText_:
+
+1. (Absolute & relative URIs.) Text enclosed by double quotes
+ followed by a colon, a URI, and concluded by punctuation plus white
+ space, or just white space, is treated as a hyperlink::
+
+ "Python":http://www.python.org/
+
+2. (Absolute URIs only.) Text enclosed by double quotes followed by a
+ comma, one or more spaces, an absolute URI and concluded by
+ punctuation plus white space, or just white space, is treated as a
+ hyperlink::
+
+ "mail me", mailto:me@mail.com
+
+3. (Endnotes.) Text enclosed by brackets link to an endnote at the
+ end of the document: at the beginning of the line, two dots, a
+ space, and the same text in brackets, followed by the end note
+ itself::
+
+ Please refer to the fine manual [GVR2001].
+
+ .. [GVR2001] Python Documentation, Release 2.1, van Rossum,
+ Drake, et al., http://www.python.org/doc/
+
+The problem with forms 1 and 2 is that they are neither intuitive nor
+unobtrusive (they break design goals 5 & 2). They overload
+double-quotes, which are too often used in ordinary text (potentially
+breaking design goal 4). The brackets in form 3 are also too common
+in ordinary text (such as [nested] asides and Python lists like [12]).
+
+Alternatives:
+
+1. Have no special markup for hyperlinks.
+
+2. A. Interpret and mark up hyperlinks as any contiguous text
+ containing '://' or ':...@' (absolute URI) or '@' (email
+ address) after an alphanumeric word. To de-emphasize the URI,
+ simply enclose it in parentheses:
+
+ Python (http://www.python.org/)
+
+ B. Leave special hyperlink markup as a domain-specific extension.
+ Hyperlinks in ordinary reStructuredText documents would be
+ required to be standalone (i.e. the URI text inline in the
+ document text). Processed hyperlinks (where the URI text is
+ hidden behind the link) are important enough to warrant syntax.
+
+3. The original Setext_ introduced a mechanism of indirect hyperlinks.
+ A source link word ('hot word') in the text was given a trailing
+ underscore::
+
+ Here is some text with a hyperlink_ built in.
+
+ The hyperlink itself appeared at the end of the document on a line
+ by itself, beginning with two dots, a space, the link word with a
+ leading underscore, whitespace, and the URI itself::
+
+ .. _hyperlink http://www.123.xyz
+
+ Setext used ``underscores_instead_of_spaces_`` for phrase links.
+
+With some modification, alternative 3 best satisfies the design goals.
+It has the advantage of being readable and relatively unobtrusive.
+Since each source link must match up to a target, the odd variable
+ending in an underscore can be spared being marked up (although it
+should generate a "no such link target" warning). The only
+disadvantage is that phrase-links aren't possible without some
+obtrusive syntax.
+
+We could achieve phrase-links if we enclose the link text:
+
+1. in double quotes::
+
+ "like this"_
+
+2. in brackets::
+
+ [like this]_
+
+3. or in backquotes::
+
+ `like this`_
+
+Each gives us somewhat obtrusive markup, but that is unavoidable. The
+bracketed syntax (#2) is reminiscent of links on many web pages
+(intuitive), although it is somewhat obtrusive. Alternative #3 is
+much less obtrusive, and is consistent with interpreted text: the
+trailing underscore indicates the interpretation of the phrase, as a
+hyperlink. #3 also disambiguates hyperlinks from footnote references.
+Alternative #3 wins.
+
+The same trailing underscore markup can also be used for footnote and
+citation references, removing the problem with ordinary bracketed text
+and Python lists::
+
+ Please refer to the fine manual [GVR2000]_.
+
+ .. [GVR2000] Python Documentation, van Rossum, Drake, et al.,
+ http://www.python.org/doc/
+
+The two-dots-and-a-space syntax was generalized by Setext for
+comments, which are removed from the (visible) processed output.
+reStructuredText uses this syntax for comments, footnotes, and link
+target, collectively termed "explicit markup". For link targets, in
+order to eliminate ambiguity with comments and footnotes,
+reStructuredText specifies that a colon always follow the link target
+word/phrase. The colon denotes 'maps to'. There is no reason to
+restrict target links to the end of the document; they could just as
+easily be interspersed.
+
+Internal hyperlinks (links from one point to another within a single
+document) can be expressed by a source link as before, and a target
+link with a colon but no URI. In effect, these targets 'map to' the
+element immediately following.
+
+As an added bonus, we now have a perfect candidate for
+reStructuredText directives, a simple extension mechanism: explicit
+markup containing a single word followed by two colons and whitespace.
+The interpretation of subsequent data on the directive line or
+following is directive-dependent.
+
+To summarize::
+
+ .. This is a comment.
+
+ .. The line below is an example of a directive.
+ .. version:: 1
+
+ This is a footnote [1]_.
+
+ This internal hyperlink will take us to the footnotes_ area below.
+
+ Here is a one-word_ external hyperlink.
+
+ Here is `a hyperlink phrase`_.
+
+ .. _footnotes:
+ .. [1] Footnote text goes here.
+
+ .. external hyperlink target mappings:
+ .. _one-word: http://www.123.xyz
+ .. _a hyperlink phrase: http://www.123.xyz
+
+The presence or absence of a colon after the target link
+differentiates an indirect hyperlink from a footnote, respectively. A
+footnote requires brackets. Backquotes around a target link word or
+phrase are required if the phrase contains a colon, optional
+otherwise.
+
+Below are examples using no markup, the two StructuredText hypertext
+styles, and the reStructuredText hypertext style. Each example
+contains an indirect link, a direct link, a footnote/endnote, and
+bracketed text. In HTML, each example should evaluate to::
+
+ <P>A <A HREF="http://spam.org">URI</A>, see <A HREF="#eggs2000">
+ [eggs2000]</A> (in Bacon [Publisher]). Also see
+ <A HREF="http://eggs.org">http://eggs.org</A>.</P>
+
+ <P><A NAME="eggs2000">[eggs2000]</A> "Spam, Spam, Spam, Eggs,
+ Bacon, and Spam"</P>
+
+1. No markup::
+
+ A URI http://spam.org, see eggs2000 (in Bacon [Publisher]).
+ Also see http://eggs.org.
+
+ eggs2000 "Spam, Spam, Spam, Eggs, Bacon, and Spam"
+
+2. StructuredText absolute/relative URI syntax
+ ("text":http://www.url.org)::
+
+ A "URI":http://spam.org, see [eggs2000] (in Bacon [Publisher]).
+ Also see "http://eggs.org":http://eggs.org.
+
+ .. [eggs2000] "Spam, Spam, Spam, Eggs, Bacon, and Spam"
+
+ Note that StructuredText does not recognize standalone URIs,
+ forcing doubling up as shown in the second line of the example
+ above.
+
+3. StructuredText absolute-only URI syntax
+ ("text", mailto:you@your.com)::
+
+ A "URI", http://spam.org, see [eggs2000] (in Bacon
+ [Publisher]). Also see "http://eggs.org", http://eggs.org.
+
+ .. [eggs2000] "Spam, Spam, Spam, Eggs, Bacon, and Spam"
+
+4. reStructuredText syntax::
+
+ 4. A URI_, see [eggs2000]_ (in Bacon [Publisher]).
+ Also see http://eggs.org.
+
+ .. _URI: http:/spam.org
+ .. [eggs2000] "Spam, Spam, Spam, Eggs, Bacon, and Spam"
+
+The bracketed text '[Publisher]' may be problematic with
+StructuredText (syntax 2 & 3).
+
+reStructuredText's syntax (#4) is definitely the most readable. The
+text is separated from the link URI and the footnote, resulting in
+cleanly readable text.
+
+.. _StructuredText:
+ http://www.zope.org/DevHome/Members/jim/StructuredTextWiki/FrontPage
+.. _Setext: http://docutils.sourceforge.net/mirror/setext.html
+.. _reStructuredText: http://docutils.sourceforge.net/rst.html
+.. _detailed description:
+ http://homepage.ntlworld.com/tibsnjoan/docutils/STNG-format.html
+.. _STMinus: http://www.cis.upenn.edu/~edloper/pydoc/stminus.html
+.. _StructuredTextNG:
+ http://www.zope.org/DevHome/Members/jim/StructuredTextWiki/StructuredTextNG
+.. _README: http://cvs.sourceforge.net/cgi-bin/viewcvs.cgi/~checkout~/
+ python/python/dist/src/README
+.. _Emacs table mode: http://table.sourceforge.net/
+.. _reStructuredText Markup Specification:
+ ../../ref/rst/restructuredtext.html
+
+\f
+..
+ Local Variables:
+ mode: indented-text
+ indent-tabs-mode: nil
+ sentence-end-double-space: t
+ fill-column: 70
+ End:
--- /dev/null
+=====================
+ Docstring Semantics
+=====================
+:Author: David Goodger
+:Contact: docutils-develop@lists.sourceforge.net
+:Revision: $Revision: 7302 $
+:Date: $Date: 2012-01-03 20:23:53 +0100 (Di, 03. Jän 2012) $
+:Copyright: This document has been placed in the public domain.
+
+These are notes for a possible future PEP providing the final piece of
+the Python docstring puzzle: docstring semantics or documentation
+methodology. `PEP 257`_, Docstring Conventions, sketches out some
+guidelines, but does not get into methodology details.
+
+I haven't explored documentation methodology more because, in my
+opinion, it is a completely separate issue from syntax, and it's even
+more controversial than syntax. Nobody wants to be told how to lay
+out their documentation, a la JavaDoc_. I think the JavaDoc way is
+butt-ugly, but it *is* an established standard for the Java world.
+Any standard documentation methodology has to be formal enough to be
+useful but remain light enough to be usable. If the methodology is
+too strict, too heavy, or too ugly, many/most will not want to use it.
+
+I think a standard methodology could benefit the Python community, but
+it would be a hard sell. A PEP would be the place to start. For most
+human-readable documentation needs, the free-form text approach is
+adequate. We'd only need a formal methodology if we want to extract
+the parameters into a data dictionary, index, or summary of some kind.
+
+
+PythonDoc
+=========
+
+(Not to be confused with Daniel Larsson's pythondoc_ project.)
+
+A Python version of the JavaDoc_ semantics (not syntax). A set of
+conventions which are understood by the Docutils. What JavaDoc has
+done is to establish a syntax that enables a certain documentation
+methodology, or standard *semantics*. JavaDoc is not just syntax; it
+prescribes a methodology.
+
+- Use field lists or definition lists for "tagged blocks". By this I
+ mean that field lists can be used similarly to JavaDoc's ``@tag``
+ syntax. That's actually one of the motivators behind field lists.
+ For example, we could have::
+
+ """
+ :Parameters:
+ - `lines`: a list of one-line strings without newlines.
+ - `until_blank`: Stop collecting at the first blank line if
+ true (1).
+ - `strip_indent`: Strip common leading indent if true (1,
+ default).
+
+ :Return:
+ - a list of indented lines with mininum indent removed;
+ - the amount of the indent;
+ - whether or not the block finished with a blank line or at
+ the end of `lines`.
+ """
+
+ This is taken straight out of docutils/statemachine.py, in which I
+ experimented with a simple documentation methodology. Another
+ variation I've thought of exploits the Grouch_-compatible
+ "classifier" element of definition lists. For example::
+
+ :Parameters:
+ `lines` : [string]
+ List of one-line strings without newlines.
+ `until_blank` : boolean
+ Stop collecting at the first blank line if true (1).
+ `strip_indent` : boolean
+ Strip common leading indent if true (1, default).
+
+- Field lists could even be used in a one-to-one correspondence with
+ JavaDoc ``@tags``, although I doubt if I'd recommend it. Several
+ ports of JavaDoc's ``@tag`` methodology exist in Python, most
+ recently Ed Loper's "epydoc_".
+
+
+Other Ideas
+===========
+
+- Can we extract comments from parsed modules? Could be handy for
+ documenting function/method parameters::
+
+ def method(self,
+ source, # path of input file
+ dest # path of output file
+ ):
+
+ This would save having to repeat parameter names in the docstring.
+
+ Idea from Mark Hammond's 1998-06-23 Doc-SIG post, "Re: [Doc-SIG]
+ Documentation tool":
+
+ it would be quite hard to add a new param to this method without
+ realising you should document it
+
+- Frederic Giacometti's `iPhrase Python documentation conventions`_ is
+ an attachment to his Doc-SIG post of 2001-05-30.
+
+
+.. _PEP 257: http://www.python.org/peps/pep-0257.html
+.. _JavaDoc: http://java.sun.com/j2se/javadoc/
+.. _pythondoc: http://starship.python.net/crew/danilo/pythondoc/
+.. _Grouch: http://www.mems-exchange.org/software/grouch/
+.. _epydoc: http://epydoc.sf.net/
+.. _iPhrase Python documentation conventions:
+ http://mail.python.org/pipermail/doc-sig/2001-May/001840.html
+
+\f
+..
+ Local Variables:
+ mode: indented-text
+ indent-tabs-mode: nil
+ sentence-end-double-space: t
+ fill-column: 70
+ End:
--- /dev/null
+===================
+ Docutils_ Testing
+===================
+
+:Authors: Lea Wiemann <LeWiemann@gmail.com>;
+ David Goodger <goodger@python.org>
+:Revision: $Revision: 8407 $
+:Date: $Date: 2019-10-29 23:48:34 +0100 (Di, 29. Okt 2019) $
+:Copyright: This document has been placed in the public domain.
+
+.. _Docutils: http://docutils.sourceforge.net/
+
+.. contents::
+
+When adding new functionality (or fixing bugs), be sure to add test
+cases to the test suite. Practise test-first programming; it's fun,
+it's addictive, and it works!
+
+This document describes how to run the Docutils test suite, how the
+tests are organized and how to add new tests or modify existing tests.
+
+
+Running the Test Suite
+======================
+
+Before checking in any changes, run the entire Docutils test suite to
+be sure that you haven't broken anything. From a shell::
+
+ cd docutils/test
+ ./alltests.py
+
+
+Python Versions
+===============
+
+A docutils release has a commitment to support a minimum version and beyond.
+Before a release is cut, tests must pass in all supported Python versions.
+
+Docutils 0.16 supports Python 2.7 and Python 3.5 or later.
+
+Therefore, you should install Python 2.7 as well as 3.5 up to the latest Python
+(3.7 at the time of this writing) and always run the tests on all of
+them (see `Testing across multiple python versions`_).
+In a pinch, the edge cases (2.7, and 3.7) should cover most of it.
+
+Good resources covering the differences between Python versions:
+
+* `What's New in Python 2.7`__
+* `What's New in Python 3.5`__
+* `What's New in Python 3.6`__
+* `What's New in Python 3.7`__
+* `PEP 290 - Code Migration and Modernization`__
+
+__ https://docs.python.org/whatsnew/2.6.html
+__ https://docs.python.org/3/whatsnew/3.5.html
+__ https://docs.python.org/3/whatsnew/3.6.html
+__ https://docs.python.org/3/whatsnew/3.7.html
+__ http://www.python.org/peps/pep-0290.html
+
+.. _Python Check-in Policies: http://www.python.org/dev/tools.html
+.. _sandbox directory:
+ http://docutils.svn.sourceforge.net/svnroot/docutils/trunk/sandbox/
+
+
+Testing across multiple python versions
+---------------------------------------
+
+`pyenv`_ can be installed and configured (see `installing pyenv`_) to
+test multiple python versions::
+
+ # assuming your system runs 2.7.x
+ pyenv install 3.5.7
+ pyenv install 3.6.9
+ pyenv install 3.7.3
+ pyenv global system 3.5.7 3.6.9 3.7.3
+
+ # reset your shims
+ rm -rf ~/.pyenv/shims && pyenv rehash
+
+This will give you ``python2.7`` and ``python3.5`` through ``python3.7``.
+You will also get ``pip2.7``, ``pip3.5``, etc.
+
+To save time, you can use `tox`_. To install tox, run ``pip install tox``.
+Once installed, from shell::
+
+ cd docutils
+ tox
+
+.. _tox: https://tox.readthedocs.org/en/latest/
+.. _pyenv: https://github.com/yyuu/pyenv
+.. _installing pyenv: https://github.com/yyuu/pyenv#installation
+
+
+Unit Tests
+==========
+
+Unit tests test single functions or modules (i.e. whitebox testing).
+
+If you are implementing a new feature, be sure to write a test case
+covering its functionality. It happens very frequently that your
+implementation (or even only a part of it) doesn't work with an older
+(or even newer) Python version, and the only reliable way to detect
+those cases is using tests.
+
+Often, it's easier to write the test first and then implement the
+functionality required to make the test pass.
+
+
+Writing New Tests
+-----------------
+
+When writing new tests, it very often helps to see how a similar test
+is implemented. For example, the files in the
+``test_parsers/test_rst/`` directory all look very similar. So when
+adding a test, you don't have to reinvent the wheel.
+
+If there is no similar test, you can write a new test from scratch
+using Python's ``unittest`` module. For an example, please have a
+look at the following imaginary ``test_square.py``::
+
+ #! /usr/bin/env python
+
+ # $Id: testing.txt 8407 2019-10-29 22:48:34Z milde $
+ # Author: Your Name <your_email_address@example.org>
+ # Copyright: This module has been placed in the public domain.
+
+ """
+ Test module for docutils.square.
+ """
+
+ import unittest
+ import docutils.square
+
+
+ class SquareTest(unittest.TestCase):
+
+ def test_square(self):
+ self.assertEqual(docutils.square.square(0), 0)
+ self.assertEqual(docutils.square.square(5), 25)
+ self.assertEqual(docutils.square.square(7), 49)
+
+ def test_square_root(self):
+ self.assertEqual(docutils.square.sqrt(49), 7)
+ self.assertEqual(docutils.square.sqrt(0), 0)
+ self.assertRaises(docutils.square.SquareRootError,
+ docutils.square.sqrt, 20)
+
+
+ if __name__ == '__main__':
+ unittest.main()
+
+For more details on how to write tests, please refer to the
+documentation of the ``unittest`` module.
+
+.. Note::
+
+ Unit tests and functional test should generally set ::
+
+ settings_overrides['_disable_config'] = True
+
+ in order to be independent on the users local configuration.
+
+.. _functional:
+
+Functional Tests
+================
+
+The directory ``test/functional/`` contains data for functional tests.
+
+Performing functional testing means testing the Docutils system as a
+whole (i.e. blackbox testing).
+
+
+Directory Structure
+-------------------
+
++ ``functional/`` The main data directory.
+
+ + ``input/`` The input files.
+
+ - ``some_test.txt``, for example.
+
+ + ``output/`` The actual output.
+
+ - ``some_test.html``, for example.
+
+ + ``expected/`` The expected output.
+
+ - ``some_test.html``, for example.
+
+ + ``tests/`` The config files for processing the input files.
+
+ - ``some_test.py``, for example.
+
+ - ``_default.py``, the `default configuration file`_.
+
+
+The Testing Process
+-------------------
+
+When running ``test_functional.py``, all config files in
+``functional/tests/`` are processed. (Config files whose names begin
+with an underscore are ignored.) The current working directory is
+always Docutils' main test directory (``test/``).
+
+For example, ``functional/tests/some_test.py`` could read like this::
+
+ # Source and destination file names.
+ test_source = "some_test.txt"
+ test_destination = "some_test.html"
+
+ # Keyword parameters passed to publish_file.
+ reader_name = "standalone"
+ parser_name = "rst"
+ writer_name = "html"
+ settings_overrides['output-encoding'] = 'utf-8'
+ # Relative to main ``test/`` directory.
+ settings_overrides['stylesheet_path'] = '../docutils/writers/html4css1/html4css1.css'
+
+The two variables ``test_source`` and ``test_destination`` contain the
+input file name (relative to ``functional/input/``) and the output
+file name (relative to ``functional/output/`` and
+``functional/expected/``). Note that the file names can be chosen
+arbitrarily. However, the file names in ``functional/output/`` *must*
+match the file names in ``functional/expected/``.
+
+If defined, ``_test_more`` must be a function with the following
+signature::
+
+ def _test_more(expected_dir, output_dir, test_case, parameters):
+
+This function is called from the test case to perform tests beyond the
+simple comparison of expected and actual output files.
+
+``test_source`` and ``test_destination`` are removed from the
+namespace, as are all variables whose names begin with an underscore
+("_"). The remaining names are passed as keyword arguments to
+``docutils.core.publish_file``, so you can set reader, parser, writer
+and anything else you want to configure. Note that
+``settings_overrides`` is already initialized as a dictionary *before*
+the execution of the config file.
+
+
+Creating New Tests
+------------------
+
+In order to create a new test, put the input test file into
+``functional/input/``. Then create a config file in
+``functional/tests/`` which sets at least input and output file names,
+reader, parser and writer.
+
+Now run ``test_functional.py``. The test will fail, of course,
+because you do not have an expected output yet. However, an output
+file will have been generated in ``functional/output/``. Check this
+output file for validity [#]_ and correctness. Then copy the file to
+``functional/expected/``.
+
+If you rerun ``test_functional.py`` now, it should pass.
+
+If you run ``test_functional.py`` later and the actual output doesn't
+match the expected output anymore, the test will fail.
+
+If this is the case and you made an intentional change, check the
+actual output for validity and correctness, copy it to
+``functional/expected/`` (overwriting the old expected output), and
+commit the change.
+
+.. [#] The validity of `Docutils XML` can be tested with
+ ``xmllint <document-referencing-local-Docutils-DTD>.xml --valid --noout``.
+
+ .. note: the ``--dtdvalid`` and ``--nonet`` options did not help override
+ a reference to the PUBLIC "docutils.dtd" if there is a local version
+ on the system (e.g. /usr/share/xml/docutils/docutils.dtd in Debian).
+
+
+.. _default configuration file:
+
+The Default Configuration File
+------------------------------
+
+The file ``functional/tests/_default.py`` contains default settings.
+It is executed just before the actual configuration files, which has
+the same effect as if the contents of ``_default.py`` were prepended
+to every configuration file.
--- /dev/null
+======================
+ Docutils_ To Do List
+======================
+
+:Author: David Goodger (with input from many); open to all Docutils
+ developers
+:Contact: docutils-develop@lists.sourceforge.net
+:Date: $Date: 2019-08-27 17:30:40 +0200 (Di, 27. Aug 2019) $
+:Revision: $Revision: 8375 $
+:Copyright: This document has been placed in the public domain.
+
+.. _Docutils: http://docutils.sourceforge.net/
+
+.. contents::
+
+
+Priority items are marked with "@" symbols. The more @s, the higher
+the priority. Items in question form (containing "?") are ideas which
+require more thought and debate; they are potential to-do's.
+
+Many of these items are awaiting champions. If you see something
+you'd like to tackle, please do! If there's something you'd like to
+see done but are unable to implement it yourself, please consider
+donating to Docutils: |donate|
+
+.. |donate| image:: http://images.sourceforge.net/images/project-support.jpg
+ :target: http://sourceforge.net/donate/index.php?group_id=38414
+ :align: middle
+ :width: 88
+ :height: 32
+ :alt: Support the Docutils project!
+
+Please see also the Bugs_ document for a list of bugs in Docutils.
+
+.. _bugs: ../../BUGS.html
+
+
+Minimum Requirements for Python Standard Library Candidacy
+==========================================================
+
+Below are action items that must be added and issues that must be
+addressed before Docutils can be considered suitable to be proposed
+for inclusion in the Python standard library.
+
+Many of these are now handled by Sphinx_
+
+* Support for `document splitting`_. May require some major code
+ rework.
+
+* Support for subdocuments (see `large documents`_).
+
+* `Object numbering and object references`_.
+
+* `Nested inline markup`_.
+
+* `Python Source Reader`_.
+
+* The HTML writer needs to be rewritten (or a second HTML writer
+ added) to allow for custom classes, and for arbitrary splitting
+ (stack-based?).
+
+* Documentation_ of the architecture. Other docs too.
+
+* Plugin support.
+
+* Suitability for `Python module documentation
+ <http://docutils.sf.net/sandbox/README.html#documenting-python>`_.
+
+.. _Sphinx: http://sphinx.pocoo.org/
+
+General
+=======
+
+* Encoding of command line arguments can only be guessed:
+
+ * try UTF-8/strict first, then try the locale's encoding with
+ strict error handling, then ASCII/replace?
+
+ UTF-8 is almost 100% safe to try first; false positives are rare,
+ The locale's encoding with strict error handling may be a
+ reasonable compromise, but any error would indicate that the
+ locale's encoding is inappropriate. The only safe fallback is
+ ASCII/replace.
+
+ * Do not decode argv before option parsing but individual string
+ values?
+
+ +1 Allows for separate command-line vs. filesystem encodings,
+ respectively to keep file names encoded.
+ +1 Allows to configure command-line encoding in a config file,
+ -1 More complicated.
+
+ Cf. <http://thread.gmane.org/gmane.text.docutils.user/2890/focus=2957>.
+
+* Improve handling on Windows:
+
+ - Get graphical installer.
+ - Make rst2html.py an .exe file using py2exe.
+
+* .. _GUI:
+
+ The user interface is very difficult to use for most Windows users;
+ you can't really expect them to use the command line. We need some
+ kind of GUI that can launch rst2html.py, and save the HTML output to
+ a file, and launch a browser. What's important is that we get
+ settings to work with the GUI. So we need some way to dynamically
+ generate a list of settings for the GUI. The current settings_spec
+ for OptionParser doesn't seem to be usable for this for the
+ following reasons:
+
+ - It's biased toward the command line -- there are *two* options for
+ one boolean setting.
+
+ - You cannot have both a one-line description and a longer
+ description for tooltips/help-texts.
+
+ - It doesn't provide hints for the input type. You cannot easily
+ infer the type of a setting from its validator, because any
+ component can add new validators. In fact, it may be necessary to
+ have both a hint about the input type (e.g. string) and a
+ validator (valid ID), or it may be necessary to have a different
+ set of choices for the CLI (1, INFO, 2, ...) and for the GUI
+ (INFO, WARNING, ...).
+
+ - It's coupled to the OptionParser. We want to be able to change
+ the underlying system without breaking everything.
+
+ - It's a bunch of primitive structures. We want an extensible (thus
+ object-oriented) interface.
+
+ So we probably need to create a class for storing all the settings,
+ and auto-generate the OptionParser data from that.
+
+ I talked to Stephan Deibel about getting Docutils integrated into
+ Wing IDE. He said it's possible, and he'd be willing to help.
+ There's a scripting interface to Wing, which we'd use. We can
+ dynamically generate a list of preferences and not worry too much
+ about the rendering (from what I understood); Wing's whole GUI is
+ dynamic anyway. The interface could be made usable for other GUIs.
+ For example, we could try to get option support for DocFactory. //
+ FW
+
+* Allow different report levels for STDERR and system_messages inside
+ the document?
+
+* Change the docutils-update script (in sandbox/infrastructure), to
+ support arbitrary branch snapshots.
+
+* Move some general-interest sandboxes out of individuals'
+ directories, into subprojects?
+
+* Add option for file (and URL) access restriction to make Docutils
+ usable in Wikis and similar applications.
+
+ 2005-03-21: added ``file_insertion_enabled`` & ``raw_enabled``
+ settings. These partially solve the problem, allowing or disabling
+ **all** file accesses, but not limited access.
+
+* Configuration file handling needs discussion:
+
+ - There should be some error checking on the contents of config
+ files. How much checking should be done? How loudly should
+ Docutils complain if it encounters an error/problem?
+
+ - Docutils doesn't complain when it doesn't find a configuration
+ file supplied with the ``--config`` option. Should it? (If yes,
+ error or warning?)
+
+* Internationalization:
+
+ - I18n needs refactoring, the language dictionaries are difficult to
+ maintain. Maybe have a look at gettext or similar tools.
+
+ (This would make a nice Google Summer of Code project)
+
+ - Language modules: in accented languages it may be useful to have
+ both accented and unaccented entries in the
+ ``bibliographic_fields`` mapping for versatility.
+
+ - Add a "--strict-language" option & setting: no English fallback
+ for language-dependent features.
+
+ Make this the default for output (as opposed to input)?
+ Throw an error with a helpfull message, e.g.
+
+ Default "contents" title for language %s missing, please specify
+ an explicit title.
+
+ or
+
+ "attention" title for language %s missing, please use a generic
+ admonition with explicit title.
+
+ - Add internationalization to _`footer boilerplate text` (resulting
+ from "--generator", "--source-link", and "--date" etc.), allowing
+ translations.
+
+
+* Add validation? See http://pytrex.sourceforge.net, RELAX NG, pyRXP.
+
+* In ``docutils.readers.get_reader_class`` (& ``parsers`` &
+ ``writers`` too), should we be importing "standalone" or
+ "docutils.readers.standalone"? (This would avoid importing
+ top-level modules if the module name is not in docutils/readers.
+ Potential nastiness.)
+
+* Perhaps store a _`name-to-id mapping file`? This could be stored
+ permanently, read by subsequent processing runs, and updated with
+ new entries. ("Persistent ID mapping"?)
+
+* Perhaps the ``Component.supports`` method should deal with
+ individual features ("meta" etc.) instead of formats ("html" etc.)?
+
+* Think about _`large documents` made up of multiple subdocument
+ files. Issues: continuity (`persistent sequences`_ above),
+ cross-references (`name-to-id mapping file`_ above and `targets in
+ other documents`_ below), splitting (`document splitting`_ below).
+
+ When writing a book, the author probably wants to split it up into
+ files, perhaps one per chapter (but perhaps even more detailed).
+ However, we'd like to be able to have references from one chapter to
+ another, and have continuous numbering (pages and chapters, as
+ applicable). Of course, none of this is implemented yet. There has
+ been some thought put into some aspects; see `the "include"
+ directive`__ and the `Reference Merging`_ transform below.
+
+ When I was working with SGML in Japan, we had a system where there
+ was a top-level coordinating file, book.sgml, which contained the
+ top-level structure of a book: the <book> element, containing the
+ book <title> and empty component elements (<preface>, <chapter>,
+ <appendix>, etc.), each with filename attributes pointing to the
+ actual source for the component. Something like this::
+
+ <book id="bk01">
+ <title>Title of the Book</title>
+ <preface inrefid="pr01"></preface>
+ <chapter inrefid="ch01"></chapter>
+ <chapter inrefid="ch02"></chapter>
+ <chapter inrefid="ch03"></chapter>
+ <appendix inrefid="ap01"></appendix>
+ </book>
+
+ (The "inrefid" attribute stood for "insertion reference ID".)
+
+ The processing system would process each component separately, but
+ it would recognize and use the book file to coordinate chapter and
+ page numbering, and keep a persistent ID to (title, page number)
+ mapping database for cross-references. Docutils could use a similar
+ system for large-scale, multipart documents.
+
+ __ ../ref/rst/directives.html#including-an-external-document-fragment
+
+ Aahz's idea:
+
+ First the ToC::
+
+ .. ToC-list::
+ Introduction.txt
+ Objects.txt
+ Data.txt
+ Control.txt
+
+ Then a sample use::
+
+ .. include:: ToC.txt
+
+ As I said earlier in chapter :chapter:`Objects.txt`, the
+ reference count gets increased every time a binding is made.
+
+ Which produces::
+
+ As I said earlier in chapter 2, the
+ reference count gets increased every time a binding is made.
+
+ The ToC in this form doesn't even need to be references to actual
+ reST documents; I'm simply doing it that way for a minimum of
+ future-proofing, in case I do want to add the ability to pick up
+ references within external chapters.
+
+ Perhaps, instead of ToC (which would overload the "contents"
+ directive concept already in use), we could use "manifest". A
+ "manifest" directive might associate local reference names with
+ files::
+
+ .. manifest::
+ intro: Introduction.txt
+ objects: Objects.txt
+ data: Data.txt
+ control: Control.txt
+
+ Then the sample becomes::
+
+ .. include:: manifest.txt
+
+ As I said earlier in chapter :chapter:`objects`, the
+ reference count gets increased every time a binding is made.
+
+* Add support for _`multiple output files` and _`generic data
+ handling`:
+
+ It should be possible for a component to **emit or reference** data
+ to be either **included or referenced** in the output document.
+ Examples of such data are stylesheets or images.
+
+ For this, we need a "data" object which stores the data either
+ inline or by referring to a file. The Docutils framework is
+ responsible for either:
+
+ * storing the data in the appropriate location (e.g. in the
+ directory of the output file, or in a user-specified directory)
+ and providing the paths of the stored files to the writer, *or*
+
+ * providing the data itself to the writer so that it can be embedded
+ in the output document.
+
+ This approach decouples data handling from the data source (which
+ can either be embedded or referenced) and the destination (which can
+ either be embedded or referenced as well).
+
+ See <http://article.gmane.org/gmane.text.docutils.devel/3631>.
+
+* Add testing for Docutils' front end tools?
+
+* Publisher: "Ordinary setup" shouldn't requre specific ordering; at
+ the very least, there ought to be error checking higher up in the
+ call chain. [Aahz]
+
+ ``Publisher.get_settings`` requires that all components be set up
+ before it's called. Perhaps the I/O *objects* shouldn't be set, but
+ I/O *classes*. Then options are set up (``.set_options``), and
+ ``Publisher.set_io`` (or equivalent code) is called with source &
+ destination paths, creating the I/O objects.
+
+ Perhaps I/O objects shouldn't be instantiated until required. For
+ split output, the Writer may be called multiple times, once for each
+ doctree, and each doctree should have a separate Output object (with
+ a different path). Is the "Builder" pattern applicable here?
+
+* Perhaps I/O objects should become full-fledged components (i.e.
+ subclasses of ``docutils.Component``, as are Readers, Parsers, and
+ Writers now), and thus have associated option/setting specs and
+ transforms.
+
+* Multiple file I/O suggestion from Michael Hudson: use a file-like
+ object or something you can iterate over to get file-like objects.
+
+* Add an "--input-language" option & setting? Specify a different
+ language module for input (bibliographic fields, directives) than
+ for output. The "--language" option would set both input & output
+ languages.
+
+* Auto-generate reference tables for language-dependent features?
+ Could be generated from the source modules. A special command-line
+ option could be added to Docutils front ends to do this. (Idea from
+ Engelbert Gruber.)
+
+* Enable feedback of some kind from internal decisions, such as
+ reporting the successful input encoding. Modify runtime settings?
+ System message? Simple stderr output?
+
+* Rationalize Writer settings (HTML/LaTeX/PEP) -- share settings.
+
+* Add an "--include file" command-line option (config setting too?),
+ equivalent to ".. include:: file" as the first line of the doc text?
+ Especially useful for character entity sets, text transform specs,
+ boilerplate, etc.
+
+* Support "include" as embedded inline-compatible directive in substitution
+ definitions, e.g. ::
+
+ .. |version| include:: version.txt
+
+ This document describes version |version| of ...
+
+ (cf. Grzegorz Adam Hankiewicz's post from 2014-10-01 in docutils-devel)
+
+* Add an ``:optional: <replacement text>`` option to the "include"
+ directive? This would not throw an error for a missing file, instead a
+ warning is given and ``<replacement text>`` is used instead. It would be
+ the responsibility of the author to ensure the missing file does not lead
+ to problems later in the document.
+
+ Use cases:
+
+ + Standard rST syntax to replace Sphinx's "literalinclude"::
+
+ .. include:: blah.cpp
+ :literal:
+ :optional: file ``blah.cpp`` not found
+
+ + Variable content taken from a file, e.g.
+
+ version.txt::
+
+ .. |version| replace:: 3.1
+
+ optionally used as::
+
+ .. include:: version.txt
+ :optional: .. |version| replace:: unknown
+
+ This document describes version |version| of ...
+
+ (cf. Grzegorz Adam Hankiewicz's post from 2014-10-01 in docutils-devel)
+
+* Parameterize the Reporter object or class? See the `2004-02-18
+ "rest checking and source path"`_ thread.
+
+ .. _2004-02-18 "rest checking and source path":
+ http://thread.gmane.org/gmane.text.docutils.user/1112
+
+* Add a "disable_transforms" setting? And a dummy Writer subclass
+ that does nothing when its .write() method is called? Would allow
+ for easy syntax checking. See the `2004-02-18 "rest checking and
+ source path"`_ thread.
+
+* Add a generic meta-stylesheet mechanism? An external file could
+ associate style names ("class" attributes) with specific elements.
+ Could be generalized to arbitrary output attributes; useful for HTML
+ & XMLs. Aahz implemented something like this in
+ sandbox/aahz/Effective/EffMap.py.
+
+* .. _classes for table cells:
+
+ William Dode suggested that table cells be assigned "class"
+ attributes by columns, so that stylesheets can affect text
+ alignment. Unfortunately, there doesn't seem to be a way (in HTML
+ at least) to leverage the "colspec" elements (HTML "col" tags) by
+ adding classes to them. The resulting HTML is very verbose::
+
+ <td class="col1">111</td>
+ <td class="col2">222</td>
+ ...
+
+ At the very least, it should be an option. People who don't use it
+ shouldn't be penalized by increases in their HTML file sizes.
+
+ Table rows could also be assigned classes (like odd/even). That
+ would be easier to implement.
+
+ How should it be implemented?
+
+ * There could be writer options (column classes & row classes) with
+ standard values.
+
+ * The table directive could grow some options. Something like
+ ":cell-classes: col1 col2 col3" (either must match the number of
+ columns, or repeat to fill?) and ":row-classes: odd even" (repeat
+ to fill; body rows only, or header rows too?).
+
+ Probably per-table directive options are best. The "class" values
+ could be used by any writer, and applying such classes to all tables
+ in a document with writer options is too broad.
+
+ See also the `table_styling Sphinx extension`_ which defines
+
+ :widths: also in Docutils core (but different implementation)
+ :column-alignment: Sets per-column text alignment
+ :column-wrapping: Sets per-column text wrapping
+ :column-dividers: Add dividers between columns
+ :column-classes: Add per-column css classes.
+ :header-columns: Specify number of “stub” columns
+
+ .. _table_styling Sphinx extension: https://pythonhosted.org/cloud_sptheme/
+ lib/cloud_sptheme.ext.table_styling.html
+
+* Add file-specific settings support to config files, like::
+
+ [file index.txt]
+ compact-lists: no
+
+ Is this even possible? Should the criterion be the name of the
+ input file or the output file? Alternative (more explicit) syntax::
+
+ [source_file index.txt]
+ ...
+
+ [dest_file index.html]
+ ...
+
+ Or rather allow settings configuration from the rst source file
+ (see misc.settings_ directive)?
+
+* The "validator" support added to OptionParser is very similar to
+ "traits_" in SciPy_. Perhaps something could be done with them?
+ (Had I known about traits when I was implementing docutils.frontend,
+ I may have used them instead of rolling my own.)
+
+ .. _traits: http://code.enthought.com/traits/
+ .. _SciPy: http://www.scipy.org/
+
+* tools/buildhtml.py: Extend the --prune option ("prune" config
+ setting) to accept file names (generic path) in addition to
+ directories (e.g. --prune=docs/user/rst/cheatsheet.txt, which should
+ *not* be converted to HTML).
+
+* Add support for _`plugins`.
+
+* _`Config directories`: Currently, ~/.docutils, ./docutils.conf/, &
+ /etc/docutils.conf are read as configuration files. Proposal: allow
+ ~/.docutils to be a a configuration *directory*, along with
+ /etc/docutils/ and ./docutils.conf/. Within these directories,
+ check for config.txt files. We can also have subdirectories here,
+ for plugins, S5 themes, components (readers/writers/parsers) etc.
+
+ Docutils will continue to support configuration files for backwards
+ compatibility.
+
+* Add support for document decorations other than headers & footers?
+ For example, top/bottom/side navigation bars for web pages. Generic
+ decorations?
+
+ Seems like a bad idea as long as it isn't independent from the ouput
+ format (for example, navigation bars are only useful for web pages).
+
+* docutils_update: Check for a ``Makefile`` in a directory, and run
+ ``make`` if found? This would allow for variant processing on
+ specific source files, such as running rst2s5.py instead of
+ rst2html.py.
+
+* Add a "disable table of contents" setting? The S5 writer could set
+ it as a default. Rationale:
+
+ The ``contents`` (table of contents) directive must not be used
+ [in S5/HTML documents]. It changes the CSS class of headings
+ and they won't show up correctly in the screen presentation.
+
+ -- `Easy Slide Shows With reStructuredText & S5
+ <../user/slide-shows.html>`_
+
+ Analogue to the ``sectnum_xform`` setting, it could be used by the
+ latex writer to switch to a LaTeX generated ToC (currently, the latex
+ writer calls it "use_latex_toc").
+
+object numbering and object references
+--------------------------------------
+
+For equations, tables & figures.
+
+These would be the equivalent of DocBook's "formal" elements.
+
+In LaTeX, automatic counters are implemented for sections, equations and
+floats (figures, tables) (configurable via stylesheets or in the
+latex-preamble). Objects can be given `reference names`_ with the
+``\label{<refname}`` command, ``\ref{<refname>}`` inserts the
+corresponding number.
+
+No such mechanism exists in HTML.
+
+* We need _`persistent sequences`, similar to chapter and footnote
+ numbers. See `OpenOffice.org XML`_ "fields".
+
+ - Should the sequences be automatic or manual (user-specifyable)?
+
+* It is already possible to give `reference names`_ to objects via
+ internal hyperlink targets or the "name" directive option::
+
+ .. _figure name:
+
+ .. figure:: image.png
+
+ or ::
+
+ .. figure:: image.png
+ :name: figure name
+
+ Improve the mapping of "phrase references" to IDs/labels with
+ Literal transcription (i.e. ü -> ue, ß -> ss, å -> aa) instead of just
+ stripping the accents and other non-ASCII chars.
+ Use http://pypi.python.org/pypi/Unidecode?
+
+ A "table" directive has been implemented, supporting table titles.
+
+ Perhaps the name could derive from the title/caption?
+
+ .. _reference names: ../ref/rst/restructuredtext.html#reference-names
+
+* We need syntax for object references. Cf. `OpenOffice.org XML`_
+ "reference fields":
+
+ - Parameterized substitutions are too complicated
+ (cf. `or not to do`: `object references`_)
+
+ - An interpreted text approach is simpler and better::
+
+ See Figure :ref:`figure name` and Equation :ref:`eq:identity`.
+
+ - "equation", "figure", and "page" roles could generate appropriate
+ boilerplate text::
+
+ See :figure:`figure name` on :page:`figure name`.
+
+ See `Interpreted Text`_ below.
+
+ Reference boilerplate could be specified in the document
+ (defaulting to nothing)::
+
+ .. fignum::
+ :prefix-ref: "Figure "
+ :prefix-caption: "Fig. "
+ :suffix-caption: :
+
+ The position of the role (prefix or suffix) could also be utilized
+
+ .. _OpenOffice.org XML: http://xml.openoffice.org/
+ .. _object references: rst/alternatives.html#object-references
+
+See also the `Modified rst2html
+<http://www.loria.fr/~rougier/coding/article/rst2html.py>`__
+by Nicolas Rougier for a sample implementation.
+
+
+Documentation
+=============
+
+User Docs
+---------
+
+* Add a FAQ entry about using Docutils (with reStructuredText) on a
+ server and that it's terribly slow. See the first paragraphs in
+ <http://article.gmane.org/gmane.text.docutils.user/1584>.
+
+* Add document about what Docutils has previously been used for
+ (web/use-cases.txt?).
+
+* Improve index in docs/user/config.txt.
+
+
+Developer Docs
+--------------
+
+* Complete `Docutils Runtime Settings <../api/runtime-settings.html>`_.
+
+* Improve the internal module documentation (docstrings in the code).
+ Specific deficiencies listed below.
+
+ - docutils.parsers.rst.states.State.build_table: data structure
+ required (including StringList).
+
+ - docutils.parsers.rst.states: more complete documentation of parser
+ internals.
+
+* docs/ref/doctree.txt: DTD element structural relationships,
+ semantics, and attributes. In progress; element descriptions to be
+ completed.
+
+* Document the ``pending`` elements, how they're generated and what
+ they do.
+
+* Document the transforms (perhaps in docstrings?): how they're used,
+ what they do, dependencies & order considerations.
+
+* Document the HTML classes used by html4css1.py.
+
+* Write an overview of the Docutils architecture, as an introduction
+ for developers. What connects to what, why, and how. Either update
+ PEP 258 (see PEPs_ below) or as a separate doc.
+
+* Give information about unit tests. Maybe as a howto?
+
+* Document the docutils.nodes APIs.
+
+* Complete the docs/api/publisher.txt docs.
+
+
+How-Tos
+-------
+
+* Creating Docutils Writers
+
+* Creating Docutils Readers
+
+* Creating Docutils Transforms
+
+* Creating Docutils Parsers
+
+* Using Docutils as a Library
+
+
+PEPs
+----
+
+* Complete PEP 258 Docutils Design Specification.
+
+ - Fill in the blanks in API details.
+
+ - Specify the nodes.py internal data structure implementation?
+
+ [Tibs:] Eventually we need to have direct documentation in
+ there on how it all hangs together - the DTD is not enough
+ (indeed, is it still meant to be correct? [Yes, it is.
+ --DG]).
+
+* Rework PEP 257, separating style from spec from tools, wrt Docutils?
+ See Doc-SIG from 2001-06-19/20.
+
+
+Python Source Reader
+====================
+
+General:
+
+* Analyze Tony Ibbs' PySource code.
+
+* Analyze Doug Hellmann's HappyDoc project.
+
+* Investigate how POD handles literate programming.
+
+* Take the best ideas and integrate them into Docutils.
+
+Miscellaneous ideas:
+
+* Ask Python-dev for opinions (GvR for a pronouncement) on special
+ variables (__author__, __version__, etc.): convenience vs. namespace
+ pollution. Ask opinions on whether or not Docutils should recognize
+ & use them.
+
+* If we can detect that a comment block begins with ``##``, a la
+ JavaDoc, it might be useful to indicate interspersed section headers
+ & explanatory text in a module. For example::
+
+ """Module docstring."""
+
+ ##
+ # Constants
+ # =========
+
+ a = 1
+ b = 2
+
+ ##
+ # Exception Classes
+ # =================
+
+ class MyException(Exception): pass
+
+ # etc.
+
+* Should standalone strings also become (module/class) docstrings?
+ Under what conditions? We want to prevent arbitrary strings from
+ becomming docstrings of prior attribute assignments etc. Assume
+ that there must be no blank lines between attributes and attribute
+ docstrings? (Use lineno of NEWLINE token.)
+
+ Triple-quotes are sometimes used for multi-line comments (such as
+ commenting out blocks of code). How to reconcile?
+
+* HappyDoc's idea of using comment blocks when there's no docstring
+ may be useful to get around the conflict between `additional
+ docstrings`_ and ``from __future__ import`` for module docstrings.
+ A module could begin like this::
+
+ #!/usr/bin/env python
+ # :Author: Me
+ # :Copyright: whatever
+
+ """This is the public module docstring (``__doc__``)."""
+
+ # More docs, in comments.
+ # All comments at the beginning of a module could be
+ # accumulated as docstrings.
+ # We can't have another docstring here, because of the
+ # ``__future__`` statement.
+
+ from __future__ import division
+
+ Using the JavaDoc convention of a doc-comment block beginning with
+ ``##`` is useful though. It allows doc-comments and implementation
+ comments.
+
+ .. _additional docstrings:
+ ../peps/pep-0258.html#additional-docstrings
+
+* HappyDoc uses an initial comment block to set "parser configuration
+ values". Do the same thing for Docutils, to set runtime settings on
+ a per-module basis? I.e.::
+
+ # Docutils:setting=value
+
+ Could be used to turn on/off function parameter comment recognition
+ & other marginal features. Could be used as a general mechanism to
+ augment config files and command-line options (but which takes
+ precedence?).
+
+* Multi-file output should be divisible at arbitrary level.
+
+* Support all forms of ``import`` statements:
+
+ - ``import module``: listed as "module"
+ - ``import module as alias``: "alias (module)"
+ - ``from module import identifier``: "identifier (from module)"
+ - ``from module import identifier as alias``: "alias (identifier
+ from module)"
+ - ``from module import *``: "all identifiers (``*``) from module"
+
+* Have links to colorized Python source files from API docs? And
+ vice-versa: backlinks from the colorized source files to the API
+ docs!
+
+* In summaries, use the first *sentence* of a docstring if the first
+ line is not followed by a blank line.
+
+
+reStructuredText Parser
+=======================
+
+Also see the `... Or Not To Do?`__ list.
+
+__ rst/alternatives.html#or-not-to-do
+
+Misc
+----
+
+* Another list problem::
+
+ * foo
+ * bar
+ * baz
+
+ This ends up as a definition list. This is more of a usability
+ issue.
+
+* This case is probably meant to be a nested list, but it ends up as a
+ list inside a block-quote without an error message::
+
+ - foo
+
+ - bar
+
+ It should probably just be an error.
+
+ The problem with this is that you don't notice easily in HTML that
+ it's not a nested list but a block-quote -- there's not much of a
+ visual difference.
+
+* Treat enumerated lists that are not arabic and consist of only one
+ item in a single line as ordinary paragraphs. See
+ <http://article.gmane.org/gmane.text.docutils.user/2635>.
+
+* The citation syntax could use some improvements. See
+ <http://thread.gmane.org/gmane.text.docutils.user/2499> (and the
+ sub-thread at
+ <http://thread.gmane.org/gmane.text.docutils.user/2499/focus=3028>,
+ and the follow-ups at
+ <http://thread.gmane.org/gmane.text.docutils.user/3087>,
+ <http://thread.gmane.org/gmane.text.docutils.user/3110>,
+ <http://thread.gmane.org/gmane.text.docutils.user/3114>),
+ <http://thread.gmane.org/gmane.text.docutils.user/2443>,
+ <http://thread.gmane.org/gmane.text.docutils.user/2715>,
+ <http://thread.gmane.org/gmane.text.docutils.user/3027>,
+ <http://thread.gmane.org/gmane.text.docutils.user/3120>,
+ <http://thread.gmane.org/gmane.text.docutils.user/3253>.
+
+* The current list-recognition logic has too many false positives, as
+ in ::
+
+ * Aorta
+ * V. cava superior
+ * V. cava inferior
+
+ Here ``V.`` is recognized as an enumerator, which leads to
+ confusion. We need to find a solution that resolves such problems
+ without complicating the spec to much.
+
+ See <http://thread.gmane.org/gmane.text.docutils.user/2524>.
+
+* Add indirect links via citation references & footnote references.
+ Example::
+
+ `Goodger (2005)`_ is helpful.
+
+ .. _Goodger (2005): [goodger2005]_
+ .. [goodger2005] citation text
+
+ See <http://thread.gmane.org/gmane.text.docutils.user/2499>.
+
+* Complain about bad URI characters
+ (http://article.gmane.org/gmane.text.docutils.user/2046) and
+ disallow internal whitespace
+ (http://article.gmane.org/gmane.text.docutils.user/2214).
+
+* Create ``info``-level system messages for unnecessarily
+ backslash-escaped characters (as in ``"\something"``, rendered as
+ "something") to allow checking for errors which silently slipped
+ through.
+
+* Add (functional) tests for untested roles.
+
+* Add test for ":figwidth: image" option of "figure" directive. (Test
+ code needs to check if PIL is available on the system.)
+
+* Add support for CJK double-width whitespace (indentation) &
+ punctuation characters (markup; e.g. double-width "*", "-", "+")?
+
+* Add motivation sections for constructs in spec.
+
+* Support generic hyperlink references to _`targets in other
+ documents`? Not in an HTML-centric way, though (it's trivial to say
+ ``http://www.example.com/doc#name``, and useless in non-HTML
+ contexts). XLink/XPointer? ``.. baseref::``? See Doc-SIG
+ 2001-08-10.
+
+* .. _adaptable file extensions:
+
+ In target URLs, it would be useful to not explicitly specify the
+ file extension. If we're generating HTML, then ".html" is
+ appropriate; if PDF, then ".pdf"; etc. How about using ".*" to
+ indicate "choose the most appropriate filename extension"? For
+ example::
+
+ .. _Another Document: another.*
+
+ What is to be done for output formats that don't *have* hyperlinks?
+ For example, LaTeX targeted at print. Hyperlinks may be "called
+ out", as footnotes with explicit URLs. (Don't convert the links.)
+
+ But then there's also LaTeX targeted at PDFs, which *can* have
+ links. Perhaps a runtime setting for "*" could explicitly provide
+ the extension, defaulting to the output file's extension.
+
+ Should the system check for existing files? No, not practical.
+
+ Handle documents only, or objects (images, etc.) also?
+
+ If this handles images also, how to differentiate between document
+ and image links? Element context (within "image")? Which image
+ extension to use for which document format? Again, a runtime
+ setting would suffice.
+
+ This may not be just a parser issue; it may need framework support.
+
+ Mailing list threads: `Images in both HTML and LaTeX`__ (especially
+ `this summary of Lea's objections`__), `more-universal links?`__,
+ `Output-format-sensitive link targets?`__
+
+ __ http://thread.gmane.org/gmane.text.docutils.user/1239
+ __ http://article.gmane.org/gmane.text.docutils.user/1278
+ __ http://thread.gmane.org/gmane.text.docutils.user/1915
+ __ http://thread.gmane.org/gmane.text.docutils.user/2438
+
+ Idea from Jim Fulton: an external lookup table of targets:
+
+ I would like to specify the extension (e.g. .txt) [in the
+ source, rather than ``filename.*``], but tell the converter to
+ change references to the files anticipating that the files will
+ be converted too.
+
+ For example::
+
+ .. _Another Document: another.txt
+
+ rst2html.py --convert-links "another.txt bar.txt" foo.txt
+
+ That is, name the files for which extensions should be converted.
+
+ Note that I want to refer to original files in the original text
+ (another.txt rather than another.txt) because I want the
+ unconverted text to stand on its own.
+
+ Note that in most cases, people will be able to use globs::
+
+ rst2html.py --convert-link-extensions-for "`echo *.txt`" foo.txt
+
+ It might be nice to be able to use multiple arguments, as in::
+
+ rst2html.py --convert-link-extensions-for *.txt -- foo.txt
+
+ ::
+
+ > What is to be done for output formats
+ > that don't have hyperlinks?
+
+ Don't convert the links.
+
+ ::
+
+ > Handle documents only, or objects
+ > (images, etc.) also?
+
+ No, documents only, but there really is no need for gueswork.
+ Just get the file names as command-line arguments. EIBTI
+ [explicit is better than implicit].
+
+ For images, we probably need separate solution (which is being
+ worked on), whereas for documents, the issue is basically
+ interlinking between reStructuredText documents. IMO, this cries
+ for support for multiple input and output files, i.e. support for
+ documents which comprise multiple files. Adding adaptable file
+ extensions seems like a kludge. // FW
+
+* Implement the header row separator modification to table.el. (Wrote
+ to Takaaki Ota & the table.el mailing list on 2001-08-12, suggesting
+ support for "=====" header rows. On 2001-08-17 he replied, saying
+ he'd put it on his to-do list, but "don't hold your breath".)
+
+* Fix the parser's indentation handling to conform with the stricter
+ definition in the spec. (Explicit markup blocks should be strict or
+ forgiving?)
+
+ .. XXX What does this mean? Can you elaborate, David?
+
+* Make the parser modular. Allow syntax constructs to be added or
+ disabled at run-time. Subclassing is probably not enough because it
+ makes it difficult to apply multiple extensions.
+
+* Generalize the "doctest block" construct (which is overly
+ Python-centric) to other interactive sessions? "Doctest block"
+ could be renamed to "I/O block" or "interactive block", and each of
+ these could also be recognized as such by the parser:
+
+ - Shell sessions::
+
+ $ cat example1.txt
+ A block beginning with a "$ " prompt is interpreted as a shell
+ session interactive block. As with Doctest blocks, the
+ interactive block ends with the first blank line, and wouldn't
+ have to be indented.
+
+ - Root shell sessions::
+
+ # cat example2.txt
+ A block beginning with a "# " prompt is interpreted as a root
+ shell session (the user is or has to be logged in as root)
+ interactive block. Again, the block ends with a blank line.
+
+ Other standard (and unambiguous) interactive session prompts could
+ easily be added (such as "> " for WinDOS).
+
+ Tony Ibbs spoke out against this idea (2002-06-14 Doc-SIG thread
+ "docutils feedback").
+
+* Add support for pragma (syntax-altering) directives.
+
+ Some pragma directives could be local-scope unless explicitly
+ specified as global/pragma using ":global:" options.
+
+* Support whitespace in angle-bracketed standalone URLs according to
+ Appendix E ("Recommendations for Delimiting URI in Context") of `RFC
+ 2396`_.
+
+ .. _RFC 2396: http://www.rfc-editor.org/rfc/rfc2396.txt
+
+* Use the vertical spacing of the source text to determine the
+ corresponding vertical spacing of the output?
+
+* [From Mark Nodine] For cells in simple tables that comprise a
+ single line, the justification can be inferred according to the
+ following rules:
+
+ 1. If the text begins at the leftmost column of the cell,
+ then left justification, ELSE
+ 2. If the text begins at the rightmost column of the cell,
+ then right justification, ELSE
+ 3. Center justification.
+
+ The onus is on the author to make the text unambiguous by adding
+ blank columns as necessary. There should be a parser setting to
+ turn off justification-recognition (normally on would be fine).
+
+ Decimal justification?
+
+ All this shouldn't be done automatically. Only when it's requested
+ by the user, e.g. with something like this::
+
+ .. table::
+ :auto-indent:
+
+ (Table goes here.)
+
+ Otherwise it will break existing documents.
+
+* Generate a warning or info message for paragraphs which should have
+ been lists, like this one::
+
+ 1. line one
+ 3. line two
+
+* Generalize the "target-notes" directive into a command-line option
+ somehow? See docutils-develop 2003-02-13.
+
+* Allow a "::"-only paragraph (first line, actually) to introduce a
+ _`literal block without a blank line`? (Idea from Paul Moore.) ::
+
+ ::
+ This is a literal block
+
+ Is indentation enough to make the separation between a paragraph
+ which contains just a ``::`` and the literal text unambiguous?
+ (There's one problem with this concession: If one wants a definition
+ list item which defines the term "::", we'd have to escape it.) It
+ would only be reasonable to apply it to "::"-only paragraphs though.
+ I think the blank line is visually necessary if there's text before
+ the "::"::
+
+ The text in this paragraph needs separation
+ from the literal block following::
+ This doesn't look right.
+
+* Add new syntax for _`nested inline markup`? Or extend the parser to
+ parse nested inline markup somehow? See the `collected notes
+ <rst/alternatives.html#nested-inline-markup>`__.
+
+* Drop the backticks from embedded URIs with omitted reference text?
+ Should the angle brackets be kept in the output or not? ::
+
+ <file_name>_
+
+ Probably not worth the trouble.
+
+* How about a syntax for alternative hyperlink behavior, such as "open
+ in a new window" (as in HTML's ``<a target="_blank">``)?
+
+ The MoinMoin wiki uses a caret ("^") at the beginning of the URL
+ ("^" is not a legal URI character). That could work for both inline
+ and explicit targets::
+
+ The `reference docs <^url>`__ may be handy.
+
+ .. _name: ^url
+
+ This may be too specific to HTML. It hasn't been requested very
+ often either.
+
+* Add an option to add URI schemes at runtime.
+
+* _`Segmented lists`::
+
+ : segment : segment : segment
+ : segment : segment : very long
+ segment
+ : segment : segment : segment
+
+ The initial colon (":") can be thought of as a type of bullet
+
+ We could even have segment titles::
+
+ :: title : title : title
+ : segment : segment : segment
+ : segment : segment : segment
+
+ This would correspond well to DocBook's SegmentedList. Output could
+ be tabular or "name: value" pairs, as described in DocBook's docs.
+
+* Enable grid _`tables inside XML comments`, where "``--``" ends comments.
+
+ Implementation possibilities:
+
+ 1. Make the table syntax characters into "table" directive options.
+ This is the most flexible but most difficult, and we probably
+ don't need that much flexibility.
+
+ 2. Substitute "~" for "-" with a specialized directive option
+ (e.g. ":tildes:").
+
+ 3. Make the standard table syntax recognize "~" as well as "-", even
+ without a directive option. Individual tables would have to be
+ internally consistent.
+
+ 4. Allow Unicode box characters for table markup
+ (`feature request [6]`_)
+
+ Directive options are preferable to configuration settings, because
+ tables are document-specific. A pragma directive would be another
+ approach, to set the syntax once for a whole document.
+
+ Unicode box character markup would kill two birds with one stone.
+
+ In the meantime, the list-table_ directive is a good replacement for
+ grid tables inside XML comments.
+
+ .. _feature request [6]:
+ http://sourceforge.net/p/docutils/feature-requests/6
+ .. _list-table: ../ref/rst/directives.html#list-table
+
+
+* Generalize docinfo contents (bibliographic fields): remove specific
+ fields, and have only a single generic "field"?
+
+* _`Line numbers` and "source" in system messages:
+
+ - Add "source" and "line" keyword arguments to all Reporter calls?
+ This would require passing source/line arguments along all
+ intermediate functions (where currently only `line` is used).
+
+ Or rather specify "line" only if actually needed?
+
+ Currently, `document.reporter` uses a state machine instance to
+ determine the "source" and "line" info from
+ `statemachine.input_lines` if not given explicitely. Except for
+ special cases, the "line" argument is not needed because,
+ `document.statemachine` keeps record of the current line number.
+
+ - For system messages generated after the parsing is completed (i.e. by
+ transforms or the writer) "line" info must be present in the doctree
+ elements.
+
+ Elements' .line assignments should be checked. (Assign to .source
+ too? Add a set_info method? To what?)
+
+ The "source" (and line number in the source) can either be added
+ explicitely to the elements or determined from the “raw” line
+ number by `document.statemachine.get_source_and_line`.
+
+ - Some line numbers in elements are not being set properly
+ (explicitly), just implicitly/automatically. See rev. 1.74 of
+ docutils/parsers/rst/states.py for an example of how to set.
+
+ - The line numbers of definition list items are wrong::
+
+ $ rst2pseudoxml.py --expose-internal-attribute line
+ 1
+ 2
+ 3
+
+ 5
+ 6
+ 7
+
+ <document source="<stdin>">
+ <definition_list>
+ <definition_list_item internal:line="3">
+ <term>
+ 1
+ <definition>
+ <paragraph internal:line="2">
+ 2
+ 3
+ <definition_list_item internal:line="6">
+ <term>
+ 5
+ <definition>
+ <paragraph internal:line="6">
+ 6
+ 7
+
+* .. _none source:
+
+ Quite a few nodes are getting a "None" source attribute as well. In
+ particular, see the bodies of definition lists.
+
+
+
+Math Markup
+-----------
+
+Since Docutils 0.8, a "math" role and directive using LaTeX math
+syntax as input format is part of reStructuredText.
+
+Open issues:
+
+* Use a "Transform" for math format conversions as extensively discussed in
+ the "math directive issues" thread in May 2008
+ (http://osdir.com/ml/text.docutils.devel/2008-05/threads.html)?
+
+* Generic `math-output setting`_ (currently specific to HTML).
+ (List of math-output preferences?)
+
+* Try to be compatible with `Math support in Sphinx`_?
+
+ * The ``:label:`` option selects a label for the equation, by which it
+ can be cross-referenced, and causes an equation number to be issued.
+ In Docutils, the option ``:name:`` sets the label.
+ Equation numbering is not implemented yet.
+
+ * Option ``:nowrap:`` prevents wrapping of the given math in a
+ math environment (you have to specify the math environment in the
+ content).
+
+ .. _Math support in Sphinx: http://sphinx.pocoo.org/ext/math.html
+
+* Equation numbering and references. (see the section on
+ `object numbering and object references` for equations,
+ formal tables, and images.)
+
+.. _math-output setting: ../user/config.html#math-output
+
+
+alternative input formats
+`````````````````````````
+
+Use a directive option to specify an alternative input format, e.g. (but not
+limited to):
+
+MathML_
+ Not for hand-written code but maybe usefull when pasted in (or included
+ from a file)
+
+ For an overview of MathML implementations and tests, see, e.g.,
+ the `mathweb wiki`_ or the `ConTeXT MathML page`_.
+
+ .. _MathML: http://www.w3.org/TR/MathML2/
+ .. _mathweb wiki: http://www.mathweb.org/wiki/MathML
+ .. _ConTeXT MathML page: http://wiki.contextgarden.net/MathML
+
+ A MathML to LaTeX XSLT sheet:
+ https://github.com/davidcarlisle/web-xslt/tree/master/pmml2tex
+
+
+ASCIIMath_
+ Simple, ASCII based math input language (see also `ASCIIMath tutorial`_).
+
+ * The Python module ASCIIMathML_ translates a string with ASCIIMath into a
+ MathML tree. Used, e.g., by MultiMarkdown__.
+
+ A more comprehensive implementation is ASCIIMathPython_ by
+ Paul Trembley (also used in his sandbox projects).
+
+ * For conversion to LaTeX, there is
+
+ - a JavaScript script at
+ http://dlippman.imathas.com/asciimathtex/ASCIIMath2TeX.js
+
+ - The javascript `asciimath-to-latex` AsciiMath to LaTex converter at
+ the node package manager
+ https://www.npmjs.com/package/asciimath-to-latex
+ and at GitHub https://github.com/tylerlong/asciimath-to-latex
+
+ - a javascript and a PHP converter script at GitHub
+ https://github.com/asciimath/asciimathml/tree/master/asciimath-based
+
+ .. _ASCIIMath: http://www1.chapman.edu/~jipsen/mathml/asciimath.html
+ .. _ASCIIMath tutorial:
+ http://www.wjagray.co.uk/maths/ASCIIMathTutorial.html
+ .. _ASCIIMathML: http://pypi.python.org/pypi/asciimathml/
+ .. _ASCIIMathPython: http://sourceforge.net/projects/asciimathpython/
+ __ http://fletcherpenney.net/multimarkdown/
+
+`Unicode Nearly Plain Text Encoding of Mathematics`_
+ format for lightly marked-up representation of mathematical
+ expressions in Unicode.
+
+ (Unicode Technical Note. Sole responsibility for its contents rests
+ with the author(s). Publication does not imply any endorsement by
+ the Unicode Consortium.)
+
+ .. _Unicode Nearly Plain Text Encoding of Mathematics:
+ http://www.unicode.org/notes/tn28/
+
+itex
+ See `the culmination of a relevant discussion in 2003
+ <http://article.gmane.org/gmane.text.docutils.user/118>`__.
+
+
+
+LaTeX output
+````````````
+
+Which equation environments should be supported by the math directive?
+
+* one line:
+
+ + numbered: `equation`
+ + unnumbered: `equation*`
+
+* multiline (test for ``\\`` outside of a nested environment
+ (e.g. `array` or `cases`)
+
+ + numbered: `align` (number every line)
+
+ (To give one common number to all lines, put them in a `split`
+ environment. Docutils then places it in an `equation` environment.)
+
+ + unnumbered: `align*`
+
+ + Sphinx math also supports `gather` (checking for blank lines in
+ the content). Docutils puts content blocks separated by blank
+ lines in separate math-block doctree nodes. (The only difference of
+ `gather` to two consecutive "normal" environments seems to be that
+ page-breaks between the two are prevented.)
+
+See http://www.math.uiuc.edu/~hildebr/tex/displays.html.
+
+
+HTML output
+```````````
+
+There is no native math support in HTML.
+For supported math output variants see the `math-output setting`_.
+Add more/better alternatives?
+
+MathML_
+ Converters from LaTeX to MathML include
+
+ * TtM_ (C), ``--math-output=MathML ttm``, undocumented, may be removed.
+
+ No "matrix", "align" and "cases" environments.
+
+ * MathToWeb_ (Java)
+ * TeX4ht_ (TeX based)
+ * itex_ (also `used in Abiword`__)
+ * `Steve’s LATEX-to-MathML translator`_
+ ('mini-language', javascript, Python)
+ * `MathJax for Node`_
+
+ * Write a new converter? E.g. based on:
+
+ * a generic tokenizer (see e.g. a `latex-codec recipe`_,
+ `updated latex-codec`_, )
+ * the Unicode-Char <-> LaTeX mappings database unimathsymbols_
+
+ __ http://msevior.livejournal.com/26377.html
+ .. _MathML: http://www.w3.org/TR/MathML2/
+ .. _ttm: http://hutchinson.belmont.ma.us/tth/mml/
+ .. _TeX4ht: http://www.tug.org/applications/tex4ht/mn.html
+ .. _MathToWeb: http://www.mathtoweb.com/
+ .. _itex: http://golem.ph.utexas.edu/~distler/blog/itex2MMLcommands.html
+ .. _Steve’s LATEX-to-MathML translator:
+ http://www.gold-saucer.org/mathml/greasemonkey/dist/display-latex
+ .. _latex-codec recipe:
+ http://code.activestate.com/recipes/252124-latex-codec/
+ .. _updated latex-codec:
+ http://mirror.ctan.org/biblio/bibtex/utils/mab2bib/latex.py
+ .. _unimathsymbols: http://milde.users.sourceforge.net/LUCR/Math/
+ .. _MathJax for Node: https://github.com/mathjax/MathJax-node
+
+.. URL seems down:
+ .. _itex: http://pear.math.pitt.edu/mathzilla/itex2mmlItex.html
+
+
+HTML/CSS
+ format math in standard HTML enhanced by CSS rules
+ (Overview__, `Examples and experiments`__).
+ The ``math-output=html`` option uses the converter from eLyXer_
+ (included with Docutils).
+
+ Alternatives: LaTeX-math to HTML/CSS converters include
+
+ * TtH_ (C)
+ * Hevea_ (Objective Caml)
+ * `MathJax for Node`_
+
+ __ http://www.cs.tut.fi/~jkorpela/math/
+ __ http://www.zipcon.net/~swhite/docs/math/math.html
+ .. _elyxer: http://elyxer.nongnu.org/
+ .. _TtH: ttp://hutchinson.belmont.ma.us/tth/index.html
+ .. _Hevea: http://para.inria.fr/~maranget/hevea/
+
+images
+ (PNG or SVG) like e.g. Wikipedia.
+
+ * dvisvgm_
+ * the pure-python MathML->SVG converter SVGMath_)
+ * `MathJax for Node`_
+
+ .. _dvisvgm: http://dvisvgm.sourceforge.net/
+ .. _SVGMath: http://www.grigoriev.ru/svgmath/
+
+
+client side JavaScript conversion
+ Use TeX notation in the web page and JavaScript in the displaying browser.
+ (implemented as `math-output setting`_ "mathjax").
+
+ * jqMath_ (faster and lighter than MathJax_)
+
+ .. _MathJax: http://www.mathjax.org/
+ .. _jqMath: http://mathscribe.com/author/jqmath.html
+
+OpenOffice output
+`````````````````
+
+* The `OpenDocument standard`_ version 1.1 says:
+
+ Mathematical content is represented by MathML 2.0
+
+ However, putting MathML into an ODP file seems tricky as these
+ (maybe outdated) links suppose:
+ http://idippedut.dk/post/2008/01/25/Do-your-math-ODF-and-MathML.aspx
+ http://idippedut.dk/post/2008/03/03/Now-I-get-it-ODF-and-MathML.aspx
+
+ .. _OpenDocument standard:
+ http://www.oasis-open.org/standards#opendocumentv1.1
+
+* OOoLaTeX__: "a set of macros designed to bring the power of LaTeX
+ into OpenOffice."
+
+ __ http://ooolatex.sourceforge.net/
+
+
+Directives
+----------
+
+Directives below are often referred to as "module.directive", the
+directive function. The "module." is not part of the directive name
+when used in a document.
+
+* Allow for field lists in list tables. See
+ <http://thread.gmane.org/gmane.text.docutils.devel/3392>.
+
+* .. _unify tables:
+
+ Unify table implementations and unify options of table directives
+ (http://article.gmane.org/gmane.text.docutils.user/1857).
+
+* Allow directives to be added at run-time?
+
+* Use the language module for directive option names?
+
+* Add "substitution_only" and "substitution_ok" function attributes,
+ and automate context checking?
+
+* Implement options or features on existing directives:
+
+ - All directives that produce titled elements should grow implicit
+ reference names based on the titles.
+
+ - Allow the _`:trim:` option for all directives when they occur in a
+ substitution definition, not only the unicode_ directive.
+
+ .. _unicode: ../ref/rst/directives.html#unicode-character-codes
+
+ - Add the "class" option to the unicode_ directive. For example, you
+ might want to get characters or strings with borders around them.
+
+ - _`images.figure`: "title" and "number", to indicate a formal
+ figure?
+
+ - _`parts.sectnum`: "local"?, "refnum"
+
+ A "local" option could enable numbering for sections from a
+ certain point down, and sections in the rest of the document are
+ not numbered. For example, a reference section of a manual might
+ be numbered, but not the rest. OTOH, an all-or-nothing approach
+ would probably be enough.
+
+ The "sectnum" directive should be usable multiple times in a
+ single document. For example, in a long document with "chapter"
+ and "appendix" sections, there could be a second "sectnum" before
+ the first appendix, changing the sequence used (from 1,2,3... to
+ A,B,C...). This is where the "local" concept comes in. This part
+ of the implementation can be left for later.
+
+ A "refnum" option (better name?) would insert reference names
+ (targets) consisting of the reference number. Then a URL could be
+ of the form ``http://host/document.html#2.5`` (or "2-5"?). Allow
+ internal references by number? Allow name-based *and*
+ number-based ids at the same time, or only one or the other (which
+ would the table of contents use)? Usage issue: altering the
+ section structure of a document could render hyperlinks invalid.
+
+ - _`parts.contents`: Add a "suppress" or "prune" option? It would
+ suppress contents display for sections in a branch from that point
+ down. Or a new directive, like "prune-contents"?
+
+ Add an option to include topics in the TOC? Another for sidebars?
+ The "topic" directive could have a "contents" option, or the
+ "contents" directive" could have an "include-topics" option. See
+ docutils-develop 2003-01-29.
+
+ - _`parts.header` & _`parts.footer`: Support multiple, named headers
+ & footers? For example, separate headers & footers for odd, even,
+ and the first page of a document.
+
+ This may be too specific to output formats which have a notion of
+ "pages".
+
+ - _`misc.class`:
+
+ - Add a ``:parent:`` option for setting the parent's class
+ (http://article.gmane.org/gmane.text.docutils.devel/3165).
+
+ - _`misc.include`:
+
+ - Option to label lines?
+
+ - How about an environment variable, say RSTINCLUDEPATH or
+ RSTPATH, for standard includes (as in ``.. include:: <name>``)?
+ This could be combined with a setting/option to allow
+ user-defined include directories.
+
+ - Add support for inclusion by URL? ::
+
+ .. include::
+ :url: http://www.example.org/inclusion.txt
+
+ - Strip blank lines from begin and end of a literal included file or
+ file section. This would correspond to the way a literal block is
+ handled.
+
+ As nodes.literal_block expects (and we have) the text as a string
+ (rather than a list of lines), using a regexp seems the way.
+
+ - _`misc.raw`: add a "destination" option to the "raw" directive? ::
+
+ .. raw:: html
+ :destination: head
+
+ <link ...>
+
+ It needs thought & discussion though, to come up with a consistent
+ set of destination labels and consistent behavior.
+
+ And placing HTML code inside the <head> element of an HTML
+ document is rather the job of a templating system.
+
+ - _`body.sidebar`: Allow internal section structure? Adornment
+ styles would be independent of the main document.
+
+ That is really complicated, however, and the document model
+ greatly benefits from its simplicity.
+
+* Implement directives. Each of the list items below begins with an
+ identifier of the form, "module_name.directive_function_name". The
+ directive name itself could be the same as the
+ directive_function_name, or it could differ.
+
+ - _`html.imagemap`
+
+ It has the disadvantage that it's only easily implementable for
+ HTML, so it's specific to one output format.
+
+ (For non-HTML writers, the imagemap would have to be replaced with
+ the image only.)
+
+ - _`parts.endnotes` (or "footnotes"): See `Footnote & Citation Gathering`_.
+
+ - _`parts.citations`: See `Footnote & Citation Gathering`_.
+
+ - _`misc.language`: Specify (= change) the language of a document at
+ parse time?
+
+ * The misc.settings_ directive suggested below offers a more generic
+ approach.
+
+ * The language of document parts can be indicated by the "special class
+ value" ``"language-"`` + `BCP 47`_ language code. Class arguments to
+ the title are attached to the document's base node - hence titled
+ documents can be given a different language at parse time. However,
+ "language by class attribute" does not change parsing (localized
+ directives etc.), only supporting writers.
+
+ .. _BCP 47: http://www.rfc-editor.org/rfc/bcp/bcp47.txt
+
+
+ - _`misc.settings`: Set any(?) Docutils runtime setting from within
+ a document? Needs much thought and discussion.
+
+ Security concerns need to be taken into account (it shouldn't be
+ possible to enable ``file_insertion_enabled`` from within a
+ document), and settings that only would have taken effect before
+ the directive (like ``tab-width``) shouldn't be accessible either.
+
+ See this sub-thread:
+ <http://thread.gmane.org/gmane.text.docutils.user/3620/focus=3649>
+
+ - _`misc.gather`: Gather (move, or copy) all instances of a specific
+ element. A generalization of the `Footnote & Citation Gathering`_
+ ideas.
+
+ - Add a custom "directive" directive, equivalent to "role"? For
+ example::
+
+ .. directive:: incr
+
+ .. class:: incremental
+
+ .. incr::
+
+ "``.. incr::``" above is equivalent to "``.. class:: incremental``".
+
+ Another example::
+
+ .. directive:: printed-links
+
+ .. topic:: Links
+ :class: print-block
+
+ .. target-notes::
+ :class: print-inline
+
+ This acts like macros. The directive contents will have to be
+ evaluated when referenced, not when defined.
+
+ * Needs a better name? "Macro", "substitution"?
+ * What to do with directive arguments & options when the
+ macro/directive is referenced?
+
+ - Make the meaning of block quotes overridable? Only a 1-shot
+ though; doesn't solve the general problem.
+
+ - _`conditional directives`:
+
+ .. note:: See also the implementation in Sphinx_.
+
+ Docutils already has the ability to say "use this content for
+ Writer X" via the "raw" directive. It also does have the ability
+ to say "use this content for any Writer other than X" via the
+ "strip-elements with class" config value. However, using "raw"
+ input just to select a special writer is inconvenient in many
+ cases.
+ It wouldn't be difficult to get more straightforward support, though.
+
+ My first idea would be to add a set of conditional directives.
+ Let's call them "writer-is" and "writer-is-not" for discussion
+ purposes (don't worry about implemention details). We might
+ have::
+
+ .. writer-is:: text-only
+
+ ::
+
+ +----------+
+ | SNMP |
+ +----------+
+ | UDP |
+ +----------+
+ | IP |
+ +----------+
+ | Ethernet |
+ +----------+
+
+ .. writer-is:: pdf
+
+ .. figure:: protocol_stack.eps
+
+ .. writer-is-not:: text-only pdf
+
+ .. figure:: protocol_stack.png
+
+ This could be an interface to the Filter transform
+ (docutils.transforms.components.Filter).
+
+ The ideas in `adaptable file extensions`_ above may also be
+ applicable here.
+
+ SVG's "switch" statement may provide inspiration.
+
+ Here's an example of a directive that could produce multiple
+ outputs (*both* raw troff pass-through *and* a GIF, for example)
+ and allow the Writer to select. ::
+
+ .. eqn::
+
+ .EQ
+ delim %%
+ .EN
+ %sum from i=o to inf c sup i~=~lim from {m -> inf}
+ sum from i=0 to m sup i%
+ .EQ
+ delim off
+ .EN
+
+ - _`body.example`: Examples; suggested by Simon Hefti. Semantics as
+ per Docbook's "example"; admonition-style, numbered, reference,
+ with a caption/title.
+
+ - _`body.index`: Index targets.
+
+ See `Index Entries & Indexes
+ <./rst/alternatives.html#index-entries-indexes>`__.
+
+ - _`body.literal`: Literal block, possibly "formal" (see `object
+ numbering and object references`_ above). Possible options:
+
+ - "highlight" a range of lines
+
+ - include only a specified range of lines
+
+ - "number" or "line-numbers"? (since 0.9 available with "code" directive)
+
+ - "styled" could indicate that the directive should check for
+ style comments at the end of lines to indicate styling or
+ markup.
+
+ Specific derivatives (i.e., a "python-interactive" directive)
+ could interpret style based on cues, like the ">>> " prompt and
+ "input()"/"raw_input()" calls.
+
+ See docutils-users 2003-03-03.
+
+ - _`body.listing`: Code listing with title (to be numbered
+ eventually), equivalent of "figure" and "table" directives.
+
+ - _`pysource.usage`: Extract a usage message from the program,
+ either by running it at the command line with a ``--help`` option
+ or through an exposed API. [Suggestion for Optik.]
+
+ - _`body.float`: Generic float that can be used for figures, tables,
+ code listings, flowcharts, ...
+
+ There is a Sphinx extension by Ignacio Fernández Galván <jellby@gmail.com>
+
+ I implemented something for generic floats in sphinx, and submitted a
+ pull request that is still waiting::
+
+ .. float::
+ :type: figure
+ :caption: My caption
+
+ https://github.com/sphinx-doc/sphinx/pull/1858
+
+
+Interpreted Text
+----------------
+
+Interpreted text is entirely a reStructuredText markup construct, a
+way to get around built-in limitations of the medium. Some roles are
+intended to introduce new doctree elements, such as "title-reference".
+Others are merely convenience features, like "RFC".
+
+All supported interpreted text roles must already be known to the
+Parser when they are encountered in a document. Whether pre-defined
+in core/client code, or in the document, doesn't matter; the roles
+just need to have already been declared. Adding a new role may
+involve adding a new element to the DTD and may require extensive
+support, therefore such additions should be well thought-out. There
+should be a limited number of roles.
+
+The only place where no limit is placed on variation is at the start,
+at the Reader/Parser interface. Transforms are inserted by the Reader
+into the Transformer's queue, where non-standard elements are
+converted. Once past the Transformer, no variation from the standard
+Docutils doctree is possible.
+
+An example is the Python Source Reader, which will use interpreted
+text extensively. The default role will be "Python identifier", which
+will be further interpreted by namespace context into <class>,
+<method>, <module>, <attribute>, etc. elements (see pysource.dtd),
+which will be transformed into standard hyperlink references, which
+will be processed by the various Writers. No Writer will need to have
+any knowledge of the Python-Reader origin of these elements.
+
+* Add explicit interpreted text roles for the rest of the implicit
+ inline markup constructs: named-reference, anonymous-reference,
+ footnote-reference, citation-reference, substitution-reference,
+ target, uri-reference (& synonyms).
+
+* Add directives for each role as well? This would allow indirect
+ nested markup::
+
+ This text contains |nested inline markup|.
+
+ .. |nested inline markup| emphasis::
+
+ nested ``inline`` markup
+
+* Implement roles:
+
+ - "_`raw-wrapped`" (or "_`raw-wrap`"): Base role to wrap raw text
+ around role contents.
+
+ For example, the following reStructuredText source ... ::
+
+ .. role:: red(raw-formatting)
+ :prefix:
+ :html: <font color="red">
+ :latex: {\color{red}
+ :suffix:
+ :html: </font>
+ :latex: }
+
+ colored :red:`text`
+
+ ... will yield the following document fragment::
+
+ <paragraph>
+ colored
+ <inline classes="red">
+ <raw format="html">
+ <font color="red">
+ <raw format="latex">
+ {\color{red}
+ <inline classes="red">
+ text
+ <raw format="html">
+ </font>
+ <raw format="latex">
+ }
+
+ Possibly without the intermediate "inline" node.
+
+ - _`"acronym" and "abbreviation"`: Associate the full text with a
+ short form. Jason Diamond's description:
+
+ I want to translate ```reST`:acronym:`` into ``<acronym
+ title='reStructuredText'>reST</acronym>``. The value of the
+ title attribute has to be defined out-of-band since you can't
+ parameterize interpreted text. Right now I have them in a
+ separate file but I'm experimenting with creating a directive
+ that will use some form of reST syntax to let you define them.
+
+ Should Docutils complain about undefined acronyms or
+ abbreviations?
+
+ What to do if there are multiple definitions? How to
+ differentiate between CSS (Content Scrambling System) and CSS
+ (Cascading Style Sheets) in a single document? David Priest
+ responds,
+
+ The short answer is: you don't. Anyone who did such a thing
+ would be writing very poor documentation indeed. (Though I
+ note that `somewhere else in the docs`__, there's mention of
+ allowing replacement text to be associated with the
+ abbreviation. That takes care of the duplicate
+ acronyms/abbreviations problem, though a writer would be
+ foolish to ever need it.)
+
+ __ `inline parameter syntax`_
+
+ How to define the full text? Possibilities:
+
+ 1. With a directive and a definition list? ::
+
+ .. acronyms::
+
+ reST
+ reStructuredText
+ DPS
+ Docstring Processing System
+
+ Would this list remain in the document as a glossary, or would
+ it simply build an internal lookup table? A "glossary"
+ directive could be used to make the intention clear.
+ Acronyms/abbreviations and glossaries could work together.
+
+ Then again, a glossary could be formed by gathering individual
+ definitions from around the document.
+
+ 2. Some kind of `inline parameter syntax`_? ::
+
+ `reST <reStructuredText>`:acronym: is `WYSIWYG <what you
+ see is what you get>`:acronym: plaintext markup.
+
+ .. _inline parameter syntax:
+ rst/alternatives.html#parameterized-interpreted-text
+
+ 3. A combination of 1 & 2?
+
+ The multiple definitions issue could be handled by establishing
+ rules of priority. For example, directive-based lookup tables
+ have highest priority, followed by the first inline definition.
+ Multiple definitions in directive-based lookup tables would
+ trigger warnings, similar to the rules of `implicit hyperlink
+ targets`__.
+
+ __ ../ref/rst/restructuredtext.html#implicit-hyperlink-targets
+
+ 4. Using substitutions? ::
+
+ .. |reST| acronym:: reST
+ :text: reStructuredText
+
+ What do we do for other formats than HTML which do not support
+ tool tips? Put the full text in parentheses?
+
+ - "figure", "table", "listing", "chapter", "page", etc: See `object
+ numbering and object references`_ above.
+
+ - "glossary-term": This would establish a link to a glossary. It
+ would require an associated "glossary-entry" directive, whose
+ contents could be a definition list::
+
+ .. glossary-entry::
+
+ term1
+ definition1
+ term2
+ definition2
+
+ This would allow entries to be defined anywhere in the document,
+ and collected (via a "glossary" directive perhaps) at one point.
+
+
+Doctree pruning
+---------------
+
+[DG 2017-01-02: These are not definitive to-dos, just one developer's
+opinion. Added 2009-10-13 by Günter Milde, in r6178.]
+[Updated by GM 2017-02-04]
+
+The number of doctree nodes can be reduced by "normalizing" some related
+nodes. This makes the document model and the writers somewhat simpler.
+
+* The "doctest" element can be replaced by literal blocks with a class
+ attribute (similar to the "code" directive output).
+ The syntax shall be left in reST.
+
+ [DG 2017-01-02:] +0.
+
+ Discussion
+ The syntax could be left in reST (for a set period of time?).
+
+ [DG 2017-01-02:] The syntax must be left in reST, practically
+ forever. Removing it would introduce a huge backwards
+ incompatibility. Any syntax removal must be preceded by a thorough
+ review and planning, including a deprecation warning process. My
+ opinion: it's not worth it.
+
+* "Normalize" special admonitions (note, hint, warning, ...) during parsing
+ (similar to _`transforms.writer_aux.Admonitions`). There is no need to
+ keep them as distinct elements in the doctree specification.
+
+ [DG 2017-01-02:] -1: <note>{body}</> is much more concise and
+ expressive than <admonition><title>Note</>{body}</>, and the title
+ translation can be put off until much later in the process.
+
+ [GM 2017-02-04]:
+
+ -0 for <admonition class=note><title>Note</>... instead of <note>:
+ a document is rarely printed/used as doctree or XML.
+
+ +1 reduce the complexity of the doctree
+ (there is no 1:1 rST syntax element <-> doctree node mapping anyway).
+
+ +2 every writer needs 9 visit_*/depart_* method pairs to handle the 9
+ subtypes of an admonition, i.e. we could but also remove 36 redundant
+ methods (HTML, LaTeX, Manpage, ODF).
+
+ -1 the most unfortunately named of these directives will survive. [#]_
+
+ .. [#] with "biblical touch" and hard to translate:
+
+ :admonition: | Ermahnung; Verweis; Warnung; Rüge
+ | (exhortation; censure; warning; reprimand, rebuke)
+
+
+ Keep the special admonition directives in reStructuredText syntax.
+
+ [DG 2017-01-02:] We must definitely keep the syntax. Removing it
+ would introduce a huge backwards incompatibility.
+
+
+Unimplemented Transforms
+========================
+
+* _`Footnote & Citation Gathering`
+
+ Collect and move footnotes & citations to the end of a document or the
+ place of a "footnotes" or "citations" directive
+ (see `<./ref/rst/directives.html>_`)
+
+ Footnotes:
+ Collect all footnotes that are referenced in the document before the
+ directive (and after an eventually preceding ``.. footnotes::``
+ directive) and insert at this place.
+
+ Allows "endnotes" at a configurable place.
+
+ Citations:
+ Collect citations that are referenced ...
+
+ Citations can be:
+
+ a) defined in the document as citation elements
+
+ b) auto-generated from entries in a bibliographic database.
+
+ + based on bibstuff_?
+ + also have a look at
+
+ * CrossTeX_, a backwards-compatible, improved bibtex
+ re-implementation in Python (including HTML export).
+ (development stalled since 2 years)
+
+ * Pybtex_,a drop-in replacement for BibTeX written in Python.
+
+ * BibTeX styles & (experimental) pythonic style API.
+ * Database in BibTeX, BibTeXML and YAML formats.
+ * full Unicode support.
+ * Write to TeX, HTML and plain text.
+
+ * `Zotero plain <http://e6h.org/%7Eegh/hg/zotero-plain/>`__
+ supports Zotero databases and CSL_ styles with Docutils with an
+ ``xcite`` role.
+
+ * `sphinxcontrib-bibtex`_ Sphinx extension with "bibliography"
+ directive and "cite" role supporting BibTeX databases.
+
+ * `Modified rst2html
+ <http://www.loria.fr/~rougier/coding/article/rst2html.py>`__ by
+ Nicolas Rougier.
+
+
+ * Automatically insert a "References" heading?
+
+.. _CrossTeX: http://www.cs.cornell.edu/people/egs/crosstex/
+.. _Pybtex: http://pybtex.sourceforge.net/
+.. _CSL: http://www.citationstyles.org/
+.. _sphinxcontrib-bibtex: http://sphinxcontrib-bibtex.readthedocs.org/
+
+* _`Reference Merging`
+
+ When merging two or more subdocuments (such as docstrings),
+ conflicting references may need to be resolved. There may be:
+
+ * duplicate reference and/or substitution names that need to be made
+ unique; and/or
+ * duplicate footnote numbers that need to be renumbered.
+
+ Should this be done before or after reference-resolving transforms
+ are applied? What about references from within one subdocument to
+ inside another?
+
+* _`Document Splitting`
+
+ If the processed document is written to multiple files (possibly in
+ a directory tree), it will need to be split up. Internal references
+ will have to be adjusted.
+
+ (HTML only? Initially, yes. Eventually, anything should be
+ splittable.)
+
+ Ideas:
+
+ - Insert a "destination" attribute into the root element of each
+ split-out document, containing the path/filename. The Output
+ object or Writer will recognize this attribute and split out the
+ files accordingly. Must allow for common headers & footers,
+ prev/next, breadcrumbs, etc.
+
+ - Transform a single-root document into a document containing
+ multiple subdocuments, recursively. The content model of the
+ "document" element would have to change to::
+
+ <!ELEMENT document
+ ( (title, subtitle?)?,
+ decoration?,
+ (docinfo, transition?)?,
+ %structure.model;,
+ document* )>
+
+ (I.e., add the last line -- 0 or more document elements.)
+
+ Let's look at the case of hierarchical (directories and files)
+ HTML output. Each document element containing further document
+ elements would correspond to a directory (with an index.html file
+ for the content preceding the subdocuments). Each document
+ element containing no subdocuments (i.e., structure model elements
+ only) corresponds to a concrete file with no directory.
+
+ The natural transform would be to map sections to subdocuments,
+ but possibly only a given number of levels deep.
+
+* _`Navigation`
+
+ If a document is split up, each segment will need navigation links:
+ parent, children (small TOC), previous (preorder), next (preorder).
+ Part of `Document Splitting`_?
+
+* _`List of System Messages`
+
+ The ``system_message`` elements are inserted into the document tree,
+ adjacent to the problems themselves where possible. Some (those
+ generated post-parse) are kept until later, in
+ ``document.messages``, and added as a special final section,
+ "Docutils System Messages".
+
+ Docutils could be made to generate hyperlinks to all known
+ system_messages and add them to the document, perhaps to the end of
+ the "Docutils System Messages" section.
+
+ Fred L. Drake, Jr. wrote:
+
+ I'd like to propose that both parse- and transformation-time
+ messages are included in the "Docutils System Messages" section.
+ If there are no objections, I can make the change.
+
+ The advantage of the current way of doing things is that parse-time
+ system messages don't require a transform; they're already in the
+ document. This is valuable for testing (unit tests,
+ tools/quicktest.py). So if we do decide to make a change, I think
+ the insertion of parse-time system messages ought to remain as-is
+ and the Messages transform ought to move all parse-time system
+ messages (remove from their originally inserted positions, insert in
+ System Messages section).
+
+* _`Index Generation`
+
+
+HTML Writer
+===========
+
+* Make it easier to find out fragment names (#foo-bar) of ``_`inline
+ targets```. Currently you have to either look at the source or
+ guess the fragment.
+
+ For example, we could add support for self-referencing targets
+ (i.e. inline targets would [unobtrusively] link to themselves, so
+ that you can just click them and then copy the address). Or we
+ could add support for titles that display the fragment name (as in
+ <http://subversion.tigris.org/mailing-list-guidelines.html>; just
+ hover the paragraphs).
+
+ Either way it should be optional and deactivated by default.
+
+ This would be useful for documents like Docutils' bug list or to-do
+ list.
+
+* Make the _`list compacting` logic more generic: For example, allow
+ for literal blocks or line blocks inside of compact list items.
+
+ This is not implementable as long as list compacting is done by
+ omitting ``<p>`` tags. List compacting would need to be done by
+ adjusting CSS margins instead.
+
+ :2015-04-02: The new html writer no longer strips <p> tags but adds the
+ class value ``simple`` to the list.
+ Formatting is done by CSS --- configurable by a custom style
+ sheet.
+
+ Auto-compactization can be overridden by the ``open`` vs.
+ ``compact`` class arguments.
+
+* Idea for field-list rendering: hanging indent::
+
+ Field name (bold): First paragraph of field body begins
+ with the field name inline.
+
+ If the first item of a field body is not a paragraph,
+ it would begin on the following line.
+
+ :2015-04-02: The new html writer writes field-lists as definition lists
+ with class ``field-list``.
+ Formatting is done by CSS --- configurable by a custom style
+ sheet. The default style sheet has some examples, including a
+ run-in field-list style.
+
+* Add more support for <link> elements, especially for navigation
+ bars.
+
+ The framework does not have a notion of document relationships, so
+ probably raw.destination_ should be used.
+
+ We'll have framework support for document relationships when support
+ for `multiple output files`_ is added. The HTML writer could
+ automatically generate <link> elements then.
+
+ .. _raw.destination: misc.raw_
+
+* Base list compaction on the spacing of source list? Would require
+ parser support. (Idea: fantasai, 16 Dec 2002, doc-sig.)
+
+* Add a tool tip ("title" attribute?) to footnote back-links
+ identifying them as such. Text in Docutils language module.
+
+
+PEP/HTML Writer
+===============
+
+* Remove the generic style information (duplicated from html4css1.css)
+ from pep.css to avoid redundancy.
+
+ Set ``stylesheet-path`` to "html4css.css,pep.css" and the
+ ``stylesheet-dirs`` accordingly instead. (See the xhtml11 writer for an
+ example.)
+
+
+S5/HTML Writer
+==============
+
+* Add a way to begin an untitled slide.
+
+* Add a way to begin a new slide, continuation, using the same title
+ as the previous slide? (Unnecessary?) You need that if you have a
+ lot of items in one section which don't fit on one slide.
+
+ Maybe either this item or the previous one can be realized using
+ transitions.
+
+* Have a timeout on incremental items, so the colour goes away after 1
+ second.
+
+* Add an empty, black last slide (optionally). Currently the handling
+ of the last slide is not very nice, it re-cycles through the
+ incremental items on the last slide if you hit space-bar after the
+ last item.
+
+* Add a command-line option to disable advance-on-click.
+
+* Add a speaker's master document, which would contain a small version
+ of the slide text with speaker's notes interspersed. The master
+ document could use ``target="whatever"`` to direct links to a
+ separate window on a second monitor (e.g., a projector).
+
+ .. Note:: This item and the following items are partially
+ accomplished by the S5 1.2 code (currently in alpha), which has
+ not yet been integrated into Docutils.
+
+* Speaker's notes -- how to intersperse? Could use reST comments
+ (".."), but make them visible in the speaker's master document. If
+ structure is necessary, we could use a "comment" directive (to avoid
+ nonsensical DTD changes, the "comment" directive could produce an
+ untitled topic element).
+
+ The speaker's notes could (should?) be separate from S5's handout
+ content.
+
+* The speaker's master document could use frames for easy navigation:
+ TOC on the left, content on the right.
+
+ - It would be nice if clicking in the TOC frame simultaneously
+ linked to both the speaker's notes frame and to the slide window,
+ synchronizing both. Needs JavaScript?
+
+ - TOC would have to be tightly formatted -- minimal indentation.
+
+ - TOC auto-generated, as in the PEP Reader. (What if there already
+ is a "contents" directive in the document?)
+
+ - There could be another frame on the left (top-left or bottom-left)
+ containing a single "Next" link, always pointing to the next slide
+ (synchronized, of course). Also "Previous" link? FF/Rew go to
+ the beginning of the next/current parent section? First/Last
+ also? Tape-player-style buttons like ``|<< << < > >> >>|``?
+
+Epub/HTML Writer
+================
+
+Add epub as an output format.
+
+ epub is an open file format for ebooks based on HTML, specified by the
+ `International Digital Publishing Forum`_. Thus, documents in epub
+ format are suited to be read with `electronic reading devices`_.
+
+Pack the output of a HTML writer and supporting files (e.g. images)
+into one single epub document.
+
+There are `links to two 3rd party ePub writers`__ in the Docutils link list.
+Test and consider moving the better one into the docutils core.
+
+__ ../user/links.html#ePub
+.. _International Digital Publishing Forum: http://www.idpf.org/
+.. _electronic reading devices:
+ http://en.wikipedia.org/wiki/List_of_e-book_readers
+
+
+LaTeX writer
+============
+
+Also see the Problems__ section in the `latex writer documentation`_.
+
+__ ../user/latex.html#problems
+
+.. _latex writer documentation: ../user/latex.html
+
+.. _latex-variants:
+ ../../../sandbox/latex-variants/README.html
+
+Bug fixes
+---------
+
+* Too deeply nested lists fail: generate a warning and provide
+ a workaround.
+
+ 2017-02-09 this is fixed for enumeration in 0.13.1
+
+ for others, cf. sandbox/latex-variants/tests/rst-levels.txt
+
+* File names of included graphics (see also `grffile` package).
+
+* Paragraph following field-list or table in compound is indented.
+
+ This is a problem with the current DUfieldlist definition and with
+ the use of "longtable" for tables.
+ See `LaTeX constructs and packages instead of re-implementations`_ for
+ alternatives.
+
+
+Generate clean and configurable LaTeX source
+----------------------------------------------
+
+* Check the generated source with package `nag`.
+
+Configurable placement of figure and table floats
+`````````````````````````````````````````````````
+
+* Special class argument to individually place figures?
+
+ Either:
+
+ placement-<optional arg> -> \figure[<optional arg>]{...}
+
+ e.g. ``.. class:: placement-htb``,
+
+ or more verbose:
+
+ :H: place-here
+ :h: place-here-if-possible
+ :t: place-top
+ :b: place-bottom
+ :p: place-on-extra-page
+
+ e.g.: ``.. class:: place-here-if-possible place-top place-bottom``
+
+ Maybe support both variants?
+
+
+LaTeX constructs and packages instead of re-implementations
+```````````````````````````````````````````````````````````
+
+Which packages do we want to use?
+
+ + base and "recommended" packages
+
+ (packages that should be in a "reasonably sized and reasonably modern
+ LaTeX installation like the `texlive-latex-recommended` Debian package,
+ say):
+
+ + No "fancy" or "exotic" requirements.
+
+ + pointers to advanced packages and their use in the `latex writer
+ documentation`_.
+
+* footnotes
+
+ + True footnotes with LaTeX auto-numbering (as option ``--latex-footnotes``)
+ (also for target-footnotes):
+
+ - attach footnote text to footnote-symobol node
+ - write \footnote{<footnote text>}
+ - consider cases where LaTeX does not support footnotes
+ (inside tables, headings, ...)?
+ - consider multiple footnote refs to common footnote text.
+
+ .. Quote:
+
+ If the symbol you want is not one of the ones listed, you'll need to
+ redefine ``\@fnsymbol`` and add it, e.g. perhaps like::
+
+ \def\@fnsymbol#1{\ifcase#1\hbox{}\or *\or \dagger\or \ddagger\or
+ \mathchar "278\or \mathchar "27B\or \|\or **\or \dagger\dagger \or
+ \ddagger\ddagger \or \mathchar"27C \else\@ctrerr\fi\relax}
+
+ which would allow \symbolfootnote[10]{footnote} to have a club as its
+ mark.
+
+ + document customization (links to how-to and packages):
+
+ .. Footnote packages:
+
+ :footnote: texlive-latex-recommended % savenotes environment
+ :footmisc: texlive-latex-extra % formatting options
+ :manyfoot: texlive-latex-extra
+ :bigfoot: texlive-latex-extra
+ :perpage: texlive-latex-extra
+ :ftnxtra: new on CTAN
+ fixes the issue of footnote inside \caption{},
+ tabular environment and \section{} like commands.
+
+
+ German tutorial:
+ http://www2.informatik.hu-berlin.de/~ahamann/studies/footnotes.pdf
+
+ .. Footnote FAQs:
+
+ `Footnotes whose texts are identical
+ <http://www.tex.ac.uk/cgi-bin/texfaq2html?label=repfootnote>`__
+
+ * label per hand or use footmisc
+
+ `More than one sequence of footnotes
+ <http://www.tex.ac.uk/cgi-bin/texfaq2html?label=multfoot>`__
+
+ * manyfoot, bigfoot
+
+ `Footnotes in tables
+ <http://www.tex.ac.uk/cgi-bin/texfaq2html?label=footintab>`__
+
+ * `tabularx` and longtable allow footnotes.
+ * `footnote` provides a "savenotes" environment which collects all
+ footnotes and emits them at ``end{savenotes}``
+
+ `Footnotes in LaTeX section headings
+ <http://www.tex.ac.uk/cgi-bin/texfaq2html?label=ftnsect>`__
+
+ * Take advantage of the fact that the mandatory argument doesn't
+ move if the optional argument is present::
+
+ \section[title] {title\footnote{title ftnt}}
+
+ * Use the footmisc package, with package option stable - this modifies
+ footnotes so that they softly and silently vanish away if used in a
+ moving argument.
+
+ * Use ftnxtra.
+
+ `Footnotes numbered per page
+ <http://www.tex.ac.uk/cgi-bin/texfaq2html?label=footnpp>`__
+
+ * perpage provides a general mechanism for resetting counters per page
+ * footmisc provides a package option perpage
+
+* use `eqlist` or `enumitem` (texlive-latex-extra) for field-lists?
+
+* ``--use-latex-when-possible`` »super option« that would set the
+ following::
+
+ --no-section-numbering
+ --use-latex-toc
+ --use-latex-docinfo
+ --use-latex-abstract
+ --use-latex-footnotes
+ --use-latex-citations
+
+ ? (My preference is to default to use-latex-* whenever possible [GM])
+
+
+Default layout
+--------------
+
+* Use italic instead of slanted for titlereference?
+
+* Start a new paragraph after lists (as currently)
+ or continue (no blank line in source, no parindent in output)?
+
+ Overriding:
+
+ * continue if the `compound paragraph`_ directive is used (as currently),
+ or
+ * force a new paragraph with an empty comment.
+
+* Sidebar handling (environment with `framed`, `marginnote`, `wrapfig`,
+ ...)?
+
+* Use optionlist for docinfo?
+
+* Keep literal-blocks together on a page, avoid pagebreaks.
+
+ Failed experiments up to now: samepage, minipage, pagebreak 1 to 4 before
+ the block.
+
+ Should be possible with ``--literal-block-env==lstlistings`` and some
+ configuration...
+
+* More space between title and subtitle? ::
+
+ - \\ % subtitle%
+ + \\[0.5em] % subtitle%
+
+.. _PSNFSS documentation:
+ http://mirror.ctan.org/macros/latex/required/psnfss/psnfss2e.pdf
+.. _compound paragraph:
+ ../ref/rst/directives.html#compound-paragraph
+.. _fixltx2e:
+ http://mirror.ctan.org/help/Catalogue/entries/fixltx2e.html
+
+Tables
+``````
+
+* Improve/simplify logic to set the column width in the output.
+
+ + Assumed reST line length for table width setting configurable, or
+ + use `ltxtable` (a combination of `tabularx` (auto-width) and
+ `longtable` (page breaks)), or
+ + use tabularx column type ``X`` and let LaTeX decide width, or
+ + use tabulary_?
+
+ .. _tabulary:
+ http://tug.ctan.org/cgi-bin/ctanPackageInformation.py?id=tabulary
+
+* From comp.text.tex (13. 4. 2011):
+
+ When using fixed width columns, you should ensure that the total
+ width does not exceed \linewidth: if the first column is p{6cm}
+ the second one should be p{\dimexpr\linewidth-6cm-4\tabcolsep}
+ because the glue \tabcolsep is added twice at every column edge.
+ You may also consider to set \tabcolsep to a different value...
+
+* csv-tables do not have a colwidth.
+
+* Add more classes or options, e.g. for
+
+ + horizontal alignment and rules.
+ + long table vs. tabular (see next item).
+
+* Use tabular instead of longtable for tables in legends or generally
+ inside a float?
+
+ Alternatively, default to tabular and use longtable only if specified
+ by config setting or class argument (analogue to booktable)?
+
+* Table heads and footer for longtable (firstpage lastpage ..)?
+
+* In tools.txt the option tables right column, there should be some more
+ spacing between the description and the next paragraph "Default:".
+
+* Paragraph separation in tables is hairy.
+ see http://www.tex.ac.uk/cgi-bin/texfaq2html?label=struttab
+
+ - The strut solution did not work.
+ - setting extrarowheight added ad top of row not between paragraphs in
+ a cell. ALTHOUGH i set it to 2pt because, text is too close to the topline.
+ - baselineskip/stretch does not help.
+
+* Should there be two hlines after table head and on table end?
+
+* Place titled tables in a float ('table' environment)?
+
+ The 'table', 'csv-table', and 'list-table' directives support an (optional)
+ table title. In analogy to the 'figure' directive this should map to a
+ table float.
+
+Image and figure directives
+```````````````````````````
+
+* compare the test case in:
+
+ + `<../../test/functional/input/data/standard.txt>`__
+ + `<../../test/functional/expected/standalone_rst_html4css1.html>`__
+ + `<../../test/functional/expected/standalone_rst_latex.tex>`__
+
+* The default CSS styling for HTML output (plain.css, default.css) lets
+ text following a right- or left-aligned image float to the side of the
+ image/figure.
+
+ + Use this default also for LaTeX?
+
+ + Wrap text around figures/images with class argument "wrap"
+ (like the odt writer)?
+
+ Use `wrapfig` (or other recommended) package.
+
+* support more graphic formats (especially SVG, the only standard
+ vector format for HTML)
+
+ There is a `SWF package`_ at CTAN.
+
+.. _SWF package:
+ http://mirror.ctan.org/macros/latex/contrib/flashmovie
+
+
+Missing features
+----------------
+
+* support "figwidth" argument for figures.
+
+ As the 'figwidth' argument is still ignored and the "natural width" of
+ a figure in LaTeX is 100 % of the text width, setting the 'align'
+ argument has currently no effect on the LaTeX output.
+
+
+* Let `meta` directive insert PDF-keywords into header?
+
+* Multiple author entries in docinfo (same thing as in html).
+ (already solved?)
+
+* Consider supporting the "compact" option and class argument (from
+ rst2html) as some lists look better compact and others need the space.
+
+* Better citation support
+ (see `Footnote & Citation Gathering`_).
+
+* If ``use-latex-citations`` is used, a bibliography is inserted right at the
+ end of the document.
+
+ Put in place of the to-be-implemented "citations" directive
+ (see `Footnote & Citation Gathering`_).
+
+
+Unicode to LaTeX
+````````````````
+
+The `LyX <http://www.lyx.org>`_ document processor has a comprehensive
+Unicode to LaTeX conversion feature with a file called ``unicodesymbols``
+that lists LaTeX counterparts for a wide range of Unicode characters.
+
+* Use this in the LaTeXTranslator?
+ Think of copyright issues!
+
+* The "ucs" package has many translations in ...doc/latex/ucs/config/
+
+* The bibstuff_ tool ships a `latex_codec` Python module!
+
+.. _bibstuff: http://code.google.com/p/bibstuff/
+
+Allow choice between utf8 (standard) and utf8x (extended) encodings
+```````````````````````````````````````````````````````````````````
+
+* Allow the user to select *utf8* or *utf8x* LaTeX encoding. (Docutil's
+ output encoding becomes LaTeX's input encoding.)
+
+The `ucs` package provides extended support for UTF-8 encoding in LaTeX
+via the `inputenc`-option ``utf8x``. It is, however, a non-standard
+extension and no longer developed.
+
+Ideas:
+ a) Python has 4 names for the UTF-8 encoding (``utf_8, U8, UTF, utf8``)
+ give a special meaning to one of the aliases,
+
+ b) scan "stylesheets" and "latex-preamble" options and use ``utf8x``
+ if it contains ``ucs``
+
+XeTeX writer
+````````````
+
+* Glyphs missing in the font are left out in the PDF without warning
+ (e.g. ⇔ left-right double arrow in the functional test output).
+
+* Disable word-wrap (hyphenation) in literal text locally with
+ ``providecommand{\nohyphenation}{\addfontfeatures{HyphenChar=None}}``?
+
+
+problematic URLs
+````````````````
+
+* ^^ LaTeX's special syntax for characters results in "strange" replacements
+ (both with \href and \url).
+
+ `file with ^^ <../strange^^name>`__:
+ `<../strange^^name>`__
+
+* Unbalanced braces, { or }, will fail (both with \href and \url)::
+
+ `file with { <../strange{name>`__
+ `<../strange{name>`__
+
+Currently, a warning is written to the error output stream.
+
+For correct printing, we can
+
+* use the \href command with "normal" escaped name argument, or
+* define a url-command in the preamble ::
+
+ \urldef{\fragileURLi}\nolinkurl{myself%node@gateway.net}
+
+but need to find a way to insert it as href argument.
+
+The following fails::
+
+ \href{http://www.w3.org/XML/Schema^^dev}{\fragileURLi}
+
+Use %-replacement like http://nowhere/url_with%28parens%29 ?
+
+-> does not work for file paths (with pdflatex and xpdf).
+
+
+add-stylesheet option
+`````````````````````
+
+From http://article.gmane.org/gmane.text.docutils.devel/3429/
+
+The problem is that since we have a default value, we have to
+differentiate between adding another stylesheet and replacing the
+default. I suggest that the existing --stylesheet & --stylesheet-path
+options keep their semantics to replace the existing settings. We
+could introduce new --add-stylesheet & --add-stylesheet-path options,
+which accumulate; further --stylesheet/--stylesheet-path options would
+clear these lists. The stylesheet or stylesheet_path setting (only
+one may be set), plus the added_stylesheets and added_stylesheet_paths
+settings, describe the combined styles.
+
+For example, this run will have only one custom stylesheet:
+
+ rstpep2html.py --stylesheet-path custom.css ...
+
+This run will use the default stylesheet, and the custom one:
+
+ rstpep2html.py --add-stylesheet-path custom.css ...
+
+This run will use the default stylesheet, a custom local stylesheet,
+and an external stylesheet:
+
+ rstpep2html.py --add-stylesheet-path custom.css \
+ --add-stylesheet http://www.example.org/external.css ...
+
+This run will use only the second custom stylesheet:
+
+ rstpep2html.py --add-stylesheet-path custom.css \
+ --stylesheet-path second.css ...
+
+
+
+
+Front-End Tools
+===============
+
+* What about if we don't know which Reader and/or Writer we are
+ going to use? If the Reader/Writer is specified on the
+ command-line? (Will this ever happen?)
+
+ Perhaps have different types of front ends:
+
+ a) _`Fully qualified`: Reader and Writer are hard-coded into the
+ front end (e.g. ``pep2html [options]``, ``pysource2pdf
+ [options]``).
+
+ b) _`Partially qualified`: Reader is hard-coded, and the Writer is
+ specified a sub-command (e.g. ``pep2 html [options]``,
+ ``pysource2 pdf [options]``). The Writer is known before option
+ processing happens, allowing the OptionParser to be built
+ dynamically. Alternatively, the Writer could be hard-coded and
+ the Reader specified as a sub-command (e.g. ``htmlfrom pep
+ [options]``).
+
+ c) _`Unqualified`: Reader and Writer are specified as subcommands
+ (e.g. ``publish pep html [options]``, ``publish pysource pdf
+ [options]``). A single front end would be sufficient, but
+ probably only useful for testing purposes.
+
+ d) _`Dynamic`: Reader and/or Writer are specified by options, with
+ defaults if unspecified (e.g. ``publish --writer pdf
+ [options]``). Is this possible? The option parser would have
+ to be told about new options it needs to handle, on the fly.
+ Component-specific options would have to be specified *after*
+ the component-specifying option.
+
+ Allow common options before subcommands, as in CVS? Or group all
+ options together? In the case of the `fully qualified`_
+ front ends, all the options will have to be grouped together
+ anyway, so there's no advantage (we can't use it to avoid
+ conflicts) to splitting common and component-specific options
+ apart.
+
+* Parameterize help text & defaults somehow? Perhaps a callback? Or
+ initialize ``settings_spec`` in ``__init__`` or ``init_options``?
+
+* Disable common options that don't apply?
+ (This should now be easier with ``frontend.filter_settings_spec``.)
+
+* Add ``--section-numbering`` command line option. The "sectnum"
+ directive should override the ``--no-section-numbering`` command
+ line option then.
+
+* Create a single dynamic_ or unqualified_ front end that can be
+ installed?
+
+\f
+..
+ Local Variables:
+ mode: indented-text
+ indent-tabs-mode: nil
+ sentence-end-double-space: t
+ fill-column: 70
+ End:
--- /dev/null
+===================
+ Docutils Web Site
+===================
+
+:Author: David Goodger; open to all Docutils developers
+:Contact: docutils-develop@lists.sourceforge.net
+:Date: $Date: 2017-07-05 16:33:33 +0200 (Mi, 05. Jul 2017) $
+:Revision: $Revision: 8133 $
+:Copyright: This document has been placed in the public domain.
+
+The Docutils web site, <http://docutils.sourceforge.net/>, is
+maintained by the ``docutils-update.local`` script, run by project
+maintainers on their local machines. The script
+will process any .txt file which is newer than the corresponding .html
+file in the local copy of the project's web directory and upload the changes
+to the web site at SourceForge.
+
+.. .. old instructions, for cron job:
+
+ The Docutils web site, <http://docutils.sourceforge.net/>, is
+ maintained automatically by the ``docutils-update`` script, run as an
+ hourly cron job on shell.berlios.de (by user "wiemann"). The script
+ will process any .txt file which is newer than the corresponding .html
+ file in the project's web directory on shell.berlios.de
+ (``/home/groups/docutils/htdocs/aux/htdocs/``) and upload the changes
+ to the web site at SourceForge.
+
+Please **do not** add any generated .html files to the Docutils
+repository. They will be generated automatically after a one-time
+setup (`described below`__).
+
+__ `Adding .txt Files`_
+
+The docutils-update.local__ script is located at
+``sandbox/infrastructure/docutils-update.local``.
+
+__ http://docutils.sf.net/sandbox/infrastructure/docutils-update.local
+
+If you want to share files via the web, you can upload them using the
+uploaddocutils.sh__ script
+(``sandbox/infrastructure/uploaddocutils.sh``).
+
+__ http://docutils.sf.net/sandbox/infrastructure/uploaddocutils.sh
+
+
+Setting Up
+==========
+
+(TBA)
+
+.. hint::
+ Anyone with checkin privileges can be a web-site maintainer. You need to
+ set up the directories for a local website build.
+
+ The procedure for that was on the docutils-devel list a while ago.
+
+
+Adding .txt Files
+=================
+
+User/Contributor
+----------------
+
+When adding a new .txt file that should be converted to HTML:
+
+#. Edit sandbox/infrastructure/htmlfiles.lst, and add the .html file
+ corresponding to the new .txt file (please keep the sorted order).
+
+#. Commit the edited version to the SVN repository.
+
+Maintainer
+----------
+
+#. If there are new directories in the SVN, allow the update script to run
+ once to create the directories in the filesystem before preparing for
+ HTML processing.
+
+#. Run the sandbox/infrastructure/update-htmlfiles shell script to generate
+ .html files::
+
+ cd <DOCUTILS-ROOT>/docutils/
+ sandbox/infrastructure/update-htmlfiles \
+ sandbox/infrastructure/htmlfiles.lst
+
+ (Maybe this should become part of docutils-update.local.)
+
+
+Removing Files & Directories
+============================
+
+#. Remove from SVN
+
+#. Remove to-be-generated HTML files from
+ ``sandbox/infrastructure/htmlfiles.lst``.
+
+#. Removing files and directories from SVN will not trigger their removal
+ from the web site. Files and directories must be manually removed from
+ sourceforge.net (under ``/home/project-web/docutils/htdocs/``).
+
+\f
+..
+ Local Variables:
+ mode: indented-text
+ indent-tabs-mode: nil
+ sentence-end-double-space: t
+ fill-column: 70
+ End:
--- /dev/null
+==============================================
+ Writing HTML (CSS) Stylesheets for Docutils_
+==============================================
+
+:Author: Lea Wiemann
+:Contact: docutils-develop@lists.sourceforge.net
+:Date: $Date: 2016-11-29 13:00:39 +0100 (Di, 29. Nov 2016) $
+:Revision: $Revision: 7977 $
+:Copyright: This document has been placed in the public domain.
+
+.. _Docutils: http://docutils.sourceforge.net/
+
+
+The look of Docutils' HTML output is customizable via CSS stylesheets.
+The default stylesheets can be found in the
+``docutils/writers/html*/`` directories of the ``html4css1`` and
+``html-base`` writers in the Docutils installation. Use the front-end
+command (``rst2html.py`` or ``rst2html5.py``) with the
+``--help`` option and look at the description of the ``--stylesheet-path``
+command-line option for the exact machine-specific location.
+
+To customize the look of HTML documents, you can override the settings
+of the default stylesheet in your own stylesheet. Specify both, the
+default stylesheet and your stylesheet to the ``--stylesheet`` or
+``--stylesheet-path`` command line option (or the corresponding
+settings in a configuration_ file), e.g. ::
+
+ rst2html.py --stylesheet=html4css1.css,transition-stars.css
+
+This is the preferable approach if you want to embed the stylesheet(s), as
+this ensures that an up-to-date version of ``html4css1.css`` is embedded.
+
+Alternatively, copy the default style sheet to the same place as your
+output HTML files will go and place a new file (e.g. called
+``my-docutils.css``) in the same directory and use the following
+template::
+
+ /*
+ :Author: Your Name
+ :Contact: Your Email Address
+ :Copyright: This stylesheet has been placed in the public domain.
+
+ Stylesheet for use with Docutils. [Optionally place a more
+ detailed description here.]
+ */
+
+ @import url(html4css1.css);
+
+ /* Your customizations go here. For example: */
+
+ h1, h2, h3, h4, h5, h6, p.topic-title {
+ font-family: sans-serif }
+
+For help on the CSS syntax, please see `the WDG's guide to Cascading
+Style Sheets`__ and, in particular, their `list of CSS properties`__.
+Another good reference site is http://selfhtml.org (German and French).
+
+__ http://www.htmlhelp.com/reference/css/
+__ http://www.htmlhelp.com/reference/css/all-properties.html
+
+It is important that you do not edit a copy of ``html4css1.css``
+directly because ``html4css1.css`` is frequently updated with each new
+release of Docutils.
+
+Also make sure that you import ``html4css1.css`` (using "``@import
+url(html4css1.css);``") because the definitions contained in the
+default stylesheet are required for correct rendering (margins,
+alignment, etc.).
+
+If you think your stylesheet is fancy and you would like to let others
+benefit from your efforts, you are encouraged to post the stylesheet to the
+Docutils-users_ mailing list. It might find its place in the `stylesheet
+collection`_ in the Docutils Sandbox_.
+
+If you decide to share your stylesheet with other users of Docutils,
+please keep website-specific customizations not applicable to
+Docutils' HTML code in a separate stylesheet.
+
+.. base for relative links is /docutils/docs/howto/
+
+.. _Docutils-users: ../user/mailing-lists.html#docutils-users
+.. _configuration: ../user/config.txt
+.. _sandbox: ../../../sandbox
+.. _stylesheet collection: ../../../sandbox/stylesheets/
+
+
+
+\f
+..
+ Local Variables:
+ mode: indented-text
+ indent-tabs-mode: nil
+ sentence-end-double-space: t
+ fill-column: 70
+ End:
--- /dev/null
+================================
+ Docutils_ Internationalization
+================================
+
+:Author: David Goodger
+:Contact: docutils-develop@lists.sourceforge.net
+:Date: $Date: 2014-07-07 05:12:02 +0200 (Mo, 07. Jul 2014) $
+:Revision: $Revision: 7769 $
+:Copyright: This document has been placed in the public domain.
+
+
+.. contents::
+
+
+This document describes the internationalization facilities of the
+Docutils_ project. `Introduction to i18n`_ by Tomohiro KUBOTA is a
+good general reference. "Internationalization" is often abbreviated
+as "i18n": "i" + 18 letters + "n".
+
+.. Note::
+
+ The i18n facilities of Docutils should be considered a "first
+ draft". They work so far, but improvements are welcome.
+ Specifically, standard i18n facilities like "gettext" have yet to
+ be explored.
+
+Docutils is designed to work flexibly with text in multiple languages
+(one language at a time). Language-specific features are (or should
+be [#]_) fully parameterized. To enable a new language, two modules
+have to be added to the project: one for Docutils itself (the
+`Docutils Language Module`_) and one for the reStructuredText parser
+(the `reStructuredText Language Module`_).
+
+.. [#] If anything in Docutils is insufficiently parameterized, it
+ should be considered a bug. Please report bugs to the Docutils
+ project bug tracker on SourceForge at
+ http://sourceforge.net/p/docutils/bugs/
+
+.. _Docutils: http://docutils.sourceforge.net/
+.. _Introduction to i18n:
+ http://www.debian.org/doc/manuals/intro-i18n/
+
+
+Language Module Names
+=====================
+
+Language modules are named using `language tags`_ as defined in
+`BCP 47`_. [#]_ in lowercase, converting hyphens to underscores [#]_.
+
+A typical language identifier consists of a 2-letter language code
+from `ISO 639`_ (3-letter codes can be used if no 2-letter code
+exists). The language identifier can have an optional subtag,
+typically for variations based on country (from `ISO 3166`_ 2-letter
+country codes). If no language identifier is specified, the default
+is "en" for English. Examples of module names include ``en.py``,
+``fr.py``, ``ja.py``, and ``pt_br.py``.
+
+.. [#] BCP stands for 'Best Current Practice', and is a persistent
+ name for a series of RFCs whose numbers change as they are updated.
+ The latest RFC describing language tag syntax is RFC 5646, Tags for
+ the Identification of Languages, and it obsoletes the older RFCs
+ 4646, 3066 and 1766.
+
+.. [#] Subtags are separated from primary tags by underscores instead
+ of hyphens, to conform to Python naming rules.
+
+.. _language tags: http://www.w3.org/International/articles/language-tags/
+.. _BCP 47: http://www.rfc-editor.org/rfc/bcp/bcp47.txt
+.. _ISO 639: http://www.loc.gov/standards/iso639-2/php/English_list.php
+.. _ISO 3166: http://www.iso.ch/iso/en/prods-services/iso3166ma/
+ 02iso-3166-code-lists/index.html
+
+
+Python Code
+===========
+
+Generally Python code in Docutils is ASCII-only. In language modules,
+Unicode-escapes can be used for non-ASCII characters.
+
+`PEP 263`_ introduces source code encodings to Python modules,
+implemented beginning in Python 2.3. Especially for languages with
+non-Latin scripts, using UTF-8 encoded literal Unicode strings increases the
+readability. Start the source code file with the magic comment::
+
+ # -*- coding: utf-8 -*-
+
+As mentioned in the note above, developers are invited to explore
+"gettext" and other i18n technologies.
+
+.. _PEP 263: http://www.python.org/peps/pep-0263.html
+
+
+Docutils Language Module
+========================
+
+Modules in ``docutils/languages`` contain language mappings for
+markup-independent language-specific features of Docutils. To make a
+new language module, just copy the ``en.py`` file, rename it with the
+code for your language (see `Language Module Names`_ above), and
+translate the terms as described below.
+
+Each Docutils language module contains three module attributes:
+
+``labels``
+ This is a mapping of node class names to language-dependent
+ boilerplate label text. The label text is used by Writer
+ components when they encounter document tree elements whose class
+ names are the mapping keys.
+
+ The entry values (*not* the keys) should be translated to the
+ target language.
+
+``bibliographic_fields``
+ This is a mapping of language-dependent field names (converted to
+ lower case) to canonical field names (keys of
+ ``DocInfo.biblio_notes`` in ``docutils.transforms.frontmatter``).
+ It is used when transforming bibliographic fields.
+
+ The keys should be translated to the target language.
+
+``author_separators``
+ This is a list of strings used to parse the 'Authors'
+ bibliographic field. They separate individual authors' names, and
+ are tried in order (i.e., earlier items take priority, and the
+ first item that matches wins). The English-language module
+ defines them as ``[';', ',']``; semi-colons can be used to
+ separate names like "Arthur Pewtie, Esq.".
+
+ Most languages won't have to "translate" this list.
+
+
+reStructuredText Language Module
+================================
+
+Modules in ``docutils/parsers/rst/languages`` contain language
+mappings for language-specific features of the reStructuredText
+parser. To make a new language module, just copy the ``en.py`` file,
+rename it with the code for your language (see `Language Module
+Names`_ above), and translate the terms as described below.
+
+Each reStructuredText language module contains two module attributes:
+
+``directives``
+ This is a mapping from language-dependent directive names to
+ canonical directive names. The canonical directive names are
+ registered in ``docutils/parsers/rst/directives/__init__.py``, in
+ ``_directive_registry``.
+
+ The keys should be translated to the target language. Synonyms
+ (multiple keys with the same values) are allowed; this is useful
+ for abbreviations.
+
+``roles``
+ This is a mapping language-dependent role names to canonical role
+ names for interpreted text. The canonical directive names are
+ registered in ``docutils/parsers/rst/states.py``, in
+ ``Inliner._interpreted_roles`` (this may change).
+
+ The keys should be translated to the target language. Synonyms
+ (multiple keys with the same values) are allowed; this is useful
+ for abbreviations.
+
+
+Testing the Language Modules
+============================
+
+Whenever a new language module is added or an existing one modified,
+the unit tests should be run. The test modules can be found in the
+docutils/test directory from code_ or from the `latest snapshot`_.
+
+The ``test_language.py`` module can be run as a script. With no
+arguments, it will test all language modules. With one or more
+language codes, it will test just those languages. For example::
+
+ $ python test_language.py en
+ ..
+ ----------------------------------------
+ Ran 2 tests in 0.095s
+
+ OK
+
+Use the "alltests.py" script to run all test modules, exhaustively
+testing the parser and other parts of the Docutils system.
+
+.. _code: https://sourceforge.net/p/docutils/code/HEAD/tree/trunk/
+.. _latest snapshot: https://sourceforge.net/p/docutils/code/HEAD/tarball
+
+
+Submitting the Language Modules
+===============================
+
+If you do not have repository write access and want to contribute your
+language modules, feel free to submit them via the `SourceForge patch
+tracker`__.
+
+__ http://sourceforge.net/p/docutils/patches/
--- /dev/null
+=======================================
+ Creating reStructuredText_ Directives
+=======================================
+
+:Authors: Dethe Elza, David Goodger, Lea Wiemann
+:Contact: docutils-develop@lists.sourceforge.net
+:Date: $Date: 2012-01-03 20:23:53 +0100 (Di, 03. Jän 2012) $
+:Revision: $Revision: 7302 $
+:Copyright: This document has been placed in the public domain.
+
+.. _reStructuredText: http://docutils.sourceforge.net/rst.html
+
+
+Directives are the primary extension mechanism of reStructuredText.
+This document aims to make the creation of new directives as easy and
+understandable as possible. There are only a couple of
+reStructuredText-specific features the developer needs to know to
+create a basic directive.
+
+The syntax of directives is detailed in the `reStructuredText Markup
+Specification`_, and standard directives are described in
+`reStructuredText Directives`_.
+
+Directives are a reStructuredText markup/parser concept. There is no
+"directive" document tree element, no single element that corresponds
+exactly to the concept of directives. Instead, choose the most
+appropriate elements from the existing Docutils elements. Directives
+build structures using the existing building blocks. See `The
+Docutils Document Tree`_ and the ``docutils.nodes`` module for more
+about the building blocks of Docutils documents.
+
+.. _reStructuredText Markup Specification:
+ ../ref/rst/restructuredtext.html#directives
+.. _reStructuredText Directives: ../ref/rst/directives.html
+.. _The Docutils Document Tree: ../ref/doctree.html
+
+
+.. contents:: Table of Contents
+
+
+The Directive Class
+===================
+
+Directives are created by defining a directive class that inherits
+from ``docutils.parsers.rst.Directive``::
+
+ from docutils.parsers import rst
+
+ class MyDirective(rst.Directive):
+
+ ...
+
+To understand how to implement the directive, let's have a look at the
+docstring of the ``Directive`` base class::
+
+ >>> from docutils.parsers import rst
+ >>> print rst.Directive.__doc__
+
+ Base class for reStructuredText directives.
+
+ The following attributes may be set by subclasses. They are
+ interpreted by the directive parser (which runs the directive
+ class):
+
+ - `required_arguments`: The number of required arguments (default:
+ 0).
+
+ - `optional_arguments`: The number of optional arguments (default:
+ 0).
+
+ - `final_argument_whitespace`: A boolean, indicating if the final
+ argument may contain whitespace (default: False).
+
+ - `option_spec`: A dictionary, mapping known option names to
+ conversion functions such as `int` or `float` (default: {}, no
+ options). Several conversion functions are defined in the
+ directives/__init__.py module.
+
+ Option conversion functions take a single parameter, the option
+ argument (a string or ``None``), validate it and/or convert it
+ to the appropriate form. Conversion functions may raise
+ `ValueError` and `TypeError` exceptions.
+
+ - `has_content`: A boolean; True if content is allowed. Client
+ code must handle the case where content is required but not
+ supplied (an empty content list will be supplied).
+
+ Arguments are normally single whitespace-separated words. The
+ final argument may contain whitespace and/or newlines if
+ `final_argument_whitespace` is True.
+
+ If the form of the arguments is more complex, specify only one
+ argument (either required or optional) and set
+ `final_argument_whitespace` to True; the client code must do any
+ context-sensitive parsing.
+
+ When a directive implementation is being run, the directive class
+ is instantiated, and the `run()` method is executed. During
+ instantiation, the following instance variables are set:
+
+ - ``name`` is the directive type or name (string).
+
+ - ``arguments`` is the list of positional arguments (strings).
+
+ - ``options`` is a dictionary mapping option names (strings) to
+ values (type depends on option conversion functions; see
+ `option_spec` above).
+
+ - ``content`` is a list of strings, the directive content line by line.
+
+ - ``lineno`` is the line number of the first line of the directive.
+
+ - ``content_offset`` is the line offset of the first line of the content from
+ the beginning of the current input. Used when initiating a nested parse.
+
+ - ``block_text`` is a string containing the entire directive.
+
+ - ``state`` is the state which called the directive function.
+
+ - ``state_machine`` is the state machine which controls the state which called
+ the directive function.
+
+ Directive functions return a list of nodes which will be inserted
+ into the document tree at the point where the directive was
+ encountered. This can be an empty list if there is nothing to
+ insert.
+
+ For ordinary directives, the list must contain body elements or
+ structural elements. Some directives are intended specifically
+ for substitution definitions, and must return a list of `Text`
+ nodes and/or inline elements (suitable for inline insertion, in
+ place of the substitution reference). Such directives must verify
+ substitution definition context, typically using code like this::
+
+ if not isinstance(state, states.SubstitutionDef):
+ error = state_machine.reporter.error(
+ 'Invalid context: the "%s" directive can only be used '
+ 'within a substitution definition.' % (name),
+ nodes.literal_block(block_text, block_text), line=lineno)
+ return [error]
+
+ >>>
+
+
+Option Conversion Functions
+===========================
+
+An option specification (``Directive.option_spec``) must be defined
+detailing the options available to the directive. An option spec is a
+mapping of option name to conversion function; conversion functions
+are applied to each option value to check validity and convert them to
+the expected type. Python's built-in conversion functions are often
+usable for this, such as ``int``, ``float``. Other useful conversion
+functions are included in the ``docutils.parsers.rst.directives``
+package (in the ``__init__.py`` module):
+
+- ``flag``: For options with no option arguments. Checks for an
+ argument (raises ``ValueError`` if found), returns ``None`` for
+ valid flag options.
+
+- ``unchanged_required``: Returns the text argument, unchanged.
+ Raises ``ValueError`` if no argument is found.
+
+- ``unchanged``: Returns the text argument, unchanged. Returns an
+ empty string ("") if no argument is found.
+
+- ``path``: Returns the path argument unwrapped (with newlines
+ removed). Raises ``ValueError`` if no argument is found.
+
+- ``uri``: Returns the URI argument with whitespace removed. Raises
+ ``ValueError`` if no argument is found.
+
+- ``nonnegative_int``: Checks for a nonnegative integer argument,
+ and raises ``ValueError`` if not.
+
+- ``class_option``: Converts the argument into an ID-compatible
+ string and returns it. Raises ``ValueError`` if no argument is
+ found.
+
+- ``unicode_code``: Convert a Unicode character code to a Unicode
+ character.
+
+- ``single_char_or_unicode``: A single character is returned as-is.
+ Unicode characters codes are converted as in ``unicode_code``.
+
+- ``single_char_or_whitespace_or_unicode``: As with
+ ``single_char_or_unicode``, but "tab" and "space" are also
+ supported.
+
+- ``positive_int``: Converts the argument into an integer. Raises
+ ValueError for negative, zero, or non-integer values.
+
+- ``positive_int_list``: Converts a space- or comma-separated list
+ of integers into a Python list of integers. Raises ValueError for
+ non-positive-integer values.
+
+- ``encoding``: Verfies the encoding argument by lookup. Raises
+ ValueError for unknown encodings.
+
+A further utility function, ``choice``, is supplied to enable
+options whose argument must be a member of a finite set of possible
+values. A custom conversion function must be written to use it.
+For example::
+
+ from docutils.parsers.rst import directives
+
+ def yesno(argument):
+ return directives.choice(argument, ('yes', 'no'))
+
+For example, here is an option spec for a directive which allows two
+options, "name" and "value", each with an option argument::
+
+ option_spec = {'name': unchanged, 'value': int}
+
+
+Error Handling
+==============
+
+If your directive implementation encounters an error during
+processing, you should call ``self.error()`` inside the ``run()``
+method::
+
+ if error_condition:
+ raise self.error('Error message.')
+
+The ``self.error()`` method will immediately raise an exception that
+will be caught by the reStructuredText directive handler. The
+directive handler will then insert an error-level system message in
+the document at the place where the directive occurred.
+
+Instead of ``self.error``, you can also use ``self.severe`` and
+``self.warning`` for more or less severe problems.
+
+If you want to return a system message *and* document contents, you need to
+create the system message yourself instead of using the ``self.error``
+convenience method::
+
+ def run(self):
+ # Create node(s).
+ node = nodes.paragraph(...)
+ # Node list to return.
+ node_list = [node]
+ if error_condition:
+ # Create system message.
+ error = self.reporter.error(
+ 'Error in "%s" directive: Your error message.' % self.name,
+ nodes.literal_block(block_text, block_text), line=lineno)
+ node_list.append(error)
+ return node_list
+
+
+Register the Directive
+======================
+
+* If the directive is a general-use **addition to the Docutils core**,
+ it must be registered with the parser and language mappings added:
+
+ 1. Register the new directive using its canonical name in
+ ``docutils/parsers/rst/directives/__init__.py``, in the
+ ``_directive_registry`` dictionary. This allows the
+ reStructuredText parser to find and use the directive.
+
+ 2. Add an entry to the ``directives`` dictionary in
+ ``docutils/parsers/rst/languages/en.py`` for the directive, mapping
+ the English name to the canonical name (both lowercase). Usually
+ the English name and the canonical name are the same.
+
+ 3. Update all the other language modules as well. For languages in
+ which you are proficient, please add translations. For other
+ languages, add the English directive name plus "(translation
+ required)".
+
+* If the directive is **application-specific**, use the
+ ``register_directive`` function::
+
+ from docutils.parsers.rst import directives
+ directives.register_directive(directive_name, directive_class)
+
+
+Examples
+========
+
+For the most direct and accurate information, "Use the Source, Luke!".
+All standard directives are documented in `reStructuredText
+Directives`_, and the source code implementing them is located in the
+``docutils/parsers/rst/directives`` package. The ``__init__.py``
+module contains a mapping of directive name to module and function
+name. Several representative directives are described below.
+
+
+Admonitions
+-----------
+
+`Admonition directives`__, such as "note" and "caution", are quite
+simple. They have no directive arguments or options. Admonition
+directive content is interpreted as ordinary reStructuredText.
+
+__ ../ref/rst/directives.html#specific-admonitions
+
+The resulting document tree for a simple reStructuredText line
+"``.. note:: This is a note.``" looks as follows:
+
+ <note>
+ <paragraph>
+ This is a note.
+
+The directive class for the "note" directive simply derives from a
+generic admonition directive class::
+
+ class Note(BaseAdmonition):
+
+ node_class = nodes.note
+
+Note that the only thing distinguishing the various admonition
+directives is the element (node class) generated. In the code above,
+the node class is set as a class attribute and is read by the
+``run()`` method of ``BaseAdmonition``, where the actual processing
+takes place::
+
+ # Import Docutils document tree nodes module.
+ from docutils import nodes
+ # Import Directive base class.
+ from docutils.parsers.rst import Directive
+
+ class BaseAdmonition(Directive):
+
+ required_arguments = 0
+ optional_arguments = 0
+ final_argument_whitespace = True
+ option_spec = {}
+ has_content = True
+
+ node_class = None
+ """Subclasses must set this to the appropriate admonition node class."""
+
+ def run(self):
+ # Raise an error if the directive does not have contents.
+ self.assert_has_content()
+ text = '\n'.join(self.content)
+ # Create the admonition node, to be populated by `nested_parse`.
+ admonition_node = self.node_class(rawsource=text)
+ # Parse the directive contents.
+ self.state.nested_parse(self.content, self.content_offset,
+ admonition_node)
+ return [admonition_node]
+
+Three things are noteworthy in the ``run()`` method above:
+
+* The ``admonition_node = self.node_class(text)`` line creates the
+ wrapper element, using the class set by the specific admonition
+ subclasses (as in note, ``node_class = nodes.note``).
+
+* The call to ``state.nested_parse()`` is what does the actual
+ processing. It parses the directive content and adds any generated
+ elements as child elements of ``admonition_node``.
+
+* If there was no directive content, the ``assert_has_content()``
+ convenience method raises an error exception by calling
+ ``self.error()`` (see `Error Handling`_ above).
+
+
+"image"
+-------
+
+.. _image: ../ref/rst/directives.html#image
+
+The "image_" directive is used to insert a picture into a document.
+This directive has one argument, the path to the image file, and
+supports several options. There is no directive content. Here's an
+early version of the image directive class::
+
+ # Import Docutils document tree nodes module.
+ from docutils import nodes
+ # Import ``directives`` module (contains conversion functions).
+ from docutils.parsers.rst import directives
+ # Import Directive base class.
+ from docutils.parsers.rst import Directive
+
+ def align(argument):
+ """Conversion function for the "align" option."""
+ return directives.choice(argument, ('left', 'center', 'right'))
+
+ class Image(Directive):
+
+ required_arguments = 1
+ optional_arguments = 0
+ final_argument_whitespace = True
+ option_spec = {'alt': directives.unchanged,
+ 'height': directives.nonnegative_int,
+ 'width': directives.nonnegative_int,
+ 'scale': directives.nonnegative_int,
+ 'align': align,
+ }
+ has_content = False
+
+ def run(self):
+ reference = directives.uri(self.arguments[0])
+ self.options['uri'] = reference
+ image_node = nodes.image(rawsource=self.block_text,
+ **self.options)
+ return [image_node]
+
+Several things are noteworthy in the code above:
+
+* The "image" directive requires a single argument, which is allowed
+ to contain whitespace (``final_argument_whitespace = True``). This
+ is to allow for long URLs which may span multiple lines. The first
+ line of the ``run()`` method joins the URL, discarding any embedded
+ whitespace.
+
+* The reference is added to the ``options`` dictionary under the
+ "uri" key; this becomes an attribute of the ``nodes.image`` element
+ object. Any other attributes have already been set explicitly in
+ the reStructuredText source text.
+
+
+The Pending Element
+-------------------
+
+Directives that cause actions to be performed *after* the complete
+document tree has been generated can be implemented using a
+``pending`` node. The ``pending`` node causes a transform_ to be run
+after the document has been parsed.
+
+For an example usage of the ``pending`` node, see the implementation
+of the ``contents`` directive in
+docutils.parsers.rst.directives.parts__.
+
+.. _transform: ../ref/transforms.html
+__ http://docutils.sf.net/docutils/parsers/rst/directives/parts.py
--- /dev/null
+==================================================
+ Creating reStructuredText Interpreted Text Roles
+==================================================
+
+:Authors: David Goodger
+:Contact: docutils-develop@lists.sourceforge.net
+:Date: $Date: 2012-01-03 20:23:53 +0100 (Di, 03. Jän 2012) $
+:Revision: $Revision: 7302 $
+:Copyright: This document has been placed in the public domain.
+
+Interpreted text roles are an extension mechanism for inline markup in
+reStructuredText. This document aims to make the creation of new
+roles as easy and understandable as possible.
+
+Standard roles are described in `reStructuredText Interpreted Text
+Roles`_. See the `Interpreted Text`_ section in the `reStructuredText
+Markup Specification`_ for syntax details.
+
+.. _reStructuredText Interpreted Text Roles: ../ref/rst/roles.html
+.. _Interpreted Text:
+ ../ref/rst/restructuredtext.html#interpreted-text
+.. _reStructuredText Markup Specification:
+ ../ref/rst/restructuredtext.html
+
+
+.. contents::
+
+
+Define the Role Function
+========================
+
+The role function creates and returns inline elements (nodes) and does
+any additional processing required. Its signature is as follows::
+
+ def role_fn(name, rawtext, text, lineno, inliner,
+ options={}, content=[]):
+ code...
+
+ # Set function attributes for customization:
+ role_fn.options = ...
+ role_fn.content = ...
+
+Function attributes are described below (see `Specify Role Function
+Options and Content`_). The role function parameters are as follows:
+
+* ``name``: The local name of the interpreted role, the role name
+ actually used in the document.
+
+* ``rawtext``: A string containing the enitre interpreted text input,
+ including the role and markup. Return it as a ``problematic`` node
+ linked to a system message if a problem is encountered.
+
+* ``text``: The interpreted text content.
+
+* ``lineno``: The line number where the interpreted text begins.
+
+* ``inliner``: The ``docutils.parsers.rst.states.Inliner`` object that
+ called role_fn. It contains the several attributes useful for error
+ reporting and document tree access.
+
+* ``options``: A dictionary of directive options for customization
+ (from the `"role" directive`_), to be interpreted by the role
+ function. Used for additional attributes for the generated elements
+ and other functionality.
+
+* ``content``: A list of strings, the directive content for
+ customization (from the `"role" directive`_). To be interpreted by
+ the role function.
+
+Role functions return a tuple of two values:
+
+* A list of nodes which will be inserted into the document tree at the
+ point where the interpreted role was encountered (can be an empty
+ list).
+
+* A list of system messages, which will be inserted into the document tree
+ immediately after the end of the current block (can also be empty).
+
+
+Specify Role Function Options and Content
+=========================================
+
+Function attributes are for customization, and are interpreted by the
+`"role" directive`_. If unspecified, role function attributes are
+assumed to have the value ``None``. Two function attributes are
+recognized:
+
+- ``options``: The option specification. All role functions
+ implicitly support the "class" option, unless disabled with an
+ explicit ``{'class': None}``.
+
+ An option specification must be defined detailing the options
+ available to the "role" directive. An option spec is a mapping of
+ option name to conversion function; conversion functions are applied
+ to each option value to check validity and convert them to the
+ expected type. Python's built-in conversion functions are often
+ usable for this, such as ``int``, ``float``, and ``bool`` (included
+ in Python from version 2.2.1). Other useful conversion functions
+ are included in the ``docutils.parsers.rst.directives`` package.
+ For further details, see `Creating reStructuredText Directives`_.
+
+- ``content``: A boolean; true if "role" directive content is allowed.
+ Role functions must handle the case where content is required but
+ not supplied (an empty content list will be supplied).
+
+ As of this writing, no roles accept directive content.
+
+Note that unlike directives, the "arguments" function attribute is not
+supported for role customization. Directive arguments are handled by
+the "role" directive itself.
+
+.. _"role" directive: ../ref/rst/directives.html#role
+.. _Creating reStructuredText Directives:
+ rst-directives.html#specify-directive-arguments-options-and-content
+
+
+Register the Role
+=================
+
+If the role is a general-use addition to the Docutils core, it must be
+registered with the parser and language mappings added:
+
+1. Register the new role using the canonical name::
+
+ from docutils.parsers.rst import roles
+ roles.register_canonical_role(name, role_function)
+
+ This code is normally placed immediately after the definition of
+ the role funtion.
+
+2. Add an entry to the ``roles`` dictionary in
+ ``docutils/parsers/rst/languages/en.py`` for the role, mapping the
+ English name to the canonical name (both lowercase). Usually the
+ English name and the canonical name are the same. Abbreviations
+ and other aliases may also be added here.
+
+3. Update all the other language modules as well. For languages in
+ which you are proficient, please add translations. For other
+ languages, add the English role name plus "(translation required)".
+
+If the role is application-specific, use the ``register_local_role``
+function::
+
+ from docutils.parsers.rst import roles
+ roles.register_local_role(name, role_function)
+
+
+Examples
+========
+
+For the most direct and accurate information, "Use the Source, Luke!".
+All standard roles are documented in `reStructuredText Interpreted
+Text Roles`_, and the source code implementing them is located in the
+``docutils/parsers/rst/roles.py`` module. Several representative
+roles are described below.
+
+
+Generic Roles
+-------------
+
+Many roles simply wrap a given element around the text. There's a
+special helper function, ``register_generic_role``, which generates a
+role function from the canonical role name and node class::
+
+ register_generic_role('emphasis', nodes.emphasis)
+
+For the implementation of ``register_generic_role``, see the
+``docutils.parsers.rst.roles`` module.
+
+
+RFC Reference Role
+------------------
+
+This role allows easy references to RFCs_ (Request For Comments
+documents) by automatically providing the base URL,
+http://www.faqs.org/rfcs/, and appending the RFC document itself
+(rfcXXXX.html, where XXXX is the RFC number). For example::
+
+ See :RFC:`2822` for information about email headers.
+
+This is equivalent to::
+
+ See `RFC 2822`__ for information about email headers.
+
+ __ http://www.faqs.org/rfcs/rfc2822.html
+
+Here is the implementation of the role::
+
+ def rfc_reference_role(role, rawtext, text, lineno, inliner,
+ options={}, content=[]):
+ try:
+ rfcnum = int(text)
+ if rfcnum <= 0:
+ raise ValueError
+ except ValueError:
+ msg = inliner.reporter.error(
+ 'RFC number must be a number greater than or equal to 1; '
+ '"%s" is invalid.' % text, line=lineno)
+ prb = inliner.problematic(rawtext, rawtext, msg)
+ return [prb], [msg]
+ # Base URL mainly used by inliner.rfc_reference, so this is correct:
+ ref = inliner.document.settings.rfc_base_url + inliner.rfc_url % rfcnum
+ set_classes(options)
+ node = nodes.reference(rawtext, 'RFC ' + utils.unescape(text), refuri=ref,
+ **options)
+ return [node], []
+
+ register_canonical_role('rfc-reference', rfc_reference_role)
+
+Noteworthy in the code above are:
+
+1. The interpreted text itself should contain the RFC number. The
+ ``try`` clause verifies by converting it to an integer. If the
+ conversion fails, the ``except`` clause is executed: a system
+ message is generated, the entire interpreted text construct (in
+ ``rawtext``) is wrapped in a ``problematic`` node (linked to the
+ system message), and the two are returned.
+
+2. The RFC reference itself is constructed from a stock URI, set as
+ the "refuri" attribute of a "reference" element.
+
+3. The ``options`` function parameter, a dictionary, may contain a
+ "class" customization attribute; it is interpreted and replaced
+ with a "classes" attribute by the ``set_classes()`` function. The
+ resulting "classes" attribute is passed through to the "reference"
+ element node constructor.
+
+.. _RFCs: http://foldoc.doc.ic.ac.uk/foldoc/foldoc.cgi?query=rfc&action=Search&sourceid=Mozilla-search
--- /dev/null
+=============================
+ Deploying Docutils Securely
+=============================
+
+:Author: David Goodger
+:Contact: docutils-develop@lists.sourceforge.net
+:Date: $Date: 2019-12-12 14:04:57 +0100 (Do, 12. Dez 2019) $
+:Revision: $Revision: 8435 $
+:Copyright: This document has been placed in the public domain.
+
+.. contents::
+
+Introduction
+============
+
+Initially, Docutils was intended for command-line tools and
+single-user applications. Through-the-web editing and processing was
+not envisaged, therefore web security was not a consideration. Once
+Docutils/reStructuredText started being incorporated into an
+ever-increasing number of web applications (blogs__, wikis__, content
+management systems, and others), several security issues arose and
+have been addressed. This document provides instructions to help you
+secure the Docutils software in your applications.
+
+Docutils does not come in a through-the-web secure state, because this
+would inconvenience ordinary users.
+
+__ ../../FAQ.html#are-there-any-weblog-blog-projects-that-use-restructuredtext-syntax
+__ ../../FAQ.html#are-there-any-wikis-that-use-restructuredtext-syntax
+
+
+The Issues
+==========
+
+External Data Insertion
+-----------------------
+
+There are several `reStructuredText directives`_ that can insert
+external data (files and URLs) into the immediate document. These
+directives are:
+
+* "include_", by its very nature
+* "raw_", through its ``:file:`` and ``:url:`` options
+* "csv-table_", through its ``:file:`` and ``:url:`` options
+
+The "include_" directive and the other directives' file insertion
+features can be disabled by setting "file_insertion_enabled_" to
+0/false.
+
+.. _reStructuredText directives: ../ref/rst/directives.html
+.. _include: ../ref/rst/directives.html#include
+.. _raw: ../ref/rst/directives.html#raw-directive
+.. _csv-table: ../ref/rst/directives.html#csv-table
+.. _file_insertion_enabled: ../user/config.html#file-insertion-enabled
+
+
+Raw HTML Insertion
+------------------
+
+The "raw_" directive is intended for the insertion of
+non-reStructuredText data that is passed untouched to the Writer.
+This directive can be abused to bypass site features or insert
+malicious JavaScript code into a web page. The "raw_" directive can
+be disabled by setting "raw_enabled_" to 0/false.
+
+.. _raw_enabled: ../user/config.html#raw-enabled
+
+
+CPU and memory utilization
+--------------------------
+
+Parsing complex reStructuredText documents may require high processing
+ressources. This enables `Denial of Service` attacs using specially crafted
+input.
+
+It is recommended to enforce limits for the computation time and resource
+utilization of the Docutils process when processing untrusted input.
+
+
+Securing Docutils
+=================
+
+Programmatically Via Application Default Settings
+-------------------------------------------------
+
+If your application calls Docutils via one of the `convenience
+functions`_, you can pass a dictionary of default settings that
+override the component defaults::
+
+ defaults = {'file_insertion_enabled': 0,
+ 'raw_enabled': 0}
+ output = docutils.core.publish_string(
+ ..., settings_overrides=defaults)
+
+Note that these defaults can be overridden by configuration files (and
+command-line options if applicable). If this is not desired, you can
+disable configuration file processing with the ``_disable_config``
+setting::
+
+ defaults = {'file_insertion_enabled': 0,
+ 'raw_enabled': 0,
+ '_disable_config': 1}
+ output = docutils.core.publish_string(
+ ..., settings_overrides=defaults)
+
+.. _convenience functions: ../api/publisher.html
+
+
+Via a Configuration File
+------------------------
+
+You should secure Docutils via a configuration file:
+
+* if your application executes one of the `Docutils front-end tools`_
+ as a separate process;
+* if you cannot or choose not to alter the source code of your
+ application or the component that calls Docutils; or
+* if you want to secure all Docutils deployments system-wide.
+
+If you call Docutils programmatically, it may be preferable to use the
+methods described in section below.
+
+Docutils automatically looks in three places for a configuration file:
+
+* ``/etc/docutils.conf``, for system-wide configuration,
+* ``./docutils.conf`` (in the current working directory), for
+ project-specific configuration, and
+* ``~/.docutils`` (in the user's home directory), for user-specific
+ configuration.
+
+These locations can be overridden by the ``DOCUTILSCONFIG``
+environment variable. Details about configuration files, the purpose
+of the various locations, and ``DOCUTILSCONFIG`` are available in the
+`"Configuration Files"`_ section of `Docutils Configuration`_.
+
+To fully secure your Docutils installation, the configuration file
+should contain the following lines::
+
+ [general]
+ file-insertion-enabled:
+ raw-enabled:
+
+.. Note:: Due to a bug in the definitions of these security-related
+ settings, the right-hand-side of the above lines (the values)
+ should be left blank, as shown. The bug was corrected on
+ 2006-11-12 and is reflected in Docutils releases 0.4.1 and higher.
+ In these versions, more verbose forms may be used, such as::
+
+ [general]
+ file-insertion-enabled: off
+ raw-enabled: no
+
+.. _Docutils front-end tools: ../user/tools.html
+.. _"Configuration Files": ../user/config.html#configuration-files
+.. _Docutils Configuration: ../user/config.html
+
+
+Version Applicability
+=====================
+
+The ``file_insertion_enabled`` & ``raw_enabled`` settings were added
+to Docutils 0.3.9; previous versions will ignore these settings. A
+bug existed in the configuration file handling of these settings in
+Docutils 0.4 and earlier. The bug was fixed with the 0.4.1 release on
+2006-11-12.
+
+
+Related Documents
+=================
+
+`Docutils Runtime Settings`_ explains the relationship between
+component settings specifications, application settings
+specifications, configuration files, and command-line options
+
+`Docutils Configuration`_ describes configuration files (locations,
+structure, and syntax), and lists all settings and command-line
+options.
+
+.. _Docutils Runtime Settings: ../api/runtime-settings.html
--- /dev/null
+==========================================
+ Docutils_ Project Documentation Overview
+==========================================
+
+:Author: David Goodger
+:Contact: docutils-develop@lists.sourceforge.net
+:Date: $Date: 2016-01-13 22:09:13 +0100 (Mi, 13. Jän 2016) $
+:Revision: $Revision: 7933 $
+:Copyright: This document has been placed in the public domain.
+
+The latest working documents may be accessed individually below, or
+from the ``docs`` directory of the `Docutils distribution`_.
+
+.. _Docutils: http://docutils.sourceforge.net/
+.. _Docutils distribution: http://docutils.sourceforge.net/#download
+
+.. contents::
+
+
+Docutils Stakeholders
+=====================
+
+Docutils stakeholders can be categorized in several groups:
+
+1. End-users: users of reStructuredText and the Docutils tools.
+ Although some are developers (e.g. Python developers utilizing
+ reStructuredText for docstrings in their source), many are not.
+
+2. Client-developers: developers using Docutils as a library,
+ programmers developing *with* Docutils.
+
+3. Component-developers: those who implement application-specific
+ components, directives, and/or roles, separately from Docutils.
+
+4. Core-developers: developers of the Docutils codebase and
+ participants in the Docutils project community.
+
+5. Re-implementers: developers of alternate implementations of
+ Docutils.
+
+There's a lot of overlap between these groups. Most (perhaps all)
+core-developers, component-developers, client-developers, and
+re-implementers are also end-users. Core-developers are also
+client-developers, and may also be component-developers in other
+projects. Component-developers are also client-developers.
+
+
+Project Fundamentals
+====================
+
+These files are for all Docutils stakeholders. They are kept at the
+top level of the Docutils project directory.
+
+:README.txt_: Project overview: quick-start, requirements,
+ installation, and usage.
+:COPYING.txt_: Conditions for Docutils redistribution, with links to
+ licenses.
+:FAQ.txt_: Docutils Frequently Asked Questions. If you have a
+ question or issue, there's a good chance it's already
+ answered here.
+:BUGS.txt_: A list of known bugs, and how to report a bug.
+:RELEASE-NOTES.txt_: Summary of the major changes in recent releases.
+:HISTORY.txt_: Detailed change history log.
+:THANKS.txt_: Acknowledgements.
+
+.. _README.txt: ../README.html
+.. _BUGS.txt: ../BUGS.html
+.. _COPYING.txt: ../COPYING.html
+.. _Docutils FAQ:
+.. _FAQ.txt: ../FAQ.html
+.. _RELEASE-NOTES.txt: ../RELEASE-NOTES.html
+.. _HISTORY.txt: ../HISTORY.html
+.. _THANKS.txt: ../THANKS.html
+
+
+.. _user:
+
+``user/``: Introductory & Tutorial Material for End-Users
+=========================================================
+
+Docutils-general:
+
+* `Docutils Front-End Tools <user/tools.html>`__
+* `Docutils Configuration <user/config.html>`__
+* `Docutils Mailing Lists <user/mailing-lists.html>`__
+* `Docutils Link List <user/links.html>`__
+
+Writer-specific:
+
+* `Docutils HTML writers <user/html.html>`__
+* `Easy Slide Shows With reStructuredText & S5 <user/slide-shows.html>`__
+* `Docutils LaTeX Writer <user/latex.html>`__
+* `Docutils ODF/OpenOffice/odt Writer <user/odt.html>`__
+
+`reStructuredText <http://docutils.sourceforge.net/rst.html>`_:
+
+* `A ReStructuredText Primer (HTML) <user/rst/quickstart.html>`__ (or
+ `text source <user/rst/quickstart.txt>`__)
+* `Quick reStructuredText <user/rst/quickref.html>`__ (user reference)
+* `reStructuredText Cheat Sheet <user/rst/cheatsheet.txt>`__ (text
+ only; 1 page for syntax, 1 page directive & role reference)
+* `reStructuredText Demonstration <user/rst/demo.html>`_ (a
+ demonstration of most reStructuredText features; you can also have a
+ look at the `text source <user/rst/demo.txt>`__)
+
+Editor support:
+
+* `Emacs support for reStructuredText <user/emacs.html>`_
+
+
+.. _ref:
+
+``ref/``: Reference Material for All Groups
+===========================================
+
+Many of these files began as developer specifications, but now that
+they're mature and used by end-users and client-developers, they have
+become reference material. Successful specs evolve into refs.
+
+Docutils-general:
+
+* `The Docutils Document Tree <ref/doctree.html>`__ (incomplete)
+* `Docutils Transforms <ref/transforms.html>`__
+* `Docutils Generic DTD <ref/docutils.dtd>`__
+* `OASIS XML Exchange Table Model Declaration Module
+ <ref/soextblx.dtd>`__ (CALS tables DTD module)
+
+Although not in the "ref" directory, `PEP 258`_ is a must-read
+reference for any Docutils developer.
+
+reStructuredText_:
+
+* `An Introduction to reStructuredText <ref/rst/introduction.html>`__
+ (includes the `Goals <ref/rst/introduction.html#goals>`__ and
+ `History <ref/rst/introduction.html#history>`__ of reStructuredText)
+* `reStructuredText Markup Specification <ref/rst/restructuredtext.html>`__
+* `reStructuredText Directives <ref/rst/directives.html>`__
+* `reStructuredText Interpreted Text Roles <ref/rst/roles.html>`__
+* `reStructuredText Standard Definition Files
+ <ref/rst/definitions.html>`_
+
+Prehistoric:
+
+* `Setext Documents Mirror
+ <http://docutils.sourceforge.net/mirror/setext.html>`__
+
+
+.. _peps:
+
+``peps/``: Python Enhancement Proposals
+=======================================
+
+* `PEP 256: Docstring Processing System Framework`__ is a high-level
+ generic proposal. [`PEP 256`__ in the `master repository`_]
+* `PEP 257: Docstring Conventions`__ addresses docstring style and
+ touches on content. [`PEP 257`__ in the `master repository`_]
+* `PEP 258: Docutils Design Specification`__ is an overview of the
+ architecture of Docutils. It documents design issues and
+ implementation details. [`PEP 258`__ in the `master repository`_]
+* `PEP 287: reStructuredText Docstring Format`__ proposes a standard
+ markup syntax. [`PEP 287`__ in the `master repository`_]
+
+Please note that PEPs in the `master repository`_ may not be current,
+whereas the local versions are.
+
+__ peps/pep-0256.html
+__ http://www.python.org/peps/pep-0256.html
+__ peps/pep-0257.html
+__ http://www.python.org/peps/pep-0257.html
+.. _PEP 258:
+__ peps/pep-0258.html
+__ http://www.python.org/peps/pep-0258.html
+__ peps/pep-0287.html
+__ http://www.python.org/peps/pep-0287.html
+.. _master repository: http://www.python.org/peps/
+
+
+.. _api:
+
+``api/``: API Reference Material for Client-Developers
+======================================================
+
+* `The Docutils Publisher <api/publisher.html>`__
+* `Inside A Docutils Command-Line Front-End Tool <api/cmdline-tool.html>`__
+* `Docutils Runtime Settings <api/runtime-settings.html>`__
+* (`Docutils Transforms <ref/transforms.html>`__ should be moved here)
+
+`PEP 258`_ is an overview of the architecture of Docutils.
+
+
+.. _howto:
+
+``howto/``: Instructions for Developers
+=======================================
+
+* **Security:** `Deploying Docutils Securely <howto/security.html>`__
+* `Writing HTML (CSS) Stylesheets for Docutils
+ <howto/html-stylesheets.html>`__
+* `Docutils Internationalization <howto/i18n.html>`__
+* `Creating reStructuredText Directives <howto/rst-directives.html>`__
+* `Creating reStructuredText Interpreted Text Roles
+ <howto/rst-roles.html>`__
+
+
+.. _dev:
+
+``dev/``: Development Notes and Plans for Core-Developers
+=========================================================
+
+Docutils-general:
+
+* `Docutils Hacker's Guide <dev/hacking.html>`__
+* `Docutils Distributor's Guide <dev/distributing.html>`__
+* `Docutils To Do List <dev/todo.html>`__
+* `Docutils Project Policies <dev/policies.html>`__
+* `Docutils Web Site <dev/website.html>`__
+* `Docutils Release Procedure <dev/release.html>`__
+* `The Docutils Subversion Repository <dev/repository.html>`__
+* `Docutils Testing <dev/testing.html>`__
+* `Docstring Semantics <dev/semantics.html>`__ (incomplete)
+* `Python Source Reader <dev/pysource.html>`_ (incomplete)
+* `Docutils Python DTD <dev/pysource.dtd>`_ (experimental)
+* `Plan for Enthought API Documentation Tool <dev/enthought-plan.html>`_
+* `Enthought API Documentation Tool RFP <dev/enthought-rfp.html>`_
+
+reStructuredText_:
+
+* `A Record of reStructuredText Syntax Alternatives
+ <dev/rst/alternatives.html>`__
+* `Problems With StructuredText <dev/rst/problems.html>`__
+
+\f
+..
+ Local Variables:
+ mode: indented-text
+ indent-tabs-mode: nil
+ sentence-end-double-space: t
+ fill-column: 70
+ End:
--- /dev/null
+PEP: 256
+Title: Docstring Processing System Framework
+Version: $Revision: 4564 $
+Last-Modified: $Date: 2006-05-21 22:44:42 +0200 (So, 21. Mai 2006) $
+Author: David Goodger <goodger@python.org>
+Discussions-To: <doc-sig@python.org>
+Status: Draft
+Type: Standards Track
+Content-Type: text/x-rst
+Created: 01-Jun-2001
+Post-History: 13-Jun-2001
+
+
+Abstract
+========
+
+Python lends itself to inline documentation. With its built-in
+docstring syntax, a limited form of `Literate Programming`_ is easy to
+do in Python. However, there are no satisfactory standard tools for
+extracting and processing Python docstrings. The lack of a standard
+toolset is a significant gap in Python's infrastructure; this PEP aims
+to fill the gap.
+
+The issues surrounding docstring processing have been contentious and
+difficult to resolve. This PEP proposes a generic Docstring
+Processing System (DPS) framework, which separates out the components
+(program and conceptual), enabling the resolution of individual issues
+either through consensus (one solution) or through divergence (many).
+It promotes standard interfaces which will allow a variety of plug-in
+components (input context readers, markup parsers, and output format
+writers) to be used.
+
+The concepts of a DPS framework are presented independently of
+implementation details.
+
+
+Road Map to the Docstring PEPs
+==============================
+
+There are many aspects to docstring processing. The "Docstring PEPs"
+have broken up the issues in order to deal with each of them in
+isolation, or as close as possible. The individual aspects and
+associated PEPs are as follows:
+
+* Docstring syntax. PEP 287, "reStructuredText Docstring Format"
+ [#PEP-287]_, proposes a syntax for Python docstrings, PEPs, and
+ other uses.
+
+* Docstring semantics consist of at least two aspects:
+
+ - Conventions: the high-level structure of docstrings. Dealt with
+ in PEP 257, "Docstring Conventions" [#PEP-257]_.
+
+ - Methodology: rules for the informational content of docstrings.
+ Not addressed.
+
+* Processing mechanisms. This PEP (PEP 256) outlines the high-level
+ issues and specification of an abstract docstring processing system
+ (DPS). PEP 258, "Docutils Design Specification" [#PEP-258]_, is an
+ overview of the design and implementation of one DPS under
+ development.
+
+* Output styles: developers want the documentation generated from
+ their source code to look good, and there are many different ideas
+ about what that means. PEP 258 touches on "Stylist Transforms".
+ This aspect of docstring processing has yet to be fully explored.
+
+By separating out the issues, we can form consensus more easily
+(smaller fights ;-), and accept divergence more readily.
+
+
+Rationale
+=========
+
+There are standard inline documentation systems for some other
+languages. For example, Perl has POD_ ("Plain Old Documentation") and
+Java has Javadoc_, but neither of these mesh with the Pythonic way.
+POD syntax is very explicit, but takes after Perl in terms of
+readability. Javadoc is HTML-centric; except for "``@field``" tags,
+raw HTML is used for markup. There are also general tools such as
+Autoduck_ and Web_ (Tangle & Weave), useful for multiple languages.
+
+There have been many attempts to write auto-documentation systems
+for Python (not an exhaustive list):
+
+- Marc-Andre Lemburg's doc.py_
+
+- Daniel Larsson's pythondoc_ & gendoc_
+
+- Doug Hellmann's HappyDoc_
+
+- Laurence Tratt's Crystal (no longer available on the web)
+
+- Ka-Ping Yee's pydoc_ (pydoc.py is now part of the Python standard
+ library; see below)
+
+- Tony Ibbs' docutils_ (Tony has donated this name to the `Docutils
+ project`_)
+
+- Edward Loper's STminus_ formalization and related efforts
+
+These systems, each with different goals, have had varying degrees of
+success. A problem with many of the above systems was over-ambition
+combined with inflexibility. They provided a self-contained set of
+components: a docstring extraction system, a markup parser, an
+internal processing system and one or more output format writers with
+a fixed style. Inevitably, one or more aspects of each system had
+serious shortcomings, and they were not easily extended or modified,
+preventing them from being adopted as standard tools.
+
+It has become clear (to this author, at least) that the "all or
+nothing" approach cannot succeed, since no monolithic self-contained
+system could possibly be agreed upon by all interested parties. A
+modular component approach designed for extension, where components
+may be multiply implemented, may be the only chance for success.
+Standard inter-component APIs will make the DPS components
+comprehensible without requiring detailed knowledge of the whole,
+lowering the barrier for contributions, and ultimately resulting in a
+rich and varied system.
+
+Each of the components of a docstring processing system should be
+developed independently. A "best of breed" system should be chosen,
+either merged from existing systems, and/or developed anew. This
+system should be included in Python's standard library.
+
+
+PyDoc & Other Existing Systems
+------------------------------
+
+PyDoc became part of the Python standard library as of release 2.1.
+It extracts and displays docstrings from within the Python interactive
+interpreter, from the shell command line, and from a GUI window into a
+web browser (HTML). Although a very useful tool, PyDoc has several
+deficiencies, including:
+
+- In the case of the GUI/HTML, except for some heuristic hyperlinking
+ of identifier names, no formatting of the docstrings is done. They
+ are presented within ``<p><small><tt>`` tags to avoid unwanted line
+ wrapping. Unfortunately, the result is not attractive.
+
+- PyDoc extracts docstrings and structural information (class
+ identifiers, method signatures, etc.) from imported module objects.
+ There are security issues involved with importing untrusted code.
+ Also, information from the source is lost when importing, such as
+ comments, "additional docstrings" (string literals in non-docstring
+ contexts; see PEP 258 [#PEP-258]_), and the order of definitions.
+
+The functionality proposed in this PEP could be added to or used by
+PyDoc when serving HTML pages. The proposed docstring processing
+system's functionality is much more than PyDoc needs in its current
+form. Either an independent tool will be developed (which PyDoc may
+or may not use), or PyDoc could be expanded to encompass this
+functionality and *become* the docstring processing system (or one
+such system). That decision is beyond the scope of this PEP.
+
+Similarly for other existing docstring processing systems, their
+authors may or may not choose compatibility with this framework.
+However, if this framework is accepted and adopted as the Python
+standard, compatibility will become an important consideration in
+these systems' future.
+
+
+Specification
+=============
+
+The docstring processing system framework is broken up as follows:
+
+1. Docstring conventions. Documents issues such as:
+
+ - What should be documented where.
+
+ - First line is a one-line synopsis.
+
+ PEP 257 [#PEP-257]_ documents some of these issues.
+
+2. Docstring processing system design specification. Documents
+ issues such as:
+
+ - High-level spec: what a DPS does.
+
+ - Command-line interface for executable script.
+
+ - System Python API.
+
+ - Docstring extraction rules.
+
+ - Readers, which encapsulate the input context.
+
+ - Parsers.
+
+ - Document tree: the intermediate internal data structure. The
+ output of the Parser and Reader, and the input to the Writer all
+ share the same data structure.
+
+ - Transforms, which modify the document tree.
+
+ - Writers for output formats.
+
+ - Distributors, which handle output management (one file, many
+ files, or objects in memory).
+
+ These issues are applicable to any docstring processing system
+ implementation. PEP 258 [#PEP-258]_ documents these issues.
+
+3. Docstring processing system implementation.
+
+4. Input markup specifications: docstring syntax. PEP 287 [#PEP-287]_
+ proposes a standard syntax.
+
+5. Input parser implementations.
+
+6. Input context readers ("modes": Python source code, PEP, standalone
+ text file, email, etc.) and implementations.
+
+7. Stylists: certain input context readers may have associated
+ stylists which allow for a variety of output document styles.
+
+8. Output formats (HTML, XML, TeX, DocBook, info, etc.) and writer
+ implementations.
+
+Components 1, 2/3/5, and 4 are the subject of individual companion
+PEPs. If there is another implementation of the framework or
+syntax/parser, additional PEPs may be required. Multiple
+implementations of each of components 6 and 7 will be required; the
+PEP mechanism may be overkill for these components.
+
+
+Project Web Site
+================
+
+A SourceForge project has been set up for this work at
+http://docutils.sourceforge.net/.
+
+
+References and Footnotes
+========================
+
+.. [#PEP-287] PEP 287, reStructuredText Docstring Format, Goodger
+ (http://www.python.org/peps/pep-0287.html)
+
+.. [#PEP-257] PEP 257, Docstring Conventions, Goodger, Van Rossum
+ (http://www.python.org/peps/pep-0257.html)
+
+.. [#PEP-258] PEP 258, Docutils Design Specification, Goodger
+ (http://www.python.org/peps/pep-0258.html)
+
+.. _Literate Programming: http://www.literateprogramming.com/
+
+.. _POD: http://perldoc.perl.org/perlpod.html
+
+.. _Javadoc: http://java.sun.com/j2se/javadoc/
+
+.. _Autoduck:
+ http://www.helpmaster.com/hlp-developmentaids-autoduck.htm
+
+.. _Web: http://www-cs-faculty.stanford.edu/~knuth/cweb.html
+
+.. _doc.py:
+ http://www.egenix.com/files/python/SoftwareDescriptions.html#doc.py
+
+.. _pythondoc:
+.. _gendoc: http://starship.python.net/crew/danilo/pythondoc/
+
+.. _HappyDoc: http://happydoc.sourceforge.net/
+
+.. _pydoc: http://www.python.org/doc/current/lib/module-pydoc.html
+
+.. _docutils: http://www.tibsnjoan.co.uk/docutils.html
+
+.. _Docutils project: http://docutils.sourceforge.net/
+
+.. _STMinus: http://www.cis.upenn.edu/~edloper/pydoc/
+
+.. _Python Doc-SIG: http://www.python.org/sigs/doc-sig/
+
+
+Copyright
+=========
+
+This document has been placed in the public domain.
+
+
+Acknowledgements
+================
+
+This document borrows ideas from the archives of the `Python
+Doc-SIG`_. Thanks to all members past & present.
+
+
+\f
+..
+ Local Variables:
+ mode: indented-text
+ indent-tabs-mode: nil
+ sentence-end-double-space: t
+ fill-column: 70
+ End:
--- /dev/null
+PEP: 257
+Title: Docstring Conventions
+Version: $Revision: 4564 $
+Last-Modified: $Date: 2006-05-21 22:44:42 +0200 (So, 21. Mai 2006) $
+Authors: David Goodger <goodger@python.org>,
+ Guido van Rossum <guido@python.org>
+Discussions-To: doc-sig@python.org
+Status: Active
+Type: Informational
+Content-Type: text/x-rst
+Created: 29-May-2001
+Post-History: 13-Jun-2001
+
+
+Abstract
+========
+
+This PEP documents the semantics and conventions associated with
+Python docstrings.
+
+
+Rationale
+=========
+
+The aim of this PEP is to standardize the high-level structure of
+docstrings: what they should contain, and how to say it (without
+touching on any markup syntax within docstrings). The PEP contains
+conventions, not laws or syntax.
+
+ "A universal convention supplies all of maintainability, clarity,
+ consistency, and a foundation for good programming habits too.
+ What it doesn't do is insist that you follow it against your will.
+ That's Python!"
+
+ -- Tim Peters on comp.lang.python, 2001-06-16
+
+If you violate these conventions, the worst you'll get is some dirty
+looks. But some software (such as the Docutils_ docstring processing
+system [1]_ [2]_) will be aware of the conventions, so following them
+will get you the best results.
+
+
+Specification
+=============
+
+What is a Docstring?
+--------------------
+
+A docstring is a string literal that occurs as the first statement in
+a module, function, class, or method definition. Such a docstring
+becomes the ``__doc__`` special attribute of that object.
+
+All modules should normally have docstrings, and all functions and
+classes exported by a module should also have docstrings. Public
+methods (including the ``__init__`` constructor) should also have
+docstrings. A package may be documented in the module docstring of
+the ``__init__.py`` file in the package directory.
+
+String literals occurring elsewhere in Python code may also act as
+documentation. They are not recognized by the Python bytecode
+compiler and are not accessible as runtime object attributes (i.e. not
+assigned to ``__doc__``), but two types of extra docstrings may be
+extracted by software tools:
+
+1. String literals occurring immediately after a simple assignment at
+ the top level of a module, class, or ``__init__`` method are called
+ "attribute docstrings".
+
+2. String literals occurring immediately after another docstring are
+ called "additional docstrings".
+
+Please see PEP 258, "Docutils Design Specification" [2]_, for a
+detailed description of attribute and additional docstrings.
+
+XXX Mention docstrings of 2.2 properties.
+
+For consistency, always use ``"""triple double quotes"""`` around
+docstrings. Use ``r"""raw triple double quotes"""`` if you use any
+backslashes in your docstrings. For Unicode docstrings, use
+``u"""Unicode triple-quoted strings"""``.
+
+There are two forms of docstrings: one-liners and multi-line
+docstrings.
+
+
+One-line Docstrings
+--------------------
+
+One-liners are for really obvious cases. They should really fit on
+one line. For example::
+
+ def kos_root():
+ """Return the pathname of the KOS root directory."""
+ global _kos_root
+ if _kos_root: return _kos_root
+ ...
+
+Notes:
+
+- Triple quotes are used even though the string fits on one line.
+ This makes it easy to later expand it.
+
+- The closing quotes are on the same line as the opening quotes. This
+ looks better for one-liners.
+
+- There's no blank line either before or after the docstring.
+
+- The docstring is a phrase ending in a period. It prescribes the
+ function or method's effect as a command ("Do this", "Return that"),
+ not as a description; e.g. don't write "Returns the pathname ...".
+
+- The one-line docstring should NOT be a "signature" reiterating the
+ function/method parameters (which can be obtained by introspection).
+ Don't do::
+
+ def function(a, b):
+ """function(a, b) -> list"""
+
+ This type of docstring is only appropriate for C functions (such as
+ built-ins), where introspection is not possible. However, the
+ nature of the *return value* cannot be determined by introspection,
+ so it should be mentioned. The preferred form for such a docstring
+ would be something like::
+
+ def function(a, b):
+ """Do X and return a list."""
+
+ (Of course "Do X" should be replaced by a useful description!)
+
+
+Multi-line Docstrings
+----------------------
+
+Multi-line docstrings consist of a summary line just like a one-line
+docstring, followed by a blank line, followed by a more elaborate
+description. The summary line may be used by automatic indexing
+tools; it is important that it fits on one line and is separated from
+the rest of the docstring by a blank line. The summary line may be on
+the same line as the opening quotes or on the next line. The entire
+docstring is indented the same as the quotes at its first line (see
+example below).
+
+Insert a blank line before and after all docstrings (one-line or
+multi-line) that document a class -- generally speaking, the class's
+methods are separated from each other by a single blank line, and the
+docstring needs to be offset from the first method by a blank line;
+for symmetry, put a blank line between the class header and the
+docstring. Docstrings documenting functions or methods generally
+don't have this requirement, unless the function or method's body is
+written as a number of blank-line separated sections -- in this case,
+treat the docstring as another section, and precede it with a blank
+line.
+
+The docstring of a script (a stand-alone program) should be usable as
+its "usage" message, printed when the script is invoked with incorrect
+or missing arguments (or perhaps with a "-h" option, for "help").
+Such a docstring should document the script's function and command
+line syntax, environment variables, and files. Usage messages can be
+fairly elaborate (several screens full) and should be sufficient for a
+new user to use the command properly, as well as a complete quick
+reference to all options and arguments for the sophisticated user.
+
+The docstring for a module should generally list the classes,
+exceptions and functions (and any other objects) that are exported by
+the module, with a one-line summary of each. (These summaries
+generally give less detail than the summary line in the object's
+docstring.) The docstring for a package (i.e., the docstring of the
+package's ``__init__.py`` module) should also list the modules and
+subpackages exported by the package.
+
+The docstring for a function or method should summarize its behavior
+and document its arguments, return value(s), side effects, exceptions
+raised, and restrictions on when it can be called (all if applicable).
+Optional arguments should be indicated. It should be documented
+whether keyword arguments are part of the interface.
+
+The docstring for a class should summarize its behavior and list the
+public methods and instance variables. If the class is intended to be
+subclassed, and has an additional interface for subclasses, this
+interface should be listed separately (in the docstring). The class
+constructor should be documented in the docstring for its ``__init__``
+method. Individual methods should be documented by their own
+docstring.
+
+If a class subclasses another class and its behavior is mostly
+inherited from that class, its docstring should mention this and
+summarize the differences. Use the verb "override" to indicate that a
+subclass method replaces a superclass method and does not call the
+superclass method; use the verb "extend" to indicate that a subclass
+method calls the superclass method (in addition to its own behavior).
+
+*Do not* use the Emacs convention of mentioning the arguments of
+functions or methods in upper case in running text. Python is case
+sensitive and the argument names can be used for keyword arguments, so
+the docstring should document the correct argument names. It is best
+to list each argument on a separate line. For example::
+
+ def complex(real=0.0, imag=0.0):
+ """Form a complex number.
+
+ Keyword arguments:
+ real -- the real part (default 0.0)
+ imag -- the imaginary part (default 0.0)
+
+ """
+ if imag == 0.0 and real == 0.0: return complex_zero
+ ...
+
+The BDFL [3]_ recommends inserting a blank line between the last
+paragraph in a multi-line docstring and its closing quotes, placing
+the closing quotes on a line by themselves. This way, Emacs'
+``fill-paragraph`` command can be used on it.
+
+
+Handling Docstring Indentation
+------------------------------
+
+Docstring processing tools will strip a uniform amount of indentation
+from the second and further lines of the docstring, equal to the
+minimum indentation of all non-blank lines after the first line. Any
+indentation in the first line of the docstring (i.e., up to the first
+newline) is insignificant and removed. Relative indentation of later
+lines in the docstring is retained. Blank lines should be removed
+from the beginning and end of the docstring.
+
+Since code is much more precise than words, here is an implementation
+of the algorithm::
+
+ def trim(docstring):
+ if not docstring:
+ return ''
+ # Convert tabs to spaces (following the normal Python rules)
+ # and split into a list of lines:
+ lines = docstring.expandtabs().splitlines()
+ # Determine minimum indentation (first line doesn't count):
+ indent = sys.maxint
+ for line in lines[1:]:
+ stripped = line.lstrip()
+ if stripped:
+ indent = min(indent, len(line) - len(stripped))
+ # Remove indentation (first line is special):
+ trimmed = [lines[0].strip()]
+ if indent < sys.maxint:
+ for line in lines[1:]:
+ trimmed.append(line[indent:].rstrip())
+ # Strip off trailing and leading blank lines:
+ while trimmed and not trimmed[-1]:
+ trimmed.pop()
+ while trimmed and not trimmed[0]:
+ trimmed.pop(0)
+ # Return a single string:
+ return '\n'.join(trimmed)
+
+The docstring in this example contains two newline characters and is
+therefore 3 lines long. The first and last lines are blank::
+
+ def foo():
+ """
+ This is the second line of the docstring.
+ """
+
+To illustrate::
+
+ >>> print repr(foo.__doc__)
+ '\n This is the second line of the docstring.\n '
+ >>> foo.__doc__.splitlines()
+ ['', ' This is the second line of the docstring.', ' ']
+ >>> trim(foo.__doc__)
+ 'This is the second line of the docstring.'
+
+Once trimmed, these docstrings are equivalent::
+
+ def foo():
+ """A multi-line
+ docstring.
+ """
+
+ def bar():
+ """
+ A multi-line
+ docstring.
+ """
+
+
+References and Footnotes
+========================
+
+.. [1] PEP 256, Docstring Processing System Framework, Goodger
+ (http://www.python.org/peps/pep-0256.html)
+
+.. [2] PEP 258, Docutils Design Specification, Goodger
+ (http://www.python.org/peps/pep-0258.html)
+
+.. [3] Guido van Rossum, Python's creator and Benevolent Dictator For
+ Life.
+
+.. _Docutils: http://docutils.sourceforge.net/
+
+.. _Python Style Guide:
+ http://www.python.org/doc/essays/styleguide.html
+
+.. _Doc-SIG: http://www.python.org/sigs/doc-sig/
+
+
+Copyright
+=========
+
+This document has been placed in the public domain.
+
+
+Acknowledgements
+================
+
+The "Specification" text comes mostly verbatim from the `Python Style
+Guide`_ essay by Guido van Rossum.
+
+This document borrows ideas from the archives of the Python Doc-SIG_.
+Thanks to all members past and present.
+
+
+\f
+..
+ Local Variables:
+ mode: indented-text
+ indent-tabs-mode: nil
+ fill-column: 70
+ sentence-end-double-space: t
+ End:
--- /dev/null
+PEP: 258
+Title: Docutils Design Specification
+Version: $Revision: 6154 $
+Last-Modified: $Date: 2009-10-05 21:08:10 +0200 (Mo, 05. Okt 2009) $
+Author: David Goodger <goodger@python.org>
+Discussions-To: <doc-sig@python.org>
+Status: Draft
+Type: Standards Track
+Content-Type: text/x-rst
+Requires: 256, 257
+Created: 31-May-2001
+Post-History: 13-Jun-2001
+
+
+==========
+ Abstract
+==========
+
+This PEP documents design issues and implementation details for
+Docutils, a Python Docstring Processing System (DPS). The rationale
+and high-level concepts of a DPS are documented in PEP 256, "Docstring
+Processing System Framework" [#PEP-256]_. Also see PEP 256 for a
+"Road Map to the Docstring PEPs".
+
+Docutils is being designed modularly so that any of its components can
+be replaced easily. In addition, Docutils is not limited to the
+processing of Python docstrings; it processes standalone documents as
+well, in several contexts.
+
+No changes to the core Python language are required by this PEP. Its
+deliverables consist of a package for the standard library and its
+documentation.
+
+
+===============
+ Specification
+===============
+
+Docutils Project Model
+======================
+
+Project components and data flow::
+
+ +---------------------------+
+ | Docutils: |
+ | docutils.core.Publisher, |
+ | docutils.core.publish_*() |
+ +---------------------------+
+ / | \
+ / | \
+ 1,3,5 / 6 | \ 7
+ +--------+ +-------------+ +--------+
+ | READER | ----> | TRANSFORMER | ====> | WRITER |
+ +--------+ +-------------+ +--------+
+ / \\ |
+ / \\ |
+ 2 / 4 \\ 8 |
+ +-------+ +--------+ +--------+
+ | INPUT | | PARSER | | OUTPUT |
+ +-------+ +--------+ +--------+
+
+The numbers above each component indicate the path a document's data
+takes. Double-width lines between Reader & Parser and between
+Transformer & Writer indicate that data sent along these paths should
+be standard (pure & unextended) Docutils doc trees. Single-width
+lines signify that internal tree extensions or completely unrelated
+representations are possible, but they must be supported at both ends.
+
+
+Publisher
+---------
+
+The ``docutils.core`` module contains a "Publisher" facade class and
+several convenience functions: "publish_cmdline()" (for command-line
+front ends), "publish_file()" (for programmatic use with file-like
+I/O), and "publish_string()" (for programmatic use with string I/O).
+The Publisher class encapsulates the high-level logic of a Docutils
+system. The Publisher class has overall responsibility for
+processing, controlled by the ``Publisher.publish()`` method:
+
+1. Set up internal settings (may include config files & command-line
+ options) and I/O objects.
+
+2. Call the Reader object to read data from the source Input object
+ and parse the data with the Parser object. A document object is
+ returned.
+
+3. Set up and apply transforms via the Transformer object attached to
+ the document.
+
+4. Call the Writer object which translates the document to the final
+ output format and writes the formatted data to the destination
+ Output object. Depending on the Output object, the output may be
+ returned from the Writer, and then from the ``publish()`` method.
+
+Calling the "publish" function (or instantiating a "Publisher" object)
+with component names will result in default behavior. For custom
+behavior (customizing component settings), create custom component
+objects first, and pass *them* to the Publisher or ``publish_*``
+convenience functions.
+
+
+Readers
+-------
+
+Readers understand the input context (where the data is coming from),
+send the whole input or discrete "chunks" to the parser, and provide
+the context to bind the chunks together back into a cohesive whole.
+
+Each reader is a module or package exporting a "Reader" class with a
+"read" method. The base "Reader" class can be found in the
+``docutils/readers/__init__.py`` module.
+
+Most Readers will have to be told what parser to use. So far (see the
+list of examples below), only the Python Source Reader ("PySource";
+still incomplete) will be able to determine the parser on its own.
+
+Responsibilities:
+
+* Get input text from the source I/O.
+
+* Pass the input text to the parser, along with a fresh `document
+ tree`_ root.
+
+Examples:
+
+* Standalone (Raw/Plain): Just read a text file and process it.
+ The reader needs to be told which parser to use.
+
+ The "Standalone Reader" has been implemented in module
+ ``docutils.readers.standalone``.
+
+* Python Source: See `Python Source Reader`_ below. This Reader is
+ currently in development in the Docutils sandbox.
+
+* Email: RFC-822 headers, quoted excerpts, signatures, MIME parts.
+
+* PEP: RFC-822 headers, "PEP xxxx" and "RFC xxxx" conversion to URIs.
+ The "PEP Reader" has been implemented in module
+ ``docutils.readers.pep``; see PEP 287 and PEP 12.
+
+* Wiki: Global reference lookups of "wiki links" incorporated into
+ transforms. (CamelCase only or unrestricted?) Lazy
+ indentation?
+
+* Web Page: As standalone, but recognize meta fields as meta tags.
+ Support for templates of some sort? (After ``<body>``, before
+ ``</body>``?)
+
+* FAQ: Structured "question & answer(s)" constructs.
+
+* Compound document: Merge chapters into a book. Master manifest
+ file?
+
+
+Parsers
+-------
+
+Parsers analyze their input and produce a Docutils `document tree`_.
+They don't know or care anything about the source or destination of
+the data.
+
+Each input parser is a module or package exporting a "Parser" class
+with a "parse" method. The base "Parser" class can be found in the
+``docutils/parsers/__init__.py`` module.
+
+Responsibilities: Given raw input text and a doctree root node,
+populate the doctree by parsing the input text.
+
+Example: The only parser implemented so far is for the
+reStructuredText markup. It is implemented in the
+``docutils/parsers/rst/`` package.
+
+The development and integration of other parsers is possible and
+encouraged.
+
+
+.. _transforms:
+
+Transformer
+-----------
+
+The Transformer class, in ``docutils/transforms/__init__.py``, stores
+transforms and applies them to documents. A transformer object is
+attached to every new document tree. The Publisher_ calls
+``Transformer.apply_transforms()`` to apply all stored transforms to
+the document tree. Transforms change the document tree from one form
+to another, add to the tree, or prune it. Transforms resolve
+references and footnote numbers, process interpreted text, and do
+other context-sensitive processing.
+
+Some transforms are specific to components (Readers, Parser, Writers,
+Input, Output). Standard component-specific transforms are specified
+in the ``default_transforms`` attribute of component classes. After
+the Reader has finished processing, the Publisher_ calls
+``Transformer.populate_from_components()`` with a list of components
+and all default transforms are stored.
+
+Each transform is a class in a module in the ``docutils/transforms/``
+package, a subclass of ``docutils.tranforms.Transform``. Transform
+classes each have a ``default_priority`` attribute which is used by
+the Transformer to apply transforms in order (low to high). The
+default priority can be overridden when adding transforms to the
+Transformer object.
+
+Transformer responsibilities:
+
+* Apply transforms to the document tree, in priority order.
+
+* Store a mapping of component type name ('reader', 'writer', etc.) to
+ component objects. These are used by certain transforms (such as
+ "components.Filter") to determine suitability.
+
+Transform responsibilities:
+
+* Modify a doctree in-place, either purely transforming one structure
+ into another, or adding new structures based on the doctree and/or
+ external data.
+
+Examples of transforms (in the ``docutils/transforms/`` package):
+
+* frontmatter.DocInfo: Conversion of document metadata (bibliographic
+ information).
+
+* references.AnonymousHyperlinks: Resolution of anonymous references
+ to corresponding targets.
+
+* parts.Contents: Generates a table of contents for a document.
+
+* document.Merger: Combining multiple populated doctrees into one.
+ (Not yet implemented or fully understood.)
+
+* document.Splitter: Splits a document into a tree-structure of
+ subdocuments, perhaps by section. It will have to transform
+ references appropriately. (Neither implemented not remotely
+ understood.)
+
+* components.Filter: Includes or excludes elements which depend on a
+ specific Docutils component.
+
+
+Writers
+-------
+
+Writers produce the final output (HTML, XML, TeX, etc.). Writers
+translate the internal `document tree`_ structure into the final data
+format, possibly running Writer-specific transforms_ first.
+
+By the time the document gets to the Writer, it should be in final
+form. The Writer's job is simply (and only) to translate from the
+Docutils doctree structure to the target format. Some small
+transforms may be required, but they should be local and
+format-specific.
+
+Each writer is a module or package exporting a "Writer" class with a
+"write" method. The base "Writer" class can be found in the
+``docutils/writers/__init__.py`` module.
+
+Responsibilities:
+
+* Translate doctree(s) into specific output formats.
+
+ - Transform references into format-native forms.
+
+* Write the translated output to the destination I/O.
+
+Examples:
+
+* XML: Various forms, such as:
+
+ - Docutils XML (an expression of the internal document tree,
+ implemented as ``docutils.writers.docutils_xml``).
+
+ - DocBook (being implemented in the Docutils sandbox).
+
+* HTML (XHTML implemented as ``docutils.writers.html4css1``).
+
+* PDF (a ReportLabs interface is being developed in the Docutils
+ sandbox).
+
+* TeX (a LaTeX Writer is being implemented in the sandbox).
+
+* Docutils-native pseudo-XML (implemented as
+ ``docutils.writers.pseudoxml``, used for testing).
+
+* Plain text
+
+* reStructuredText?
+
+
+Input/Output
+------------
+
+I/O classes provide a uniform API for low-level input and output.
+Subclasses will exist for a variety of input/output mechanisms.
+However, they can be considered an implementation detail. Most
+applications should be satisfied using one of the convenience
+functions associated with the Publisher_.
+
+I/O classes are currently in the preliminary stages; there's a lot of
+work yet to be done. Issues:
+
+* How to represent multi-file input (files & directories) in the API?
+
+* How to represent multi-file output? Perhaps "Writer" variants, one
+ for each output distribution type? Or Output objects with
+ associated transforms?
+
+Responsibilities:
+
+* Read data from the input source (Input objects) or write data to the
+ output destination (Output objects).
+
+Examples of input sources:
+
+* A single file on disk or a stream (implemented as
+ ``docutils.io.FileInput``).
+
+* Multiple files on disk (``MultiFileInput``?).
+
+* Python source files: modules and packages.
+
+* Python strings, as received from a client application
+ (implemented as ``docutils.io.StringInput``).
+
+Examples of output destinations:
+
+* A single file on disk or a stream (implemented as
+ ``docutils.io.FileOutput``).
+
+* A tree of directories and files on disk.
+
+* A Python string, returned to a client application (implemented as
+ ``docutils.io.StringOutput``).
+
+* No output; useful for programmatic applications where only a portion
+ of the normal output is to be used (implemented as
+ ``docutils.io.NullOutput``).
+
+* A single tree-shaped data structure in memory.
+
+* Some other set of data structures in memory.
+
+
+Docutils Package Structure
+==========================
+
+* Package "docutils".
+
+ - Module "__init__.py" contains: class "Component", a base class for
+ Docutils components; class "SettingsSpec", a base class for
+ specifying runtime settings (used by docutils.frontend); and class
+ "TransformSpec", a base class for specifying transforms.
+
+ - Module "docutils.core" contains facade class "Publisher" and
+ convenience functions. See `Publisher`_ above.
+
+ - Module "docutils.frontend" provides runtime settings support, for
+ programmatic use and front-end tools (including configuration file
+ support, and command-line argument and option processing).
+
+ - Module "docutils.io" provides a uniform API for low-level input
+ and output. See `Input/Output`_ above.
+
+ - Module "docutils.nodes" contains the Docutils document tree
+ element class library plus tree-traversal Visitor pattern base
+ classes. See `Document Tree`_ below.
+
+ - Module "docutils.statemachine" contains a finite state machine
+ specialized for regular-expression-based text filters and parsers.
+ The reStructuredText parser implementation is based on this
+ module.
+
+ - Module "docutils.urischemes" contains a mapping of known URI
+ schemes ("http", "ftp", "mail", etc.).
+
+ - Module "docutils.utils" contains utility functions and classes,
+ including a logger class ("Reporter"; see `Error Handling`_
+ below).
+
+ - Package "docutils.parsers": markup parsers_.
+
+ - Function "get_parser_class(parser_name)" returns a parser module
+ by name. Class "Parser" is the base class of specific parsers.
+ (``docutils/parsers/__init__.py``)
+
+ - Package "docutils.parsers.rst": the reStructuredText parser.
+
+ - Alternate markup parsers may be added.
+
+ See `Parsers`_ above.
+
+ - Package "docutils.readers": context-aware input readers.
+
+ - Function "get_reader_class(reader_name)" returns a reader module
+ by name or alias. Class "Reader" is the base class of specific
+ readers. (``docutils/readers/__init__.py``)
+
+ - Module "docutils.readers.standalone" reads independent document
+ files.
+
+ - Module "docutils.readers.pep" reads PEPs (Python Enhancement
+ Proposals).
+
+ - Module "docutils.readers.doctree" is used to re-read a
+ previously stored document tree for reprocessing.
+
+ - Readers to be added for: Python source code (structure &
+ docstrings), email, FAQ, and perhaps Wiki and others.
+
+ See `Readers`_ above.
+
+ - Package "docutils.writers": output format writers.
+
+ - Function "get_writer_class(writer_name)" returns a writer module
+ by name. Class "Writer" is the base class of specific writers.
+ (``docutils/writers/__init__.py``)
+
+ - Package "docutils.writers.html4css1" is a simple HyperText
+ Markup Language document tree writer for HTML 4.01 and CSS1.
+
+ - Package "docutils.writers.pep_html" generates HTML from
+ reStructuredText PEPs.
+
+ - Package "docutils.writers.s5_html" generates S5/HTML slide
+ shows.
+
+ - Package "docutils.writers.latex2e" writes LaTeX.
+
+ - Package "docutils.writers.newlatex2e" also writes LaTeX; it is a
+ new implementation.
+
+ - Module "docutils.writers.docutils_xml" writes the internal
+ document tree in XML form.
+
+ - Module "docutils.writers.pseudoxml" is a simple internal
+ document tree writer; it writes indented pseudo-XML.
+
+ - Module "docutils.writers.null" is a do-nothing writer; it is
+ used for specialized purposes such as storing the internal
+ document tree.
+
+ - Writers to be added: HTML 3.2 or 4.01-loose, XML (various forms,
+ such as DocBook), PDF, plaintext, reStructuredText, and perhaps
+ others.
+
+ Subpackages of "docutils.writers" contain modules and data files
+ (such as stylesheets) that support the individual writers.
+
+ See `Writers`_ above.
+
+ - Package "docutils.transforms": tree transform classes.
+
+ - Class "Transformer" stores transforms and applies them to
+ document trees. (``docutils/transforms/__init__.py``)
+
+ - Class "Transform" is the base class of specific transforms.
+ (``docutils/transforms/__init__.py``)
+
+ - Each module contains related transform classes.
+
+ See `Transforms`_ above.
+
+ - Package "docutils.languages": Language modules contain
+ language-dependent strings and mappings. They are named for their
+ language identifier (as defined in `Choice of Docstring Format`_
+ below), converting dashes to underscores.
+
+ - Function "get_language(language_code)", returns matching
+ language module. (``docutils/languages/__init__.py``)
+
+ - Modules: en.py (English), de.py (German), fr.py (French), it.py
+ (Italian), sk.py (Slovak), sv.py (Swedish).
+
+ - Other languages to be added.
+
+* Third-party modules: "extras" directory. These modules are
+ installed only if they're not already present in the Python
+ installation.
+
+ - ``extras/roman.py`` contains Roman numeral conversion routines.
+
+
+Front-End Tools
+===============
+
+The ``tools/`` directory contains several front ends for common
+Docutils processing. See `Docutils Front-End Tools`_ for details.
+
+.. _Docutils Front-End Tools:
+ http://docutils.sourceforge.net/docs/user/tools.html
+
+
+Document Tree
+=============
+
+A single intermediate data structure is used internally by Docutils,
+in the interfaces between components; it is defined in the
+``docutils.nodes`` module. It is not required that this data
+structure be used *internally* by any of the components, just
+*between* components as outlined in the diagram in the `Docutils
+Project Model`_ above.
+
+Custom node types are allowed, provided that either (a) a transform
+converts them to standard Docutils nodes before they reach the Writer
+proper, or (b) the custom node is explicitly supported by certain
+Writers, and is wrapped in a filtered "pending" node. An example of
+condition (a) is the `Python Source Reader`_ (see below), where a
+"stylist" transform converts custom nodes. The HTML ``<meta>`` tag is
+an example of condition (b); it is supported by the HTML Writer but
+not by others. The reStructuredText "meta" directive creates a
+"pending" node, which contains knowledge that the embedded "meta" node
+can only be handled by HTML-compatible writers. The "pending" node is
+resolved by the ``docutils.transforms.components.Filter`` transform,
+which checks that the calling writer supports HTML; if it doesn't, the
+"pending" node (and enclosed "meta" node) is removed from the
+document.
+
+The document tree data structure is similar to a DOM tree, but with
+specific node names (classes) instead of DOM's generic nodes. The
+schema is documented in an XML DTD (eXtensible Markup Language
+Document Type Definition), which comes in two parts:
+
+* the Docutils Generic DTD, docutils.dtd_, and
+
+* the OASIS Exchange Table Model, soextbl.dtd_.
+
+The DTD defines a rich set of elements, suitable for many input and
+output formats. The DTD retains all information necessary to
+reconstruct the original input text, or a reasonable facsimile
+thereof.
+
+See `The Docutils Document Tree`_ for details (incomplete).
+
+
+Error Handling
+==============
+
+When the parser encounters an error in markup, it inserts a system
+message (DTD element "system_message"). There are five levels of
+system messages:
+
+* Level-0, "DEBUG": an internal reporting issue. There is no effect
+ on the processing. Level-0 system messages are handled separately
+ from the others.
+
+* Level-1, "INFO": a minor issue that can be ignored. There is little
+ or no effect on the processing. Typically level-1 system messages
+ are not reported.
+
+* Level-2, "WARNING": an issue that should be addressed. If ignored,
+ there may be minor problems with the output. Typically level-2
+ system messages are reported but do not halt processing.
+
+* Level-3, "ERROR": a major issue that should be addressed. If
+ ignored, the output will contain unpredictable errors. Typically
+ level-3 system messages are reported but do not halt processing.
+
+* Level-4, "SEVERE": a critical error that must be addressed.
+ Typically level-4 system messages are turned into exceptions which
+ do halt processing. If ignored, the output will contain severe
+ errors.
+
+Although the initial message levels were devised independently, they
+have a strong correspondence to `VMS error condition severity
+levels`_; the names in quotes for levels 1 through 4 were borrowed
+from VMS. Error handling has since been influenced by the `log4j
+project`_.
+
+
+Python Source Reader
+====================
+
+The Python Source Reader ("PySource") is the Docutils component that
+reads Python source files, extracts docstrings in context, then
+parses, links, and assembles the docstrings into a cohesive whole. It
+is a major and non-trivial component, currently under experimental
+development in the Docutils sandbox. High-level design issues are
+presented here.
+
+
+Processing Model
+----------------
+
+This model will evolve over time, incorporating experience and
+discoveries.
+
+1. The PySource Reader uses an Input class to read in Python packages
+ and modules, into a tree of strings.
+
+2. The Python modules are parsed, converting the tree of strings into
+ a tree of abstract syntax trees with docstring nodes.
+
+3. The abstract syntax trees are converted into an internal
+ representation of the packages/modules. Docstrings are extracted,
+ as well as code structure details. See `AST Mining`_ below.
+ Namespaces are constructed for lookup in step 6.
+
+4. One at a time, the docstrings are parsed, producing standard
+ Docutils doctrees.
+
+5. PySource assembles all the individual docstrings' doctrees into a
+ Python-specific custom Docutils tree paralleling the
+ package/module/class structure; this is a custom Reader-specific
+ internal representation (see the `Docutils Python Source DTD`_).
+ Namespaces must be merged: Python identifiers, hyperlink targets.
+
+6. Cross-references from docstrings (interpreted text) to Python
+ identifiers are resolved according to the Python namespace lookup
+ rules. See `Identifier Cross-References`_ below.
+
+7. A "Stylist" transform is applied to the custom doctree (by the
+ Transformer_), custom nodes are rendered using standard nodes as
+ primitives, and a standard document tree is emitted. See `Stylist
+ Transforms`_ below.
+
+8. Other transforms are applied to the standard doctree by the
+ Transformer_.
+
+9. The standard doctree is sent to a Writer, which translates the
+ document into a concrete format (HTML, PDF, etc.).
+
+10. The Writer uses an Output class to write the resulting data to its
+ destination (disk file, directories and files, etc.).
+
+
+AST Mining
+----------
+
+Abstract Syntax Tree mining code will be written (or adapted) that
+scans a parsed Python module, and returns an ordered tree containing
+the names, docstrings (including attribute and additional docstrings;
+see below), and additional info (in parentheses below) of all of the
+following objects:
+
+* packages
+* modules
+* module attributes (+ initial values)
+* classes (+ inheritance)
+* class attributes (+ initial values)
+* instance attributes (+ initial values)
+* methods (+ parameters & defaults)
+* functions (+ parameters & defaults)
+
+(Extract comments too? For example, comments at the start of a module
+would be a good place for bibliographic field lists.)
+
+In order to evaluate interpreted text cross-references, namespaces for
+each of the above will also be required.
+
+See the python-dev/docstring-develop thread "AST mining", started on
+2001-08-14.
+
+
+Docstring Extraction Rules
+--------------------------
+
+1. What to examine:
+
+ a) If the "``__all__``" variable is present in the module being
+ documented, only identifiers listed in "``__all__``" are
+ examined for docstrings.
+
+ b) In the absence of "``__all__``", all identifiers are examined,
+ except those whose names are private (names begin with "_" but
+ don't begin and end with "__").
+
+ c) 1a and 1b can be overridden by runtime settings.
+
+2. Where:
+
+ Docstrings are string literal expressions, and are recognized in
+ the following places within Python modules:
+
+ a) At the beginning of a module, function definition, class
+ definition, or method definition, after any comments. This is
+ the standard for Python ``__doc__`` attributes.
+
+ b) Immediately following a simple assignment at the top level of a
+ module, class definition, or ``__init__`` method definition,
+ after any comments. See `Attribute Docstrings`_ below.
+
+ c) Additional string literals found immediately after the
+ docstrings in (a) and (b) will be recognized, extracted, and
+ concatenated. See `Additional Docstrings`_ below.
+
+ d) @@@ 2.2-style "properties" with attribute docstrings? Wait for
+ syntax?
+
+3. How:
+
+ Whenever possible, Python modules should be parsed by Docutils, not
+ imported. There are several reasons:
+
+ - Importing untrusted code is inherently insecure.
+
+ - Information from the source is lost when using introspection to
+ examine an imported module, such as comments and the order of
+ definitions.
+
+ - Docstrings are to be recognized in places where the byte-code
+ compiler ignores string literal expressions (2b and 2c above),
+ meaning importing the module will lose these docstrings.
+
+ Of course, standard Python parsing tools such as the "parser"
+ library module should be used.
+
+ When the Python source code for a module is not available
+ (i.e. only the ``.pyc`` file exists) or for C extension modules, to
+ access docstrings the module can only be imported, and any
+ limitations must be lived with.
+
+Since attribute docstrings and additional docstrings are ignored by
+the Python byte-code compiler, no namespace pollution or runtime bloat
+will result from their use. They are not assigned to ``__doc__`` or
+to any other attribute. The initial parsing of a module may take a
+slight performance hit.
+
+
+Attribute Docstrings
+''''''''''''''''''''
+
+(This is a simplified version of PEP 224 [#PEP-224]_.)
+
+A string literal immediately following an assignment statement is
+interpreted by the docstring extraction machinery as the docstring of
+the target of the assignment statement, under the following
+conditions:
+
+1. The assignment must be in one of the following contexts:
+
+ a) At the top level of a module (i.e., not nested inside a compound
+ statement such as a loop or conditional): a module attribute.
+
+ b) At the top level of a class definition: a class attribute.
+
+ c) At the top level of the "``__init__``" method definition of a
+ class: an instance attribute. Instance attributes assigned in
+ other methods are assumed to be implementation details. (@@@
+ ``__new__`` methods?)
+
+ d) A function attribute assignment at the top level of a module or
+ class definition.
+
+ Since each of the above contexts are at the top level (i.e., in the
+ outermost suite of a definition), it may be necessary to place
+ dummy assignments for attributes assigned conditionally or in a
+ loop.
+
+2. The assignment must be to a single target, not to a list or a tuple
+ of targets.
+
+3. The form of the target:
+
+ a) For contexts 1a and 1b above, the target must be a simple
+ identifier (not a dotted identifier, a subscripted expression,
+ or a sliced expression).
+
+ b) For context 1c above, the target must be of the form
+ "``self.attrib``", where "``self``" matches the "``__init__``"
+ method's first parameter (the instance parameter) and "attrib"
+ is a simple identifier as in 3a.
+
+ c) For context 1d above, the target must be of the form
+ "``name.attrib``", where "``name``" matches an already-defined
+ function or method name and "attrib" is a simple identifier as
+ in 3a.
+
+Blank lines may be used after attribute docstrings to emphasize the
+connection between the assignment and the docstring.
+
+Examples::
+
+ g = 'module attribute (module-global variable)'
+ """This is g's docstring."""
+
+ class AClass:
+
+ c = 'class attribute'
+ """This is AClass.c's docstring."""
+
+ def __init__(self):
+ """Method __init__'s docstring."""
+
+ self.i = 'instance attribute'
+ """This is self.i's docstring."""
+
+ def f(x):
+ """Function f's docstring."""
+ return x**2
+
+ f.a = 1
+ """Function attribute f.a's docstring."""
+
+
+Additional Docstrings
+'''''''''''''''''''''
+
+(This idea was adapted from PEP 216 [#PEP-216]_.)
+
+Many programmers would like to make extensive use of docstrings for
+API documentation. However, docstrings do take up space in the
+running program, so some programmers are reluctant to "bloat up" their
+code. Also, not all API documentation is applicable to interactive
+environments, where ``__doc__`` would be displayed.
+
+Docutils' docstring extraction tools will concatenate all string
+literal expressions which appear at the beginning of a definition or
+after a simple assignment. Only the first strings in definitions will
+be available as ``__doc__``, and can be used for brief usage text
+suitable for interactive sessions; subsequent string literals and all
+attribute docstrings are ignored by the Python byte-code compiler and
+may contain more extensive API information.
+
+Example::
+
+ def function(arg):
+ """This is __doc__, function's docstring."""
+ """
+ This is an additional docstring, ignored by the byte-code
+ compiler, but extracted by Docutils.
+ """
+ pass
+
+.. topic:: Issue: ``from __future__ import``
+
+ This would break "``from __future__ import``" statements introduced
+ in Python 2.1 for multiple module docstrings (main docstring plus
+ additional docstring(s)). The Python Reference Manual specifies:
+
+ A future statement must appear near the top of the module. The
+ only lines that can appear before a future statement are:
+
+ * the module docstring (if any),
+ * comments,
+ * blank lines, and
+ * other future statements.
+
+ Resolution?
+
+ 1. Should we search for docstrings after a ``__future__``
+ statement? Very ugly.
+
+ 2. Redefine ``__future__`` statements to allow multiple preceding
+ string literals?
+
+ 3. Or should we not even worry about this? There probably
+ shouldn't be ``__future__`` statements in production code, after
+ all. Perhaps modules with ``__future__`` statements will simply
+ have to put up with the single-docstring limitation.
+
+
+Choice of Docstring Format
+--------------------------
+
+Rather than force everyone to use a single docstring format, multiple
+input formats are allowed by the processing system. A special
+variable, ``__docformat__``, may appear at the top level of a module
+before any function or class definitions. Over time or through
+decree, a standard format or set of formats should emerge.
+
+A module's ``__docformat__`` variable only applies to the objects
+defined in the module's file. In particular, the ``__docformat__``
+variable in a package's ``__init__.py`` file does not apply to objects
+defined in subpackages and submodules.
+
+The ``__docformat__`` variable is a string containing the name of the
+format being used, a case-insensitive string matching the input
+parser's module or package name (i.e., the same name as required to
+"import" the module or package), or a registered alias. If no
+``__docformat__`` is specified, the default format is "plaintext" for
+now; this may be changed to the standard format if one is ever
+established.
+
+The ``__docformat__`` string may contain an optional second field,
+separated from the format name (first field) by a single space: a
+case-insensitive language identifier as defined in RFC 1766. A
+typical language identifier consists of a 2-letter language code from
+`ISO 639`_ (3-letter codes used only if no 2-letter code exists; RFC
+1766 is currently being revised to allow 3-letter codes). If no
+language identifier is specified, the default is "en" for English.
+The language identifier is passed to the parser and can be used for
+language-dependent markup features.
+
+
+Identifier Cross-References
+---------------------------
+
+In Python docstrings, interpreted text is used to classify and mark up
+program identifiers, such as the names of variables, functions,
+classes, and modules. If the identifier alone is given, its role is
+inferred implicitly according to the Python namespace lookup rules.
+For functions and methods (even when dynamically assigned),
+parentheses ('()') may be included::
+
+ This function uses `another()` to do its work.
+
+For class, instance and module attributes, dotted identifiers are used
+when necessary. For example (using reStructuredText markup)::
+
+ class Keeper(Storer):
+
+ """
+ Extend `Storer`. Class attribute `instances` keeps track
+ of the number of `Keeper` objects instantiated.
+ """
+
+ instances = 0
+ """How many `Keeper` objects are there?"""
+
+ def __init__(self):
+ """
+ Extend `Storer.__init__()` to keep track of instances.
+
+ Keep count in `Keeper.instances`, data in `self.data`.
+ """
+ Storer.__init__(self)
+ Keeper.instances += 1
+
+ self.data = []
+ """Store data in a list, most recent last."""
+
+ def store_data(self, data):
+ """
+ Extend `Storer.store_data()`; append new `data` to a
+ list (in `self.data`).
+ """
+ self.data = data
+
+Each of the identifiers quoted with backquotes ("`") will become
+references to the definitions of the identifiers themselves.
+
+
+Stylist Transforms
+------------------
+
+Stylist transforms are specialized transforms specific to the PySource
+Reader. The PySource Reader doesn't have to make any decisions as to
+style; it just produces a logically constructed document tree, parsed
+and linked, including custom node types. Stylist transforms
+understand the custom nodes created by the Reader and convert them
+into standard Docutils nodes.
+
+Multiple Stylist transforms may be implemented and one can be chosen
+at runtime (through a "--style" or "--stylist" command-line option).
+Each Stylist transform implements a different layout or style; thus
+the name. They decouple the context-understanding part of the Reader
+from the layout-generating part of processing, resulting in a more
+flexible and robust system. This also serves to "separate style from
+content", the SGML/XML ideal.
+
+By keeping the piece of code that does the styling small and modular,
+it becomes much easier for people to roll their own styles. The
+"barrier to entry" is too high with existing tools; extracting the
+stylist code will lower the barrier considerably.
+
+
+==========================
+ References and Footnotes
+==========================
+
+.. [#PEP-256] PEP 256, Docstring Processing System Framework, Goodger
+ (http://www.python.org/peps/pep-0256.html)
+
+.. [#PEP-224] PEP 224, Attribute Docstrings, Lemburg
+ (http://www.python.org/peps/pep-0224.html)
+
+.. [#PEP-216] PEP 216, Docstring Format, Zadka
+ (http://www.python.org/peps/pep-0216.html)
+
+.. _docutils.dtd:
+ http://docutils.sourceforge.net/docs/ref/docutils.dtd
+
+.. _soextbl.dtd:
+ http://docutils.sourceforge.net/docs/ref/soextblx.dtd
+
+.. _The Docutils Document Tree:
+ http://docutils.sourceforge.net/docs/ref/doctree.html
+
+.. _VMS error condition severity levels:
+ http://www.openvms.compaq.com:8000/73final/5841/841pro_027.html
+ #error_cond_severity
+
+.. _log4j project: http://logging.apache.org/log4j/docs/index.html
+
+.. _Docutils Python Source DTD:
+ http://docutils.sourceforge.net/docs/dev/pysource.dtd
+
+.. _ISO 639: http://www.loc.gov/standards/iso639-2/englangn.html
+
+.. _Python Doc-SIG: http://www.python.org/sigs/doc-sig/
+
+
+
+==================
+ Project Web Site
+==================
+
+A SourceForge project has been set up for this work at
+http://docutils.sourceforge.net/.
+
+
+===========
+ Copyright
+===========
+
+This document has been placed in the public domain.
+
+
+==================
+ Acknowledgements
+==================
+
+This document borrows ideas from the archives of the `Python
+Doc-SIG`_. Thanks to all members past & present.
+
+
+\f
+..
+ Local Variables:
+ mode: indented-text
+ indent-tabs-mode: nil
+ sentence-end-double-space: t
+ fill-column: 70
+ End:
--- /dev/null
+PEP: 287
+Title: reStructuredText Docstring Format
+Version: $Revision: 4564 $
+Last-Modified: $Date: 2006-05-21 22:44:42 +0200 (So, 21. Mai 2006) $
+Author: David Goodger <goodger@python.org>
+Discussions-To: <doc-sig@python.org>
+Status: Draft
+Type: Informational
+Content-Type: text/x-rst
+Created: 25-Mar-2002
+Post-History: 02-Apr-2002
+Replaces: 216
+
+
+Abstract
+========
+
+When plaintext hasn't been expressive enough for inline documentation,
+Python programmers have sought out a format for docstrings. This PEP
+proposes that the `reStructuredText markup`_ be adopted as a standard
+markup format for structured plaintext documentation in Python
+docstrings, and for PEPs and ancillary documents as well.
+reStructuredText is a rich and extensible yet easy-to-read,
+what-you-see-is-what-you-get plaintext markup syntax.
+
+Only the low-level syntax of docstrings is addressed here. This PEP
+is not concerned with docstring semantics or processing at all (see
+PEP 256 for a "Road Map to the Docstring PEPs"). Nor is it an attempt
+to deprecate pure plaintext docstrings, which are always going to be
+legitimate. The reStructuredText markup is an alternative for those
+who want more expressive docstrings.
+
+
+Benefits
+========
+
+Programmers are by nature a lazy breed. We reuse code with functions,
+classes, modules, and subsystems. Through its docstring syntax,
+Python allows us to document our code from within. The "holy grail"
+of the Python Documentation Special Interest Group (Doc-SIG_) has been
+a markup syntax and toolset to allow auto-documentation, where the
+docstrings of Python systems can be extracted in context and processed
+into useful, high-quality documentation for multiple purposes.
+
+Document markup languages have three groups of customers: the authors
+who write the documents, the software systems that process the data,
+and the readers, who are the final consumers and the most important
+group. Most markups are designed for the authors and software
+systems; readers are only meant to see the processed form, either on
+paper or via browser software. ReStructuredText is different: it is
+intended to be easily readable in source form, without prior knowledge
+of the markup. ReStructuredText is entirely readable in plaintext
+format, and many of the markup forms match common usage (e.g.,
+``*emphasis*``), so it reads quite naturally. Yet it is rich enough
+to produce complex documents, and extensible so that there are few
+limits. Of course, to write reStructuredText documents some prior
+knowledge is required.
+
+The markup offers functionality and expressivity, while maintaining
+easy readability in the source text. The processed form (HTML etc.)
+makes it all accessible to readers: inline live hyperlinks; live links
+to and from footnotes; automatic tables of contents (with live
+links!); tables; images for diagrams etc.; pleasant, readable styled
+text.
+
+The reStructuredText parser is available now, part of the Docutils_
+project. Standalone reStructuredText documents and PEPs can be
+converted to HTML; other output format writers are being worked on and
+will become available over time. Work is progressing on a Python
+source "Reader" which will implement auto-documentation from
+docstrings. Authors of existing auto-documentation tools are
+encouraged to integrate the reStructuredText parser into their
+projects, or better yet, to join forces to produce a world-class
+toolset for the Python standard library.
+
+Tools will become available in the near future, which will allow
+programmers to generate HTML for online help, XML for multiple
+purposes, and eventually PDF, DocBook, and LaTeX for printed
+documentation, essentially "for free" from the existing docstrings.
+The adoption of a standard will, at the very least, benefit docstring
+processing tools by preventing further "reinventing the wheel".
+
+Eventually PyDoc, the one existing standard auto-documentation tool,
+could have reStructuredText support added. In the interim it will
+have no problem with reStructuredText markup, since it treats all
+docstrings as preformatted plaintext.
+
+
+Goals
+=====
+
+These are the generally accepted goals for a docstring format, as
+discussed in the Doc-SIG:
+
+1. It must be readable in source form by the casual observer.
+
+2. It must be easy to type with any standard text editor.
+
+3. It must not need to contain information which can be deduced from
+ parsing the module.
+
+4. It must contain sufficient information (structure) so it can be
+ converted to any reasonable markup format.
+
+5. It must be possible to write a module's entire documentation in
+ docstrings, without feeling hampered by the markup language.
+
+reStructuredText meets and exceeds all of these goals, and sets its
+own goals as well, even more stringent. See `Docstring-Significant
+Features`_ below.
+
+The goals of this PEP are as follows:
+
+1. To establish reStructuredText as a standard structured plaintext
+ format for docstrings (inline documentation of Python modules and
+ packages), PEPs, README-type files and other standalone documents.
+ "Accepted" status will be sought through Python community consensus
+ and eventual BDFL pronouncement.
+
+ Please note that reStructuredText is being proposed as *a*
+ standard, not *the only* standard. Its use will be entirely
+ optional. Those who don't want to use it need not.
+
+2. To solicit and address any related concerns raised by the Python
+ community.
+
+3. To encourage community support. As long as multiple competing
+ markups are out there, the development community remains fractured.
+ Once a standard exists, people will start to use it, and momentum
+ will inevitably gather.
+
+4. To consolidate efforts from related auto-documentation projects.
+ It is hoped that interested developers will join forces and work on
+ a joint/merged/common implementation.
+
+Once reStructuredText is a Python standard, effort can be focused on
+tools instead of arguing for a standard. Python needs a standard set
+of documentation tools.
+
+With regard to PEPs, one or both of the following strategies may be
+applied:
+
+a) Keep the existing PEP section structure constructs (one-line
+ section headers, indented body text). Subsections can either be
+ forbidden, or supported with reStructuredText-style underlined
+ headers in the indented body text.
+
+b) Replace the PEP section structure constructs with the
+ reStructuredText syntax. Section headers will require underlines,
+ subsections will be supported out of the box, and body text need
+ not be indented (except for block quotes).
+
+Strategy (b) is recommended, and its implementation is complete.
+
+Support for RFC 2822 headers has been added to the reStructuredText
+parser for PEPs (unambiguous given a specific context: the first
+contiguous block of the document). It may be desired to concretely
+specify what over/underline styles are allowed for PEP section
+headers, for uniformity.
+
+
+Rationale
+=========
+
+The lack of a standard syntax for docstrings has hampered the
+development of standard tools for extracting and converting docstrings
+into documentation in standard formats (e.g., HTML, DocBook, TeX).
+There have been a number of proposed markup formats and variations,
+and many tools tied to these proposals, but without a standard
+docstring format they have failed to gain a strong following and/or
+floundered half-finished.
+
+Throughout the existence of the Doc-SIG, consensus on a single
+standard docstring format has never been reached. A lightweight,
+implicit markup has been sought, for the following reasons (among
+others):
+
+1. Docstrings written within Python code are available from within the
+ interactive interpreter, and can be "print"ed. Thus the use of
+ plaintext for easy readability.
+
+2. Programmers want to add structure to their docstrings, without
+ sacrificing raw docstring readability. Unadorned plaintext cannot
+ be transformed ("up-translated") into useful structured formats.
+
+3. Explicit markup (like XML or TeX) is widely considered unreadable
+ by the uninitiated.
+
+4. Implicit markup is aesthetically compatible with the clean and
+ minimalist Python syntax.
+
+Many alternative markups for docstrings have been proposed on the
+Doc-SIG over the years; a representative sample is listed below. Each
+is briefly analyzed in terms of the goals stated above. Please note
+that this is *not* intended to be an exclusive list of all existing
+markup systems; there are many other markups (Texinfo, Doxygen, TIM,
+YODL, AFT, ...) which are not mentioned.
+
+- XML_, SGML_, DocBook_, HTML_, XHTML_
+
+ XML and SGML are explicit, well-formed meta-languages suitable for
+ all kinds of documentation. XML is a variant of SGML. They are
+ best used behind the scenes, because to untrained eyes they are
+ verbose, difficult to type, and too cluttered to read comfortably as
+ source. DocBook, HTML, and XHTML are all applications of SGML
+ and/or XML, and all share the same basic syntax and the same
+ shortcomings.
+
+- TeX_
+
+ TeX is similar to XML/SGML in that it's explicit, but not very easy
+ to write, and not easy for the uninitiated to read.
+
+- `Perl POD`_
+
+ Most Perl modules are documented in a format called POD (Plain Old
+ Documentation). This is an easy-to-type, very low level format with
+ strong integration with the Perl parser. Many tools exist to turn
+ POD documentation into other formats: info, HTML and man pages,
+ among others. However, the POD syntax takes after Perl itself in
+ terms of readability.
+
+- JavaDoc_
+
+ Special comments before Java classes and functions serve to document
+ the code. A program to extract these, and turn them into HTML
+ documentation is called javadoc, and is part of the standard Java
+ distribution. However, JavaDoc has a very intimate relationship
+ with HTML, using HTML tags for most markup. Thus it shares the
+ readability problems of HTML.
+
+- Setext_, StructuredText_
+
+ Early on, variants of Setext (Structure Enhanced Text), including
+ Zope Corp's StructuredText, were proposed for Python docstring
+ formatting. Hereafter these variants will collectively be called
+ "STexts". STexts have the advantage of being easy to read without
+ special knowledge, and relatively easy to write.
+
+ Although used by some (including in most existing Python
+ auto-documentation tools), until now STexts have failed to become
+ standard because:
+
+ - STexts have been incomplete. Lacking "essential" constructs that
+ people want to use in their docstrings, STexts are rendered less
+ than ideal. Note that these "essential" constructs are not
+ universal; everyone has their own requirements.
+
+ - STexts have been sometimes surprising. Bits of text are
+ unexpectedly interpreted as being marked up, leading to user
+ frustration.
+
+ - SText implementations have been buggy.
+
+ - Most STexts have have had no formal specification except for the
+ implementation itself. A buggy implementation meant a buggy spec,
+ and vice-versa.
+
+ - There has been no mechanism to get around the SText markup rules
+ when a markup character is used in a non-markup context. In other
+ words, no way to escape markup.
+
+Proponents of implicit STexts have vigorously opposed proposals for
+explicit markup (XML, HTML, TeX, POD, etc.), and the debates have
+continued off and on since 1996 or earlier.
+
+reStructuredText is a complete revision and reinterpretation of the
+SText idea, addressing all of the problems listed above.
+
+
+Specification
+=============
+
+The specification and user documentaton for reStructuredText is
+quite extensive. Rather than repeating or summarizing it all
+here, links to the originals are provided.
+
+Please first take a look at `A ReStructuredText Primer`_, a short and
+gentle introduction. The `Quick reStructuredText`_ user reference
+quickly summarizes all of the markup constructs. For complete and
+extensive details, please refer to the following documents:
+
+- `An Introduction to reStructuredText`_
+
+- `reStructuredText Markup Specification`_
+
+- `reStructuredText Directives`_
+
+In addition, `Problems With StructuredText`_ explains many markup
+decisions made with regards to StructuredText, and `A Record of
+reStructuredText Syntax Alternatives`_ records markup decisions made
+independently.
+
+
+Docstring-Significant Features
+==============================
+
+- A markup escaping mechanism.
+
+ Backslashes (``\``) are used to escape markup characters when needed
+ for non-markup purposes. However, the inline markup recognition
+ rules have been constructed in order to minimize the need for
+ backslash-escapes. For example, although asterisks are used for
+ *emphasis*, in non-markup contexts such as "*" or "(*)" or "x * y",
+ the asterisks are not interpreted as markup and are left unchanged.
+ For many non-markup uses of backslashes (e.g., describing regular
+ expressions), inline literals or literal blocks are applicable; see
+ the next item.
+
+- Markup to include Python source code and Python interactive
+ sessions: inline literals, literal blocks, and doctest blocks.
+
+ Inline literals use ``double-backquotes`` to indicate program I/O or
+ code snippets. No markup interpretation (including backslash-escape
+ [``\``] interpretation) is done within inline literals.
+
+ Literal blocks (block-level literal text, such as code excerpts or
+ ASCII graphics) are indented, and indicated with a double-colon
+ ("::") at the end of the preceding paragraph (right here -->)::
+
+ if literal_block:
+ text = 'is left as-is'
+ spaces_and_linebreaks = 'are preserved'
+ markup_processing = None
+
+ Doctest blocks begin with ">>> " and end with a blank line. Neither
+ indentation nor literal block double-colons are required. For
+ example::
+
+ Here's a doctest block:
+
+ >>> print 'Python-specific usage examples; begun with ">>>"'
+ Python-specific usage examples; begun with ">>>"
+ >>> print '(cut and pasted from interactive sessions)'
+ (cut and pasted from interactive sessions)
+
+- Markup that isolates a Python identifier: interpreted text.
+
+ Text enclosed in single backquotes is recognized as "interpreted
+ text", whose interpretation is application-dependent. In the
+ context of a Python docstring, the default interpretation of
+ interpreted text is as Python identifiers. The text will be marked
+ up with a hyperlink connected to the documentation for the
+ identifier given. Lookup rules are the same as in Python itself:
+ LGB namespace lookups (local, global, builtin). The "role" of the
+ interpreted text (identifying a class, module, function, etc.) is
+ determined implicitly from the namespace lookup. For example::
+
+ class Keeper(Storer):
+
+ """
+ Keep data fresher longer.
+
+ Extend `Storer`. Class attribute `instances` keeps track
+ of the number of `Keeper` objects instantiated.
+ """
+
+ instances = 0
+ """How many `Keeper` objects are there?"""
+
+ def __init__(self):
+ """
+ Extend `Storer.__init__()` to keep track of
+ instances. Keep count in `self.instances` and data
+ in `self.data`.
+ """
+ Storer.__init__(self)
+ self.instances += 1
+
+ self.data = []
+ """Store data in a list, most recent last."""
+
+ def storedata(self, data):
+ """
+ Extend `Storer.storedata()`; append new `data` to a
+ list (in `self.data`).
+ """
+ self.data = data
+
+ Each piece of interpreted text is looked up according to the local
+ namespace of the block containing its docstring.
+
+- Markup that isolates a Python identifier and specifies its type:
+ interpreted text with roles.
+
+ Although the Python source context reader is designed not to require
+ explicit roles, they may be used. To classify identifiers
+ explicitly, the role is given along with the identifier in either
+ prefix or suffix form::
+
+ Use :method:`Keeper.storedata` to store the object's data in
+ `Keeper.data`:instance_attribute:.
+
+ The syntax chosen for roles is verbose, but necessarily so (if
+ anyone has a better alternative, please post it to the Doc-SIG_).
+ The intention of the markup is that there should be little need to
+ use explicit roles; their use is to be kept to an absolute minimum.
+
+- Markup for "tagged lists" or "label lists": field lists.
+
+ Field lists represent a mapping from field name to field body.
+ These are mostly used for extension syntax, such as "bibliographic
+ field lists" (representing document metadata such as author, date,
+ and version) and extension attributes for directives (see below).
+ They may be used to implement methodologies (docstring semantics),
+ such as identifying parameters, exceptions raised, etc.; such usage
+ is beyond the scope of this PEP.
+
+ A modified RFC 2822 syntax is used, with a colon *before* as well as
+ *after* the field name. Field bodies are more versatile as well;
+ they may contain multiple field bodies (even nested field lists).
+ For example::
+
+ :Date: 2002-03-22
+ :Version: 1
+ :Authors:
+ - Me
+ - Myself
+ - I
+
+ Standard RFC 2822 header syntax cannot be used for this construct
+ because it is ambiguous. A word followed by a colon at the
+ beginning of a line is common in written text.
+
+- Markup extensibility: directives and substitutions.
+
+ Directives are used as an extension mechanism for reStructuredText,
+ a way of adding support for new block-level constructs without
+ adding new syntax. Directives for images, admonitions (note,
+ caution, etc.), and tables of contents generation (among others)
+ have been implemented. For example, here's how to place an image::
+
+ .. image:: mylogo.png
+
+ Substitution definitions allow the power and flexibility of
+ block-level directives to be shared by inline text. For example::
+
+ The |biohazard| symbol must be used on containers used to
+ dispose of medical waste.
+
+ .. |biohazard| image:: biohazard.png
+
+- Section structure markup.
+
+ Section headers in reStructuredText use adornment via underlines
+ (and possibly overlines) rather than indentation. For example::
+
+ This is a Section Title
+ =======================
+
+ This is a Subsection Title
+ --------------------------
+
+ This paragraph is in the subsection.
+
+ This is Another Section Title
+ =============================
+
+ This paragraph is in the second section.
+
+
+Questions & Answers
+===================
+
+1. Is reStructuredText rich enough?
+
+ Yes, it is for most people. If it lacks some construct that is
+ required for a specific application, it can be added via the
+ directive mechanism. If a useful and common construct has been
+ overlooked and a suitably readable syntax can be found, it can be
+ added to the specification and parser.
+
+2. Is reStructuredText *too* rich?
+
+ For specific applications or individuals, perhaps. In general, no.
+
+ Since the very beginning, whenever a docstring markup syntax has
+ been proposed on the Doc-SIG_, someone has complained about the
+ lack of support for some construct or other. The reply was often
+ something like, "These are docstrings we're talking about, and
+ docstrings shouldn't have complex markup." The problem is that a
+ construct that seems superfluous to one person may be absolutely
+ essential to another.
+
+ reStructuredText takes the opposite approach: it provides a rich
+ set of implicit markup constructs (plus a generic extension
+ mechanism for explicit markup), allowing for all kinds of
+ documents. If the set of constructs is too rich for a particular
+ application, the unused constructs can either be removed from the
+ parser (via application-specific overrides) or simply omitted by
+ convention.
+
+3. Why not use indentation for section structure, like StructuredText
+ does? Isn't it more "Pythonic"?
+
+ Guido van Rossum wrote the following in a 2001-06-13 Doc-SIG post:
+
+ I still think that using indentation to indicate sectioning is
+ wrong. If you look at how real books and other print
+ publications are laid out, you'll notice that indentation is
+ used frequently, but mostly at the intra-section level.
+ Indentation can be used to offset lists, tables, quotations,
+ examples, and the like. (The argument that docstrings are
+ different because they are input for a text formatter is wrong:
+ the whole point is that they are also readable without
+ processing.)
+
+ I reject the argument that using indentation is Pythonic: text
+ is not code, and different traditions and conventions hold.
+ People have been presenting text for readability for over 30
+ centuries. Let's not innovate needlessly.
+
+ See `Section Structure via Indentation`__ in `Problems With
+ StructuredText`_ for further elaboration.
+
+ __ http://docutils.sourceforge.net/docs/dev/rst/problems.html
+ #section-structure-via-indentation
+
+4. Why use reStructuredText for PEPs? What's wrong with the existing
+ standard?
+
+ The existing standard for PEPs is very limited in terms of general
+ expressibility, and referencing is especially lacking for such a
+ reference-rich document type. PEPs are currently converted into
+ HTML, but the results (mostly monospaced text) are less than
+ attractive, and most of the value-added potential of HTML
+ (especially inline hyperlinks) is untapped.
+
+ Making reStructuredText a standard markup for PEPs will enable much
+ richer expression, including support for section structure, inline
+ markup, graphics, and tables. In several PEPs there are ASCII
+ graphics diagrams, which are all that plaintext documents can
+ support. Since PEPs are made available in HTML form, the ability
+ to include proper diagrams would be immediately useful.
+
+ Current PEP practices allow for reference markers in the form "[1]"
+ in the text, and the footnotes/references themselves are listed in
+ a section toward the end of the document. There is currently no
+ hyperlinking between the reference marker and the
+ footnote/reference itself (it would be possible to add this to
+ pep2html.py, but the "markup" as it stands is ambiguous and
+ mistakes would be inevitable). A PEP with many references (such as
+ this one ;-) requires a lot of flipping back and forth. When
+ revising a PEP, often new references are added or unused references
+ deleted. It is painful to renumber the references, since it has to
+ be done in two places and can have a cascading effect (insert a
+ single new reference 1, and every other reference has to be
+ renumbered; always adding new references to the end is suboptimal).
+ It is easy for references to go out of sync.
+
+ PEPs use references for two purposes: simple URL references and
+ footnotes. reStructuredText differentiates between the two. A PEP
+ might contain references like this::
+
+ Abstract
+
+ This PEP proposes adding frungible doodads [1] to the core.
+ It extends PEP 9876 [2] via the BCA [3] mechanism.
+
+ ...
+
+ References and Footnotes
+
+ [1] http://www.example.org/
+
+ [2] PEP 9876, Let's Hope We Never Get Here
+ http://www.python.org/peps/pep-9876.html
+
+ [3] "Bogus Complexity Addition"
+
+ Reference 1 is a simple URL reference. Reference 2 is a footnote
+ containing text and a URL. Reference 3 is a footnote containing
+ text only. Rewritten using reStructuredText, this PEP could look
+ like this::
+
+ Abstract
+ ========
+
+ This PEP proposes adding `frungible doodads`_ to the core. It
+ extends PEP 9876 [#pep9876]_ via the BCA [#]_ mechanism.
+
+ ...
+
+ References & Footnotes
+ ======================
+
+ .. _frungible doodads: http://www.example.org/
+
+ .. [#pep9876] PEP 9876, Let's Hope We Never Get Here
+
+ .. [#] "Bogus Complexity Addition"
+
+ URLs and footnotes can be defined close to their references if
+ desired, making them easier to read in the source text, and making
+ the PEPs easier to revise. The "References and Footnotes" section
+ can be auto-generated with a document tree transform. Footnotes
+ from throughout the PEP would be gathered and displayed under a
+ standard header. If URL references should likewise be written out
+ explicitly (in citation form), another tree transform could be
+ used.
+
+ URL references can be named ("frungible doodads"), and can be
+ referenced from multiple places in the document without additional
+ definitions. When converted to HTML, references will be replaced
+ with inline hyperlinks (HTML <a> tags). The two footnotes are
+ automatically numbered, so they will always stay in sync. The
+ first footnote also contains an internal reference name, "pep9876",
+ so it's easier to see the connection between reference and footnote
+ in the source text. Named footnotes can be referenced multiple
+ times, maintaining consistent numbering.
+
+ The "#pep9876" footnote could also be written in the form of a
+ citation::
+
+ It extends PEP 9876 [PEP9876]_ ...
+
+ .. [PEP9876] PEP 9876, Let's Hope We Never Get Here
+
+ Footnotes are numbered, whereas citations use text for their
+ references.
+
+5. Wouldn't it be better to keep the docstring and PEP proposals
+ separate?
+
+ The PEP markup proposal may be removed if it is deemed that there
+ is no need for PEP markup, or it could be made into a separate PEP.
+ If accepted, PEP 1, PEP Purpose and Guidelines [#PEP-1]_, and PEP
+ 9, Sample PEP Template [#PEP-9]_ will be updated.
+
+ It seems natural to adopt a single consistent markup standard for
+ all uses of structured plaintext in Python, and to propose it all
+ in one place.
+
+6. The existing pep2html.py script converts the existing PEP format to
+ HTML. How will the new-format PEPs be converted to HTML?
+
+ A new version of pep2html.py with integrated reStructuredText
+ parsing has been completed. The Docutils project supports PEPs
+ with a "PEP Reader" component, including all functionality
+ currently in pep2html.py (auto-recognition of PEP & RFC references,
+ email masking, etc.).
+
+7. Who's going to convert the existing PEPs to reStructuredText?
+
+ PEP authors or volunteers may convert existing PEPs if they like,
+ but there is no requirement to do so. The reStructuredText-based
+ PEPs will coexist with the old PEP standard. The pep2html.py
+ mentioned in answer 6 processes both old and new standards.
+
+8. Why use reStructuredText for README and other ancillary files?
+
+ The reasoning given for PEPs in answer 4 above also applies to
+ README and other ancillary files. By adopting a standard markup,
+ these files can be converted to attractive cross-referenced HTML
+ and put up on python.org. Developers of other projects can also
+ take advantage of this facility for their own documentation.
+
+9. Won't the superficial similarity to existing markup conventions
+ cause problems, and result in people writing invalid markup (and
+ not noticing, because the plaintext looks natural)? How forgiving
+ is reStructuredText of "not quite right" markup?
+
+ There will be some mis-steps, as there would be when moving from
+ one programming language to another. As with any language,
+ proficiency grows with experience. Luckily, reStructuredText is a
+ very little language indeed.
+
+ As with any syntax, there is the possibility of syntax errors. It
+ is expected that a user will run the processing system over their
+ input and check the output for correctness.
+
+ In a strict sense, the reStructuredText parser is very unforgiving
+ (as it should be; "In the face of ambiguity, refuse the temptation
+ to guess" [#Zen]_ applies to parsing markup as well as computer
+ languages). Here's design goal 3 from `An Introduction to
+ reStructuredText`_:
+
+ Unambiguous. The rules for markup must not be open for
+ interpretation. For any given input, there should be one and
+ only one possible output (including error output).
+
+ While unforgiving, at the same time the parser does try to be
+ helpful by producing useful diagnostic output ("system messages").
+ The parser reports problems, indicating their level of severity
+ (from least to most: debug, info, warning, error, severe). The
+ user or the client software can decide on reporting thresholds;
+ they can ignore low-level problems or cause high-level problems to
+ bring processing to an immediate halt. Problems are reported
+ during the parse as well as included in the output, often with
+ two-way links between the source of the problem and the system
+ message explaining it.
+
+10. Will the docstrings in the Python standard library modules be
+ converted to reStructuredText?
+
+ No. Python's library reference documentation is maintained
+ separately from the source. Docstrings in the Python standard
+ library should not try to duplicate the library reference
+ documentation. The current policy for docstrings in the Python
+ standard library is that they should be no more than concise
+ hints, simple and markup-free (although many *do* contain ad-hoc
+ implicit markup).
+
+11. I want to write all my strings in Unicode. Will anything
+ break?
+
+ The parser fully supports Unicode. Docutils supports arbitrary
+ input and output encodings.
+
+12. Why does the community need a new structured text design?
+
+ The existing structured text designs are deficient, for the
+ reasons given in "Rationale" above. reStructuredText aims to be a
+ complete markup syntax, within the limitations of the "readable
+ plaintext" medium.
+
+13. What is wrong with existing documentation methodologies?
+
+ What existing methodologies? For Python docstrings, there is
+ **no** official standard markup format, let alone a documentation
+ methodology akin to JavaDoc. The question of methodology is at a
+ much higher level than syntax (which this PEP addresses). It is
+ potentially much more controversial and difficult to resolve, and
+ is intentionally left out of this discussion.
+
+
+References & Footnotes
+======================
+
+.. [#PEP-1] PEP 1, PEP Guidelines, Warsaw, Hylton
+ (http://www.python.org/peps/pep-0001.html)
+
+.. [#PEP-9] PEP 9, Sample PEP Template, Warsaw
+ (http://www.python.org/peps/pep-0009.html)
+
+.. [#Zen] From `The Zen of Python (by Tim Peters)`__ (or just
+ "``import this``" in Python)
+
+__ http://www.python.org/doc/Humor.html#zen
+
+.. [#PEP-216] PEP 216, Docstring Format, Zadka
+ (http://www.python.org/peps/pep-0216.html)
+
+.. _reStructuredText markup: http://docutils.sourceforge.net/rst.html
+
+.. _Doc-SIG: http://www.python.org/sigs/doc-sig/
+
+.. _XML: http://www.w3.org/XML/
+
+.. _SGML: http://www.oasis-open.org/cover/general.html
+
+.. _DocBook: http://docbook.org/tdg/en/html/docbook.html
+
+.. _HTML: http://www.w3.org/MarkUp/
+
+.. _XHTML: http://www.w3.org/MarkUp/#xhtml1
+
+.. _TeX: http://www.tug.org/interest.html
+
+.. _Perl POD: http://perldoc.perl.org/perlpod.html
+
+.. _JavaDoc: http://java.sun.com/j2se/javadoc/
+
+.. _Setext: http://docutils.sourceforge.net/mirror/setext.html
+
+.. _StructuredText:
+ http://www.zope.org/DevHome/Members/jim/StructuredTextWiki/FrontPage
+
+.. _A ReStructuredText Primer:
+ http://docutils.sourceforge.net/docs/user/rst/quickstart.html
+
+.. _Quick reStructuredText:
+ http://docutils.sourceforge.net/docs/user/rst/quickref.html
+
+.. _An Introduction to reStructuredText:
+ http://docutils.sourceforge.net/docs/ref/rst/introduction.html
+
+.. _reStructuredText Markup Specification:
+ http://docutils.sourceforge.net/docs/ref/rst/restructuredtext.html
+
+.. _reStructuredText Directives:
+ http://docutils.sourceforge.net/docs/ref/rst/directives.html
+
+.. _Problems with StructuredText:
+ http://docutils.sourceforge.net/docs/dev/rst/problems.html
+
+.. _A Record of reStructuredText Syntax Alternatives:
+ http://docutils.sourceforge.net/docs/dev/rst/alternatives.html
+
+.. _Docutils: http://docutils.sourceforge.net/
+
+
+Copyright
+=========
+
+This document has been placed in the public domain.
+
+
+Acknowledgements
+================
+
+Some text is borrowed from PEP 216, Docstring Format [#PEP-216]_, by
+Moshe Zadka.
+
+Special thanks to all members past & present of the Python Doc-SIG_.
+
+
+\f
+..
+ Local Variables:
+ mode: indented-text
+ indent-tabs-mode: nil
+ sentence-end-double-space: t
+ fill-column: 70
+ End:
--- /dev/null
+============================
+ The Docutils Document Tree
+============================
+
+A Guide to the Docutils DTD
+***************************
+
+:Author: David Goodger
+:Contact: docutils-develop@lists.sourceforge.net
+:Revision: $Revision: 8407 $
+:Date: $Date: 2019-10-29 23:48:34 +0100 (Di, 29. Okt 2019) $
+:Copyright: This document has been placed in the public domain.
+
+
+.. contents:: :depth: 1
+
+
+This document describes the XML data structure of Docutils_ documents:
+the relationships and semantics of elements and attributes. The
+Docutils document structure is formally defined by the `Docutils
+Generic DTD`_ XML document type definition, docutils.dtd_, which is
+the definitive source for details of element structural relationships.
+
+This document does not discuss implementation details. Those can be
+found in internal documentation (docstrings) for the
+``docutils.nodes`` module, where the document tree data structure is
+implemented in a class library.
+
+The reader is assumed to have some familiarity with XML or SGML, and
+an understanding of the data structure meaning of "tree". For a list
+of introductory articles, see `Introducing the Extensible Markup
+Language (XML)`_.
+
+The reStructuredText_ markup is used for illustrative examples
+throughout this document. For a gentle introduction, see `A
+ReStructuredText Primer`_. For complete technical details, see the
+`reStructuredText Markup Specification`_.
+
+.. _Docutils: http://docutils.sourceforge.net/
+.. _Docutils Generic DTD:
+.. _Docutils DTD:
+.. _docutils.dtd: docutils.dtd
+.. _Introducing the Extensible Markup Language (XML):
+ http://xml.coverpages.org/xmlIntro.html
+.. _reStructuredText: http://docutils.sourceforge.net/rst.html
+.. _A ReStructuredText Primer: ../user/rst/quickstart.html
+.. _reStructuredText Markup Specification: rst/restructuredtext.html
+
+
+-------------------
+ Element Hierarchy
+-------------------
+
+.. contents:: :local:
+
+Below is a simplified diagram of the hierarchy of elements in the
+Docutils document tree structure. An element may contain any other
+elements immediately below it in the diagram. Notes are written in
+square brackets. Element types in parentheses indicate recursive or
+one-to-many relationships; sections may contain (sub)sections, tables
+contain further body elements, etc. ::
+
+ +--------------------------------------------------------------------+
+ | document [may begin with a title, subtitle, decoration, docinfo] |
+ | +--------------------------------------+
+ | | sections [each begins with a title] |
+ +-----------------------------+-------------------------+------------+
+ | [body elements:] | (sections) |
+ | | - literal | - lists | | - hyperlink +------------+
+ | | blocks | - tables | | targets |
+ | para- | - doctest | - block | foot- | - sub. defs |
+ | graphs | blocks | quotes | notes | - comments |
+ +---------+-----------+----------+-------+--------------+
+ | [text]+ | [text] | (body elements) | [text] |
+ | (inline +-----------+------------------+--------------+
+ | markup) |
+ +---------+
+
+The Docutils document model uses a simple, recursive model for section
+structure. A document_ node may contain body elements and section_
+elements. Sections in turn may contain body elements and sections.
+The level (depth) of a section element is determined from its physical
+nesting level; unlike other document models (``<h1>`` in HTML_,
+``<sect1>`` in DocBook_, ``<div1>`` in XMLSpec_) the level is not
+incorporated into the element name.
+
+The Docutils document model uses strict element content models. Every
+element has a unique structure and semantics, but elements may be
+classified into general categories (below). Only elements which are
+meant to directly contain text data have a mixed content model, where
+text data and inline elements may be intermixed. This is unlike the
+much looser HTML_ document model, where paragraphs and text data may
+occur at the same level.
+
+
+Structural Elements
+===================
+
+Structural elements may only contain child elements; they do not
+directly contain text data. Structural elements may contain body
+elements or further structural elements. Structural elements can only
+be child elements of other structural elements.
+
+Category members: document_, section_, topic_, sidebar_
+
+
+Structural Subelements
+----------------------
+
+Structural subelements are child elements of structural elements.
+Simple structuctural subelements (title_, subtitle_) contain text
+data; the others are compound and do not directly contain text data.
+
+Category members: title_, subtitle_, decoration_, docinfo_,
+transition_
+
+
+Bibliographic Elements
+``````````````````````
+
+The docinfo_ element is an optional child of document_. It groups
+bibliographic elements together. All bibliographic elements except
+authors_ and field_ contain text data. authors_ contains further
+bibliographic elements (most notably author_). field_ contains
+field_name_ and field_body_ body subelements.
+
+Category members: address_, author_, authors_, contact_, copyright_,
+date_, field_, organization_, revision_, status_, version_
+
+
+Decorative Elements
+```````````````````
+
+The decoration_ element is also an optional child of document_. It
+groups together elements used to generate page headers and footers.
+
+Category members: footer_, header_
+
+
+Body Elements
+=============
+
+Body elements are contained within structural elements and compound
+body elements. There are two subcategories of body elements: simple
+and compound.
+
+Category members: admonition_, attention_, block_quote_, bullet_list_,
+caution_, citation_, comment_, compound_, container_, danger_,
+definition_list_, doctest_block_, enumerated_list_, error_,
+field_list_, figure_, footnote_, hint_, image_, important_,
+line_block_, literal_block_, note_, option_list_, paragraph_,
+pending_, raw_, rubric_, substitution_definition_, system_message_,
+table_, target_, tip_, warning_
+
+
+Simple Body Elements
+--------------------
+
+Simple body elements are empty or directly contain text data. Those
+that contain text data may also contain inline elements. Such
+elements therefore have a "mixed content model".
+
+Category members: comment_, doctest_block_, image_, literal_block_,
+math_block_, paragraph_, pending_, raw_, rubric_, substitution_definition_,
+target_
+
+
+Compound Body Elements
+----------------------
+
+Compound body elements contain local substructure (body subelements)
+and further body elements. They do not directly contain text data.
+
+Category members: admonition_, attention_, block_quote_, bullet_list_,
+caution_, citation_, compound_, container_, danger_, definition_list_,
+enumerated_list_, error_, field_list_, figure_, footnote_, hint_,
+important_, line_block, note_, option_list_, system_message_, table_,
+tip_, warning_
+
+
+Body Subelements
+````````````````
+
+Compound body elements contain specific subelements (e.g. bullet_list_
+contains list_item_). Subelements may themselves be compound elements
+(containing further child elements, like field_) or simple data
+elements (containing text data, like field_name_). These subelements
+always occur within specific parent elements, never at the body
+element level (beside paragraphs, etc.).
+
+Category members (simple): attribution_, caption_, classifier_,
+colspec_, field_name_, label_, line_, option_argument_,
+option_string_, term_
+
+Category members (compound): definition_, definition_list_item_,
+description_, entry_, field_, field_body_, legend_, list_item_,
+option_, option_group_, option_list_item_, row_, tbody_, tgroup_,
+thead_
+
+
+Inline Elements
+===============
+
+Inline elements directly contain text data, and may also contain
+further inline elements. Inline elements are contained within simple
+body elements. Most inline elements have a "mixed content model".
+
+Category members: abbreviation_, acronym_, citation_reference_,
+emphasis_, footnote_reference_, generated_, image_, inline_, literal_,
+math_, problematic_, reference_, strong_, subscript_,
+substitution_reference_, superscript_, target_, title_reference_, raw_
+
+
+.. _HTML: http://www.w3.org/MarkUp/
+.. _DocBook: http://docbook.org/tdg/en/html/docbook.html
+.. _XMLSpec: http://www.w3.org/XML/1998/06/xmlspec-report.htm
+
+
+-------------------
+ Element Reference
+-------------------
+
+.. contents:: :local:
+ :depth: 1
+
+Each element in the DTD (document type definition) is described in its
+own section below. Each section contains an introduction plus the
+following subsections:
+
+* Details (of element relationships and semantics):
+
+ - Category: One or more references to the element categories in
+ `Element Hierarchy`_ above. Some elements belong to more than one
+ category.
+
+ - Parents: A list of elements which may contain the element.
+
+ - Children: A list of elements which may occur within the element.
+
+ - Analogues: Describes analogous elements in well-known document
+ models such as HTML_ or DocBook_. Lists similarities and
+ differences.
+
+ - Processing: Lists formatting or rendering recommendations for the
+ element.
+
+* Content Model:
+
+ The formal XML content model from the `Docutils DTD`_, followed by:
+
+ - Attributes: Describes (or refers to descriptions of) the possible
+ values and semantics of each attribute.
+
+ - Parameter Entities: Lists the parameter entities which directly or
+ indirectly include the element.
+
+* Examples: reStructuredText_ examples are shown along with
+ fragments of the document trees resulting from parsing.
+ _`Pseudo-XML` is used for the results of parsing and processing.
+ Pseudo-XML is a representation of XML where nesting is indicated by
+ indentation and end-tags are not shown. Some of the precision of
+ real XML is given up in exchange for easier readability. For
+ example, the following are equivalent:
+
+ - Real XML::
+
+ <document>
+ <section ids="a-title" names="a title">
+ <title>A Title</title>
+ <paragraph>A paragraph.</paragraph>
+ </section>
+ </document>
+
+ - Pseudo-XML::
+
+ <document>
+ <section ids="a-title" names="a title">
+ <title>
+ A Title
+ <paragraph>
+ A paragraph.
+
+--------------------
+
+Many of the element reference sections below are marked "_`to be
+completed`". Please help complete this document by contributing to
+its writing.
+
+
+``abbreviation``
+================
+
+The ``abbreviation`` element is an inline element used to represent an
+abbreviation being used in the document. An example of an abbreviation is 'St'
+being used instead of 'Street'.
+
+Details
+-------
+
+:Category:
+ `Inline Elements`_
+
+:Parents:
+ All elements employing the %inline.elements; parameter entities in their
+ content models may contain ``abbreviation``.
+
+:Children:
+ ``abbreviation`` elements may contain text data plus `inline elements`_.
+
+:Analogues:
+ ``abbreviation`` is analogous to the HTML "abbr" element.
+
+Content Model
+-------------
+
+.. parsed-literal::
+
+ `%text.model;`_
+
+:Attributes:
+ The ``abbreviation`` element contains only the `common attributes`_:
+ ids_, names_, dupnames_, source_, and classes_.
+
+Examples
+--------
+
+The ``abbreviation`` element is not exposed in default restructured text. It
+can only be accessed through custom roles.
+
+Pseudo-XML_ example from a custom `:abbr:` role::
+
+ <paragraph>
+ <abbreviation explanation="Street">
+ St
+ is a common abbreviation for "street".
+
+
+``acronym``
+===========
+
+`To be completed`_.
+
+
+``address``
+===========
+
+The ``address`` element holds the surface mailing address information
+for the author (individual or group) of the document, or a third-party
+contact address. Its structure is identical to that of the
+literal_block_ element: whitespace is significant, especially
+newlines.
+
+
+Details
+-------
+
+:Category:
+ `Bibliographic Elements`_
+
+:Parents:
+ The following elements may contain ``address``: docinfo_, authors_
+
+:Children:
+ ``address`` elements contain text data plus `inline elements`_.
+
+:Analogues:
+ ``address`` is analogous to the DocBook "address" element.
+
+:Processing:
+ As with the literal_block_ element, newlines and other whitespace
+ is significant and must be preserved. However, a monospaced
+ typeface need not be used.
+
+ See also docinfo_.
+
+
+Content Model
+-------------
+
+.. parsed-literal::
+
+ `%text.model;`_
+
+:Attributes:
+ The ``address`` element contains the `common attributes`_ (ids_,
+ names_, dupnames_, source_, and classes_), plus `xml:space`_.
+
+:Parameter Entities:
+ The `%bibliographic.elements;`_ parameter entity directly includes
+ ``address``.
+
+
+Examples
+--------
+
+reStructuredText_ source::
+
+ Document Title
+ ==============
+
+ :Address: 123 Example Ave.
+ Example, EX
+
+Complete pseudo-XML_ result after parsing and applying transforms::
+
+ <document ids="document-title" names="document title">
+ <title>
+ Document Title
+ <docinfo>
+ <address>
+ 123 Example Ave.
+ Example, EX
+
+See docinfo_ for a more complete example, including processing
+context.
+
+
+``admonition``
+==============
+
+This element is a generic, titled admonition. Also see the specific
+admonition elements Docutils offers (in alphabetical order): caution_,
+danger_, error_, hint_, important_, note_, tip_, warning_.
+
+
+Details
+-------
+
+:Category:
+ `Compound Body Elements`_
+
+:Parents:
+ All elements employing the `%body.elements;`_ or
+ `%structure.model;`_ parameter entities in their content models
+ may contain ``admonition``.
+
+:Children:
+ ``admonition`` elements begin with a title_ and may contain one or
+ more `body elements`_.
+
+:Analogues:
+ ``admonition`` has no direct analogues in common DTDs. It can be
+ emulated with primitives and type effects.
+
+:Processing:
+ Rendered distinctly (inset and/or in a box, etc.).
+
+
+Content Model
+-------------
+
+.. parsed-literal::
+
+ (title_, (`%body.elements;`_)+)
+
+:Attributes:
+ The ``admonition`` element contains only the `common attributes`_:
+ ids_, names_, dupnames_, source_, and classes_.
+
+:Parameter Entities:
+ The `%body.elements;`_ parameter entity directly includes
+ ``admonition``. The `%structure.model;`_ parameter entity
+ indirectly includes ``admonition``.
+
+
+Examples
+--------
+
+reStructuredText source::
+
+ .. admonition:: And, by the way...
+
+ You can make up your own admonition too.
+
+Pseudo-XML_ fragment from simple parsing::
+
+ <admonition class="admonition-and-by-the-way">
+ <title>
+ And, by the way...
+ <paragraph>
+ You can make up your own admonition too.
+
+
+``attention``
+=============
+
+The ``attention`` element is an admonition, a distinctive and
+self-contained notice. Also see the other admonition elements
+Docutils offers (in alphabetical order): caution_, danger_, error_,
+hint_, important_, note_, tip_, warning_, and the generic admonition_.
+
+
+Details
+-------
+
+:Category:
+ `Compound Body Elements`_
+
+:Parents:
+ All elements employing the `%body.elements;`_ or
+ `%structure.model;`_ parameter entities in their content models
+ may contain ``attention``.
+
+:Children:
+ ``attention`` elements contain one or more `body elements`_.
+
+:Analogues:
+ ``attention`` has no direct analogues in common DTDs. It can be
+ emulated with primitives and type effects.
+
+:Processing:
+ Rendered distinctly (inset and/or in a box, etc.), with the
+ generated title "Attention!" (or similar).
+
+
+Content Model
+-------------
+
+.. parsed-literal::
+
+ (`%body.elements;`_)+
+
+:Attributes:
+ The ``attention`` element contains only the `common attributes`_:
+ ids_, names_, dupnames_, source_, and classes_.
+
+:Parameter Entities:
+ The `%body.elements;`_ parameter entity directly includes
+ ``attention``. The `%structure.model;`_ parameter entity
+ indirectly includes ``attention``.
+
+
+Examples
+--------
+
+reStructuredText source::
+
+ .. Attention:: All your base are belong to us.
+
+Pseudo-XML_ fragment from simple parsing::
+
+ <attention>
+ <paragraph>
+ All your base are belong to us.
+
+
+``attribution``
+===============
+
+`To be completed`_.
+
+
+``author``
+==========
+
+The ``author`` element holds the name of the author of the document.
+
+
+Details
+-------
+
+:Category:
+ `Bibliographic Elements`_
+
+:Parents:
+ The following elements may contain ``author``: docinfo_, authors_
+
+:Children:
+ ``author`` elements may contain text data plus `inline elements`_.
+
+:Analogues:
+ ``author`` is analogous to the DocBook "author" element.
+
+:Processing:
+ See docinfo_.
+
+
+Content Model
+-------------
+
+.. parsed-literal::
+
+ `%text.model;`_
+
+:Attributes:
+ The ``author`` element contains only the `common attributes`_:
+ ids_, names_, dupnames_, source_, and classes_.
+
+:Parameter Entities:
+ The `%bibliographic.elements;`_ parameter entity directly includes
+ ``author``.
+
+
+Examples
+--------
+
+reStructuredText_ source::
+
+ Document Title
+ ==============
+
+ :Author: J. Random Hacker
+
+Complete pseudo-XML_ result after parsing and applying transforms::
+
+ <document ids="document-title" names="document title">
+ <title>
+ Document Title
+ <docinfo>
+ <author>
+ J. Random Hacker
+
+See docinfo_ for a more complete example, including processing
+context.
+
+
+``authors``
+===========
+
+The ``authors`` element is a container for author information for
+documents with multiple authors.
+
+
+Details
+-------
+
+:Category:
+ `Bibliographic Elements`_
+
+:Parents:
+ Only the docinfo_ element contains ``authors``.
+
+:Children:
+ ``authors`` elements may contain the following elements: author_,
+ organization_, address_, contact_
+
+:Analogues:
+ ``authors`` is analogous to the DocBook "authors" element.
+
+:Processing:
+ See docinfo_.
+
+
+Content Model
+-------------
+
+.. parsed-literal::
+
+ ((author_, organization_?, address_?, contact_?)+)
+
+:Attributes:
+ The ``authors`` element contains only the `common attributes`_:
+ ids_, names_, dupnames_, source_, and classes_.
+
+:Parameter Entities:
+ The `%bibliographic.elements;`_ parameter entity directly includes
+ ``authors``.
+
+
+Examples
+--------
+
+reStructuredText_ source::
+
+ Document Title
+ ==============
+
+ :Authors: J. Random Hacker; Jane Doe
+
+Complete pseudo-XML_ result after parsing and applying transforms::
+
+ <document ids="document-title" names="document title">
+ <title>
+ Document Title
+ <docinfo>
+ <authors>
+ <author>
+ J. Random Hacker
+ <author>
+ Jane Doe
+
+In reStructuredText, multiple author's names are separated with
+semicolons (";") or commas (","); semicolons take precedence. There
+is currently no way to represent the author's organization, address,
+or contact in a reStructuredText "Authors" field.
+
+See docinfo_ for a more complete example, including processing
+context.
+
+
+``block_quote``
+===============
+
+The ``block_quote`` element is used for quotations set off from the
+main text (standalone).
+
+
+Details
+-------
+
+:Category:
+ `Compound Body Elements`_
+
+:Parents:
+ All elements employing the `%body.elements;`_ or
+ `%structure.model;`_ parameter entities in their content models
+ may contain ``block_quote``.
+
+:Children:
+ ``block_quote`` elements contain `body elements`_ followed by an
+ optional attribution_ element.
+
+:Analogues:
+ ``block_quote`` is analogous to the "blockquote" element in both
+ HTML and DocBook.
+
+:Processing:
+ ``block_quote`` elements serve to set their contents off from the
+ main text, typically with indentation and/or other decoration.
+
+
+Content Model
+-------------
+
+.. parsed-literal::
+
+ ((`%body.elements;`_)+, attribution_?)
+
+:Attributes:
+ The ``block_quote`` element contains only the `common
+ attributes`_: ids_, names_, dupnames_, source_, and classes_.
+
+:Parameter Entities:
+ The `%body.elements;`_ parameter entity directly includes
+ ``block_quote``. The `%structure.model;`_ parameter entity
+ indirectly includes ``block_quote``.
+
+
+Examples
+--------
+
+reStructuredText source::
+
+ As a great paleontologist once said,
+
+ This theory, that is mine, is mine.
+
+ -- Anne Elk (Miss)
+
+Pseudo-XML_ fragment from simple parsing::
+
+ <paragraph>
+ As a great paleontologist once said,
+ <block_quote>
+ <paragraph>
+ This theory, that is mine, is mine.
+ <attribution>
+ Anne Elk (Miss)
+
+
+``bullet_list``
+===============
+
+The ``bullet_list`` element contains list_item_ elements which are
+uniformly marked with bullets. Bullets are typically simple dingbats
+(symbols) such as circles and squares.
+
+
+Details
+-------
+
+:Category:
+ `Compound Body Elements`_
+
+:Parents:
+ All elements employing the `%body.elements;`_ or
+ `%structure.model;`_ parameter entities in their content models
+ may contain ``bullet_list``.
+
+:Children:
+ ``bullet_list`` elements contain one or more list_item_ elements.
+
+:Analogues:
+ ``bullet_list`` is analogous to the HTML "ul" element and to the
+ DocBook "itemizedlist" element. HTML's "ul" is short for
+ "unordered list", which we consider to be a misnomer. "Unordered"
+ implies that the list items may be randomly rearranged without
+ affecting the meaning of the list. Bullet lists *are* often
+ ordered; the ordering is simply left implicit.
+
+:Processing:
+ Each list item should begin a new vertical block, prefaced by a
+ bullet/dingbat.
+
+
+Content Model
+-------------
+
+.. parsed-literal::
+
+ (list_item_ +)
+
+:Attributes:
+ The ``bullet_list`` element contains the `common attributes`_
+ (ids_, names_, dupnames_, source_, and classes_), plus bullet_.
+
+ ``bullet`` is used to record the style of bullet from the input
+ data. In documents processed from reStructuredText_, it contains
+ one of "-", "+", or "*". It may be ignored in processing.
+
+:Parameter Entities:
+ The `%body.elements;`_ parameter entity directly includes
+ ``bullet_list``. The `%structure.model;`_ parameter entity
+ indirectly includes ``bullet_list``.
+
+
+Examples
+--------
+
+reStructuredText_ source::
+
+ - Item 1, paragraph 1.
+
+ Item 1, paragraph 2.
+
+ - Item 2.
+
+Pseudo-XML_ fragment from simple parsing::
+
+ <bullet_list bullet="-">
+ <list_item>
+ <paragraph>
+ Item 1, paragraph 1.
+ <paragraph>
+ Item 1, paragraph 2.
+ <list_item>
+ <paragraph>
+ Item 2.
+
+See list_item_ for another example.
+
+
+``caption``
+===========
+
+`To be completed`_.
+
+
+``caution``
+===========
+
+The ``caution`` element is an admonition, a distinctive and
+self-contained notice. Also see the other admonition elements
+Docutils offers (in alphabetical order): attention_, danger_, error_,
+hint_, important_, note_, tip_, warning_, and the generic admonition_.
+
+
+Details
+-------
+
+:Category:
+ `Compound Body Elements`_
+
+:Parents:
+ All elements employing the `%body.elements;`_ or
+ `%structure.model;`_ parameter entities in their content models
+ may contain ``caution``.
+
+:Children:
+ ``caution`` elements contain one or more `body elements`_.
+
+:Analogues:
+ ``caution`` is analogous to the DocBook "caution" element.
+
+:Processing:
+ Rendered distinctly (inset and/or in a box, etc.), with the
+ generated title "Caution" (or similar).
+
+
+Content Model
+-------------
+
+.. parsed-literal::
+
+ (`%body.elements;`_)+
+
+:Attributes:
+ The ``caution`` element contains only the `common attributes`_:
+ ids_, names_, dupnames_, source_, and classes_.
+
+:Parameter Entities:
+ The `%body.elements;`_ parameter entity directly includes
+ ``caution``. The `%structure.model;`_ parameter entity
+ indirectly includes ``caution``.
+
+
+Examples
+--------
+
+reStructuredText source::
+
+ .. Caution:: Don't take any wooden nickels.
+
+Pseudo-XML_ fragment from simple parsing::
+
+ <caution>
+ <paragraph>
+ Don't take any wooden nickels.
+
+
+``citation``
+============
+
+`To be completed`_.
+
+
+``citation_reference``
+======================
+
+`To be completed`_.
+
+
+``classifier``
+==============
+
+The ``classifier`` element contains the classification or type of the
+term_ being defined in a definition_list_. For example, it can be
+used to indicate the type of a variable.
+
+
+Details
+-------
+
+:Category:
+ `Body Subelements`_ (simple)
+
+:Parents:
+ Only the definition_list_item_ element contains ``classifier``.
+
+:Children:
+ ``classifier`` elements may contain text data plus `inline elements`_.
+
+:Analogues:
+ ``classifier`` has no direct analogues in common DTDs. It can be
+ emulated with primitives or type effects.
+
+:Processing:
+ See definition_list_item_.
+
+
+Content Model
+-------------
+
+.. parsed-literal::
+
+ `%text.model;`_
+
+:Attributes:
+ The ``classifier`` element contains only the `common attributes`_:
+ ids_, names_, dupnames_, source_, and classes_.
+
+
+Examples
+--------
+
+Here is a hypothetical data dictionary. reStructuredText_ source::
+
+ name : string
+ Customer name.
+ i : int
+ Temporary index variable.
+
+Pseudo-XML_ fragment from simple parsing::
+
+ <definition_list>
+ <definition_list_item>
+ <term>
+ name
+ <classifier>
+ string
+ <definition>
+ <paragraph>
+ Customer name.
+ <definition_list_item>
+ <term>
+ i
+ <classifier>
+ int
+ <definition>
+ <paragraph>
+ Temporary index variable.
+
+
+``colspec``
+===========
+
+:Attributes:
+ The ``colspec`` element contains the `common attributes`_ (ids_,
+ names_, dupnames_, source_, and classes_), plus `stub`_.
+
+
+`To be completed`_.
+
+
+``comment``
+===========
+
+`To be completed`_.
+
+
+``compound``
+============
+
+`To be completed`_.
+
+
+``contact``
+===========
+
+The ``contact`` element holds contact information for the author
+(individual or group) of the document, or a third-party contact. It
+is typically used for an email or web address.
+
+
+Details
+-------
+
+:Category:
+ `Bibliographic Elements`_
+
+:Parents:
+ The following elements may contain ``contact``: docinfo_, authors_
+
+:Children:
+ ``contact`` elements may contain text data plus `inline
+ elements`_.
+
+:Analogues:
+ ``contact`` is analogous to the DocBook "email" element. The HTML
+ "address" element serves a similar purpose.
+
+:Processing:
+ See docinfo_.
+
+
+Content Model
+-------------
+
+.. parsed-literal::
+
+ `%text.model;`_
+
+:Attributes:
+ The ``contact`` element contains only the `common attributes`_:
+ ids_, names_, dupnames_, source_, and classes_.
+
+:Parameter Entities:
+ The `%bibliographic.elements;`_ parameter entity directly includes
+ ``contact``.
+
+
+Examples
+--------
+
+reStructuredText_ source::
+
+ Document Title
+ ==============
+
+ :Contact: jrh@example.com
+
+Complete pseudo-XML_ result after parsing and applying transforms::
+
+ <document ids="document-title" names="document title">
+ <title>
+ Document Title
+ <docinfo>
+ <contact>
+ <reference refuri="mailto:jrh@example.com">
+ jrh@example.com
+
+See docinfo_ for a more complete example, including processing
+context.
+
+
+``container``
+=============
+
+`To be completed`_.
+
+
+``copyright``
+=============
+
+The ``copyright`` element contains the document's copyright statement.
+
+
+Details
+-------
+
+:Category:
+ `Bibliographic Elements`_
+
+:Parents:
+ Only the docinfo_ element contains ``copyright``.
+
+:Children:
+ ``copyright`` elements may contain text data plus `inline
+ elements`_.
+
+:Analogues:
+ ``copyright`` is analogous to the DocBook "copyright" element.
+
+:Processing:
+ See docinfo_.
+
+
+Content Model
+-------------
+
+.. parsed-literal::
+
+ `%text.model;`_
+
+:Attributes:
+ The ``copyright`` element contains only the `common attributes`_:
+ ids_, names_, dupnames_, source_, and classes_.
+
+:Parameter Entities:
+ The `%bibliographic.elements;`_ parameter entity directly includes
+ ``copyright``.
+
+
+Examples
+--------
+
+reStructuredText_ source::
+
+ Document Title
+ ==============
+
+ :Copyright: This document has been placed in the public domain.
+
+Complete pseudo-XML_ result after parsing and applying transforms::
+
+ <document ids="document-title" names="document title">
+ <title>
+ Document Title
+ <docinfo>
+ <copyright>
+ This document has been placed in the public domain.
+
+See docinfo_ for a more complete example, including processing
+context.
+
+
+``danger``
+==========
+
+The ``danger`` element is an admonition, a distinctive and
+self-contained notice. Also see the other admonition elements
+Docutils offers (in alphabetical order): attention_, caution_, error_,
+hint_, important_, note_, tip_, warning_, and the generic admonition_.
+
+
+Details
+-------
+
+:Category:
+ `Compound Body Elements`_
+
+:Parents:
+ All elements employing the `%body.elements;`_ or
+ `%structure.model;`_ parameter entities in their content models
+ may contain ``danger``.
+
+:Children:
+ ``danger`` elements contain one or more `body elements`_.
+
+:Analogues:
+ ``danger`` has no direct analogues in common DTDs. It can be
+ emulated with primitives and type effects.
+
+:Processing:
+ Rendered distinctly (inset and/or in a box, etc.), with the
+ generated title "!DANGER!" (or similar).
+
+
+Content Model
+-------------
+
+.. parsed-literal::
+
+ (`%body.elements;`_)+
+
+:Attributes:
+ The ``danger`` element contains only the `common attributes`_:
+ ids_, names_, dupnames_, source_, and classes_.
+
+:Parameter Entities:
+ The `%body.elements;`_ parameter entity directly includes
+ ``danger``. The `%structure.model;`_ parameter entity
+ indirectly includes ``danger``.
+
+
+Examples
+--------
+
+reStructuredText source::
+
+ .. DANGER:: Mad scientist at work!
+
+Pseudo-XML_ fragment from simple parsing::
+
+ <danger>
+ <paragraph>
+ Mad scientist at work!
+
+
+``date``
+========
+
+The ``date`` element contains the date of publication, release, or
+last modification of the document.
+
+
+Details
+-------
+
+:Category:
+ `Bibliographic Elements`_
+
+:Parents:
+ Only the docinfo_ element contains ``date``.
+
+:Children:
+ ``date`` elements may contain text data plus `inline elements`_.
+
+:Analogues:
+ ``date`` is analogous to the DocBook "date" element.
+
+:Processing:
+ Often used with the RCS/CVS keyword "Date". See docinfo_.
+
+
+Content Model
+-------------
+
+.. parsed-literal::
+
+ `%text.model;`_
+
+:Attributes:
+ The ``date`` element contains only the `common attributes`_:
+ ids_, names_, dupnames_, source_, and classes_.
+
+:Parameter Entities:
+ The `%bibliographic.elements;`_ parameter entity directly includes
+ ``date``.
+
+
+Examples
+--------
+
+reStructuredText_ source::
+
+ Document Title
+ ==============
+
+ :Date: 2002-08-20
+
+Complete pseudo-XML_ result after parsing and applying transforms::
+
+ <document ids="document-title" names="document title">
+ <title>
+ Document Title
+ <docinfo>
+ <date>
+ 2002-08-20
+
+See docinfo_ for a more complete example, including processing
+context.
+
+
+``decoration``
+==============
+
+The ``decoration`` element is a container for header_ and footer_
+elements and potential future extensions. These elements are used for
+notes, time/datestamp, processing information, etc.
+
+
+Details
+-------
+
+:Category:
+ `Structural Subelements`_
+
+:Parents:
+ Only the document_ element contains ``decoration``.
+
+:Children:
+ ``decoration`` elements may contain `decorative elements`_.
+
+:Analogues:
+ There are no direct analogies to ``decoration`` in HTML or in
+ DocBook. Equivalents are typically constructed from primitives
+ and/or generated by the processing system.
+
+:Processing:
+ See the individual `decorative elements`_.
+
+
+Content Model
+-------------
+
+.. parsed-literal::
+
+ (header_?, footer_?)
+
+Although the content model doesn't specifically require contents, no
+empty ``decoration`` elements are ever created.
+
+:Attributes:
+ The ``decoration`` element contains only the `common attributes`_:
+ ids_, names_, dupnames_, source_, and classes_.
+
+
+Examples
+--------
+
+reStructuredText_ source::
+
+ A paragraph.
+
+Complete pseudo-XML_ result after parsing and applying transforms,
+assuming that the datestamp command-line option or configuration
+setting has been supplied::
+
+ <document>
+ <decoration>
+ <footer>
+ <paragraph>
+ Generated on: 2002-08-20.
+ <paragraph>
+ A paragraph.
+
+
+``definition``
+==============
+
+The ``definition`` element is a container for the body elements used
+to define a term_ in a definition_list_.
+
+
+Details
+-------
+
+:Category:
+ `Body Subelements`_ (compound)
+
+:Parents:
+ Only definition_list_item_ elements contain ``definition``.
+
+:Children:
+ ``definition`` elements may contain `body elements`_.
+
+:Analogues:
+ ``definition`` is analogous to the HTML "dd" element and to the
+ DocBook "listitem" element (inside a "variablelistentry" element).
+
+:Processing:
+ See definition_list_item_.
+
+
+Content Model
+-------------
+
+.. parsed-literal::
+
+ (`%body.elements;`_)+
+
+:Attributes:
+ The ``definition`` element contains only the `common attributes`_:
+ ids_, names_, dupnames_, source_, and classes_.
+
+
+Examples
+--------
+
+See the examples for the definition_list_, definition_list_item_, and
+classifier_ elements.
+
+
+``definition_list``
+===================
+
+The ``definition_list`` element contains a list of terms and their
+definitions. It can be used for glossaries or dictionaries, to
+describe or classify things, for dialogues, or to itemize subtopics
+(such as in this reference).
+
+
+Details
+-------
+
+:Category:
+ `Compound Body Elements`_
+
+:Parents:
+ All elements employing the `%body.elements;`_ or
+ `%structure.model;`_ parameter entities in their content models
+ may contain ``definition_list``.
+
+:Children:
+ ``definition_list`` elements contain one or more
+ definition_list_item_ elements.
+
+:Analogues:
+ ``definition_list`` is analogous to the HTML "dl" element and to
+ the DocBook "variablelist" element.
+
+:Processing:
+ See definition_list_item_.
+
+
+Content Model
+-------------
+
+.. parsed-literal::
+
+ (definition_list_item_ +)
+
+:Attributes:
+ The ``definition_list`` element contains only the `common
+ attributes`_: ids_, names_, dupnames_, source_, and classes_.
+
+:Parameter Entities:
+ The `%body.elements;`_ parameter entity directly includes
+ ``definition_list``. The `%structure.model;`_ parameter entity
+ indirectly includes ``definition_list``.
+
+
+Examples
+--------
+
+reStructuredText_ source::
+
+ Term
+ Definition.
+
+ Term : classifier
+ The ' : ' indicates a classifier in
+ definition list item terms only.
+
+Pseudo-XML_ fragment from simple parsing::
+
+ <definition_list>
+ <definition_list_item>
+ <term>
+ Term
+ <definition>
+ <paragraph>
+ Definition.
+ <definition_list_item>
+ <term>
+ Term
+ <classifier>
+ classifier
+ <definition>
+ <paragraph>
+ The ' : ' indicates a classifier in
+ definition list item terms only.
+
+See definition_list_item_ and classifier_ for further examples.
+
+
+``definition_list_item``
+========================
+
+The ``definition_list_item`` element contains a single
+term_/definition_ pair (with optional classifier_).
+
+
+Details
+-------
+
+:Category:
+ `Body Subelements`_ (compound)
+
+:Parents:
+ Only the definition_list_ element contains
+ ``definition_list_item``.
+
+:Children:
+ ``definition_list_item`` elements each contain a single term_,
+ an optional classifier_, and a definition_.
+
+:Analogues:
+ ``definition_list_item`` is analogous to the DocBook
+ "variablelistentry" element.
+
+:Processing:
+ The optional classifier_ can be rendered differently from the
+ term_. They should be separated visually, typically by spaces
+ plus a colon or dash.
+
+
+Content Model
+-------------
+
+.. parsed-literal::
+
+ (term_, classifier_?, definition_)
+
+:Attributes:
+ The ``definition_list_item`` element contains only the `common
+ attributes`_: ids_, names_, dupnames_, source_, and classes_.
+
+
+Examples
+--------
+
+reStructuredText_ source::
+
+ Tyrannosaurus Rex : carnivore
+ Big and scary; the "Tyrant King".
+
+ Brontosaurus : herbivore
+ All brontosauruses are thin at one end,
+ much much thicker in the middle
+ and then thin again at the far end.
+
+ -- Anne Elk (Miss)
+
+Pseudo-XML_ fragment from simple parsing::
+
+ <definition_list>
+ <definition_list_item>
+ <term>
+ Tyrannosaurus Rex
+ <classifier>
+ carnivore
+ <definition>
+ <paragraph>
+ Big and scary; the "Tyrant King".
+ <definition_list_item>
+ <term>
+ Brontosaurus
+ <classifier>
+ herbivore
+ <definition>
+ <paragraph>
+ All brontosauruses are thin at one end,
+ much much thicker in the middle
+ and then thin again at the far end.
+ <paragraph>
+ -- Anne Elk (Miss)
+
+See definition_list_ and classifier_ for further examples.
+
+
+``description``
+===============
+
+The ``description`` element contains body elements, describing the
+purpose or effect of a command-line option or group of options.
+
+
+Details
+-------
+
+:Category:
+ `Body Subelements`_
+
+:Parents:
+ Only the option_list_item_ element contains ``description``.
+
+:Children:
+ ``description`` elements may contain `body elements`_.
+
+:Analogues:
+ ``description`` has no direct analogues in common DTDs.
+
+:Processing:
+ See option_list_.
+
+
+Content Model
+-------------
+
+.. parsed-literal::
+
+ (`%body.elements;`_)+
+
+:Attributes:
+ The ``description`` element contains only the `common attributes`_:
+ ids_, names_, dupnames_, source_, and classes_.
+
+
+Examples
+--------
+
+See the examples for the option_list_ element.
+
+
+``docinfo``
+===========
+
+The ``docinfo`` element is a container for document bibliographic
+data, or meta-data (data about the document). It corresponds to the
+front matter of a book, such as the title page and copyright page.
+
+
+Details
+-------
+
+:Category:
+ `Structural Subelements`_
+
+:Parents:
+ Only the document_ element contains ``docinfo``.
+
+:Children:
+ ``docinfo`` elements contain `bibliographic elements`_.
+
+:Analogues:
+ ``docinfo`` is analogous to DocBook "info" elements ("bookinfo"
+ etc.). There are no directly analogous HTML elements; the "meta"
+ element carries some of the same information, albeit invisibly.
+
+:Processing:
+ The ``docinfo`` element may be rendered as a two-column table or
+ in other styles. It may even be invisible or omitted from the
+ processed output. Meta-data may be extracted from ``docinfo``
+ children; for example, HTML ``<meta>`` tags may be constructed.
+
+ When Docutils_ transforms a reStructuredText_ field_list_ into a
+ ``docinfo`` element (see the examples below), RCS/CVS keywords are
+ normally stripped from simple (one paragraph) field bodies. For
+ complete details, please see `RCS Keywords`_ in the
+ `reStructuredText Markup Specification`_.
+
+ .. _RCS Keywords: rst/restructuredtext.html#rcs-keywords
+
+
+Content Model
+-------------
+
+.. parsed-literal::
+
+ (`%bibliographic.elements;`_)+
+
+:Attributes:
+ The ``docinfo`` element contains only the `common attributes`_:
+ ids_, names_, dupnames_, source_, and classes_.
+
+
+Examples
+--------
+
+Docinfo is represented in reStructuredText_ by a field_list_ in a
+bibliographic context: the first non-comment element of a document_,
+after any document title_/subtitle_. The field list is transformed
+into a ``docinfo`` element and its children by a transform. Source::
+
+ Docinfo Example
+ ===============
+
+ :Author: J. Random Hacker
+ :Contact: jrh@example.com
+ :Date: 2002-08-18
+ :Status: Work In Progress
+ :Version: 1
+ :Filename: $RCSfile$
+ :Copyright: This document has been placed in the public domain.
+
+Complete pseudo-XML_ result after parsing and applying transforms::
+
+ <document ids="docinfo-example" names="docinfo example">
+ <title>
+ Docinfo Example
+ <docinfo>
+ <author>
+ J. Random Hacker
+ <contact>
+ <reference refuri="mailto:jrh@example.com">
+ jrh@example.com
+ <date>
+ 2002-08-18
+ <status>
+ Work In Progress
+ <version>
+ 1
+ <field>
+ <field_name>
+ Filename
+ <field_body>
+ <paragraph>
+ doctree.txt
+ <copyright>
+ This document has been placed in the public domain.
+
+Note that "Filename" is a non-standard ``docinfo`` field, so becomes a
+generic ``field`` element. Also note that the "RCSfile" keyword
+syntax has been stripped from the "Filename" data.
+
+See field_list_ for an example in a non-bibliographic context. Also
+see the individual examples for the various `bibliographic elements`_.
+
+
+``doctest_block``
+=================
+
+The ``doctest_block`` element is a Python-specific variant of
+literal_block_. It is a block of text where line breaks and
+whitespace are significant and must be preserved. ``doctest_block``
+elements are used for interactive Python interpreter sessions, which
+are distinguished by their input prompt: ``>>>``. They are meant to
+illustrate usage by example, and provide an elegant and powerful
+testing environment via the `doctest module`_ in the Python standard
+library.
+
+.. _doctest module:
+ http://www.python.org/doc/current/lib/module-doctest.html
+
+
+Details
+-------
+
+:Category:
+ `Simple Body Elements`_
+
+:Parents:
+ All elements employing the `%body.elements;`_ or
+ `%structure.model;`_ parameter entities in their content models
+ may contain ``doctest_block``.
+
+:Children:
+ ``doctest_block`` elements may contain text data plus `inline
+ elements`_.
+
+:Analogues:
+ ``doctest_block`` is analogous to the HTML "pre" element and to
+ the DocBook "programlisting" and "screen" elements.
+
+:Processing:
+ As with literal_block_, ``doctest_block`` elements are typically
+ rendered in a monospaced typeface. It is crucial that all
+ whitespace and line breaks are preserved in the rendered form.
+
+
+Content Model
+-------------
+
+.. parsed-literal::
+
+ `%text.model;`_
+
+:Attributes:
+ The ``doctest_block`` element contains the `common attributes`_
+ (ids_, names_, dupnames_, source_, and classes_), plus `xml:space`_.
+
+:Parameter Entities:
+ The `%body.elements;`_ parameter entity directly includes
+ ``doctest_block``. The `%structure.model;`_ parameter entity
+ indirectly includes ``doctest_block``.
+
+
+Examples
+--------
+
+reStructuredText source::
+
+ This is an ordinary paragraph.
+
+ >>> print 'this is a Doctest block'
+ this is a Doctest block
+
+Pseudo-XML_ fragment from simple parsing::
+
+ <paragraph>
+ This is an ordinary paragraph.
+ <doctest_block xml:space="preserve">
+ >>> print 'this is a Doctest block'
+ this is a Doctest block
+
+
+``document``
+============
+
+The ``document`` element is the root (topmost) element of the Docutils
+document tree. ``document`` is the direct or indirect ancestor of
+every other element in the tree. It encloses the entire document
+tree. It is the starting point for a document.
+
+
+Details
+-------
+
+:Category:
+ `Structural Elements`_
+
+:Parents:
+ The ``document`` element has no parents.
+
+:Children:
+ ``document`` elements may contain `structural subelements`_,
+ `structural elements`_, and `body elements`_.
+
+:Analogues:
+ ``document`` is analogous to the HTML "html" element and to
+ several DocBook elements such as "book".
+
+
+Content Model
+-------------
+
+.. parsed-literal::
+
+ ( (title_, subtitle_?)?,
+ decoration_?,
+ (docinfo_, transition_?)?,
+ `%structure.model;`_ )
+
+Depending on the source of the data and the stage of processing, the
+"document" may not initially contain a "title". A document title is
+not directly representable in reStructuredText_. Instead, a lone
+top-level section may have its title promoted to become the document
+title_, and similarly for a lone second-level (sub)section's title to
+become the document subtitle_.
+
+The contents of "decoration_" may be specified in a document,
+constructed programmatically, or both. The "docinfo_" may be
+transformed from an initial field_list_.
+
+See the `%structure.model;`_ parameter entity for details of the body
+of a ``document``.
+
+:Attributes:
+ The ``document`` element contains the `common attributes`_ (ids_,
+ names_, dupnames_, source_, and classes_), plus an optional title__
+ attribute which stores the document title metadata.
+
+ __ `title (attribute)`_
+
+
+Examples
+--------
+
+reStructuredText_ source::
+
+ A Title
+ =======
+
+ A paragraph.
+
+Complete pseudo-XML_ result from simple parsing::
+
+ <document>
+ <section ids="a-title" names="a title">
+ <title>
+ A Title
+ <paragraph>
+ A paragraph.
+
+After applying transforms, the section title is promoted to become the
+document title::
+
+ <document ids="a-title" names="a title">
+ <title>
+ A Title
+ <paragraph>
+ A paragraph.
+
+
+``emphasis``
+============
+
+`To be completed`_.
+
+
+``entry``
+=========
+
+`To be completed`_.
+
+
+``enumerated_list``
+===================
+
+The ``enumerated_list`` element contains list_item_ elements which are
+uniformly marked with enumerator labels.
+
+
+Details
+-------
+
+:Category:
+ `Compound Body Elements`_
+
+:Parents:
+ All elements employing the `%body.elements;`_ or
+ `%structure.model;`_ parameter entities in their content models
+ may contain ``enumerated_list``.
+
+:Children:
+ ``enumerated_list`` elements contain one or more list_item_
+ elements.
+
+:Analogues:
+ ``enumerated_list`` is analogous to the HTML "ol" element and to
+ the DocBook "orderedlist" element.
+
+:Processing:
+ Each list item should begin a new vertical block, prefaced by a
+ enumeration marker (such as "1.").
+
+
+Content Model
+-------------
+
+.. parsed-literal::
+
+ (list_item_ +)
+
+:Attributes:
+ The ``enumerated_list`` element contains the `common attributes`_
+ (ids_, names_, dupnames_, source_, and classes_), plus enumtype_,
+ prefix_, suffix_, and start_.
+
+ ``enumtype`` is used to record the intended enumeration sequence,
+ one of "arabic" (1, 2, 3, ...), "loweralpha" (a, b, c, ..., z),
+ "upperalpha" (A, B, C, ..., Z), "lowerroman" (i, ii, iii, iv, ...,
+ mmmmcmxcix [4999]), or "upperroman" (I, II, III, IV, ...,
+ MMMMCMXCIX [4999]).
+
+ ``prefix`` stores the formatting characters used before the
+ enumerator. In documents originating from reStructuredText_ data,
+ it will contain either "" (empty string) or "(" (left
+ parenthesis). It may or may not affect processing.
+
+ ``suffix`` stores the formatting characters used after the
+ enumerator. In documents originating from reStructuredText_ data,
+ it will contain either "." (period) or ")" (right parenthesis).
+ Depending on the capabilities of the output format, this attribute
+ may or may not affect processing.
+
+ ``start`` contains the ordinal value of the first item in the
+ list, in decimal. For lists beginning at value 1 ("1", "a", "A",
+ "i", or "I"), this attribute may be omitted.
+
+:Parameter Entities:
+ The `%body.elements;`_ parameter entity directly includes
+ ``enumerated_list``. The `%structure.model;`_ parameter entity
+ indirectly includes ``enumerated_list``.
+
+
+Examples
+--------
+
+reStructuredText_ source::
+
+ 1. Item 1.
+
+ (A) Item A.
+ (B) Item B.
+ (C) Item C.
+
+ 2. Item 2.
+
+Pseudo-XML_ fragment from simple parsing::
+
+ <enumerated_list enumtype="arabic" prefix="" suffix=".">
+ <list_item>
+ <paragraph>
+ Item 1.
+ <enumerated_list enumtype="upperalpha" prefix="(" suffix=")">
+ <list_item>
+ <paragraph>
+ Item A.
+ <list_item>
+ <paragraph>
+ Item B.
+ <list_item>
+ <paragraph>
+ Item C.
+ <list_item>
+ <paragraph>
+ Item 2.
+
+See list_item_ for another example.
+
+
+``error``
+=========
+
+The ``error`` element is an admonition, a distinctive and
+self-contained notice. Also see the other admonition elements
+Docutils offers (in alphabetical order): attention_, caution_,
+danger_, hint_, important_, note_, tip_, warning_, and the generic
+admonition_.
+
+
+Details
+-------
+
+:Category:
+ `Compound Body Elements`_
+
+:Parents:
+ All elements employing the `%body.elements;`_ or
+ `%structure.model;`_ parameter entities in their content models
+ may contain ``error``.
+
+:Children:
+ ``error`` elements contain one or more `body elements`_.
+
+:Analogues:
+ ``error`` has no direct analogues in common DTDs. It can be
+ emulated with primitives and type effects.
+
+:Processing:
+ Rendered distinctly (inset and/or in a box, etc.), with the
+ generated title "Error" (or similar).
+
+
+Content Model
+-------------
+
+.. parsed-literal::
+
+ (`%body.elements;`_)+
+
+:Attributes:
+ The ``error`` element contains only the `common attributes`_: ids_,
+ names_, dupnames_, source_, and classes_.
+
+:Parameter Entities:
+ The `%body.elements;`_ parameter entity directly includes
+ ``error``. The `%structure.model;`_ parameter entity indirectly
+ includes ``error``.
+
+
+Examples
+--------
+
+reStructuredText source::
+
+ .. Error:: Does not compute.
+
+Pseudo-XML_ fragment from simple parsing::
+
+ <error>
+ <paragraph>
+ Does not compute.
+
+
+``field``
+=========
+
+The ``field`` element contains a pair of field_name_ and field_body_
+elements.
+
+
+Details
+-------
+
+:Category:
+ `Body Subelements`_
+
+:Parents:
+ The following elements may contain ``field``: docinfo_,
+ field_list_
+
+:Children:
+ Each ``field`` element contains one field_name_ and one
+ field_body_ element.
+
+:Analogues:
+ ``field`` has no direct analogues in common DTDs.
+
+:Processing:
+ See field_list_.
+
+
+Content Model
+-------------
+
+.. parsed-literal::
+
+ (field_name_, field_body_)
+
+:Attributes:
+ The ``field`` element contains only the `common attributes`_:
+ ids_, names_, dupnames_, source_, and classes_.
+
+:Parameter Entities:
+ The `%bibliographic.elements;`_ parameter entity directly includes
+ ``field``.
+
+
+Examples
+--------
+
+See the examples for the field_list_ and docinfo_ elements.
+
+
+``field_body``
+==============
+
+The ``field_body`` element contains body elements. It is analogous to
+a database field's data.
+
+
+Details
+-------
+
+:Category:
+ `Body Subelements`_
+
+:Parents:
+ Only the field_ element contains ``field_body``.
+
+:Children:
+ ``field_body`` elements may contain `body elements`_.
+
+:Analogues:
+ ``field_body`` has no direct analogues in common DTDs.
+
+:Processing:
+ See field_list_.
+
+
+Content Model
+-------------
+
+.. parsed-literal::
+
+ (`%body.elements;`_)*
+
+:Attributes:
+ The ``field_body`` element contains only the `common attributes`_:
+ ids_, names_, dupnames_, source_, and classes_.
+
+
+Examples
+--------
+
+See the examples for the field_list_ and docinfo_ elements.
+
+
+``field_list``
+==============
+
+The ``field_list`` element contains two-column table-like structures
+resembling database records (label & data pairs). Field lists are
+often meant for further processing. In reStructuredText_, field lists
+are used to represent bibliographic fields (contents of the docinfo_
+element) and `directive options`_.
+
+Details
+-------
+
+:Category:
+ `Compound Body Elements`_
+
+:Parents:
+ All elements employing the `%body.elements;`_ or
+ `%structure.model;`_ parameter entities in their content models
+ may contain ``field_list``.
+
+:Children:
+ ``field_list`` elements contain one or more field_ elements.
+
+:Analogues:
+ ``field_list`` has no direct analogues in common DTDs. It can be
+ emulated with primitives such as tables.
+
+:Processing:
+ A ``field_list`` is typically rendered as a two-column list, where
+ the first column contains "labels" (usually with a colon suffix).
+ However, field lists are often used for extension syntax or
+ special processing. Such structures do not survive as field lists
+ to be rendered.
+
+
+Content Model
+-------------
+
+.. parsed-literal::
+
+ (field_ +)
+
+:Attributes:
+ The ``field_list`` element contains only the `common attributes`_:
+ ids_, names_, dupnames_, source_, and classes_.
+
+:Parameter Entities:
+ The `%body.elements;`_ parameter entity directly includes
+ ``field_list``. The `%structure.model;`_ parameter entity
+ indirectly includes ``field_list``.
+
+
+Examples
+--------
+
+reStructuredText_ source::
+
+ :Author: Me
+ :Version: 1
+ :Date: 2001-08-11
+ :Parameter i: integer
+
+Pseudo-XML_ fragment from simple parsing::
+
+ <field_list>
+ <field>
+ <field_name>
+ Author
+ <field_body>
+ <paragraph>
+ Me
+ <field>
+ <field_name>
+ Version
+ <field_body>
+ <paragraph>
+ 1
+ <field>
+ <field_name>
+ Date
+ <field_body>
+ <paragraph>
+ 2001-08-11
+ <field>
+ <field_name>
+ Parameter i
+ <field_body>
+ <paragraph>
+ integer
+
+.. _directive options: rst/restructuredtext.html#directive-options
+
+
+``field_name``
+==============
+
+The ``field_name`` element contains text; it is analogous to a
+database field's name.
+
+
+Details
+-------
+
+:Category:
+ `Body Subelements`_ (simple)
+
+:Parents:
+ Only the field_ element contains ``field_name``.
+
+:Children:
+ ``field_name`` elements may contain text data plus `inline elements`_.
+
+:Analogues:
+ ``field_name`` has no direct analogues in common DTDs.
+
+:Processing:
+ See field_list_.
+
+
+Content Model
+-------------
+
+.. parsed-literal::
+
+ `%text.model;`_
+
+:Attributes:
+ The ``field_name`` element contains only the `common attributes`_:
+ ids_, names_, dupnames_, source_, and classes_.
+
+
+Examples
+--------
+
+See the examples for the field_list_ and docinfo_ elements.
+
+
+``figure``
+==========
+
+`To be completed`_.
+
+
+``footer``
+==========
+
+The ``footer`` element is a container element whose contents are meant
+to appear at the bottom of a web page, or repeated at the bottom of
+every printed page. The ``footer`` element may contain processing
+information (datestamp, a link to Docutils_, etc.) as well as custom
+content.
+
+
+Details
+-------
+
+:Category:
+ `Decorative Elements`_
+
+:Parents:
+ Only the decoration_ element contains ``footer``.
+
+:Children:
+ ``footer`` elements may contain `body elements`_.
+
+:Analogues:
+ There are no direct analogies to ``footer`` in HTML or DocBook.
+ Equivalents are typically constructed from primitives and/or
+ generated by the processing system.
+
+
+Content Model
+-------------
+
+.. parsed-literal::
+
+ (`%body.elements;`_)+
+
+:Attributes:
+ The ``footer`` element contains only the `common attributes`_:
+ ids_, names_, dupnames_, source_, and classes_.
+
+
+Examples
+--------
+
+reStructuredText_ source::
+
+ A paragraph.
+
+Complete pseudo-XML_ result after parsing and applying transforms,
+assuming that the datestamp command-line option or configuration
+setting has been supplied::
+
+ <document>
+ <decoration>
+ <footer>
+ <paragraph>
+ Generated on: 2002-08-20.
+ <paragraph>
+ A paragraph.
+
+
+``footnote``
+============
+
+`To be completed`_.
+
+
+``footnote_reference``
+======================
+
+`To be completed`_.
+
+
+``generated``
+=============
+
+Docutils wraps ``generated`` elements around text that is inserted
+(generated) by Docutils; i.e., text that was not in the document, like
+section numbers inserted by the "sectnum" directive.
+
+`To be completed`_.
+
+
+``header``
+==========
+
+The ``header`` element is a container element whose contents are meant
+to appear at the top of a web page, or at the top of every printed
+page.
+
+
+Details
+-------
+
+:Category:
+ `Decorative Elements`_
+
+:Parents:
+ Only the decoration_ element contains ``header``.
+
+:Children:
+ ``header`` elements may contain `body elements`_.
+
+:Analogues:
+ There are no direct analogies to ``header`` in HTML or DocBook.
+ Equivalents are typically constructed from primitives and/or
+ generated by the processing system.
+
+
+Content Model
+-------------
+
+.. parsed-literal::
+
+ (`%body.elements;`_)+
+
+:Attributes:
+ The ``header`` element contains only the `common attributes`_:
+ ids_, names_, dupnames_, source_, and classes_.
+
+
+Examples
+--------
+
+reStructuredText source fragment::
+
+ .. header:: This space for rent.
+
+Pseudo-XML_ fragment from simple parsing::
+
+ <document>
+ <decoration>
+ <header>
+ <paragraph>
+ This space for rent.
+
+
+``hint``
+========
+
+The ``hint`` element is an admonition, a distinctive and
+self-contained notice. Also see the other admonition elements
+Docutils offers (in alphabetical order): attention_, caution_,
+danger_, error_, important_, note_, tip_, warning_, and the generic
+admonition_.
+
+
+Details
+-------
+
+:Category:
+ `Compound Body Elements`_
+
+:Parents:
+ All elements employing the `%body.elements;`_ or
+ `%structure.model;`_ parameter entities in their content models
+ may contain ``hint``.
+
+:Children:
+ ``hint`` elements contain one or more `body elements`_.
+
+:Analogues:
+ ``hint`` has no direct analogues in common DTDs. It can be
+ emulated with primitives and type effects.
+
+:Processing:
+ Rendered distinctly (inset and/or in a box, etc.), with the
+ generated title "Hint" (or similar).
+
+
+Content Model
+-------------
+
+.. parsed-literal::
+
+ (`%body.elements;`_)+
+
+:Attributes:
+ The ``hint`` element contains only the `common attributes`_: ids_,
+ names_, dupnames_, source_, and classes_.
+
+:Parameter Entities:
+ The `%body.elements;`_ parameter entity directly includes
+ ``hint``. The `%structure.model;`_ parameter entity indirectly
+ includes ``hint``.
+
+
+Examples
+--------
+
+reStructuredText source::
+
+ .. Hint:: It's bigger than a bread box.
+
+Pseudo-XML_ fragment from simple parsing::
+
+ <hint>
+ <paragraph>
+ It's bigger than a bread box.
+
+
+``image``
+=========
+
+:Attributes:
+ The ``image`` element contains the `common attributes`_ (ids_,
+ names_, dupnames_, source_, and classes_), plus uri, alt, height_,
+ width_, and scale_.
+
+`To be completed`_.
+
+
+``important``
+=============
+
+The ``important`` element is an admonition, a distinctive and
+self-contained notice. Also see the other admonition elements
+Docutils offers (in alphabetical order): attention_, caution_,
+danger_, error_, hint_, note_, tip_, warning_, and the generic
+admonition_.
+
+
+Details
+-------
+
+:Category:
+ `Compound Body Elements`_
+
+:Parents:
+ All elements employing the `%body.elements;`_ or
+ `%structure.model;`_ parameter entities in their content models
+ may contain ``important``.
+
+:Children:
+ ``important`` elements contain one or more `body elements`_.
+
+:Analogues:
+ ``important`` is analogous to the DocBook "important" element.
+
+:Processing:
+ Rendered distinctly (inset and/or in a box, etc.), with the
+ generated title "Important" (or similar).
+
+
+Content Model
+-------------
+
+.. parsed-literal::
+
+ (`%body.elements;`_)+
+
+:Attributes:
+ The ``important`` element contains only the `common attributes`_:
+ ids_, names_, dupnames_, source_, and classes_.
+
+:Parameter Entities:
+ The `%body.elements;`_ parameter entity directly includes
+ ``important``. The `%structure.model;`_ parameter entity
+ indirectly includes ``important``.
+
+
+Examples
+--------
+
+reStructuredText source::
+
+ .. Important::
+
+ * Wash behind your ears.
+ * Clean up your room.
+ * Back up your data.
+ * Call your mother.
+
+Pseudo-XML_ fragment from simple parsing::
+
+ <important>
+ <bullet_list>
+ <list_item>
+ <paragraph>
+ Wash behind your ears.
+ <list_item>
+ <paragraph>
+ Clean up your room.
+ <list_item>
+ <paragraph>
+ Back up your data.
+ <list_item>
+ <paragraph>
+ Call your mother.
+
+
+``inline``
+==========
+
+`To be completed`_.
+
+
+``label``
+=========
+
+`To be completed`_.
+
+
+``legend``
+==========
+
+`To be completed`_.
+
+
+``line``
+========
+
+The ``line`` element contains a single line of text, part of a
+`line_block`_.
+
+
+Details
+-------
+
+:Category:
+ `Body Subelements`_ (simple)
+
+:Parents:
+ Only the `line_block`_ element contains ``line``.
+
+:Children:
+ ``line`` elements may contain text data plus `inline elements`_.
+
+:Analogues:
+ ``line`` has no direct analogues in common DTDs. It can be
+ emulated with primitives or type effects.
+
+:Processing:
+ See `line_block`_.
+
+
+Content Model
+-------------
+
+.. parsed-literal::
+
+ `%text.model;`_
+
+:Attributes:
+ The ``line`` element contains the `common attributes`_ (ids_,
+ names_, dupnames_, source_, and classes_), plus `xml:space`_.
+
+
+Examples
+--------
+
+See `line_block`_.
+
+
+``line_block``
+==============
+
+The ``line_block`` element contains a sequence of lines and nested
+line blocks. Line breaks (implied between elements) and leading
+whitespace (indicated by nesting) is significant and must be
+preserved. ``line_block`` elements are commonly used for verse and
+addresses. See `literal_block`_ for an alternative useful for program
+listings and interactive computer sessions.
+
+
+Details
+-------
+
+:Category:
+ `Compound Body Elements`_
+
+:Parents:
+ All elements employing the `%body.elements;`_ or
+ `%structure.model;`_ parameter entities in their content models
+ may contain ``line_block``.
+
+:Children:
+ ``line_block`` elements may contain line_ elements and nested
+ ``line_block`` elements.
+
+:Analogues:
+ ``line_block`` is analogous to the DocBook "literallayout" element
+ and to the HTML "pre" element (with modifications to typeface
+ styles).
+
+:Processing:
+ Unlike ``literal_block``, ``line_block`` elements are typically
+ rendered in an ordinary text typeface. It is crucial that leading
+ whitespace and line breaks are preserved in the rendered form.
+
+
+Content Model
+-------------
+
+.. parsed-literal::
+
+ (line_ | line_block_)+
+
+:Attributes:
+ The ``line_block`` element contains the `common attributes`_ (ids_,
+ names_, dupnames_, source_, and classes_), plus `xml:space`_.
+
+:Parameter Entities:
+ The `%body.elements;`_ parameter entity directly includes
+ ``line_block``. The `%structure.model;`_ parameter entity
+ indirectly includes ``line_block``.
+
+
+Examples
+--------
+
+reStructuredText uses a directive to indicate a ``line_block``.
+Example source::
+
+ Take it away, Eric the Orchestra Leader!
+
+ | A one, two, a one two three four
+ |
+ | Half a bee, philosophically,
+ | must, *ipso facto*, half not be.
+ | But half the bee has got to be,
+ | *vis a vis* its entity. D'you see?
+ |
+ | But can a bee be said to be
+ | or not to be an entire bee,
+ | when half the bee is not a bee,
+ | due to some ancient injury?
+ |
+ | Singing...
+
+Pseudo-XML_ fragment from simple parsing::
+
+ <paragraph>
+ Take it away, Eric the Orchestra Leader!
+ <line_block>
+ <line>
+ A one, two, a one two three four
+ <line>
+ <line>
+ Half a bee, philosophically,
+ <line_block>
+ <line>
+ must,
+ <emphasis>
+ ipso facto
+ , half not be.
+ <line>
+ But half the bee has got to be,
+ <line_block>
+ <line>
+ <emphasis>
+ vis a vis
+ its entity. D'you see?
+ <line>
+ <line>
+ But can a bee be said to be
+ <line_block>
+ <line>
+ or not to be an entire bee,
+ <line_block>
+ <line>
+ when half the bee is not a bee,
+ <line_block>
+ <line>
+ due to some ancient injury?
+ <line>
+ <line>
+ Singing...
+
+
+``list_item``
+=============
+
+The ``list_item`` element is a container for the elements of a list
+item.
+
+
+Details
+-------
+
+:Category:
+ `Body Subelements`_ (compound)
+
+:Parents:
+ The bullet_list_ and enumerated_list_ elements contain
+ ``list_item``.
+
+:Children:
+ ``list_item`` elements may contain `body elements`_.
+
+:Analogues:
+ ``list_item`` is analogous to the HTML "li" element and to the
+ DocBook "listitem" element.
+
+:Processing:
+ See bullet_list_ or enumerated_list_.
+
+
+Content Model
+-------------
+
+.. parsed-literal::
+
+ (`%body.elements;`_)*
+
+:Attributes:
+ The ``list_item`` element contains only the `common attributes`_:
+ ids_, names_, dupnames_, source_, and classes_.
+
+
+Examples
+--------
+
+reStructuredText_ source::
+
+ 1. Outer list, item 1.
+
+ * Inner list, item 1.
+ * Inner list, item 2.
+
+ 2. Outer list, item 2.
+
+Pseudo-XML_ fragment from simple parsing::
+
+ <enumerated_list enumtype="arabic" prefix="" suffix=".">
+ <list_item>
+ <paragraph>
+ Outer list, item 1.
+ <bullet_list bullet="*">
+ <list_item>
+ <paragraph>
+ Inner list, item 1.
+ <list_item>
+ <paragraph>
+ Inner list, item 2.
+ <list_item>
+ <paragraph>
+ Outer list, item 2.
+
+See bullet_list_ or enumerated_list_ for further examples.
+
+
+``literal``
+===========
+
+`To be completed`_.
+
+
+``literal_block``
+=================
+
+The ``literal_block`` element contains a block of text where line
+breaks and whitespace are significant and must be preserved.
+``literal_block`` elements are commonly used for program listings and
+interactive computer sessions. See `line_block`_ for an alternative
+useful for verse and addresses.
+
+
+Details
+-------
+
+:Category:
+ `Simple Body Elements`_
+
+:Parents:
+ All elements employing the `%body.elements;`_ or
+ `%structure.model;`_ parameter entities in their content models
+ may contain ``literal_block``.
+
+:Children:
+ ``literal_block`` elements may contain text data plus `inline
+ elements`_.
+
+:Analogues:
+ ``literal_block`` is analogous to the HTML "pre" element and to
+ the DocBook "programlisting" and "screen" elements.
+
+:Processing:
+ ``literal_block`` elements are typically rendered in a monospaced
+ typeface. It is crucial that all whitespace and line breaks are
+ preserved in the rendered form.
+
+
+Content Model
+-------------
+
+.. parsed-literal::
+
+ `%text.model;`_
+
+:Attributes:
+ The ``literal_block`` element contains the `common attributes`_
+ (ids_, names_, dupnames_, source_, and classes_), plus `xml:space`_.
+
+:Parameter Entities:
+ The `%body.elements;`_ parameter entity directly includes
+ ``literal_block``. The `%structure.model;`_ parameter entity
+ indirectly includes ``literal_block``.
+
+
+Examples
+--------
+
+reStructuredText source::
+
+ Here is a literal block::
+
+ if literal_block:
+ text = 'is left as-is'
+ spaces_and_linebreaks = 'are preserved'
+ markup_processing = None
+
+Pseudo-XML_ fragment from simple parsing::
+
+ <paragraph>
+ Here is a literal block:
+ <literal_block xml:space="preserve">
+ if literal_block:
+ text = 'is left as-is'
+ spaces_and_linebreaks = 'are preserved'
+ markup_processing = None
+
+``math``
+========
+
+The ``math`` element contains text in `LaTeX math format` [#latex-math]_
+that is typeset as mathematical notation (inline formula).
+
+If the output format does not support math typesetting, the content is
+inserted verbatim.
+
+Details
+-------
+
+:Category:
+ `Inline Elements`_
+
+:Parents:
+ All elements employing the `%inline.elements;`_ parameter entities in
+ their content models may contain ``math``.
+
+:Children:
+ ``math`` elements may contain text data.
+
+:Analogues:
+ ``math`` is analogous to a MathML "math" element or
+ the LaTeX (``$ math $``) mode.
+
+:Processing:
+ Rendered as mathematical notation.
+
+Content Model
+-------------
+
+.. parsed-literal::
+
+ `%text.model;`_
+
+:Attributes:
+ The ``math`` element contains the `common attributes`_
+ (ids_, names_, dupnames_, source_, and classes_).
+
+.. [#latex-math] For details of the supported mathematical language, see
+ the `"math" directive`_
+
+.. _"math" directive: rst/directives.html#math
+
+
+``math_block``
+==============
+
+The ``math_block`` element contains a block of text in `LaTeX math
+format` [#latex-math]_ that is typeset as mathematical notation
+(display formula). The ``math_block`` element is generated during
+the initial parse from a `"math" directive`_.
+
+If the output format does not support math typesetting, the content is
+inserted verbatim.
+
+Details
+-------
+
+:Category:
+ `Simple Body Elements`_
+
+:Parents:
+ All elements employing the `%body.elements;`_ or
+ `%structure.model;`_ parameter entities in their content models
+ may contain ``math_block``.
+
+:Children:
+ ``math_block`` elements may contain text data.
+
+:Analogues:
+ ``math_block`` is analogous to a LaTeX "equation*" environment or
+ a MathML "math" element displayed as block-level element.
+
+:Processing:
+ Rendered in a block as mathematical notation, typically centered or with
+ indentation
+
+Content Model
+-------------
+
+.. parsed-literal::
+
+ (#PCDATA)
+
+:Attributes:
+ The ``math`` element contains the `common attributes`_
+ (ids_, names_, dupnames_, source_, and classes_).
+
+
+``note``
+========
+
+The ``note`` element is an admonition, a distinctive and
+self-contained notice. Also see the other admonition elements
+Docutils offers (in alphabetical order): attention_, caution_,
+danger_, error_, hint_, important_, tip_, warning_, and the generic
+admonition_.
+
+
+Details
+-------
+
+:Category:
+ `Compound Body Elements`_
+
+:Parents:
+ All elements employing the `%body.elements;`_ or
+ `%structure.model;`_ parameter entities in their content models
+ may contain ``note``.
+
+:Children:
+ ``note`` elements contain one or more `body elements`_.
+
+:Analogues:
+ ``note`` is analogous to the DocBook "note" element.
+
+:Processing:
+ Rendered distinctly (inset and/or in a box, etc.), with the
+ generated title "Note" (or similar).
+
+
+Content Model
+-------------
+
+.. parsed-literal::
+
+ (`%body.elements;`_)+
+
+:Attributes:
+ The ``note`` element contains only the `common attributes`_: ids_,
+ names_, dupnames_, source_, and classes_.
+
+:Parameter Entities:
+ The `%body.elements;`_ parameter entity directly includes
+ ``note``. The `%structure.model;`_ parameter entity indirectly
+ includes ``note``.
+
+
+Examples
+--------
+
+reStructuredText source::
+
+ .. Note:: Admonitions can be handy to break up a
+ long boring technical document.
+
+Pseudo-XML_ fragment from simple parsing::
+
+ <note>
+ <paragraph>
+ Admonitions can be handy to break up a
+ long boring technical document.
+
+``option``
+==========
+
+The ``option`` element groups an option string together with zero or
+more option argument placeholders. Note that reStructuredText_
+currently supports only one argument per option.
+
+
+Details
+-------
+
+:Category:
+ `Body Subelements`_
+
+:Parents:
+ Only the option_group_ element contains ``option``.
+
+:Children:
+ Each ``option`` element contains one option_string_ and zero or
+ more option_argument_ elements.
+
+:Analogues:
+ ``option`` has no direct analogues in common DTDs.
+
+:Processing:
+ See option_list_.
+
+
+Content Model
+-------------
+
+.. parsed-literal::
+
+ (option_string_, option_argument_ \*)
+
+:Attributes:
+ The ``option`` element contains only the `common attributes`_:
+ ids_, names_, dupnames_, source_, and classes_.
+
+
+Examples
+--------
+
+See the examples for the option_list_ element.
+
+
+``option_argument``
+===================
+
+The ``option_argument`` element contains placeholder text for option
+arguments.
+
+
+Details
+-------
+
+:Category:
+ `Body Subelements`_
+
+:Parents:
+ Only the option_ element contains ``option_argument``.
+
+:Children:
+ ``option_argument`` elements contain text data only.
+
+:Analogues:
+ ``option_argument`` has no direct analogues in common DTDs.
+
+:Processing:
+ The value of the "delimiter" attribute is prefixed to the
+ ``option_argument``, separating it from its option_string_ or a
+ preceding ``option_argument``. The ``option_argument`` text is
+ typically rendered in a monospaced typeface, possibly italicized
+ or otherwise altered to indicate its placeholder nature.
+
+
+Content Model
+-------------
+
+.. parsed-literal::
+
+ (#PCDATA)
+
+:Attributes:
+ The ``option_argument`` element contains the `common attributes`_ (ids_,
+ names_, dupnames_, source_, and classes_), plus delimiter_.
+
+ ``delimiter`` contains the text preceding the ``option_argument``:
+ either the text separating it from the option_string_ (typically
+ either "=" or " ") or the text between option arguments (typically
+ either "," or " ").
+
+
+Examples
+--------
+
+See the examples for the option_list_ element.
+
+
+``option_group``
+================
+
+The ``option_group`` element groups together one or more option_
+elements, all synonyms.
+
+
+Details
+-------
+
+:Category:
+ `Body Subelements`_
+
+:Parents:
+ Only the option_list_item_ element contains ``option_group``.
+
+:Children:
+ ``option_group`` elements contain one or more option_ elements.
+
+ ``option_group`` is an empty element and has no children.
+
+ Each ``option_group`` element contains one _ and
+ one _ element.
+
+:Analogues:
+ ``option_group`` has no direct analogues in common DTDs.
+
+:Processing:
+ Typically option_ elements within an ``option_group`` are joined
+ together in a comma-separated list.
+
+
+Content Model
+-------------
+
+.. parsed-literal::
+
+ (option_group_, description_)
+
+:Attributes:
+ The ``option_group`` element contains only the `common attributes`_:
+ ids_, names_, dupnames_, source_, and classes_.
+
+
+Examples
+--------
+
+See the examples for the option_list_ element.
+
+
+``option_list``
+===============
+
+Each ``option_list`` element contains a two-column list of
+command-line options and descriptions, documenting a program's
+options.
+
+
+Details
+-------
+
+:Category:
+ `Compound Body Elements`_
+
+:Parents:
+ All elements employing the `%body.elements;`_ or
+ `%structure.model;`_ parameter entities in their content models
+ may contain ``option_list``.
+
+:Children:
+ ``option_list`` elements contain one or more option_list_item_
+ elements.
+
+:Analogues:
+ ``option_list`` has no direct analogues in common DTDs. It can be
+ emulated with primitives such as tables.
+
+:Processing:
+ An ``option_list`` is typically rendered as a two-column list,
+ where the first column contains option strings and arguments, and
+ the second column contains descriptions.
+
+
+Content Model
+-------------
+
+.. parsed-literal::
+
+ (option_list_item_ +)
+
+:Attributes:
+ The ``option_list`` element contains only the `common attributes`_:
+ ids_, names_, dupnames_, source_, and classes_.
+
+:Parameter Entities:
+ The `%body.elements;`_ parameter entity directly includes
+ ``option_list``. The `%structure.model;`_ parameter entity
+ indirectly includes ``option_list``.
+
+
+Examples
+--------
+
+reStructuredText_ source::
+
+ -a command-line option "a"
+ -1 file, --one=file, --two file
+ Multiple options with arguments.
+
+Pseudo-XML_ fragment from simple parsing::
+
+ <option_list>
+ <option_list_item>
+ <option_group>
+ <option>
+ <option_string>
+ -a
+ <description>
+ <paragraph>
+ command-line option "a"
+ <option_list_item>
+ <option_group>
+ <option>
+ <option_string>
+ -1
+ <option_argument delimiter=" ">
+ file
+ <option>
+ <option_string>
+ --one
+ <option_argument delimiter="=">
+ file
+ <option>
+ <option_string>
+ --two
+ <option_argument delimiter=" ">
+ file
+ <description>
+ <paragraph>
+ Multiple options with arguments.
+
+
+``option_list_item``
+====================
+
+The ``option_list_item`` element is a container for a pair of
+option_group_ and description_ elements.
+
+
+Details
+-------
+
+:Category:
+ `Body Subelements`_
+
+:Parents:
+ Only the option_list_ element contains ``option_list_item``.
+
+:Children:
+ Each ``option_list_item`` element contains one option_group_ and
+ one description_ element.
+
+:Analogues:
+ ``option_list_item`` has no direct analogues in common DTDs.
+
+:Processing:
+ See option_list_.
+
+
+Content Model
+-------------
+
+.. parsed-literal::
+
+ (option_group_, description_)
+
+:Attributes:
+ The ``option_list_item`` element contains only the `common attributes`_:
+ ids_, names_, dupnames_, source_, and classes_.
+
+
+Examples
+--------
+
+See the examples for the option_list_ element.
+
+
+``option_string``
+=================
+
+The ``option_string`` element contains the text of a command-line
+option.
+
+
+Details
+-------
+
+:Category:
+ `Body Subelements`_
+
+:Parents:
+ Only the option_ element contains ``option_string``.
+
+:Children:
+ ``option_string`` elements contain text data only.
+
+:Analogues:
+ ``option_string`` has no direct analogues in common DTDs.
+
+:Processing:
+ The ``option_string`` text is typically rendered in a monospaced
+ typeface.
+
+
+Content Model
+-------------
+
+.. parsed-literal::
+
+ (#PCDATA)
+
+:Attributes:
+ The ``option_string`` element contains only the `common attributes`_:
+ ids_, names_, dupnames_, source_, and classes_.
+
+
+Examples
+--------
+
+See the examples for the option_list_ element.
+
+
+``organization``
+================
+
+The ``organization`` element contains the name of document author's
+organization, or the organization responsible for the document.
+
+
+Details
+-------
+
+:Category:
+ `Bibliographic Elements`_
+
+:Parents:
+ Only the docinfo_ element contains ``organization``.
+
+:Children:
+ ``organization`` elements may contain text data plus `inline
+ elements`_.
+
+:Analogues:
+ ``organization`` is analogous to the DocBook "orgname",
+ "corpname", or "publishername" elements.
+
+:Processing:
+ See docinfo_.
+
+
+Content Model
+-------------
+
+.. parsed-literal::
+
+ `%text.model;`_
+
+:Attributes:
+ The ``organization`` element contains only the `common attributes`_:
+ ids_, names_, dupnames_, source_, and classes_.
+
+:Parameter Entities:
+ The `%bibliographic.elements;`_ parameter entity directly includes
+ ``organization``.
+
+
+Examples
+--------
+
+reStructuredText_ source::
+
+ Document Title
+ ==============
+
+ :Organization: Humankind
+
+Complete pseudo-XML_ result after parsing and applying transforms::
+
+ <document ids="document-title" names="document title">
+ <title>
+ Document Title
+ <docinfo>
+ <organization>
+ Humankind
+
+See docinfo_ for a more complete example, including processing
+context.
+
+
+``paragraph``
+=============
+
+The ``paragraph`` element contains the text and inline elements of a
+single paragraph, a fundamental building block of documents.
+
+
+Details
+-------
+
+:Category:
+ `Simple Body Elements`_
+
+:Parents:
+ All elements employing the `%body.elements;`_ or
+ `%structure.model;`_ parameter entities in their content models
+ may contain ``paragraph``.
+
+:Children:
+ ``paragraph`` elements may contain text data plus `inline
+ elements`_.
+
+:Analogues:
+ ``paragraph`` is analogous to the HTML "p" element and to the
+ DocBook "para" elements.
+
+
+Content Model
+-------------
+
+.. parsed-literal::
+
+ `%text.model;`_
+
+:Attributes:
+ The ``paragraph`` element contains only the `common attributes`_:
+ ids_, names_, dupnames_, source_, and classes_.
+
+:Parameter Entities:
+ The `%body.elements;`_ parameter entity directly includes
+ ``paragraph``. The `%structure.model;`_ parameter entity
+ indirectly includes ``paragraph``.
+
+
+Examples
+--------
+
+reStructuredText_ source::
+
+ A paragraph.
+
+Pseudo-XML_ fragment from simple parsing::
+
+ <paragraph>
+ A paragraph.
+
+
+``pending``
+===========
+
+`To be completed`_.
+
+
+``problematic``
+===============
+
+`To be completed`_.
+
+
+``raw``
+=======
+
+`To be completed`_.
+
+
+``reference``
+=============
+
+`To be completed`_.
+
+
+``revision``
+============
+
+The ``revision`` element contains the revision number of the document.
+It can be used alone or in conjunction with version_.
+
+
+Details
+-------
+
+:Category:
+ `Bibliographic Elements`_
+
+:Parents:
+ Only the docinfo_ element contains ``revision``.
+
+:Children:
+ ``revision`` elements may contain text data plus `inline
+ elements`_.
+
+:Analogues:
+ ``revision`` is analogous to but simpler than the DocBook
+ "revision" element. It closely matches the DocBook "revnumber"
+ element, but in a simpler context.
+
+:Processing:
+ Often used with the RCS/CVS keyword "Revision". See docinfo_.
+
+
+Content Model
+-------------
+
+.. parsed-literal::
+
+ `%text.model;`_
+
+:Attributes:
+ The ``revision`` element contains only the `common attributes`_:
+ ids_, names_, dupnames_, source_, and classes_.
+
+:Parameter Entities:
+ The `%bibliographic.elements;`_ parameter entity directly includes
+ ``revision``.
+
+
+Examples
+--------
+
+reStructuredText_ source::
+
+ Document Title
+ ==============
+
+ :Version: 1
+ :Revision: b
+
+Complete pseudo-XML_ result after parsing and applying transforms::
+
+ <document ids="document-title" names="document title">
+ <title>
+ Document Title
+ <docinfo>
+ <version>
+ 1
+ <revision>
+ b
+
+See docinfo_ for a more complete example, including processing
+context.
+
+
+``row``
+=======
+
+`To be completed`_.
+
+
+``rubric``
+==========
+
+ rubric n. 1. a title, heading, or the like, in a manuscript,
+ book, statute, etc., written or printed in red or otherwise
+ distinguished from the rest of the text. ...
+
+ -- Random House Webster's College Dictionary, 1991
+
+A rubric is like an informal heading that doesn't correspond to the
+document's structure.
+
+`To be completed`_.
+
+
+``section``
+===========
+
+The ``section`` element is the main unit of hierarchy for Docutils
+documents. Docutils ``section`` elements are a recursive structure; a
+``section`` may contain other ``section`` elements, without limit.
+Paragraphs and other body elements may occur before a ``section``, but
+not after it.
+
+
+Details
+-------
+
+:Category:
+ `Structural Elements`_
+
+:Parents:
+ The following elements may contain ``section``: document_,
+ section_
+
+:Children:
+ ``section`` elements begin with a title_, and may contain `body
+ elements`_ as well as transition_, topic_, and sidebar_ elements.
+
+:Analogues:
+ ``section`` is analogous to DocBook recursive "section" elements,
+ and to HTML "div" elements combined with "h1" etc. title elements.
+
+
+Content Model
+-------------
+
+.. parsed-literal::
+
+ (title_,
+ `%structure.model;`_)
+
+See the `%structure.model;`_ parameter entity for details of the body
+of a ``section``.
+
+:Attributes:
+ The ``section`` element contains only the `common attributes`_:
+ ids_, names_, dupnames_, source_, and classes_.
+
+:Parameter Entities:
+ The `%section.elements;`_ parameter entity directly includes
+ ``section``. The `%structure.model;`_ parameter entity indirectly
+ includes ``section``.
+
+
+Examples
+--------
+
+reStructuredText_ source::
+
+ Title 1
+ =======
+ Paragraph 1.
+
+ Title 2
+ -------
+ Paragraph 2.
+
+ Title 3
+ =======
+ Paragraph 3.
+
+ Title 4
+ -------
+ Paragraph 4.
+
+Complete pseudo-XML_ result after parsing::
+
+ <document>
+ <section ids="title-1" names="title 1">
+ <title>
+ Title 1
+ <paragraph>
+ Paragraph 1.
+ <section ids="title-2" names="title 2">
+ <title>
+ Title 2
+ <paragraph>
+ Paragraph 2.
+ <section ids="title-3" names="title 3">
+ <title>
+ Title 3
+ <paragraph>
+ Paragraph 3.
+ <section ids="title-4" names="title 4">
+ <title>
+ Title 4
+ <paragraph>
+ Paragraph 4.
+
+
+``sidebar``
+===========
+
+Sidebars are like miniature, parallel documents that occur inside
+other documents, providing related or reference material. A
+``sidebar`` is typically offset by a border and "floats" to the side
+of the page; the document's main text may flow around it. Sidebars
+can also be likened to super-footnotes; their content is outside of
+the flow of the document's main text.
+
+The ``sidebar`` element is a nonrecursive section_-like construct
+which may occur at the top level of a section_ wherever a body element
+(list, table, etc.) is allowed. In other words, ``sidebar`` elements
+cannot nest inside body elements, so you can't have a ``sidebar``
+inside a ``table`` or a ``list``, or inside another ``sidebar`` (or
+topic_).
+
+
+Details
+-------
+
+:Category:
+ `Structural Elements`_
+
+:Parents:
+ The following elements may contain ``sidebar``: document_,
+ section_
+
+:Children:
+ ``sidebar`` elements begin with a title_ and an optional subtitle_
+ and contain `body elements`_ and topic_ elements.
+
+:Analogues:
+ ``sidebar`` is analogous to the DocBook "sidebar" element.
+
+:Processing:
+ A ``sidebar`` element should be set off from the rest of the
+ document somehow, typically with a border. Sidebars typically
+ "float" to the side of the page and the document's main text flows
+ around them.
+
+
+Content Model
+-------------
+
+.. parsed-literal::
+
+ (title_, subtitle_?,
+ (`%body.elements;`_ | topic_)+)
+
+:Attributes:
+ The ``sidebar`` element contains only the `common attributes`_:
+ ids_, names_, dupnames_, source_, and classes_.
+
+:Parameter Entities:
+ The `%structure.model;`_ parameter entity directly includes
+ ``sidebar``.
+
+
+Examples
+--------
+
+The `"sidebar" directive`_ is used to create a ``sidebar`` element.
+reStructuredText_ source::
+
+ .. sidebar:: Title
+ :subtitle: If Desired
+
+ Body.
+
+Pseudo-XML_ fragment from simple parsing::
+
+ <sidebar>
+ <title>
+ Title
+ <subtitle>
+ If Desired
+ <paragraph>
+ Body.
+
+.. _"sidebar" directive: rst/directives.html#sidebar
+
+
+``status``
+==========
+
+The ``status`` element contains a status statement for the document,
+such as "Draft", "Final", "Work In Progress", etc.
+
+
+Details
+-------
+
+:Category:
+ `Bibliographic Elements`_
+
+:Parents:
+ Only the docinfo_ element contains ``status``.
+
+:Children:
+ ``status`` elements may contain text data plus `inline elements`_.
+
+:Analogues:
+ ``status`` is analogous to the DocBook "status" element.
+
+:Processing:
+ See docinfo_.
+
+
+Content Model
+-------------
+
+.. parsed-literal::
+
+ `%text.model;`_
+
+:Attributes:
+ The ``status`` element contains only the `common attributes`_:
+ ids_, names_, dupnames_, source_, and classes_.
+
+:Parameter Entities:
+ The `%bibliographic.elements;`_ parameter entity directly includes
+ ``status``.
+
+
+Examples
+--------
+
+reStructuredText_ source::
+
+ Document Title
+ ==============
+
+ :Status: Work In Progress
+
+Complete pseudo-XML_ result after parsing and applying transforms::
+
+ <document ids="document-title" names="document title">
+ <title>
+ Document Title
+ <docinfo>
+ <status>
+ Work In Progress
+
+See docinfo_ for a more complete example, including processing
+context.
+
+
+``strong``
+==========
+
+`To be completed`_.
+
+
+``subscript``
+=============
+
+`To be completed`_.
+
+
+``substitution_definition``
+===========================
+
+`To be completed`_.
+
+
+``substitution_reference``
+==========================
+
+`To be completed`_.
+
+
+``subtitle``
+============
+
+The ``subtitle`` element stores the subtitle of a document_.
+
+
+Details
+-------
+
+:Category:
+ `Structural Subelements`_
+
+:Parents:
+ The document_ and sidebar_ elements may contain ``subtitle``.
+
+:Children:
+ ``subtitle`` elements may contain text data plus `inline
+ elements`_.
+
+:Analogues:
+ ``subtitle`` is analogous to HTML header elements ("h2" etc.) and
+ to the DocBook "subtitle" element.
+
+:Processing:
+ A document's subtitle is usually rendered smaller than its title_.
+
+
+Content Model
+-------------
+
+.. parsed-literal::
+
+ `%text.model;`_
+
+:Attributes:
+ The ``subtitle`` element contains only the `common attributes`_:
+ ids_, names_, dupnames_, source_, and classes_.
+
+
+Examples
+--------
+
+reStructuredText_ source::
+
+ =======
+ Title
+ =======
+ ----------
+ Subtitle
+ ----------
+
+ A paragraph.
+
+Complete pseudo-XML_ result after parsing and applying transforms::
+
+ <document ids="title" names="title">
+ <title>
+ Title
+ <subtitle ids="subtitle" names="subtitle">
+ Subtitle
+ <paragraph>
+ A paragraph.
+
+Note how two section levels have collapsed, promoting their titles to
+become the document's title and subtitle. Since there is only one
+structural element (document), the subsection's ``ids`` and ``names``
+attributes are stored in the ``subtitle`` element.
+
+
+``superscript``
+===============
+
+`To be completed`_.
+
+
+``system_message``
+==================
+
+`To be completed`_.
+
+
+``table``
+=========
+
+Docutils tables are based on the Exchange subset of the CALS-table model
+(OASIS Technical Memorandum 9901:1999 "XML Exchange Table Model DTD",
+http://www.oasis-open.org/html/tm9901.htm).
+
+`To be completed`_.
+
+
+``target``
+==========
+
+`To be completed`_.
+
+
+``tbody``
+=========
+
+`To be completed`_.
+
+
+``term``
+========
+
+The ``term`` element contains a word or phrase being defined in a
+definition_list_.
+
+
+Details
+-------
+
+:Category:
+ `Body Subelements`_ (simple)
+
+:Parents:
+ Only the definition_list_item_ element contains ``term``.
+
+:Children:
+ ``term`` elements may contain text data plus `inline elements`_.
+
+:Analogues:
+ ``term`` is analogous to the HTML "dt" element and to the DocBook
+ "term" element.
+
+:Processing:
+ See definition_list_item_.
+
+
+Content Model
+-------------
+
+.. parsed-literal::
+
+ `%text.model;`_
+
+:Attributes:
+ The ``term`` element contains only the `common attributes`_:
+ ids_, names_, dupnames_, source_, and classes_.
+
+
+Examples
+--------
+
+See the examples for the definition_list_, definition_list_item_, and
+classifier_ elements.
+
+
+``tgroup``
+==========
+
+`To be completed`_.
+
+
+``thead``
+=========
+
+`To be completed`_.
+
+
+``tip``
+=======
+
+The ``tip`` element is an admonition, a distinctive and self-contained
+notice. Also see the other admonition elements Docutils offers (in
+alphabetical order): attention_, caution_, danger_, error_, hint_,
+important_, note_, warning_, and the generic admonition_.
+
+
+Details
+-------
+
+:Category:
+ `Compound Body Elements`_
+
+:Parents:
+ All elements employing the `%body.elements;`_ or
+ `%structure.model;`_ parameter entities in their content models
+ may contain ``tip``.
+
+:Children:
+ ``tip`` elements contain one or more `body elements`_.
+
+:Analogues:
+ ``tip`` is analogous to the DocBook "tip" element.
+
+:Processing:
+ Rendered distinctly (inset and/or in a box, etc.), with the
+ generated title "Tip" (or similar).
+
+
+Content Model
+-------------
+
+.. parsed-literal::
+
+ (`%body.elements;`_)+
+
+:Attributes:
+ The ``tip`` element contains only the `common attributes`_: ids_,
+ names_, dupnames_, source_, and classes_.
+
+:Parameter Entities:
+ The `%body.elements;`_ parameter entity directly includes ``tip``.
+ The `%structure.model;`_ parameter entity indirectly includes
+ ``tip``.
+
+
+Examples
+--------
+
+reStructuredText source::
+
+ .. Tip:: 15% if the service is good.
+
+Pseudo-XML_ fragment from simple parsing::
+
+ <tip>
+ <paragraph>
+ 15% if the service is good.
+
+
+.. _title:
+
+``title``
+=========
+
+The ``title`` element stores the title of a document_, section_,
+topic_, sidebar_, or generic admonition_.
+
+
+Details
+-------
+
+:Category:
+ `Structural Subelements`_
+
+:Parents:
+ The following elements may contain ``title``: document_, section_,
+ topic_, sidebar_, admonition_
+
+:Children:
+ ``title`` elements may contain text data plus `inline elements`_.
+
+:Analogues:
+ ``title`` is analogous to HTML "title" and header ("h1" etc.)
+ elements, and to the DocBook "title" element.
+
+
+Content Model
+-------------
+
+.. parsed-literal::
+
+ `%text.model;`_
+
+:Attributes:
+ The ``title`` element contains the `common attributes`_ (ids_,
+ names_, dupnames_, source_, and classes_), plus refid_ and auto_.
+
+ ``refid`` is used as a backlink to a table of contents entry.
+
+ ``auto`` is used to indicate (with value "1") that the ``title``
+ has been numbered automatically.
+
+
+Examples
+--------
+
+reStructuredText_ source::
+
+ A Title
+ =======
+
+ A paragraph.
+
+Pseudo-XML_ fragment from simple parsing::
+
+ <section ids="a-title" names="a title">
+ <title>
+ A Title
+ <paragraph>
+ A paragraph.
+
+
+``title_reference``
+===================
+
+`To be completed`_.
+
+
+``topic``
+=========
+
+The ``topic`` element is a nonrecursive section_-like construct which
+may occur at the top level of a section_ wherever a body element
+(list, table, etc.) is allowed. In other words, ``topic`` elements
+cannot nest inside body elements, so you can't have a ``topic`` inside
+a ``table`` or a ``list``, or inside another ``topic``.
+
+
+Details
+-------
+
+:Category:
+ `Structural Elements`_
+
+:Parents:
+ The following elements may contain ``topic``: document_, section_,
+ sidebar_
+
+:Children:
+ ``topic`` elements begin with a title_ and may contain `body
+ elements`_.
+
+:Analogues:
+ ``topic`` is analogous to the DocBook "simplesect" element.
+
+:Processing:
+ A ``topic`` element should be set off from the rest of the
+ document somehow, such as with indentation or a border.
+
+
+Content Model
+-------------
+
+.. parsed-literal::
+
+ (title_?,
+ (`%body.elements;`_)+)
+
+:Attributes:
+ The ``topic`` element contains only the `common attributes`_:
+ ids_, names_, dupnames_, source_, and classes_.
+
+:Parameter Entities:
+ The `%structure.model;`_ parameter entity directly includes
+ ``topic``.
+
+
+Examples
+--------
+
+The `"topic" directive`_ is used to create a ``topic`` element.
+reStructuredText_ source::
+
+ .. topic:: Title
+
+ Body.
+
+Pseudo-XML_ fragment from simple parsing::
+
+ <topic>
+ <title>
+ Title
+ <paragraph>
+ Body.
+
+.. _"topic" directive: rst/directives.html#topic
+
+
+``transition``
+==============
+
+The ``transition`` element is commonly seen in novels and short
+fiction, as a gap spanning one or more lines, with or without a type
+ornament such as a row of asterisks. Transitions separate body
+elements and sections, dividing a section into untitled divisions. A
+transition may not begin or end a section [#]_ or document, nor may
+two transitions be immediately adjacent.
+
+See `Doctree Representation of Transitions`__ in `A Record of
+reStructuredText Syntax Alternatives`__.
+
+.. [#] In reStructuredText markup, a transition may appear to fall at
+ the end of a section immediately before another section. A
+ transform recognizes this case and moves the transition so it
+ separates the sections.
+
+__ ../dev/rst/alternatives.html#doctree-representation-of-transitions
+__ ../dev/rst/alternatives.html
+
+
+Details
+-------
+
+:Category:
+ `Structural Subelements`_
+
+:Parents:
+ The following elements may contain ``transition``: document_,
+ section_
+
+:Children:
+ ``transition`` is an empty element and has no children.
+
+:Analogues:
+ ``transition`` is analogous to the HTML "hr" element.
+
+:Processing:
+ The ``transition`` element is typically rendered as vertical
+ whitespace (more than that separating paragraphs), with or without
+ a horizontal line or row of asterisks. In novels, transitions are
+ often represented as a row of three well-spaced asterisks with
+ vertical space above and below.
+
+
+Content Model
+-------------
+
+::
+
+ EMPTY
+
+The ``transition`` element has no content; it is a "point element".
+
+:Attributes:
+ The ``transition`` element contains only the `common attributes`_:
+ ids_, names_, dupnames_, source_, and classes_.
+
+:Parameter Entities:
+ The `%structure.model;`_ parameter entity directly includes
+ ``transition``.
+
+
+Examples
+--------
+
+reStructuredText_ source::
+
+ Paragraph 1.
+
+ --------
+
+ Paragraph 2.
+
+Complete pseudo-XML_ result after parsing::
+
+ <document>
+ <paragraph>
+ Paragraph 1.
+ <transition>
+ <paragraph>
+ Paragraph 2.
+
+
+``version``
+===========
+
+The ``version`` element contains the version number of the document.
+It can be used alone or in conjunction with revision_.
+
+
+Details
+-------
+
+:Category:
+ `Bibliographic Elements`_
+
+:Parents:
+ Only the docinfo_ element contains ``version``.
+
+:Children:
+ ``version`` elements may contain text data plus `inline
+ elements`_.
+
+:Analogues:
+ ``version`` may be considered analogous to the DocBook "revision",
+ "revnumber", or "biblioid" elements.
+
+:Processing:
+ Sometimes used with the RCS/CVS keyword "Revision". See docinfo_
+ and revision_.
+
+
+Content Model
+-------------
+
+.. parsed-literal::
+
+ `%text.model;`_
+
+:Attributes:
+ The ``version`` element contains only the `common attributes`_:
+ ids_, names_, dupnames_, source_, and classes_.
+
+:Parameter Entities:
+ The `%bibliographic.elements;`_ parameter entity directly includes
+ ``version``.
+
+
+Examples
+--------
+
+reStructuredText_ source::
+
+ Document Title
+ ==============
+
+ :Version: 1.1
+
+Complete pseudo-XML_ result after parsing and applying transforms::
+
+ <document ids="document-title" names="document title">
+ <title>
+ Document Title
+ <docinfo>
+ <version>
+ 1.1
+
+See docinfo_ for a more complete example, including processing
+context.
+
+
+``warning``
+===========
+
+The ``warning`` element is an admonition, a distinctive and
+self-contained notice. Also see the other admonition elements
+Docutils offers (in alphabetical order): attention_, caution_,
+danger_, error_, hint_, important_, note_, tip_.
+
+
+Details
+-------
+
+:Category:
+ `Compound Body Elements`_
+
+:Parents:
+ All elements employing the `%body.elements;`_ or
+ `%structure.model;`_ parameter entities in their content models
+ may contain ``warning``.
+
+:Children:
+ ``warning`` elements contain one or more `body elements`_.
+
+:Analogues:
+ ``warning`` is analogous to the DocBook "warning" element.
+
+:Processing:
+ Rendered distinctly (inset and/or in a box, etc.), with the
+ generated title "Warning" (or similar).
+
+
+Content Model
+-------------
+
+.. parsed-literal::
+
+ (`%body.elements;`_)+
+
+:Attributes:
+ The ``warning`` element contains only the `common attributes`_:
+ ids_, names_, dupnames_, source_, and classes_.
+
+:Parameter Entities:
+ The `%body.elements;`_ parameter entity directly includes
+ ``warning``. The `%structure.model;`_ parameter entity indirectly
+ includes ``warning``.
+
+
+Examples
+--------
+
+reStructuredText source::
+
+ .. WARNING:: Reader discretion is strongly advised.
+
+Pseudo-XML_ fragment from simple parsing::
+
+ <warning>
+ <paragraph>
+ Reader discretion is strongly advised.
+
+
+.. _attribute type:
+
+---------------
+Attribute types
+---------------
+
+.. contents:: :local:
+ :depth: 1
+
+Standard attribute types
+========================
+
+Attribute types defined in the `attribute types`__ section of the
+`XML 1.0 specification`_:
+
+_`CDATA`
+ Character data. CDATA attributes may contain arbitrary text.
+
+_`NMTOKEN`
+ A "name token". One or more of letters, digits, ".", "-", and
+ "_".
+
+_`NMTOKENS`
+ One or more space-separated NMTOKEN values.
+
+_`EnumeratedType`
+ The attribute value may be one of a specified list of values.
+
+Docutils uses `custom attribute types`_ instead of the ID, IDREF, and IDREFS
+standard types, because it does not adhere to the `One ID per Element Type`_
+validity constraint.
+
+__ `XML attribute types`_
+
+
+Custom attribute types
+======================
+
+The Docutils DTD defines `parameter entities`_ that resolve to standard
+attribute types to highlight specific attribute value constraints.
+
+_`yesorno`
+ Boolean: no if zero ("0"), yes if any other value.
+ Resolves to ``NMTOKEN``.
+
+ Used in the `anonymous`_ and `stub`_ attributes.
+
+_`number`
+ The attribute value must be a number. Resolves to ``NMTOKEN``.
+
+ Used in the `start`_ and `scale`_ attributes.
+
+ .. also ltrim, rtrim
+
+_`measure`
+ A number which may be immediately followed by a unit or percent sign.
+ Resolves to CDATA.
+
+ Used in the `height`_ and `width`_ attributes.
+
+_`classnames.type`
+ A space-separated list of `class names` [#classname]_. Resolves to NMTOKEN.
+
+ Used in the `classes`_ attribute.
+
+_`refname.type`
+ A normalized_ `reference name`_. Resolves to CDATA (in contrast to
+ NMTOKENS, `reference names`_ may consist of any text).
+
+ Used in the `refname`_ attribute.
+
+_`refnames.type`
+ A space-separated list of `reference names`_. Resolves to CDATA.
+
+ `Backslash escaping`_ is used for space characters inside a `reference
+ name`.
+
+ Used in the `names`_ and `dupnames`_ attributes.
+
+_`ids.type`
+ A space-separated list of unique `identifier keys` [#identifier]_.
+ Resolves to NMTOKENS (the XML `standard attribute types`_ do not provide
+ for a list of IDs).
+
+ Used in the `ids`_ attribute.
+
+_`idref.type`
+ A reference to an `identifier key`_.
+ Resolves to NMTOKEN (Docutils identifier keys do not use the ID standard
+ type as required by the `IDREF Validity constraint`_).
+
+ Used in the `refid`_ attribute.
+
+_`idrefs.type`
+ A list of references to element identifiers.
+ Resolves to NMTOKENS.
+
+ Used in the `backrefs`_ attribute.
+
+.. _`class names`:
+
+.. [#classname] `Class names` define sub-classes of existing elements.
+
+ In reStructuredText, custom `class names` can be specified using
+ the `"class" directive`_, a directive's `:class: option`_, or
+ `custom interpreted text roles`_.
+ Docutils normalizes them to conform to both, HTML4.1 and CSS1.0 `name`
+ requirements (the regular expression ``[a-z](-?[a-z0-9]+)*``) via the
+ `identifier normalization`_.
+
+.. _identifiers:
+.. _identifier key:
+.. _identifier keys:
+
+.. [#identifier] `Identifier keys` are used for cross references in
+ generated documents. Therefore, they must comply with restrictions in the
+ respective output formats (HTML4.1__, HTML5__, `polyglot HTML`__,
+ LaTeX__, ODT__, troff (manpage), XML__).
+
+ Identifier keys cannot be specified directly in reStructuredText.
+ Docutils generates them by applying the `identifier normalization`_ to
+ `reference names`_ or from the auto_id_prefix_, prepending the id_prefix_
+ and potentially appending numbers for disambiguation.
+
+ __ http://www.w3.org/TR/html401/types.html#type-name
+ __ https://www.w3.org/TR/html50/dom.html#the-id-attribute
+ __ https://www.w3.org/TR/html-polyglot/#id-attribute
+ __ https://tex.stackexchange.com/questions/18311/what-are-the-valid-names-as-labels
+ __ https://help.libreoffice.org/6.3/en-US/text/swriter/01/04040000.html?DbPAR=WRITER#bm_id4974211
+ __ https://www.w3.org/TR/REC-xml/#id
+
+
+.. _XML 1.0 specification: https://www.w3.org/TR/REC-xml
+.. _XML attribute types: https://www.w3.org/TR/REC-xml/#sec-attribute-types
+.. _One ID per Element Type: https://www.w3.org/TR/REC-xml/#one-id-per-el
+.. .. _ID attribute type: https://www.w3.org/TR/REC-xml/#id
+.. _parameter entities: https://www.w3.org/TR/REC-xml/#dt-PE
+.. _IDREF Validity constraint: https://www.w3.org/TR/REC-xml/#idref
+
+.. _reference names:
+.. _reference name: rst/restructuredtext.html#reference-names
+.. _backslash escaping: rst/restructuredtext.html#escaping-mechanism
+.. _id_prefix: ../user/config.html#id-prefix
+.. _auto_id_prefix: ../user/config.html#auto-id-prefix
+.. _identifier normalization:
+ rst/directives.html#identifier-normalization
+.. _`:class: option`: rst/directives.html#class-option
+.. _custom interpreted text roles:
+ rst/directives.html#custom-interpreted-text-roles
+
+
+---------------------
+ Attribute Reference
+---------------------
+
+.. contents:: :local:
+ :depth: 1
+
+_`Common Attributes`: Through the `%basic.atts;`_ parameter entity,
+all elements contain the following attributes: ids_, names_ or dupnames_,
+source_, and classes_.
+
+
+``anonymous``
+=============
+
+Attribute type: `yesorno`_. Default value: none (implies no).
+
+The ``anonymous`` attribute is used for unnamed hyperlinks in the
+target_ and reference_ elements (via the `%anonymous.att;`_ parameter
+entity).
+
+
+``auto``
+========
+
+Attribute type: `CDATA`_. Default value: none.
+
+The ``auto`` attribute is used to indicate automatically-numbered
+footnote_, footnote_reference_ and title_ elements (via the
+`%auto.att;`_ parameter entity).
+
+
+``backrefs``
+============
+
+Attribute type: `idrefs.type`_. Default value: none.
+
+The ``backrefs`` attribute contains a space-separated list of identifier_
+references, used for backlinks from footnote_, citation_, and
+system_message_ elements (via the `%backrefs.att;`_ parameter entity).
+
+
+``bullet``
+==========
+
+Attribute type: `CDATA`_. Default value: none.
+
+The ``bullet`` attribute is used in the bullet_list_ element.
+
+
+``classes``
+===========
+
+Attribute type: `classnames.type`_. Default value: none.
+
+The ``classes`` attribute is a space separated list containing zero or more
+`class names`_.
+
+The purpose of the attribute is to indicate an "is-a" variant relationship,
+to allow an extensible way of defining sub-classes of existing elements. It
+can be used to carry context forward between a Docutils Reader and Writer,
+when a custom structure is reduced to a standardized document tree. One
+common use is in conjunction with stylesheets, to add selection criteria.
+It should not be used to carry formatting instructions or arbitrary content.
+
+The ``classes`` attribute's contents should be ignorable. Writers that
+are not familiar with the variant expressed should be able to ignore
+the attribute.
+
+``classes`` is one of the `common attributes`_, shared by all Docutils
+elements.
+
+.. _"class" directive: rst/directives.html#class
+
+
+``delimiter``
+=============
+
+Attribute type: `CDATA`_. Default value: none.
+
+The ``delimiter`` attribute is used in the option_argument_ element.
+
+
+``dupnames``
+============
+
+Attribute type: `refnames.type`_. Default value: none.
+
+The ``dupnames`` attribute replaces the `names`_ attribute
+when there has been a naming conflict.
+``dupnames`` is one of the `common attributes`_, shared by all
+Docutils elements.
+
+
+``enumtype``
+============
+
+Attribute type: EnumeratedType_, one of "arabic", "loweralpha",
+"upperalpha", "lowerroman", or "upperroman". Default value: none.
+
+The ``enumtype`` attribute is used in the enumerated_list_ element.
+
+
+``height``
+==========
+
+Attribute type: measure_. Default value: none.
+
+The ``height`` attribute is used in the image_ element.
+
+
+``ids``
+=======
+
+Attribute type: `ids.type`_. Default value: none.
+
+The ``ids`` attribute is a space separated list containing one or more
+unique `identifier keys`_, typically assigned by the system.
+
+``ids`` is one of the `common attributes`_, shared by all Docutils
+elements.
+
+.. TODO:
+ * Use 'id' for primary identifier key?
+ * Keep additional keys in `ids`
+ or in the preceding target elements?
+
+
+``names``
+=========
+
+Attribute type: `refnames.type`_. Default value: none.
+
+The ``names`` attribute is a space-separated list containing
+`normalized`_ `reference names`_ of an element. Whitespace inside a
+name is backslash escaped.
+Each name in the list must be unique; if there are name conflicts
+(two or more elements want to the same name), the contents will be
+transferred to the `dupnames`_ attribute on the duplicate elements.
+An element may have at most one of the ``names`` or ``dupnames``
+attributes, but not both.
+
+`Reference names`_ are identifiers assigned in the markup. They
+originate from `internal hyperlink targets`_, a directive's `name
+option`_, or the element's title or content and are used for
+internal cross-references (cf. refname_).
+
+``names`` is one of the `common attributes`_, shared by all
+Docutils elements.
+
+.. _normalized:
+ rst/restructuredtext.html#normalized-reference-names
+.. _internal hyperlink targets:
+ rst/restructuredtext.html#internal-hyperlink-targets
+.. _name option: rst/directives.html#name
+
+
+``prefix``
+==========
+
+Attribute type: `CDATA`_. Default value: none.
+
+The ``prefix`` attribute is used in the enumerated_list_ element.
+
+
+``refid``
+=========
+
+Attribute type: `idref.type`_. Default value: none.
+
+The ``refid`` attribute contains a reference to an `identifier key`_
+
+``refid`` is used by the target_, reference_, footnote_reference_,
+citation_reference_, title_ and problematic_ elements (via the
+`%refid.att;`_ and `%reference.atts;`_ parameter entities).
+
+
+``refname``
+===========
+
+Attribute type: `refname.type`_. Default value: none.
+
+The ``refname`` attribute contains a reference to one of the
+`reference names`_ in the `names`_ attribute of another element. On
+a `target`_ element, ``refname`` indicates an `indirect target`_ which
+may resolve to either an internal or external reference. Docutils
+"transforms_" replace the ``refname`` attribute with a refid_ pointing
+to the same element.
+
+``refname`` is used by the target_, reference_, footnote_reference_,
+citation_reference_, and substitution_reference_ elements (via the
+`%refname.att;`_ and `%reference.atts;`_ parameter entities).
+
+.. _indirect target: rst/restructuredtext.html#indirect-hyperlink-targets
+.. _transforms: transforms.html
+
+
+``refuri``
+==========
+
+Attribute type: `CDATA`_. Default value: none.
+
+The ``refuri`` attribute contains an external reference to a URI/URL.
+It is used by the target_, reference_, footnote_reference_, and
+citation_reference_ elements (via the `%reference.atts;`_ parameter
+entity).
+
+
+``scale``
+==========
+
+Attribute type: number_. Default value: none.
+
+The ``scale`` attribute is used in the image_ element.
+
+
+``source``
+==========
+
+Attribute type: `CDATA`_. Default value: none.
+
+The ``source`` attribute is used to store the path or URL to the
+source text that was used to produce the document tree. It is one of
+the `common attributes`_, shared by all Docutils elements.
+
+
+``start``
+=========
+
+Attribute type: `number`_. Default value: none.
+
+The ``start`` attribute is used in the enumerated_list_ element.
+
+
+``stub``
+=========
+
+Attribute type: `yesorno`_. Default value: none.
+
+The ``stub`` attribute is used in the colspec_ element.
+
+
+``suffix``
+==========
+
+Attribute type: `CDATA`_. Default value: none.
+
+The ``suffix`` attribute is used in the enumerated_list_ element.
+
+
+``width``
+==========
+
+Attribute type: measure_. Default value: none.
+
+The ``width`` attribute is used in the image_ element.
+
+
+``xml:space``
+=============
+
+`Attribute type`: `EnumeratedType`_, one of "default" or "preserve".
+Default value: "preserve" (fixed).
+
+The ``xml:space`` attribute is a standard XML attribute for
+whitespace-preserving elements. It is used by the literal_block_,
+line_block_, doctest_block_, comment_, and raw_ elements (via the
+`%fixedspace.att;`_ parameter entity). It is a fixed attribute, meant
+to communicate to an XML parser that the element contains significant
+whitespace. The attribute value should not be set in a document
+instance.
+
+
+.. _title (attribute):
+
+``title``
+=========
+
+Attribute type: `CDATA`_. Default value: none.
+
+The ``title`` attribute stores the title metadata of a document. This
+title is typically not part of the rendered document. It may for
+example be used in HTML's ``title`` element.
+
+
+----------------------------
+ Parameter Entity Reference
+----------------------------
+
+.. contents:: :local:
+ :depth: 1
+
+Parameter entities are used to simplify the DTD (to share definitions
+and reduce duplication) and to allow the DTD to be customized by
+wrapper DTDs (external client DTDs that use or import the Docutils
+DTD). Parameter entities may be overridden by wrapper DTDs, replacing
+the definitions below with custom definitions. Parameter entities
+whose names begin with "additional" are meant to allow easy extension
+by wrapper DTDs.
+
+
+``%anonymous.att;``
+===================
+
+The ``%anonymous.att;`` parameter entity contains the anonymous_
+attribute, used for unnamed hyperlinks.
+
+Entity definition:
+
+.. parsed-literal::
+
+ anonymous_ %yesorno; #IMPLIED
+
+The reference_ and target_ elements directly employ the
+``%anonymous.att;`` parameter entity in their attribute lists.
+
+
+``%auto.att;``
+==============
+
+The ``%auto.att;`` parameter entity contains the auto_ attribute, used
+to indicate an automatically-numbered footnote or title.
+
+Entity definition:
+
+.. parsed-literal::
+
+ auto_ CDATA #IMPLIED
+
+The footnote_, footnote_reference_, and title_ elements directly
+employ the ``%auto.att;`` parameter entity in their attribute lists.
+
+
+``%backrefs.att;``
+==================
+
+The ``%backrefs.att;`` parameter entity contains the backrefs_
+attribute, a space-separated list of id references, for backlinks.
+
+Entity definition:
+
+.. parsed-literal::
+
+ backrefs_ %idrefs.type; #IMPLIED
+
+The citation_, footnote_, and system_message_ elements directly employ
+the ``%backrefs.att;`` parameter entity in their attribute lists.
+
+
+``%basic.atts;``
+================
+
+The ``%basic.atts;`` parameter entity lists attributes common to all
+Docutils elements. See `Common Attributes`_.
+
+Entity definition:
+
+.. parsed-literal::
+
+ ids_ NMTOKENS #IMPLIED
+ names_ CDATA #IMPLIED
+ dupnames_ CDATA #IMPLIED
+ source_ CDATA #IMPLIED
+ classes_ NMTOKENS #IMPLIED
+ %additional.basic.atts;
+
+The ``%additional.basic.atts;`` parameter entity can be used by
+wrapper DTDs to extend ``%basic.atts;``.
+
+
+``%bibliographic.elements;``
+============================
+
+The ``%bibliographic.elements;`` parameter entity contains an OR-list of all
+`bibliographic elements`_.
+
+Entity definition:
+
+.. parsed-literal::
+
+ author_ | authors_ | organization_ | contact_ | address_
+ | version_ | revision_ | status_ | date_ | copyright_
+ | field_
+ %additional.bibliographic.elements;
+
+The ``%additional.bibliographic.elements;`` parameter entity can be used by
+wrapper DTDs to extend ``%bibliographic.elements;``.
+
+Only the docinfo_ element directly employs the
+``%bibliographic.elements;`` parameter entity in its content model.
+
+
+``%body.elements;``
+===================
+
+The ``%body.elements;`` parameter entity contains an OR-list of all
+`body elements`_. ``%body.elements;`` is itself contained within the
+`%structure.model;`_ parameter entity.
+
+Entity definition:
+
+.. parsed-literal::
+
+ admonition_ | attention_ | block_quote_ | bullet_list_ | caution_
+ | citation_ | compound_ | comment_ | container_ | danger_ |
+ definition_list_ | doctest_block_ | enumerated_list_ | error_ |
+ field_list_ | figure_ | footnote_ | hint_ | image_ | important_
+ | line_block_ | literal_block_ | note_ | option_list_ |
+ paragraph_ | pending_ | raw_ reference_ | rubric_ |
+ substitution_definition_ | system_message_ | table_ | target_ |
+ tip_ | warning_ %additional.body.elements;
+
+The ``%additional.body.elements;`` parameter entity can be used by
+wrapper DTDs to extend ``%body.elements;``.
+
+The ``%body.elements;`` parameter entity is directly employed in the
+content models of the following elements: admonition_, attention_,
+block_quote_, caution_, citation_, compound_, danger_, definition_,
+description_, entry_, error_, field_body_, footer_, footnote_,
+header_, hint_, important_, legend_, list_item_, note_, sidebar_,
+system_message_, tip_, topic_, warning_
+
+Via `%structure.model;`_, the ``%body.elements;`` parameter entity is
+indirectly employed in the content models of the document_ and
+section_ elements.
+
+
+``%fixedspace.att;``
+====================
+
+The ``%fixedspace.att;`` parameter entity contains the `xml:space`_
+attribute, a standard XML attribute for whitespace-preserving
+elements.
+
+Entity definition:
+
+.. parsed-literal::
+
+ `xml:space`_ (default | preserve) #FIXED 'preserve'
+
+The ``%fixedspace.att;`` parameter entity is directly employed in the
+attribute lists of the following elements: address_, comment_,
+doctest_block_, line_block_, literal_block_, raw_
+
+
+``%inline.elements;``
+=====================
+
+The ``%inline.elements;`` parameter entity contains an OR-list of all
+`inline elements`_.
+
+Entity definition:
+
+.. parsed-literal::
+
+ abbreviation_ | acronym_ | citation_reference_ | emphasis_ |
+ footnote_reference_ | generated_ | image_ | inline_ | literal_ |
+ problematic_ | raw_ | reference_ | strong_ | substitution_reference_ |
+ subscript_ | superscript_ | target_ | title_reference_
+ %additional.inline.elements;
+
+The ``%additional.inline.elements;`` parameter entity can be used by
+wrapper DTDs to extend ``%inline.elements;``.
+
+Via `%text.model;`_, the ``%inline.elements;`` parameter entity is
+indirectly employed in the content models of the following elements:
+abbreviation_, acronym_, address_, attribution_, author_, caption_,
+classifier_, contact_, copyright_, date_, doctest_block_, emphasis_,
+generated_, inline_, line_block_, literal_block_, math_, math_block_,
+organization_,
+paragraph_, problematic_, raw_, reference_, revision_, rubric_,
+status_, strong_, subscript_, substitution_definition_,
+substitution_reference_, subtitle_, superscript_, target_, term_,
+title_, title_reference_, version_
+
+
+``%reference.atts;``
+====================
+
+The ``%reference.atts;`` parameter entity groups together the refuri_,
+refid_, and refname_ attributes.
+
+Entity definition:
+
+.. parsed-literal::
+
+ `%refuri.att;`_
+ `%refid.att;`_
+ `%refname.att;`_
+ %additional.reference.atts;
+
+The ``%additional.reference.atts;`` parameter entity can be used by
+wrapper DTDs to extend ``%additional.reference.atts;``.
+
+The citation_reference_, footnote_reference_, reference_, and target_
+elements directly employ the ``%reference.att;`` parameter entity in
+their attribute lists.
+
+
+``%refid.att;``
+================
+
+The ``%refid.att;`` parameter entity contains the refid_ attribute, an
+internal reference to the `ids`_ attribute of another element.
+
+Entity definition:
+
+.. parsed-literal::
+
+ refid_ %idref.type; #IMPLIED
+
+The title_ and problematic_ elements directly employ the
+``%refid.att;`` parameter entity in their attribute lists.
+
+Via `%reference.atts;`_, the ``%refid.att;`` parameter entity is
+indirectly employed in the attribute lists of the citation_reference_,
+footnote_reference_, reference_, and target_ elements.
+
+
+``%refname.att;``
+=================
+
+The ``%refname.att;`` parameter entity contains the refname_
+attribute, an internal reference to the `names`_ attribute of another
+element. On a `target`_ element, ``refname`` indicates an indirect
+target which may resolve to either an internal or external
+reference.
+
+Entity definition:
+
+.. parsed-literal::
+
+ refname_ %refname.type; #IMPLIED
+
+The substitution_reference_ element directly employs the
+``%refname.att;`` parameter entity in its attribute list.
+
+Via `%reference.atts;`_, the ``%refname.att;`` parameter entity is
+indirectly employed in the attribute lists of the citation_reference_,
+footnote_reference_, reference_, and target_ elements.
+
+
+``%refuri.att;``
+================
+
+The ``%refuri.att;`` parameter entity contains the refuri_ attribute,
+an external reference to a URI/URL.
+
+Entity definition:
+
+.. parsed-literal::
+
+ refuri_ CDATA #IMPLIED
+
+Via `%reference.atts;`_, the ``%refuri.att;`` parameter entity is
+indirectly employed in the attribute lists of the citation_reference_,
+footnote_reference_, reference_, and target_ elements.
+
+
+``%section.elements;``
+======================
+
+The ``%section.elements;`` parameter entity contains an OR-list of all
+section_-equivalent elements. ``%section.elements;`` is itself
+contained within the `%structure.model;`_ parameter entity.
+
+Entity definition:
+
+.. parsed-literal::
+
+ section_
+ %additional.section.elements;
+
+The ``%additional.section.elements;`` parameter entity can be used
+by wrapper DTDs to extend ``%section.elements;``.
+
+Via `%structure.model;`_, the ``%section.elements;`` parameter entity
+is indirectly employed in the content models of the document_ and
+section_ elements.
+
+
+``%structure.model;``
+=====================
+
+The ``%structure.model;`` parameter entity encapsulates the
+hierarchical structure of a document and of its constituent parts.
+See the discussion of the `element hierarchy`_ above.
+
+Entity definition:
+
+.. parsed-literal::
+
+ ( ( (`%body.elements;`_ | topic_ | sidebar_)+, transition_? )*,
+ ( (`%section.elements;`_), (transition_?, (`%section.elements;`_) )* )? )
+
+Each document_ or section_ contains zero or more body elements,
+topics, and/or sidebars, optionally interspersed with single
+transitions, followed by zero or more sections (whose contents are
+recursively the same as this model) optionally interspersed with
+transitions.
+
+The following restrictions are imposed by this model:
+
+* Transitions must be separated by other elements (body elements,
+ sections, etc.). In other words, a transition may not be
+ immediately adjacent to another transition.
+
+* A transition may not occur at the beginning of a document or
+ section.
+
+An additional restriction, which cannot be expressed in the language
+of DTDs, is imposed by software:
+
+* A transition may not occur at the end of a document or section.
+
+The `%structure.model;`_ parameter entity is directly employed in the
+content models of the document_ and section_ elements.
+
+
+``%text.model;``
+================
+
+The ``%text.model;`` parameter entity is used by many elements to
+represent text data mixed with `inline elements`_.
+
+Entity definition:
+
+.. parsed-literal::
+
+ (#PCDATA | `%inline.elements;`_)*
+
+The ``%text.model;`` parameter entity is directly employed in the
+content models of the following elements: abbreviation_, acronym_,
+address_, author_, caption_, classifier_, contact_, copyright_, date_,
+doctest_block_, emphasis_, field_name_, generated_, line_block_,
+literal_block_, organization_, paragraph_, problematic_, raw_,
+reference_, revision_, status_, strong_, substitution_definition_,
+substitution_reference_, subtitle_, target_, term_, title_, version_
+
+
+\f
+..
+ Local Variables:
+ mode: indented-text
+ indent-tabs-mode: nil
+ sentence-end-double-space: t
+ fill-column: 70
+ End:
--- /dev/null
+<!--
+======================================================================
+ Docutils Generic DTD
+======================================================================
+:Author: David Goodger
+:Contact: docutils-develop@lists.sourceforge.net
+:Revision: $Revision: 8407 $
+:Date: $Date: 2019-10-29 23:48:34 +0100 (Di, 29. Okt 2019) $
+:Copyright: This DTD has been placed in the public domain.
+:Filename: docutils.dtd
+
+More information about this DTD (document type definition) and the
+Docutils project can be found at http://docutils.sourceforge.net/.
+The latest version of this DTD is available from
+http://docutils.sourceforge.net/docs/ref/docutils.dtd.
+
+The formal public identifier for this DTD is::
+
+ +//IDN docutils.sourceforge.net//DTD Docutils Generic//EN//XML
+-->
+
+<!--
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ Parameter Entities
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Parameter entities are used to simplify the DTD (reduce duplication)
+and to allow the DTD to be customized by wrapper DTDs. Parameter
+entities beginning with "additional" are meant to allow easy extension
+by wrapper DTDs.
+-->
+
+<!-- Attribute types
+==================================================================
+
+Expand the set of `XML standard attribute types`_.
+
+-->
+
+<!-- Boolean: no if zero(s), yes if any other value. -->
+<!ENTITY % yesorno "NMTOKEN">
+
+<!-- Emphasize that the attribute value must be a number. -->
+<!ENTITY % number "NMTOKEN">
+
+<!-- A number which may be immediately followed by a unit or percent sign. -->
+<!ENTITY % measure "CDATA">
+
+<!-- A space-separated list of `class names`.
+
+Docutils normalizes class names to conform to HTML4.1 and CSS1.0 `name`
+requirements, i.e. the regular expression ``[a-z](-?[a-z0-9]+)*``, via an
+`identifier normalisation`. -->
+<!ENTITY % classnames.type "NMTOKENS">
+
+<!-- A normalized `reference name`.
+
+The CDATA type is used because a `reference name` may consist of any text.
+
+`Normalization` implies downcasing and replacing runs of whitespace with
+single space characters. -->
+<!ENTITY % refname.type "CDATA">
+
+<!-- A space-separated list of `reference names`.
+
+`Backslash escaping`_ is used for space characters inside a `reference name`.
+-->
+<!ENTITY % refnames.type "CDATA">
+
+<!-- A space-separated list of `identifier keys`.
+
+The NMTOKENS type is used because `XML standard attribute types`_
+do not include a list of IDs.
+-->
+<!ENTITY % ids.type "NMTOKENS">
+
+<!-- A reference to an `identifier key` in another element's `ids` attribute.
+
+The NMTOKEN type is used, because Docutils `identifier keys` do not use the
+``ID`` attribute type, as required by the `IDREF Validity constraint`_ -->
+<!ENTITY % idref.type "NMTOKEN">
+
+<!-- A list of references to `identifier keys` in other elements. -->
+<!ENTITY % idrefs.type "NMTOKENS">
+
+<!-- References:
+.. _XML standard attribute types:
+ https://www.w3.org/TR/REC-xml/#sec-attribute-types
+.. _IDREF Validity constraint: https://www.w3.org/TR/REC-xml/#idref
+.. _backslash escaping: rst/restructuredtext.html#escaping-mechanism
+-->
+
+
+<!-- Attributes
+================================================================== -->
+
+<!ENTITY % additional.basic.atts "">
+
+<!--
+Attributes shared by all elements in this DTD:
+
+- `ids` are unique identifiers, typically assigned by the system. The NMTOKENS
+ attribute type is used because XML doesn't support a multiple-ID "IDS" type.
+- `names` are identifiers assigned in the markup.
+- `dupnames` is the same as `name`, used when it's a duplicate.
+- `source` is the name of the source of this document or fragment.
+- `classes` is used to transmit individuality information forward.
+-->
+<!ENTITY % basic.atts
+ " ids %ids.type; #IMPLIED
+ names %refnames.type; #IMPLIED
+ dupnames %refnames.type; #IMPLIED
+ source CDATA #IMPLIED
+ classes %classnames.type; #IMPLIED
+ %additional.basic.atts; ">
+
+<!-- External reference to a URI/URL. -->
+<!ENTITY % refuri.att
+ " refuri CDATA #IMPLIED ">
+
+<!-- Internal reference to the `ids` attribute of an element. -->
+<!ENTITY % refid.att
+ " refid %idref.type; #IMPLIED ">
+
+<!-- Space-separated list of `ids` references, for backlinks. -->
+<!ENTITY % backrefs.att
+ " backrefs %idrefs.type; #IMPLIED ">
+
+<!--
+Internal reference to the `name` attribute of an element. On a
+'target' element, 'refname' indicates an indirect target which may
+resolve to either an internal or external reference.
+-->
+<!ENTITY % refname.att
+ " refname %refname.type; #IMPLIED ">
+
+<!ENTITY % additional.reference.atts "">
+<!-- Collected hyperlink reference attributes. -->
+<!ENTITY % reference.atts
+ " %refuri.att;
+ %refid.att;
+ %refname.att;
+ %additional.reference.atts; ">
+
+<!-- Unnamed hyperlink. -->
+<!ENTITY % anonymous.att
+ " anonymous %yesorno; #IMPLIED ">
+
+<!-- Auto-numbered footnote or title. -->
+<!ENTITY % auto.att
+ " auto CDATA #IMPLIED ">
+
+<!-- XML standard attribute for whitespace-preserving elements. -->
+<!ENTITY % fixedspace.att
+ " xml:space (default | preserve) #FIXED 'preserve' ">
+
+<!ENTITY % align-h.att
+ " align (left | center | right) #IMPLIED ">
+
+<!ENTITY % align-hv.att
+ " align (top | middle | bottom | left | center | right) #IMPLIED ">
+
+
+<!-- Element OR-Lists
+============================================================= -->
+
+<!ENTITY % additional.bibliographic.elements "">
+<!ENTITY % bibliographic.elements
+ " author | authors | organization | address | contact
+ | version | revision | status | date | copyright
+ | field
+ %additional.bibliographic.elements; ">
+
+<!ENTITY % additional.section.elements "">
+<!ENTITY % section.elements
+ " section
+ %additional.section.elements; ">
+
+<!ENTITY % additional.body.elements "">
+<!ENTITY % body.elements
+ " paragraph | compound | container | literal_block | doctest_block
+ | math_block | line_block | block_quote
+ | table | figure | image | footnote | citation | rubric
+ | bullet_list | enumerated_list | definition_list | field_list
+ | option_list
+ | attention | caution | danger | error | hint | important | note
+ | tip | warning | admonition
+ | reference | target | substitution_definition | comment | pending
+ | system_message | raw
+ %additional.body.elements; ">
+
+<!ENTITY % additional.inline.elements "">
+<!ENTITY % inline.elements
+ " emphasis | strong | literal | math
+ | reference | footnote_reference | citation_reference
+ | substitution_reference | title_reference
+ | abbreviation | acronym | subscript | superscript
+ | inline | problematic | generated
+ | target | image | raw
+ %additional.inline.elements; ">
+
+
+<!-- Element Content Models
+================================================================== -->
+
+<!-- The structure model may not end with a transition. -->
+<!ENTITY % structure.model
+ " ( ( (%body.elements; | topic | sidebar)+, transition? )*,
+ ( (%section.elements;), (transition?, (%section.elements;) )* )? )">
+
+<!ENTITY % text.model
+ " (#PCDATA | %inline.elements;)* ">
+
+
+<!-- Table Model
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+This DTD uses the Exchange subset of the CALS-table model (OASIS
+Technical Memorandum 9901:1999 "XML Exchange Table Model DTD",
+http://www.oasis-open.org/html/tm9901.htm).
+-->
+
+<!ENTITY % calstblx PUBLIC
+ "-//OASIS//DTD XML Exchange Table Model 19990315//EN"
+ "soextblx.dtd">
+
+<!-- These parameter entities customize the table model DTD. -->
+<!ENTITY % bodyatt " %basic.atts; "> <!-- table elt -->
+<!-- 1 colspec element is expected per table column: -->
+<!ENTITY % tbl.tgroup.mdl "colspec+,thead?,tbody">
+<!ENTITY % tbl.tgroup.att " %basic.atts; ">
+<!ENTITY % tbl.thead.att " %basic.atts; ">
+<!ENTITY % tbl.tbody.att " %basic.atts; ">
+<!ENTITY % tbl.colspec.att
+ " %basic.atts;
+ stub %yesorno; #IMPLIED ">
+<!ENTITY % tbl.row.att " %basic.atts; ">
+<!-- ``(...)*``: nested tables are supported -->
+<!ENTITY % tbl.entry.mdl " (%body.elements;)* ">
+<!ENTITY % tbl.entry.att
+ " %basic.atts;
+ morecols %number; #IMPLIED ">
+<!ATTLIST table
+ %align-h.att;
+ width %measure; #IMPLIED>
+
+<!--
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ Root Element
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+-->
+
+<!-- Optional elements may be generated by internal processing. -->
+<!ELEMENT document
+ ( (title, subtitle?)?,
+ decoration?,
+ (docinfo, transition?)?,
+ %structure.model; )>
+<!ATTLIST document
+ %basic.atts;
+ title CDATA #IMPLIED>
+
+<!--
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ Title Elements
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+-->
+
+<!ELEMENT title %text.model;>
+<!ATTLIST title
+ %basic.atts;
+ %refid.att;
+ %auto.att;>
+
+<!ELEMENT subtitle %text.model;>
+<!ATTLIST subtitle %basic.atts;>
+
+<!--
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ Bibliographic Elements
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+-->
+
+<!-- Container for bibliographic elements. May not be empty. -->
+<!ELEMENT docinfo (%bibliographic.elements;)+>
+<!ATTLIST docinfo %basic.atts;>
+
+<!-- Container for bibliographic elements. May not be empty.
+Eventual replacement for docinfo? -->
+<!ELEMENT info (%bibliographic.elements;)+>
+<!ATTLIST info %basic.atts;>
+
+<!ELEMENT author %text.model;>
+<!ATTLIST author %basic.atts;>
+
+<!ELEMENT authors (author, organization?, address?, contact?)+>
+<!ATTLIST authors %basic.atts;>
+
+<!ELEMENT organization %text.model;>
+<!ATTLIST organization %basic.atts;>
+
+<!ELEMENT address %text.model;>
+<!ATTLIST address
+ %basic.atts;
+ %fixedspace.att;>
+
+<!ELEMENT contact %text.model;>
+<!ATTLIST contact %basic.atts;>
+
+<!ELEMENT version %text.model;>
+<!ATTLIST version %basic.atts;>
+
+<!ELEMENT revision %text.model;>
+<!ATTLIST revision %basic.atts;>
+
+<!ELEMENT status %text.model;>
+<!ATTLIST status %basic.atts;>
+
+<!ELEMENT date %text.model;>
+<!ATTLIST date %basic.atts;>
+
+<!ELEMENT copyright %text.model;>
+<!ATTLIST copyright %basic.atts;>
+
+<!--
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ Decoration Elements
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+-->
+
+<!ELEMENT decoration (header?, footer?)>
+<!ATTLIST decoration %basic.atts;>
+
+<!ELEMENT header (%body.elements;)+>
+<!ATTLIST header %basic.atts;>
+
+<!ELEMENT footer (%body.elements;)+>
+<!ATTLIST footer %basic.atts;>
+
+<!--
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ Structural Elements
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+-->
+
+<!ELEMENT section
+ (title, subtitle?, info?, decoration?, %structure.model;)>
+<!ATTLIST section %basic.atts;>
+
+<!ELEMENT topic (title?, (%body.elements;)+)>
+<!ATTLIST topic %basic.atts;>
+
+<!ELEMENT sidebar (title, subtitle?, (%body.elements; | topic)+)>
+<!ATTLIST sidebar %basic.atts;>
+
+<!ELEMENT transition EMPTY>
+<!ATTLIST transition %basic.atts;>
+
+<!--
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ Body Elements
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+-->
+
+<!ELEMENT paragraph %text.model;>
+<!ATTLIST paragraph %basic.atts;>
+
+<!ELEMENT compound (%body.elements;)+>
+<!ATTLIST compound %basic.atts;>
+
+<!ELEMENT container (%body.elements;)+>
+<!ATTLIST container %basic.atts;>
+
+<!ELEMENT bullet_list (list_item+)>
+<!ATTLIST bullet_list
+ %basic.atts;
+ bullet CDATA #IMPLIED>
+
+<!ELEMENT enumerated_list (list_item+)>
+<!ATTLIST enumerated_list
+ %basic.atts;
+ enumtype (arabic | loweralpha | upperalpha
+ | lowerroman | upperroman)
+ #IMPLIED
+ prefix CDATA #IMPLIED
+ suffix CDATA #IMPLIED
+ start %number; #IMPLIED>
+
+<!ELEMENT list_item (%body.elements;)*>
+<!ATTLIST list_item %basic.atts;>
+
+<!ELEMENT definition_list (definition_list_item+)>
+<!ATTLIST definition_list %basic.atts;>
+
+<!ELEMENT definition_list_item (term, classifier*, definition)>
+<!ATTLIST definition_list_item %basic.atts;>
+
+<!ELEMENT term %text.model;>
+<!ATTLIST term %basic.atts;>
+
+<!ELEMENT classifier %text.model;>
+<!ATTLIST classifier %basic.atts;>
+
+<!ELEMENT definition (%body.elements;)+>
+<!ATTLIST definition %basic.atts;>
+
+<!ELEMENT field_list (field+)>
+<!ATTLIST field_list %basic.atts;>
+
+<!ELEMENT field (field_name, field_body)>
+<!ATTLIST field %basic.atts;>
+
+<!ELEMENT field_name %text.model;>
+<!ATTLIST field_name %basic.atts;>
+
+<!-- May be empty. -->
+<!ELEMENT field_body (%body.elements;)*>
+<!ATTLIST field_body %basic.atts;>
+
+<!ELEMENT option_list (option_list_item+)>
+<!ATTLIST option_list %basic.atts;>
+
+<!ELEMENT option_list_item (option_group, description)>
+<!ATTLIST option_list_item %basic.atts;>
+
+<!ELEMENT option_group (option+)>
+<!ATTLIST option_group %basic.atts;>
+
+<!ELEMENT option (option_string, option_argument*)>
+<!ATTLIST option %basic.atts;>
+
+<!ELEMENT option_string (#PCDATA)>
+<!ATTLIST option_string %basic.atts;>
+
+<!--
+`delimiter` contains the text preceding the `option_argument`: either
+the text separating it from the `option_string` (typically either "="
+or " ") or the text between option arguments (typically either "," or
+" ").
+-->
+<!ELEMENT option_argument (#PCDATA)>
+<!ATTLIST option_argument
+ %basic.atts;
+ delimiter CDATA #IMPLIED>
+
+<!ELEMENT description (%body.elements;)+>
+<!ATTLIST description %basic.atts;>
+
+<!ELEMENT literal_block %text.model;>
+<!ATTLIST literal_block
+ %basic.atts;
+ %fixedspace.att;>
+
+<!--
+`math_block` contains a block of text in "LaTeX math format"
+that is typeset as mathematical notation (display formula).
+-->
+<!ELEMENT math_block (#PCDATA)>
+<!ATTLIST math_block %basic.atts;>
+
+<!ELEMENT line_block (line | line_block)+>
+<!ATTLIST line_block %basic.atts;>
+
+<!ELEMENT line %text.model;>
+<!ATTLIST line %basic.atts;>
+
+<!ELEMENT block_quote ((%body.elements;)+, attribution?)>
+<!ATTLIST block_quote %basic.atts;>
+
+<!ELEMENT attribution %text.model;>
+<!ATTLIST attribution %basic.atts;>
+
+<!ELEMENT doctest_block %text.model;>
+<!ATTLIST doctest_block
+ %basic.atts;
+ %fixedspace.att;>
+
+<!ELEMENT attention (%body.elements;)+>
+<!ATTLIST attention %basic.atts;>
+
+<!ELEMENT caution (%body.elements;)+>
+<!ATTLIST caution %basic.atts;>
+
+<!ELEMENT danger (%body.elements;)+>
+<!ATTLIST danger %basic.atts;>
+
+<!ELEMENT error (%body.elements;)+>
+<!ATTLIST error %basic.atts;>
+
+<!ELEMENT hint (%body.elements;)+>
+<!ATTLIST hint %basic.atts;>
+
+<!ELEMENT important (%body.elements;)+>
+<!ATTLIST important %basic.atts;>
+
+<!ELEMENT note (%body.elements;)+>
+<!ATTLIST note %basic.atts;>
+
+<!ELEMENT tip (%body.elements;)+>
+<!ATTLIST tip %basic.atts;>
+
+<!ELEMENT warning (%body.elements;)+>
+<!ATTLIST warning %basic.atts;>
+
+<!ELEMENT admonition (title, (%body.elements;)+)>
+<!ATTLIST admonition %basic.atts;>
+
+<!ELEMENT footnote (label?, (%body.elements;)+)>
+<!ATTLIST footnote
+ %basic.atts;
+ %backrefs.att;
+ %auto.att;>
+
+<!ELEMENT citation (label, (%body.elements;)+)>
+<!ATTLIST citation
+ %basic.atts;
+ %backrefs.att;>
+
+<!ELEMENT label (#PCDATA)>
+<!ATTLIST label %basic.atts;>
+
+<!ELEMENT rubric %text.model;>
+<!ATTLIST rubric %basic.atts;>
+
+<!-- Empty except when used as an inline element. -->
+<!ELEMENT target %text.model;>
+<!ATTLIST target
+ %basic.atts;
+ %reference.atts;
+ %anonymous.att;>
+
+<!ELEMENT substitution_definition %text.model;>
+<!ATTLIST substitution_definition
+ %basic.atts;
+ ltrim %yesorno; #IMPLIED
+ rtrim %yesorno; #IMPLIED>
+
+<!ELEMENT comment (#PCDATA)>
+<!ATTLIST comment
+ %basic.atts;
+ %fixedspace.att;>
+
+<!ELEMENT pending EMPTY>
+<!ATTLIST pending %basic.atts;>
+
+<!ELEMENT figure (image, ((caption, legend?) | legend)) >
+<!ATTLIST figure
+ %basic.atts;
+ %align-h.att;
+ width %measure; #IMPLIED>
+
+<!-- Also an inline element. -->
+<!ELEMENT image EMPTY>
+<!ATTLIST image
+ %basic.atts;
+ %align-hv.att;
+ uri CDATA #REQUIRED
+ alt CDATA #IMPLIED
+ height %measure; #IMPLIED
+ width %measure; #IMPLIED
+ scale %number; #IMPLIED>
+
+<!ELEMENT caption %text.model;>
+<!ATTLIST caption %basic.atts;>
+
+<!ELEMENT legend (%body.elements;)+>
+<!ATTLIST legend %basic.atts;>
+
+<!--
+Table elements: table, tgroup, colspec, thead, tbody, row, entry.
+-->
+%calstblx;
+
+<!-- Used to record processing information. -->
+<!ELEMENT system_message (%body.elements;)+>
+<!ATTLIST system_message
+ %basic.atts;
+ %backrefs.att;
+ level %number; #IMPLIED
+ line %number; #IMPLIED
+ type NMTOKEN #IMPLIED>
+
+<!-- Used to pass raw data through the system. Also inline. -->
+<!ELEMENT raw %text.model;>
+<!ATTLIST raw
+ %basic.atts;
+ %fixedspace.att;
+ format NMTOKENS #IMPLIED>
+
+<!--
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ Inline Elements
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Inline elements occur within the text contents of body elements. Some
+nesting of inline elements is allowed by these definitions, with the
+following caveats:
+
+- An inline element may not contain a nested element of the same type
+ (e.g. <strong> may not contain another <strong>).
+- Nested inline elements may or may not be supported by individual
+ applications using this DTD.
+- The inline elements <footnote_reference>, <citation_reference>,
+ <math>, and <image> do not support nesting.
+-->
+
+<!ELEMENT emphasis %text.model;>
+<!ATTLIST emphasis %basic.atts;>
+
+<!ELEMENT strong %text.model;>
+<!ATTLIST strong %basic.atts;>
+
+<!ELEMENT literal %text.model;>
+<!ATTLIST literal %basic.atts;>
+
+<!ELEMENT math (#PCDATA)>
+<!ATTLIST math %basic.atts;>
+
+<!-- Can also be a body element, when it contains an "image" element. -->
+<!ELEMENT reference %text.model;>
+<!ATTLIST reference
+ name CDATA #IMPLIED
+ %basic.atts;
+ %reference.atts;
+ %anonymous.att;>
+
+<!ELEMENT footnote_reference (#PCDATA)>
+<!ATTLIST footnote_reference
+ %basic.atts;
+ %refid.att;
+ %refname.att;
+ %auto.att;>
+
+<!ELEMENT citation_reference (#PCDATA)>
+<!ATTLIST citation_reference
+ %basic.atts;
+ %refid.att;
+ %refname.att;>
+
+<!ELEMENT substitution_reference %text.model;>
+<!ATTLIST substitution_reference
+ %basic.atts;
+ %refname.att;>
+
+<!ELEMENT title_reference %text.model;>
+<!ATTLIST title_reference %basic.atts;>
+
+<!ELEMENT abbreviation %text.model;>
+<!ATTLIST abbreviation %basic.atts;>
+
+<!ELEMENT acronym %text.model;>
+<!ATTLIST acronym %basic.atts;>
+
+<!ELEMENT superscript %text.model;>
+<!ATTLIST superscript %basic.atts;>
+
+<!ELEMENT subscript %text.model;>
+<!ATTLIST subscript %basic.atts;>
+
+<!ELEMENT inline %text.model;>
+<!ATTLIST inline %basic.atts;>
+
+<!ELEMENT problematic %text.model;>
+<!ATTLIST problematic
+ %basic.atts;
+ %refid.att;>
+
+<!ELEMENT generated %text.model;>
+<!ATTLIST generated %basic.atts;>
+
+<!--
+Local Variables:
+mode: sgml
+indent-tabs-mode: nil
+fill-column: 70
+End:
+-->
--- /dev/null
+============================================
+ reStructuredText Standard Definition Files
+============================================
+:Author: David Goodger
+:Contact: docutils-develop@lists.sourceforge.net
+:Revision: $Revision: 7302 $
+:Date: $Date: 2012-01-03 20:23:53 +0100 (Di, 03. Jän 2012) $
+:Copyright: This document has been placed in the public domain.
+
+.. contents::
+
+
+This document describes standard definition files, such as sets of
+substitution definitions and interpreted text roles, that can be
+included in reStructuredText documents. The `"include" directive`__
+has a special syntax for these standard definition files, angle
+brackets around the file name::
+
+ .. include:: <filename.txt>
+
+__ directives.html#include
+
+The individual data files are stored with the Docutils source code in
+the "docutils" package, in the ``docutils/parsers/rst/include``
+directory.
+
+
+Substitution Definitions
+========================
+
+Many of the standard definition files contain sets of `substitution
+definitions`__, which can be used in documents via `substitution
+references`__. For example, the copyright symbol is defined in
+``isonum.txt`` as "copy"::
+
+ .. include:: <isonum.txt>
+
+ Copyright |copy| 2003 by John Q. Public, all rights reserved.
+
+__ restructuredtext.html#substitution-definitions
+__ restructuredtext.html#substitution-references
+
+Individual substitution definitions can also be copied from definition
+files and pasted into documents. This has two advantages: it removes
+dependencies, and it saves processing of unused definitions. However,
+multiple substitution definitions add clutter to the document.
+
+Substitution references require separation from the surrounding text
+with whitespace or punctuation. To use a substitution without
+intervening whitespace, you can use the disappearing-whitespace escape
+sequence, backslash-space::
+
+ .. include:: isonum.txt
+
+ Copyright |copy| 2003, BogusMegaCorp\ |trade|.
+
+Custom substitution definitions may use the `"unicode" directive`__.
+Whitespace is ignored and removed, effectively sqeezing together the
+text::
+
+ .. |copy| unicode:: U+000A9 .. COPYRIGHT SIGN
+ .. |BogusMegaCorp (TM)| unicode:: BogusMegaCorp U+2122
+ .. with trademark sign
+
+ Copyright |copy| 2003, |BogusMegaCorp (TM)|.
+
+__ directives.html#unicode
+
+In addition, the "ltrim", "rtrim", and "trim" options may be used with
+the "unicode" directive to automatically trim spaces from the left,
+right, or both sides (respectively) of substitution references::
+
+ .. |---| unicode:: U+02014 .. em dash
+ :trim:
+
+
+Character Entity Sets
+---------------------
+
+The following files contain substitution definitions corresponding to
+XML character entity sets, from the following standards: ISO 8879 &
+ISO 9573-13 (combined), MathML, and XHTML1. They were generated by
+the ``tools/dev/unicode2rstsubs.py`` program from the input file
+unicode.xml__, which is maintained as part of the MathML 2
+Recommentation XML source.
+
+__ http://www.w3.org/2003/entities/xml/
+
+=================== =================================================
+Entity Set File Description
+=================== =================================================
+isoamsa.txt_ Added Mathematical Symbols: Arrows
+isoamsb.txt_ Added Mathematical Symbols: Binary Operators
+isoamsc.txt_ Added Mathematical Symbols: Delimiters
+isoamsn.txt_ Added Mathematical Symbols: Negated Relations
+isoamso.txt_ Added Mathematical Symbols: Ordinary
+isoamsr.txt_ Added Mathematical Symbols: Relations
+isobox.txt_ Box and Line Drawing
+isocyr1.txt_ Russian Cyrillic
+isocyr2.txt_ Non-Russian Cyrillic
+isodia.txt_ Diacritical Marks
+isogrk1.txt_ Greek Letters
+isogrk2.txt_ Monotoniko Greek
+isogrk3.txt_ Greek Symbols
+isogrk4.txt_ [1]_ Alternative Greek Symbols
+isolat1.txt_ Added Latin 1
+isolat2.txt_ Added Latin 2
+isomfrk.txt_ [1]_ Mathematical Fraktur
+isomopf.txt_ [1]_ Mathematical Openface (Double-struck)
+isomscr.txt_ [1]_ Mathematical Script
+isonum.txt_ Numeric and Special Graphic
+isopub.txt_ Publishing
+isotech.txt_ General Technical
+mmlalias.txt_ MathML aliases for entities from other sets
+mmlextra.txt_ [1]_ Extra names added by MathML
+xhtml1-lat1.txt_ XHTML Latin 1
+xhtml1-special.txt_ XHTML Special Characters
+xhtml1-symbol.txt_ XHTML Mathematical, Greek and Symbolic Characters
+=================== =================================================
+
+.. [1] There are ``*-wide.txt`` variants for each of these character
+ entity set files, containing characters outside of the Unicode
+ basic multilingual plane or BMP (wide-Unicode; code points greater
+ than U+FFFF). Most pre-built Python distributions are "narrow" and
+ do not support wide-Unicode characters. Python *can* be built with
+ wide-Unicode support though; consult the Python build instructions
+ for details.
+
+For example, the copyright symbol is defined as the XML character
+entity ``©``. The equivalent reStructuredText substitution
+reference (defined in both ``isonum.txt`` and ``xhtml1-lat1.txt``) is
+``|copy|``.
+
+.. _isoamsa.txt: ../../../docutils/parsers/rst/include/isoamsa.txt
+.. _isoamsb.txt: ../../../docutils/parsers/rst/include/isoamsb.txt
+.. _isoamsc.txt: ../../../docutils/parsers/rst/include/isoamsc.txt
+.. _isoamsn.txt: ../../../docutils/parsers/rst/include/isoamsn.txt
+.. _isoamso.txt: ../../../docutils/parsers/rst/include/isoamso.txt
+.. _isoamsr.txt: ../../../docutils/parsers/rst/include/isoamsr.txt
+.. _isobox.txt: ../../../docutils/parsers/rst/include/isobox.txt
+.. _isocyr1.txt: ../../../docutils/parsers/rst/include/isocyr1.txt
+.. _isocyr2.txt: ../../../docutils/parsers/rst/include/isocyr2.txt
+.. _isodia.txt: ../../../docutils/parsers/rst/include/isodia.txt
+.. _isogrk1.txt: ../../../docutils/parsers/rst/include/isogrk1.txt
+.. _isogrk2.txt: ../../../docutils/parsers/rst/include/isogrk2.txt
+.. _isogrk3.txt: ../../../docutils/parsers/rst/include/isogrk3.txt
+.. _isogrk4.txt: ../../../docutils/parsers/rst/include/isogrk4.txt
+.. _isolat1.txt: ../../../docutils/parsers/rst/include/isolat1.txt
+.. _isolat2.txt: ../../../docutils/parsers/rst/include/isolat2.txt
+.. _isomfrk.txt: ../../../docutils/parsers/rst/include/isomfrk.txt
+.. _isomopf.txt: ../../../docutils/parsers/rst/include/isomopf.txt
+.. _isomscr.txt: ../../../docutils/parsers/rst/include/isomscr.txt
+.. _isonum.txt: ../../../docutils/parsers/rst/include/isonum.txt
+.. _isopub.txt: ../../../docutils/parsers/rst/include/isopub.txt
+.. _isotech.txt: ../../../docutils/parsers/rst/include/isotech.txt
+.. _mmlalias.txt: ../../../docutils/parsers/rst/include/mmlalias.txt
+.. _mmlextra.txt: ../../../docutils/parsers/rst/include/mmlextra.txt
+.. _xhtml1-lat1.txt: ../../../docutils/parsers/rst/include/xhtml1-lat1.txt
+.. _xhtml1-special.txt: ../../../docutils/parsers/rst/include/xhtml1-special.txt
+.. _xhtml1-symbol.txt: ../../../docutils/parsers/rst/include/xhtml1-symbol.txt
+
+
+S5/HTML Definitions
+===================
+
+The "s5defs.txt_" standard definition file contains interpreted text
+roles (classes) and other definitions for documents destined to become
+`S5/HTML slide shows`_.
+
+.. _s5defs.txt: ../../../docutils/parsers/rst/include/s5defs.txt
+.. _S5/HTML slide shows: ../../user/slide-shows.html
+
+\f
+..
+ Local Variables:
+ mode: indented-text
+ indent-tabs-mode: nil
+ sentence-end-double-space: t
+ fill-column: 70
+ End:
--- /dev/null
+=============================
+ reStructuredText Directives
+=============================
+:Author: David Goodger
+:Contact: docutils-develop@lists.sourceforge.net
+:Revision: $Revision: 8413 $
+:Date: $Date: 2019-11-13 14:45:43 +0100 (Mi, 13. Nov 2019) $
+:Copyright: This document has been placed in the public domain.
+
+.. contents::
+ :depth: 2
+
+This document describes the directives implemented in the reference
+reStructuredText parser.
+
+Directives have the following syntax::
+
+ +-------+-------------------------------+
+ | ".. " | directive type "::" directive |
+ +-------+ block |
+ | |
+ +-------------------------------+
+
+Directives begin with an explicit markup start (two periods and a
+space), followed by the directive type and two colons (collectively,
+the "directive marker"). The directive block begins immediately after
+the directive marker, and includes all subsequent indented lines. The
+directive block is divided into arguments, options (a field list), and
+content (in that order), any of which may appear. See the Directives_
+section in the `reStructuredText Markup Specification`_ for syntax
+details.
+
+Descriptions below list "doctree elements" (document tree element
+names; XML DTD generic identifiers) corresponding to individual
+directives. For details on the hierarchy of elements, please see `The
+Docutils Document Tree`_ and the `Docutils Generic DTD`_ XML document
+type definition. For directive implementation details, see `Creating
+reStructuredText Directives`_.
+
+.. _Directives: restructuredtext.html#directives
+.. _reStructuredText Markup Specification: restructuredtext.html
+.. _The Docutils Document Tree: ../doctree.html
+.. _Docutils Generic DTD: ../docutils.dtd
+.. _Creating reStructuredText Directives:
+ ../../howto/rst-directives.html
+
+
+-------------
+ Admonitions
+-------------
+
+.. From Webster's Revised Unabridged Dictionary (1913) [web1913]:
+ Admonition
+ Gentle or friendly reproof; counseling against a fault or
+ error; expression of authoritative advice; friendly caution
+ or warning.
+
+ Syn: {Admonition}, {Reprehension}, {Reproof}.
+
+ Usage: Admonition is prospective, and relates to moral delinquencies;
+ its object is to prevent further transgression.
+
+.. _attention:
+.. _caution:
+.. _danger:
+.. _error:
+.. _hint:
+.. _important:
+.. _note:
+.. _tip:
+.. _warning:
+
+Specific Admonitions
+====================
+
+:Directive Types: "attention", "caution", "danger", "error", "hint",
+ "important", "note", "tip", "warning", "admonition"
+:Doctree Elements: attention, caution, danger, error, hint, important,
+ note, tip, warning, admonition_, title
+:Directive Arguments: None.
+:Directive Options: `:class:`_, `:name:`_
+:Directive Content: Interpreted as body elements.
+
+Admonitions are specially marked "topics" that can appear anywhere an
+ordinary body element can. They contain arbitrary body elements.
+Typically, an admonition is rendered as an offset block in a document,
+sometimes outlined or shaded, with a title matching the admonition
+type. For example::
+
+ .. DANGER::
+ Beware killer rabbits!
+
+This directive might be rendered something like this::
+
+ +------------------------+
+ | !DANGER! |
+ | |
+ | Beware killer rabbits! |
+ +------------------------+
+
+The following admonition directives have been implemented:
+
+- attention
+- caution
+- danger
+- error
+- hint
+- important
+- note
+- tip
+- warning
+
+Any text immediately following the directive indicator (on the same
+line and/or indented on following lines) is interpreted as a directive
+block and is parsed for normal body elements. For example, the
+following "note" admonition directive contains one paragraph and a
+bullet list consisting of two list items::
+
+ .. note:: This is a note admonition.
+ This is the second line of the first paragraph.
+
+ - The note contains all indented body elements
+ following.
+ - It includes this bullet list.
+
+
+Generic Admonition
+==================
+
+:Directive Type: "admonition"
+:Doctree Elements: admonition_, title
+:Directive Arguments: One, required (admonition title)
+:Directive Options: Possible, see below.
+:Directive Content: Interpreted as body elements.
+
+This is a generic, titled admonition. The title may be anything the
+author desires.
+
+The author-supplied title is also used as a `"classes"`_ attribute value
+after being converted into a valid identifier form (down-cased;
+non-alphanumeric characters converted to single hyphens; "admonition-"
+prefixed). For example, this admonition::
+
+ .. admonition:: And, by the way...
+
+ You can make up your own admonition too.
+
+becomes the following document tree (pseudo-XML)::
+
+ <document source="test data">
+ <admonition classes="admonition-and-by-the-way">
+ <title>
+ And, by the way...
+ <paragraph>
+ You can make up your own admonition too.
+
+The `common options`_ are recognized:
+
+``class`` : text
+ Overrides the computed `"classes"`_ attribute value.
+
+``name`` : text
+ Add `text` to the `"names"`_ attribute of the admonition element.
+
+
+--------
+ Images
+--------
+
+There are two image directives: "image" and "figure".
+
+
+Image
+=====
+
+:Directive Type: "image"
+:Doctree Element: image_
+:Directive Arguments: One, required (image URI).
+:Directive Options: Possible.
+:Directive Content: None.
+
+An "image" is a simple picture::
+
+ .. image:: picture.png
+
+Inline images can be defined with an "image" directive in a `substitution
+definition`_
+
+The URI for the image source file is specified in the directive
+argument. As with hyperlink targets, the image URI may begin on the
+same line as the explicit markup start and target name, or it may
+begin in an indented text block immediately following, with no
+intervening blank lines. If there are multiple lines in the link
+block, they are stripped of leading and trailing whitespace and joined
+together.
+
+Optionally, the image link block may contain a flat field list, the
+_`image options`. For example::
+
+ .. image:: picture.jpeg
+ :height: 100px
+ :width: 200 px
+ :scale: 50 %
+ :alt: alternate text
+ :align: right
+
+The following options are recognized:
+
+``alt`` : text
+ Alternate text: a short description of the image, displayed by
+ applications that cannot display images, or spoken by applications
+ for visually impaired users.
+
+``height`` : `length`_
+ The desired height of the image.
+ Used to reserve space or scale the image vertically. When the "scale"
+ option is also specified, they are combined. For example, a height of
+ 200px and a scale of 50 is equivalent to a height of 100px with no scale.
+
+``width`` : `length`_ or `percentage`_ of the current line width
+ The width of the image.
+ Used to reserve space or scale the image horizontally. As with "height"
+ above, when the "scale" option is also specified, they are combined.
+
+``scale`` : integer percentage (the "%" symbol is optional)
+ The uniform scaling factor of the image. The default is "100 %", i.e.
+ no scaling.
+
+ If no "height" or "width" options are specified, the `Python Imaging
+ Library`_ (PIL) may be used to determine them, if it is installed and
+ the image file is available.
+
+``align`` : "top", "middle", "bottom", "left", "center", or "right"
+ The alignment of the image, equivalent to the HTML ``<img>`` tag's
+ deprecated "align" attribute or the corresponding "vertical-align" and
+ "text-align" CSS properties.
+ The values "top", "middle", and "bottom"
+ control an image's vertical alignment (relative to the text
+ baseline); they are only useful for inline images (substitutions).
+ The values "left", "center", and "right" control an image's
+ horizontal alignment, allowing the image to float and have the
+ text flow around it. The specific behavior depends upon the
+ browser or rendering software used.
+
+``target`` : text (URI or reference name)
+ Makes the image into a hyperlink reference ("clickable"). The
+ option argument may be a URI (relative or absolute), or a
+ `reference name`_ with underscore suffix (e.g. ```a name`_``).
+
+and the common options `:class:`_ and `:name:`_.
+
+.. _substitution definition: restructuredtext.html#substitution-definitions
+
+
+Figure
+======
+
+:Directive Type: "figure"
+:Doctree Elements: figure_, image_, caption_, legend_
+:Directive Arguments: One, required (image URI).
+:Directive Options: Possible.
+:Directive Content: Interpreted as the figure caption and an optional
+ legend.
+
+A "figure" consists of image_ data (including `image options`_), an optional
+caption (a single paragraph), and an optional legend (arbitrary body
+elements). For page-based output media, figures might float to a different
+position if this helps the page layout.
+::
+
+ .. figure:: picture.png
+ :scale: 50 %
+ :alt: map to buried treasure
+
+ This is the caption of the figure (a simple paragraph).
+
+ The legend consists of all elements after the caption. In this
+ case, the legend consists of this paragraph and the following
+ table:
+
+ +-----------------------+-----------------------+
+ | Symbol | Meaning |
+ +=======================+=======================+
+ | .. image:: tent.png | Campground |
+ +-----------------------+-----------------------+
+ | .. image:: waves.png | Lake |
+ +-----------------------+-----------------------+
+ | .. image:: peak.png | Mountain |
+ +-----------------------+-----------------------+
+
+There must be blank lines before the caption paragraph and before the
+legend. To specify a legend without a caption, use an empty comment
+("..") in place of the caption.
+
+The "figure" directive supports all of the options of the "image"
+directive (see `image options`_ above). These options (except
+"align") are passed on to the contained image.
+
+``align`` : "left", "center", or "right"
+ The horizontal alignment of the figure, allowing the image to
+ float and have the text flow around it. The specific behavior
+ depends upon the browser or rendering software used.
+
+In addition, the following options are recognized:
+
+``figwidth`` : "image", length_, or percentage_ of current line width
+ The width of the figure.
+ Limits the horizontal space used by the figure.
+ A special value of "image" is allowed, in which case the
+ included image's actual width is used (requires the `Python Imaging
+ Library`_). If the image file is not found or the required software is
+ unavailable, this option is ignored.
+
+ Sets the "width" attribute of the "figure" doctree element.
+
+ This option does not scale the included image; use the "width"
+ `image`_ option for that. ::
+
+ +---------------------------+
+ | figure |
+ | |
+ |<------ figwidth --------->|
+ | |
+ | +---------------------+ |
+ | | image | |
+ | | | |
+ | |<--- width --------->| |
+ | +---------------------+ |
+ | |
+ |The figure's caption should|
+ |wrap at this width. |
+ +---------------------------+
+
+``figclass`` : text
+ Set a `"classes"`_ attribute value on the figure element. See the
+ class_ directive below.
+
+.. _Python Imaging Library: http://www.pythonware.com/products/pil/
+
+
+---------------
+ Body Elements
+---------------
+
+Topic
+=====
+
+:Directive Type: "topic"
+:Doctree Element: topic_
+:Directive Arguments: One, required (topic title).
+:Directive Options: `:class:`_, `:name:`_
+:Directive Content: Interpreted as the topic body.
+
+A topic is like a block quote with a title, or a self-contained
+section with no subsections. Use the "topic" directive to indicate a
+self-contained idea that is separate from the flow of the document.
+Topics may occur anywhere a section or transition may occur. Body
+elements and topics may not contain nested topics.
+
+The directive's sole argument is interpreted as the topic title; the
+next line must be blank. All subsequent lines make up the topic body,
+interpreted as body elements. For example::
+
+ .. topic:: Topic Title
+
+ Subsequent indented lines comprise
+ the body of the topic, and are
+ interpreted as body elements.
+
+
+Sidebar
+=======
+
+:Directive Type: "sidebar"
+:Doctree Element: sidebar_
+:Directive Arguments: One, required (sidebar title).
+:Directive Options: Possible (see below).
+:Directive Content: Interpreted as the sidebar body.
+
+Sidebars are like miniature, parallel documents that occur inside
+other documents, providing related or reference material. A sidebar
+is typically offset by a border and "floats" to the side of the page;
+the document's main text may flow around it. Sidebars can also be
+likened to super-footnotes; their content is outside of the flow of
+the document's main text.
+
+Sidebars may occur anywhere a section or transition may occur. Body
+elements (including sidebars) may not contain nested sidebars.
+
+The directive's sole argument is interpreted as the sidebar title,
+which may be followed by a subtitle option (see below); the next line
+must be blank. All subsequent lines make up the sidebar body,
+interpreted as body elements. For example::
+
+ .. sidebar:: Sidebar Title
+ :subtitle: Optional Sidebar Subtitle
+
+ Subsequent indented lines comprise
+ the body of the sidebar, and are
+ interpreted as body elements.
+
+The following options are recognized:
+
+``subtitle`` : text
+ The sidebar's subtitle.
+
+and the common options `:class:`_ and `:name:`_.
+
+
+Line Block
+==========
+
+.. admonition:: Deprecated
+
+ The "line-block" directive is deprecated. Use the `line block
+ syntax`_ instead.
+
+ .. _line block syntax: restructuredtext.html#line-blocks
+
+:Directive Type: "line-block"
+:Doctree Element: line_block_
+:Directive Arguments: None.
+:Directive Options: `:class:`_, `:name:`_
+:Directive Content: Becomes the body of the line block.
+
+The "line-block" directive constructs an element where line breaks and
+initial indentation is significant and inline markup is supported. It
+is equivalent to a `parsed literal block`_ with different rendering:
+typically in an ordinary serif typeface instead of a
+typewriter/monospaced face, and not automatically indented. (Have the
+line-block directive begin a block quote to get an indented line
+block.) Line blocks are useful for address blocks and verse (poetry,
+song lyrics), where the structure of lines is significant. For
+example, here's a classic::
+
+ "To Ma Own Beloved Lassie: A Poem on her 17th Birthday", by
+ Ewan McTeagle (for Lassie O'Shea):
+
+ .. line-block::
+
+ Lend us a couple of bob till Thursday.
+ I'm absolutely skint.
+ But I'm expecting a postal order and I can pay you back
+ as soon as it comes.
+ Love, Ewan.
+
+
+
+.. _parsed-literal:
+
+Parsed Literal Block
+====================
+
+:Directive Type: "parsed-literal"
+:Doctree Element: literal_block_
+:Directive Arguments: None.
+:Directive Options: `:class:`_, `:name:`_
+:Directive Content: Becomes the body of the literal block.
+
+Unlike an ordinary literal block, the "parsed-literal" directive
+constructs a literal block where the text is parsed for inline markup.
+It is equivalent to a `line block`_ with different rendering:
+typically in a typewriter/monospaced typeface, like an ordinary
+literal block. Parsed literal blocks are useful for adding hyperlinks
+to code examples.
+
+However, care must be taken with the text, because inline markup is
+recognized and there is no protection from parsing. Backslash-escapes
+may be necessary to prevent unintended parsing. And because the
+markup characters are removed by the parser, care must also be taken
+with vertical alignment. Parsed "ASCII art" is tricky, and extra
+whitespace may be necessary.
+
+For example, all the element names in this content model are links::
+
+ .. parsed-literal::
+
+ ( (title_, subtitle_?)?,
+ decoration_?,
+ (docinfo_, transition_?)?,
+ `%structure.model;`_ )
+
+Code
+====
+
+:Directive Type: "code"
+:Doctree Element: literal_block_, `inline elements`_
+:Directive Arguments: One, optional (formal language).
+:Directive Options: name, class, number-lines.
+:Directive Content: Becomes the body of the literal block.
+:Configuration Setting: syntax_highlight_.
+
+(New in Docutils 0.9)
+
+The "code" directive constructs a literal block. If the code language is
+specified, the content is parsed by the Pygments_ syntax highlighter and
+tokens are stored in nested `inline elements`_ with class arguments
+according to their syntactic category. The actual highlighting requires
+a style-sheet (e.g. one `generated by Pygments`__, see the
+`sandbox/stylesheets`__ for examples).
+
+The parsing can be turned off with the syntax_highlight_ configuration
+setting and command line option or by specifying the language as `:class:`_
+option instead of directive argument. This also avoids warnings
+when Pygments_ is not installed or the language is not in the
+`supported languages and markup formats`_.
+
+For inline code, use the `"code" role`_.
+
+__ http://pygments.org/docs/cmdline/#generating-styles
+__ http://docutils.sourceforge.net/sandbox/stylesheets/
+.. _Pygments: http://pygments.org/
+.. _syntax_highlight: ../../user/config.html#syntax-highlight
+.. _supported languages and markup formats: http://pygments.org/languages/
+.. _"code" role: roles.html#code
+
+
+The following options are recognized:
+
+``number-lines`` : [start line number]
+ Precede every line with a line number.
+ The optional argument is the number of the first line (defaut 1).
+
+and the common options `:class:`_ and `:name:`_.
+
+Example::
+ The content of the following directive ::
+
+ .. code:: python
+
+ def my_function():
+ "just a test"
+ print 8/2
+
+ is parsed and marked up as Python source code.
+
+
+Math
+====
+
+:Directive Type: "math"
+:Doctree Element: math_block_
+:Directive Arguments: None.
+:Directive Options: `:class:`_, `:name:`_
+:Directive Content: Becomes the body of the math block.
+ (Content blocks separated by a blank line are put in
+ adjacent math blocks.)
+:Configuration Setting: math_output_
+
+(New in Docutils 0.8)
+
+The "math" directive inserts blocks with mathematical content
+(display formulas, equations) into the document. The input format is
+*LaTeX math syntax*\ [#math-syntax]_ with support for Unicode
+symbols, for example::
+
+ .. math::
+
+ α_t(i) = P(O_1, O_2, … O_t, q_t = S_i λ)
+
+Support is limited to a subset of *LaTeX math* by the conversion
+required for many output formats. For HTML, the `math_output`_
+configuration setting (or the corresponding ``--math-output``
+command line option) select between alternative output formats with
+different subsets of supported elements. If a writer does not
+support math typesetting at all, the content is inserted verbatim.
+
+.. [#math-syntax] The supported LaTeX commands include AMS extensions
+ (see, e.g., the `Short Math Guide`_).
+
+
+For inline formulas, use the `"math" role`_.
+
+.. _Short Math Guide: ftp://ftp.ams.org/ams/doc/amsmath/short-math-guide.pdf
+.. _"math" role: roles.html#math
+.. _math_output: ../../user/config.html#math-output
+
+Rubric
+======
+
+:Directive Type: "rubric"
+:Doctree Element: rubric_
+:Directive Arguments: One, required (rubric text).
+:Directive Options: `:class:`_, `:name:`_
+:Directive Content: None.
+
+..
+
+ rubric n. 1. a title, heading, or the like, in a manuscript,
+ book, statute, etc., written or printed in red or otherwise
+ distinguished from the rest of the text. ...
+
+ -- Random House Webster's College Dictionary, 1991
+
+The "rubric" directive inserts a "rubric" element into the document
+tree. A rubric is like an informal heading that doesn't correspond to
+the document's structure.
+
+
+Epigraph
+========
+
+:Directive Type: "epigraph"
+:Doctree Element: block_quote_
+:Directive Arguments: None.
+:Directive Options: None.
+:Directive Content: Interpreted as the body of the block quote.
+
+An epigraph is an apposite (suitable, apt, or pertinent) short
+inscription, often a quotation or poem, at the beginning of a document
+or section.
+
+The "epigraph" directive produces an "epigraph"-class block quote.
+For example, this input::
+
+ .. epigraph::
+
+ No matter where you go, there you are.
+
+ -- Buckaroo Banzai
+
+becomes this document tree fragment::
+
+ <block_quote classes="epigraph">
+ <paragraph>
+ No matter where you go, there you are.
+ <attribution>
+ Buckaroo Banzai
+
+
+Highlights
+==========
+
+:Directive Type: "highlights"
+:Doctree Element: block_quote_
+:Directive Arguments: None.
+:Directive Options: None.
+:Directive Content: Interpreted as the body of the block quote.
+
+Highlights summarize the main points of a document or section, often
+consisting of a list.
+
+The "highlights" directive produces a "highlights"-class block quote.
+See Epigraph_ above for an analogous example.
+
+
+Pull-Quote
+==========
+
+:Directive Type: "pull-quote"
+:Doctree Element: block_quote_
+:Directive Arguments: None.
+:Directive Options: None.
+:Directive Content: Interpreted as the body of the block quote.
+
+A pull-quote is a small selection of text "pulled out and quoted",
+typically in a larger typeface. Pull-quotes are used to attract
+attention, especially in long articles.
+
+The "pull-quote" directive produces a "pull-quote"-class block quote.
+See Epigraph_ above for an analogous example.
+
+
+Compound Paragraph
+==================
+
+:Directive Type: "compound"
+:Doctree Element: compound_
+:Directive Arguments: None.
+:Directive Options: `:class:`_, `:name:`_
+:Directive Content: Interpreted as body elements.
+
+(New in Docutils 0.3.6)
+
+The "compound" directive is used to create a compound paragraph, which
+is a single logical paragraph containing multiple physical body
+elements such as simple paragraphs, literal blocks, tables, lists,
+etc., instead of directly containing text and inline elements. For
+example::
+
+ .. compound::
+
+ The 'rm' command is very dangerous. If you are logged
+ in as root and enter ::
+
+ cd /
+ rm -rf *
+
+ you will erase the entire contents of your file system.
+
+In the example above, a literal block is "embedded" within a sentence
+that begins in one physical paragraph and ends in another.
+
+.. note::
+
+ The "compound" directive is *not* a generic block-level container
+ like HTML's ``<div>`` element. Do not use it only to group a
+ sequence of elements, or you may get unexpected results.
+
+ If you need a generic block-level container, please use the
+ container_ directive, described below.
+
+Compound paragraphs are typically rendered as multiple distinct text
+blocks, with the possibility of variations to emphasize their logical
+unity:
+
+* If paragraphs are rendered with a first-line indent, only the first
+ physical paragraph of a compound paragraph should have that indent
+ -- second and further physical paragraphs should omit the indents;
+* vertical spacing between physical elements may be reduced;
+* and so on.
+
+
+Container
+=========
+
+:Directive Type: "container"
+:Doctree Element: `container <container element_>`__
+:Directive Arguments: One or more, optional (class names).
+:Directive Options: `:name:`_
+:Directive Content: Interpreted as body elements.
+
+(New in Docutils 0.3.10)
+
+The "container" directive surrounds its contents (arbitrary body
+elements) with a generic block-level "container" element. Combined
+with the optional "classes_" attribute argument(s), this is an
+extension mechanism for users & applications. For example::
+
+ .. container:: custom
+
+ This paragraph might be rendered in a custom way.
+
+Parsing the above results in the following pseudo-XML::
+
+ <container classes="custom">
+ <paragraph>
+ This paragraph might be rendered in a custom way.
+
+The "container" directive is the equivalent of HTML's ``<div>``
+element. It may be used to group a sequence of elements for user- or
+application-specific purposes.
+
+
+
+--------
+ Tables
+--------
+
+Formal tables need more structure than the reStructuredText syntax
+supplies. Tables may be given titles with the table_ directive.
+Sometimes reStructuredText tables are inconvenient to write, or table
+data in a standard format is readily available. The csv-table_
+directive supports CSV data.
+
+
+Table
+=====
+
+:Directive Type: "table"
+:Doctree Element: table_
+:Directive Arguments: One, optional (table title).
+:Directive Options: Possible (see below).
+:Directive Content: A normal reStructuredText table.
+
+(New in Docutils 0.3.1)
+
+The "table" directive is used to associate a
+title with a table or specify options, e.g.::
+
+ .. table:: Truth table for "not"
+ :widths: auto
+
+ ===== =====
+ A not A
+ ===== =====
+ False True
+ True False
+ ===== =====
+
+The following options are recognized:
+
+``align`` : "left", "center", or "right"
+ The horizontal alignment of the table.
+ (New in Docutils 0.13)
+
+``widths`` : "auto", "grid" or a list of integers
+ A comma- or space-separated list of column widths.
+ The default is the width of the input columns (in characters).
+
+ The special values "auto" or "grid" may be used by writers to decide
+ whether to delegate the determination of column widths to the backend
+ (LaTeX, the HTML browser, ...).
+ See also the `table_style`_ configuration option.
+
+``width`` : `length`_ or `percentage`_ of the current line width
+ Forces the width of the table to the specified length or percentage
+ of the line width. If omitted, the renderer determines the width
+ of the table based on its contents.
+
+and the common options `:class:`_ and `:name:`_.
+
+.. _table_style: ../../user/config.html#table-style-html4css1-writer
+
+.. _csv-table:
+
+CSV Table
+=========
+
+:Directive Type: "csv-table"
+:Doctree Element: table_
+:Directive Arguments: One, optional (table title).
+:Directive Options: Possible (see below).
+:Directive Content: A CSV (comma-separated values) table.
+
+.. WARNING::
+
+ The "csv-table" directive's ":file:" and ":url:" options represent
+ a potential security holes. They can be disabled with the
+ "file_insertion_enabled_" runtime setting.
+
+(New in Docutils 0.3.4)
+
+The "csv-table" directive is used to create a table from CSV
+(comma-separated values) data. CSV is a common data format generated
+by spreadsheet applications and commercial databases. The data may be
+internal (an integral part of the document) or external (a separate
+file).
+
+Example::
+
+ .. csv-table:: Frozen Delights!
+ :header: "Treat", "Quantity", "Description"
+ :widths: 15, 10, 30
+
+ "Albatross", 2.99, "On a stick!"
+ "Crunchy Frog", 1.49, "If we took the bones out, it wouldn't be
+ crunchy, now would it?"
+ "Gannet Ripple", 1.99, "On a stick!"
+
+Block markup and inline markup within cells is supported. Line ends
+are recognized within cells.
+
+Working limitations:
+
+* There is no support for checking that the number of columns in each
+ row is the same. However, this directive supports CSV generators
+ that do not insert "empty" entries at the end of short rows, by
+ automatically adding empty entries.
+
+ .. Add "strict" option to verify input?
+
+.. [#whitespace-delim] Whitespace delimiters are supported only for external
+ CSV files.
+
+.. [#ASCII-char] With Python 2, the valuess for the ``delimiter``,
+ ``quote``, and ``escape`` options must be ASCII characters. (The csv
+ module does not support Unicode and all non-ASCII characters are
+ encoded as multi-byte utf-8 string). This limitation does not exist
+ under Python 3.
+
+The following options are recognized:
+
+``widths`` : integer [, integer...] or "auto"
+ A comma- or space-separated list of relative column widths. The
+ default is equal-width columns (100%/#columns).
+
+ The special value "auto" may be used by writers to decide
+ whether to delegate the determination of column widths to the backend
+ (LaTeX, the HTML browser, ...).
+
+``width`` : `length`_ or `percentage`_ of the current line width
+ Forces the width of the table to the specified length or percentage
+ of the line width. If omitted, the renderer determines the width
+ of the table based on its contents.
+
+``header-rows`` : integer
+ The number of rows of CSV data to use in the table header.
+ Defaults to 0.
+
+``stub-columns`` : integer
+ The number of table columns to use as stubs (row titles, on the
+ left). Defaults to 0.
+
+``header`` : CSV data
+ Supplemental data for the table header, added independently of and
+ before any ``header-rows`` from the main CSV data. Must use the
+ same CSV format as the main CSV data.
+
+``file`` : string (newlines removed)
+ The local filesystem path to a CSV data file.
+
+``url`` : string (whitespace removed)
+ An Internet URL reference to a CSV data file.
+
+``encoding`` : name of text encoding
+ The text encoding of the external CSV data (file or URL).
+ Defaults to the document's encoding (if specified).
+
+``delim`` : char | "tab" | "space" [#whitespace-delim]_
+ A one-character string\ [#ASCII-char]_ used to separate fields.
+ Defaults to ``,`` (comma). May be specified as a Unicode code
+ point; see the unicode_ directive for syntax details.
+
+``quote`` : char
+ A one-character string\ [#ASCII-char]_ used to quote elements
+ containing the delimiter or which start with the quote
+ character. Defaults to ``"`` (quote). May be specified as a
+ Unicode code point; see the unicode_ directive for syntax
+ details.
+
+``keepspace`` : flag
+ Treat whitespace immediately following the delimiter as
+ significant. The default is to ignore such whitespace.
+
+``escape`` : char
+ A one-character\ [#ASCII-char]_ string used to escape the
+ delimiter or quote characters. May be specified as a Unicode
+ code point; see the unicode_ directive for syntax details. Used
+ when the delimiter is used in an unquoted field, or when quote
+ characters are used within a field. The default is to double-up
+ the character, e.g. "He said, ""Hi!"""
+
+ .. Add another possible value, "double", to explicitly indicate
+ the default case?
+
+``align`` : "left", "center", or "right"
+ The horizontal alignment of the table.
+ (New in Docutils 0.13)
+
+and the common options `:class:`_ and `:name:`_.
+
+
+List Table
+==========
+
+:Directive Type: "list-table"
+:Doctree Element: table_
+:Directive Arguments: One, optional (table title).
+:Directive Options: Possible (see below).
+:Directive Content: A uniform two-level bullet list.
+
+(New in Docutils 0.3.8. This is an initial implementation; `further
+ideas`__ may be implemented in the future.)
+
+__ ../../dev/rst/alternatives.html#list-driven-tables
+
+The "list-table" directive is used to create a table from data in a
+uniform two-level bullet list. "Uniform" means that each sublist
+(second-level list) must contain the same number of list items.
+
+Example::
+
+ .. list-table:: Frozen Delights!
+ :widths: 15 10 30
+ :header-rows: 1
+
+ * - Treat
+ - Quantity
+ - Description
+ * - Albatross
+ - 2.99
+ - On a stick!
+ * - Crunchy Frog
+ - 1.49
+ - If we took the bones out, it wouldn't be
+ crunchy, now would it?
+ * - Gannet Ripple
+ - 1.99
+ - On a stick!
+
+The following options are recognized:
+
+``widths`` : integer [integer...] or "auto"
+ A comma- or space-separated list of relative column widths. The
+ default is equal-width columns (100%/#columns).
+
+ The special value "auto" may be used by writers to decide
+ whether to delegate the determination of column widths to the backend
+ (LaTeX, the HTML browser, ...).
+
+``width`` : `length`_ or `percentage`_ of the current line width
+ Forces the width of the table to the specified length or percentage
+ of the line width. If omitted, the renderer determines the width
+ of the table based on its contents.
+
+``header-rows`` : integer
+ The number of rows of list data to use in the table header.
+ Defaults to 0.
+
+``stub-columns`` : integer
+ The number of table columns to use as stubs (row titles, on the
+ left). Defaults to 0.
+
+``align`` : "left", "center", or "right"
+ The horizontal alignment of the table.
+ (New in Docutils 0.13)
+
+and the common options `:class:`_ and `:name:`_.
+
+
+----------------
+ Document Parts
+----------------
+
+.. _contents:
+
+Table of Contents
+=================
+
+:Directive Type: "contents"
+:Doctree Elements: pending_, topic_
+:Directive Arguments: One, optional: title.
+:Directive Options: Possible.
+:Directive Content: None.
+
+The "contents" directive generates a table of contents (TOC) in a
+topic_. Topics, and therefore tables of contents, may occur anywhere
+a section or transition may occur. Body elements and topics may not
+contain tables of contents.
+
+Here's the directive in its simplest form::
+
+ .. contents::
+
+Language-dependent boilerplate text will be used for the title. The
+English default title text is "Contents".
+
+An explicit title may be specified::
+
+ .. contents:: Table of Contents
+
+The title may span lines, although it is not recommended::
+
+ .. contents:: Here's a very long Table of
+ Contents title
+
+Options may be specified for the directive, using a field list::
+
+ .. contents:: Table of Contents
+ :depth: 2
+
+If the default title is to be used, the options field list may begin
+on the same line as the directive marker::
+
+ .. contents:: :depth: 2
+
+The following options are recognized:
+
+``depth`` : integer
+ The number of section levels that are collected in the table of
+ contents. The default is unlimited depth.
+
+``local`` : flag (empty)
+ Generate a local table of contents. Entries will only include
+ subsections of the section in which the directive is given. If no
+ explicit title is given, the table of contents will not be titled.
+
+``backlinks`` : "entry" or "top" or "none"
+ Generate links from section headers back to the table of contents
+ entries, the table of contents itself, or generate no backlinks.
+
+``class`` : text
+ Set a `"classes"`_ attribute value on the topic element. See the
+ class_ directive below.
+
+
+.. _sectnum:
+.. _section-numbering:
+
+Automatic Section Numbering
+===========================
+
+:Directive Type: "sectnum" or "section-numbering" (synonyms)
+:Doctree Elements: pending_, generated_
+:Directive Arguments: None.
+:Directive Options: Possible.
+:Directive Content: None.
+:Configuration Setting: sectnum_xform_
+
+The "sectnum" (or "section-numbering") directive automatically numbers
+sections and subsections in a document (if not disabled by the
+``--no-section-numbering`` command line option or the `sectnum_xform`_
+configuration setting).
+
+Section numbers are of the "multiple enumeration" form, where each
+level has a number, separated by periods. For example, the title of section
+1, subsection 2, subsubsection 3 would have "1.2.3" prefixed.
+
+The "sectnum" directive does its work in two passes: the initial parse
+and a transform. During the initial parse, a "pending" element is
+generated which acts as a placeholder, storing any options internally.
+At a later stage in the processing, the "pending" element triggers a
+transform, which adds section numbers to titles. Section numbers are
+enclosed in a "generated" element, and titles have their "auto"
+attribute set to "1".
+
+The following options are recognized:
+
+``depth`` : integer
+ The number of section levels that are numbered by this directive.
+ The default is unlimited depth.
+
+``prefix`` : string
+ An arbitrary string that is prefixed to the automatically
+ generated section numbers. It may be something like "3.2.", which
+ will produce "3.2.1", "3.2.2", "3.2.2.1", and so on. Note that
+ any separating punctuation (in the example, a period, ".") must be
+ explicitly provided. The default is no prefix.
+
+``suffix`` : string
+ An arbitrary string that is appended to the automatically
+ generated section numbers. The default is no suffix.
+
+``start`` : integer
+ The value that will be used for the first section number.
+ Combined with ``prefix``, this may be used to force the right
+ numbering for a document split over several source files. The
+ default is 1.
+
+.. _sectnum_xform: ../../user/config.html#sectnum-xform
+
+
+.. _header:
+.. _footer:
+
+Document Header & Footer
+========================
+
+:Directive Types: "header" and "footer"
+:Doctree Elements: decoration_, header, footer
+:Directive Arguments: None.
+:Directive Options: None.
+:Directive Content: Interpreted as body elements.
+
+(New in Docutils 0.3.8)
+
+The "header" and "footer" directives create document decorations,
+useful for page navigation, notes, time/datestamp, etc. For example::
+
+ .. header:: This space for rent.
+
+This will add a paragraph to the document header, which will appear at
+the top of the generated web page or at the top of every printed page.
+
+These directives may be used multiple times, cumulatively. There is
+currently support for only one header and footer.
+
+.. note::
+
+ While it is possible to use the "header" and "footer" directives to
+ create navigational elements for web pages, you should be aware
+ that Docutils is meant to be used for *document* processing, and
+ that a navigation bar is not typically part of a document.
+
+ Thus, you may soon find Docutils' abilities to be insufficient for
+ these purposes. At that time, you should consider using a
+ documentation generator like Sphinx_ rather than the "header" and
+ "footer" directives.
+
+ .. _Sphinx: http://sphinx-doc.org/
+
+In addition to the use of these directives to populate header and
+footer content, content may also be added automatically by the
+processing system. For example, if certain runtime settings are
+enabled, the document footer is populated with processing information
+such as a datestamp, a link to `the Docutils website`_, etc.
+
+.. _the Docutils website: http://docutils.sourceforge.net
+
+
+------------
+ References
+------------
+
+.. _target-notes:
+
+Target Footnotes
+================
+
+:Directive Type: "target-notes"
+:Doctree Elements: pending_, footnote_, footnote_reference_
+:Directive Arguments: None.
+:Directive Options: `:class:`_, `:name:`_
+:Directive Options: Possible.
+:Directive Content: None.
+
+The "target-notes" directive creates a footnote for each external
+target in the text, and corresponding footnote references after each
+reference. For every explicit target (of the form, ``.. _target name:
+URL``) in the text, a footnote will be generated containing the
+visible URL as content.
+
+
+Footnotes
+=========
+
+**NOT IMPLEMENTED YET**
+
+:Directive Type: "footnotes"
+:Doctree Elements: pending_, topic_
+:Directive Arguments: None?
+:Directive Options: Possible?
+:Directive Content: None.
+
+@@@
+
+
+Citations
+=========
+
+**NOT IMPLEMENTED YET**
+
+:Directive Type: "citations"
+:Doctree Elements: pending_, topic_
+:Directive Arguments: None?
+:Directive Options: Possible?
+:Directive Content: None.
+
+@@@
+
+
+---------------
+ HTML-Specific
+---------------
+
+Meta
+====
+
+:Directive Type: "meta"
+:Doctree Element: meta (non-standard)
+:Directive Arguments: None.
+:Directive Options: None.
+:Directive Content: Must contain a flat field list.
+
+The "meta" directive is used to specify HTML metadata stored in HTML
+META tags. "Metadata" is data about data, in this case data about web
+pages. Metadata is used to describe and classify web pages in the
+World Wide Web, in a form that is easy for search engines to extract
+and collate.
+
+Within the directive block, a flat field list provides the syntax for
+metadata. The field name becomes the contents of the "name" attribute
+of the META tag, and the field body (interpreted as a single string
+without inline markup) becomes the contents of the "content"
+attribute. For example::
+
+ .. meta::
+ :description: The reStructuredText plaintext markup language
+ :keywords: plaintext, markup language
+
+This would be converted to the following HTML::
+
+ <meta name="description"
+ content="The reStructuredText plaintext markup language">
+ <meta name="keywords" content="plaintext, markup language">
+
+Support for other META attributes ("http-equiv", "scheme", "lang",
+"dir") are provided through field arguments, which must be of the form
+"attr=value"::
+
+ .. meta::
+ :description lang=en: An amusing story
+ :description lang=fr: Une histoire amusante
+
+And their HTML equivalents::
+
+ <meta name="description" lang="en" content="An amusing story">
+ <meta name="description" lang="fr" content="Une histoire amusante">
+
+Some META tags use an "http-equiv" attribute instead of the "name"
+attribute. To specify "http-equiv" META tags, simply omit the name::
+
+ .. meta::
+ :http-equiv=Content-Type: text/html; charset=ISO-8859-1
+
+HTML equivalent::
+
+ <meta http-equiv="Content-Type"
+ content="text/html; charset=ISO-8859-1">
+
+
+Imagemap
+========
+
+**NOT IMPLEMENTED YET**
+
+Non-standard element: imagemap.
+
+
+-----------------------------------------
+ Directives for Substitution Definitions
+-----------------------------------------
+
+The directives in this section may only be used in substitution
+definitions. They may not be used directly, in standalone context.
+The `image`_ directive may be used both in substitution definitions
+and in the standalone context.
+
+
+.. _replace:
+
+Replacement Text
+================
+
+:Directive Type: "replace"
+:Doctree Element: Text & `inline elements`_
+:Directive Arguments: None.
+:Directive Options: None.
+:Directive Content: A single paragraph; may contain inline markup.
+
+The "replace" directive is used to indicate replacement text for a
+substitution reference. It may be used within substitution
+definitions only. For example, this directive can be used to expand
+abbreviations::
+
+ .. |reST| replace:: reStructuredText
+
+ Yes, |reST| is a long word, so I can't blame anyone for wanting to
+ abbreviate it.
+
+As reStructuredText doesn't support nested inline markup, the only way
+to create a reference with styled text is to use substitutions with
+the "replace" directive::
+
+ I recommend you try |Python|_.
+
+ .. |Python| replace:: Python, *the* best language around
+ .. _Python: http://www.python.org/
+
+
+.. _unicode:
+
+Unicode Character Codes
+=======================
+
+:Directive Type: "unicode"
+:Doctree Element: Text
+:Directive Arguments: One or more, required (Unicode character codes,
+ optional text, and comments).
+:Directive Options: Possible.
+:Directive Content: None.
+
+The "unicode" directive converts Unicode character codes (numerical
+values) to characters, and may be used in substitution definitions
+only.
+
+The arguments, separated by spaces, can be:
+
+* **character codes** as
+
+ - decimal numbers or
+
+ - hexadecimal numbers, prefixed by ``0x``, ``x``, ``\x``, ``U+``,
+ ``u``, or ``\u`` or as XML-style hexadecimal character entities,
+ e.g. ``ᨫ``
+
+* **text**, which is used as-is.
+
+Text following " .. " is a comment and is ignored. The spaces between
+the arguments are ignored and thus do not appear in the output.
+Hexadecimal codes are case-insensitive.
+
+For example, the following text::
+
+ Copyright |copy| 2003, |BogusMegaCorp (TM)| |---|
+ all rights reserved.
+
+ .. |copy| unicode:: 0xA9 .. copyright sign
+ .. |BogusMegaCorp (TM)| unicode:: BogusMegaCorp U+2122
+ .. with trademark sign
+ .. |---| unicode:: U+02014 .. em dash
+ :trim:
+
+results in:
+
+ Copyright |copy| 2003, |BogusMegaCorp (TM)| |---|
+ all rights reserved.
+
+ .. |copy| unicode:: 0xA9 .. copyright sign
+ .. |BogusMegaCorp (TM)| unicode:: BogusMegaCorp U+2122
+ .. with trademark sign
+ .. |---| unicode:: U+02014 .. em dash
+ :trim:
+
+The following options are recognized:
+
+``ltrim`` : flag
+ Whitespace to the left of the substitution reference is removed.
+
+``rtrim`` : flag
+ Whitespace to the right of the substitution reference is removed.
+
+``trim`` : flag
+ Equivalent to ``ltrim`` plus ``rtrim``; whitespace on both sides
+ of the substitution reference is removed.
+
+
+Date
+====
+
+:Directive Type: "date"
+:Doctree Element: Text
+:Directive Arguments: One, optional (date format).
+:Directive Options: None.
+:Directive Content: None.
+
+The "date" directive generates the current local date and inserts it
+into the document as text. This directive may be used in substitution
+definitions only.
+
+The optional directive content is interpreted as the desired date
+format, using the same codes as Python's time.strftime function. The
+default format is "%Y-%m-%d" (ISO 8601 date), but time fields can also
+be used. Examples::
+
+ .. |date| date::
+ .. |time| date:: %H:%M
+
+ Today's date is |date|.
+
+ This document was generated on |date| at |time|.
+
+
+---------------
+ Miscellaneous
+---------------
+
+.. _include:
+
+Including an External Document Fragment
+=======================================
+
+:Directive Type: "include"
+:Doctree Elements: Depend on data being included
+ (literal_block_ with ``code`` or ``literal`` option).
+:Directive Arguments: One, required (path to the file to include).
+:Directive Options: Possible.
+:Directive Content: None.
+:Configuration Setting: file_insertion_enabled_
+
+.. WARNING::
+
+ The "include" directive represents a potential security hole. It
+ can be disabled with the "file_insertion_enabled_" runtime setting.
+
+ .. _file_insertion_enabled: ../../user/config.html#file-insertion-enabled
+
+The "include" directive reads a text file. The directive argument is
+the path to the file to be included, relative to the document
+containing the directive. Unless the options ``literal`` or ``code``
+are given, the file is parsed in the current document's context at the
+point of the directive. For example::
+
+ This first example will be parsed at the document level, and can
+ thus contain any construct, including section headers.
+
+ .. include:: inclusion.txt
+
+ Back in the main document.
+
+ This second example will be parsed in a block quote context.
+ Therefore it may only contain body elements. It may not
+ contain section headers.
+
+ .. include:: inclusion.txt
+
+If an included document fragment contains section structure, the title
+adornments must match those of the master document.
+
+Standard data files intended for inclusion in reStructuredText
+documents are distributed with the Docutils source code, located in
+the "docutils" package in the ``docutils/parsers/rst/include``
+directory. To access these files, use the special syntax for standard
+"include" data files, angle brackets around the file name::
+
+ .. include:: <isonum.txt>
+
+The current set of standard "include" data files consists of sets of
+substitution definitions. See `reStructuredText Standard Definition
+Files`__ for details.
+
+__ definitions.html
+
+The following options are recognized:
+
+``start-line`` : integer
+ Only the content starting from this line will be included.
+ (As usual in Python, the first line has index 0 and negative values
+ count from the end.)
+
+``end-line`` : integer
+ Only the content up to (but excluding) this line will be included.
+
+``start-after`` : text to find in the external data file
+ Only the content after the first occurrence of the specified text
+ will be included.
+
+``end-before`` : text to find in the external data file
+ Only the content before the first occurrence of the specified text
+ (but after any ``after`` text) will be included.
+
+``literal`` : flag (empty)
+ The entire included text is inserted into the document as a single
+ literal block.
+
+``code`` : formal language (optional)
+ The argument and the content of the included file are passed to
+ the code_ directive (useful for program listings).
+ (New in Docutils 0.9)
+
+``number-lines`` : [start line number]
+ Precede every code line with a line number.
+ The optional argument is the number of the first line (defaut 1).
+ Works only with ``code`` or ``literal``.
+ (New in Docutils 0.9)
+
+``encoding`` : name of text encoding
+ The text encoding of the external data file. Defaults to the
+ document's input_encoding_.
+
+ .. _input_encoding: ../../user/config.html#input-encoding
+
+``tab-width`` : integer
+ Number of spaces for hard tab expansion.
+ A negative value prevents expansion of hard tabs. Defaults to the
+ tab_width_ configuration setting.
+
+ .. _tab_width: ../../user/config.html#tab-width
+
+
+With ``code`` or ``literal`` the common options `:class:`_ and
+`:name:`_ are recognized as well.
+
+Combining ``start/end-line`` and ``start-after/end-before`` is possible. The
+text markers will be searched in the specified lines (further limiting the
+included content).
+
+.. _raw-directive:
+
+Raw Data Pass-Through
+=====================
+
+:Directive Type: "raw"
+:Doctree Element: raw_
+:Directive Arguments: One or more, required (output format types).
+:Directive Options: Possible.
+:Directive Content: Stored verbatim, uninterpreted. None (empty) if a
+ "file" or "url" option given.
+:Configuration Setting: raw_enabled_
+
+.. WARNING::
+
+ The "raw" directive represents a potential security hole. It can
+ be disabled with the "raw_enabled_" or "file_insertion_enabled_"
+ runtime settings.
+
+ .. _raw_enabled: ../../user/config.html#raw-enabled
+
+.. Caution::
+
+ The "raw" directive is a stop-gap measure allowing the author to
+ bypass reStructuredText's markup. It is a "power-user" feature
+ that should not be overused or abused. The use of "raw" ties
+ documents to specific output formats and makes them less portable.
+
+ If you often need to use the "raw" directive or a "raw"-derived
+ interpreted text role, that is a sign either of overuse/abuse or
+ that functionality may be missing from reStructuredText. Please
+ describe your situation in a message to the Docutils-users_ mailing
+ list.
+
+.. _Docutils-users: ../../user/mailing-lists.html#docutils-users
+
+The "raw" directive indicates non-reStructuredText data that is to be
+passed untouched to the Writer. The names of the output formats are
+given in the directive arguments. The interpretation of the raw data
+is up to the Writer. A Writer may ignore any raw output not matching
+its format.
+
+For example, the following input would be passed untouched by an HTML
+Writer::
+
+ .. raw:: html
+
+ <hr width=50 size=10>
+
+A LaTeX Writer could insert the following raw content into its
+output stream::
+
+ .. raw:: latex
+
+ \setlength{\parindent}{0pt}
+
+Raw data can also be read from an external file, specified in a
+directive option. In this case, the content block must be empty. For
+example::
+
+ .. raw:: html
+ :file: inclusion.html
+
+Inline equivalents of the "raw" directive can be defined via
+`custom interpreted text roles`_ derived from the `"raw" role`_.
+
+The following options are recognized:
+
+``file`` : string (newlines removed)
+ The local filesystem path of a raw data file to be included.
+
+``url`` : string (whitespace removed)
+ An Internet URL reference to a raw data file to be included.
+
+``encoding`` : name of text encoding
+ The text encoding of the external raw data (file or URL).
+ Defaults to the document's encoding (if specified).
+
+.. _"raw" role: roles.html#raw
+
+
+.. _classes:
+
+Class
+=====
+
+:Directive Type: "class"
+:Doctree Element: pending_
+:Directive Arguments: One or more, required (class names / attribute
+ values).
+:Directive Options: None.
+:Directive Content: Optional. If present, it is interpreted as body
+ elements.
+
+The "class" directive sets the `"classes"`_ attribute value on its content
+or on the first immediately following [#]_ non-comment element [#]_.
+The directive argument consists of one or more space-separated class
+names. The names are transformed to conform to the regular expression
+``[a-z](-?[a-z0-9]+)*`` (see `Identifier Normalization`_ below).
+
+Examples::
+
+ .. class:: special
+
+ This is a "special" paragraph.
+
+ .. class:: exceptional remarkable
+
+ An Exceptional Section
+ ======================
+
+ This is an ordinary paragraph.
+
+ .. class:: multiple
+
+ First paragraph.
+
+ Second paragraph.
+
+The text above is parsed and transformed into this doctree fragment::
+
+ <paragraph classes="special">
+ This is a "special" paragraph.
+ <section classes="exceptional remarkable">
+ <title>
+ An Exceptional Section
+ <paragraph>
+ This is an ordinary paragraph.
+ <paragraph classes="multiple">
+ First paragraph.
+ <paragraph classes="multiple">
+ Second paragraph.
+
+
+.. [#] This is also true, if the class directive is "nested" at the end of
+ an indented text block, for example::
+
+ .. note:: the class values set in this directive-block do not apply to
+ the note but the next paragraph.
+
+ .. class:: special
+
+ This is a paragraph with class value "special".
+
+ This allows the "classification" of individual list items (except the
+ first, as a preceding class directive applies to the list as a whole)::
+
+ * bullet list
+
+ .. class:: classy item
+
+ * second item, with class argument
+
+.. [#] To set a "classes" attribute value on a block quote, the
+ "class" directive must be followed by an empty comment::
+
+ .. class:: highlights
+ ..
+
+ Block quote text.
+
+ Without the empty comment, the indented text would be interpreted as the
+ "class" directive's content, and the classes would be applied to each
+ element (paragraph, in this case) individually, instead of to the block
+ quote as a whole.
+
+
+Identifier Normalization
+~~~~~~~~~~~~~~~~~~~~~~~~
+
+Docutils `class names`_ and `identifier keys`_ are normalized to conform
+to the regular expression "``[a-z](-?[a-z0-9]+)*``" by converting
+
+* alphabetic characters to lowercase,
+* accented characters to the base character,
+* non-alphanumeric characters to hyphens,
+* consecutive hyphens into one hyphen
+
+and stripping
+
+* leading hyphens and number characters, and
+* trailing hyphens.
+
+For example ``"Rot.Gelb&Grün:+2008"`` becomes ``"rot-gelb-grun-2008"`` and
+``"1000_Steps!"`` becomes ``"steps"``.
+
+.. topic:: Rationale:
+
+ Identifier keys must be valid in all supported output formats.
+
+ For HTML 4.1 + CSS1 compatibility, identifiers should have no
+ underscores, colons, or periods. Hyphens may be used.
+
+ - The `HTML 4.01 spec`_ defines identifiers based on SGML tokens:
+
+ ID and NAME tokens must begin with a letter ([A-Za-z]) and
+ may be followed by any number of letters, digits ([0-9]),
+ hyphens ("-"), underscores ("_"), colons (":"), and periods
+ (".").
+
+ -- http://www.w3.org/TR/html401/types.html#type-name
+
+ - The `CSS1 spec`_ defines identifiers based on the "name" token
+ ("flex" tokenizer notation below; "latin1" and "escape" 8-bit
+ characters have been replaced with XML entities)::
+
+ unicode \\[0-9a-f]{1,4}
+ latin1 [¡-ÿ]
+ escape {unicode}|\\[ -~¡-ÿ]
+ nmchar [-A-Za-z0-9]|{latin1}|{escape}
+ name {nmchar}+
+
+ The CSS1 rule requires underscores ("_"), colons (":"), and
+ periods (".") to be escaped [#]_,
+ therefore `"classes"`_ and `"ids"`_ attributes should not
+ contain these characters. Combined with HTML4.1 requirements (the
+ first character must be a letter; no "unicode", "latin1", or
+ "escape" characters), this results in the regular expression
+ ``[A-Za-z][-A-Za-z0-9]*``. Docutils adds a normalization by
+ downcasing and merge of consecutive hyphens.
+
+ .. [#] CSS identifiers may use underscores ("_") directly in
+ `CSS Level 1`__, `CSS2.1`__, CSS2.2__, and CSS3__.
+
+ __ https://www.w3.org/TR/CSS21/syndata.html#value-def-identifier
+ __ https://www.w3.org/TR/CSS/#css-level-1
+ __ https://www.w3.org/TR/CSS22/syndata.html
+ __ https://www.w3.org/TR/css-syntax-3/#typedef-ident-token
+
+ .. _HTML 4.01 spec: http://www.w3.org/TR/html401/
+ .. _CSS1 spec: http://www.w3.org/TR/REC-CSS1
+
+.. _role:
+
+Custom Interpreted Text Roles
+=============================
+
+:Directive Type: "role"
+:Doctree Element: None; affects subsequent parsing.
+:Directive Arguments: Two; one required (new role name), one optional
+ (base role name, in parentheses).
+:Directive Options: Possible (depends on base role).
+:Directive Content: depends on base role.
+
+(New in Docutils 0.3.2)
+
+The "role" directive dynamically creates a custom interpreted text
+role and registers it with the parser. This means that after
+declaring a role like this::
+
+ .. role:: custom
+
+the document may use the new "custom" role::
+
+ An example of using :custom:`interpreted text`
+
+This will be parsed into the following document tree fragment::
+
+ <paragraph>
+ An example of using
+ <inline classes="custom">
+ interpreted text
+
+The role must be declared in a document before it can be used.
+
+The new role may be based on an existing role, specified as a second
+argument in parentheses (whitespace optional)::
+
+ .. role:: custom(emphasis)
+
+ :custom:`text`
+
+The parsed result is as follows::
+
+ <paragraph>
+ <emphasis classes="custom">
+ text
+
+A special case is the `"raw" role`_: derived roles enable
+inline `raw data pass-through`_, e.g.::
+
+ .. role:: raw-role(raw)
+ :format: html latex
+
+ :raw-role:`raw text`
+
+If no base role is explicitly specified, a generic custom role is
+automatically used. Subsequent interpreted text will produce an
+"inline" element with a `"classes"`_ attribute, as in the first example
+above.
+
+With most roles, the ":class:" option can be used to set a "classes"
+attribute that is different from the role name. For example::
+
+ .. role:: custom
+ :class: special
+
+ :custom:`interpreted text`
+
+This is the parsed result::
+
+ <paragraph>
+ <inline classes="special">
+ interpreted text
+
+.. _role class:
+
+The following option is recognized by the "role" directive for most
+base roles:
+
+``class`` : text
+ Set the `"classes"`_ attribute value on the element produced
+ (``inline``, or element associated with a base class) when the
+ custom interpreted text role is used. If no directive options are
+ specified, a "class" option with the directive argument (role
+ name) as the value is implied. See the class_ directive above.
+
+Specific base roles may support other options and/or directive
+content. See the `reStructuredText Interpreted Text Roles`_ document
+for details.
+
+.. _reStructuredText Interpreted Text Roles: roles.html
+
+
+.. _default-role:
+
+Setting the Default Interpreted Text Role
+=========================================
+
+:Directive Type: "default-role"
+:Doctree Element: None; affects subsequent parsing.
+:Directive Arguments: One, optional (new default role name).
+:Directive Options: None.
+:Directive Content: None.
+
+(New in Docutils 0.3.10)
+
+The "default-role" directive sets the default interpreted text role,
+the role that is used for interpreted text without an explicit role.
+For example, after setting the default role like this::
+
+ .. default-role:: subscript
+
+any subsequent use of implicit-role interpreted text in the document
+will use the "subscript" role::
+
+ An example of a `default` role.
+
+This will be parsed into the following document tree fragment::
+
+ <paragraph>
+ An example of a
+ <subscript>
+ default
+ role.
+
+Custom roles may be used (see the "role_" directive above), but it
+must have been declared in a document before it can be set as the
+default role. See the `reStructuredText Interpreted Text Roles`_
+document for details of built-in roles.
+
+The directive may be used without an argument to restore the initial
+default interpreted text role, which is application-dependent. The
+initial default interpreted text role of the standard reStructuredText
+parser is "title-reference".
+
+
+Metadata Document Title
+=======================
+
+:Directive Type: "title"
+:Doctree Element: None.
+:Directive Arguments: One, required (the title text).
+:Directive Options: None.
+:Directive Content: None.
+
+The "title" directive specifies the document title as metadata, which
+does not become part of the document body. It overrides a
+document-supplied title. For example, in HTML output the metadata
+document title appears in the title bar of the browser window.
+
+
+Restructuredtext-Test-Directive
+===============================
+
+:Directive Type: "restructuredtext-test-directive"
+:Doctree Element: system_warning
+:Directive Arguments: None.
+:Directive Options: None.
+:Directive Content: Interpreted as a literal block.
+
+This directive is provided for test purposes only. (Nobody is
+expected to type in a name *that* long!) It is converted into a
+level-1 (info) system message showing the directive data, possibly
+followed by a literal block containing the rest of the directive
+block.
+
+--------------
+Common Options
+--------------
+
+Most of the directives that generate doctree elements support the following
+options:
+
+.. _class-option:
+
+_`:class:` : text
+ Set a `"classes"`_ attribute value on the doctree element generated by
+ the directive. See also the class_ directive.
+
+_`:name:` : text
+ Add `text` to the `"names"`_ attribute of the doctree element generated
+ by the directive. This allows `hyperlink references`_ to the element
+ using `text` as `reference name`_.
+
+ Specifying the `name` option of a directive, e.g., ::
+
+ .. image:: bild.png
+ :name: my picture
+
+ is a concise syntax alternative to preceding it with a `hyperlink
+ target`_ ::
+
+ .. _my picture:
+
+ .. image:: bild.png
+
+ New in Docutils 0.8.
+
+
+.. _reference name: restructuredtext.html#reference-names
+.. _hyperlink target: restructuredtext.html#hyperlink-targets
+.. _hyperlink references: restructuredtext.html#hyperlink-references
+.. _class names: ../doctree.html#classnames-type
+.. _"classes": ../doctree.html#classes
+.. _identifier keys: ../doctree.html#ids-type
+.. _"ids": ../doctree.html#ids
+.. _"names": ../doctree.html#names
+.. _admonition: ../doctree.html#admonition
+.. _block_quote: ../doctree.html#block-quote
+.. _caption: ../doctree.html#caption
+.. _compound: ../doctree.html#compound
+.. _container element: ../doctree.html#container
+.. _decoration: ../doctree.html#decoration
+.. _figure: ../doctree.html#figure
+.. _footnote: ../doctree.html#footnote
+.. _footnote_reference: ../doctree.html#footnote-reference
+.. _generated: ../doctree.html#generated
+.. _image: ../doctree.html#image
+.. _inline elements: ../doctree.html#inline-elements
+.. _literal_block: ../doctree.html#literal-block
+.. _legend: ../doctree.html#legend
+.. _length: restructuredtext.html#length-units
+.. _line_block: ../doctree.html#line-block
+.. _math_block: ../doctree.html#math-block
+.. _pending: ../doctree.html#pending
+.. _percentage: restructuredtext.html#percentage-units
+.. _raw: ../doctree.html#raw
+.. _rubric: ../doctree.html#rubric
+.. _sidebar: ../doctree.html#sidebar
+.. _table: ../doctree.html#table
+.. _title: ../doctree.html#title
+.. _topic: ../doctree.html#topic
+
+
+\f
+..
+ Local Variables:
+ mode: indented-text
+ indent-tabs-mode: nil
+ sentence-end-double-space: t
+ fill-column: 70
+ End:
--- /dev/null
+=====================================
+ An Introduction to reStructuredText
+=====================================
+:Author: David Goodger
+:Contact: docutils-develop@lists.sourceforge.net
+:Revision: $Revision: 7302 $
+:Date: $Date: 2012-01-03 20:23:53 +0100 (Di, 03. Jän 2012) $
+:Copyright: This document has been placed in the public domain.
+
+reStructuredText_ is an easy-to-read, what-you-see-is-what-you-get
+plaintext markup syntax and parser system. It is useful for inline
+program documentation (such as Python docstrings), for quickly
+creating simple web pages, and for standalone documents.
+reStructuredText_ is a proposed revision and reinterpretation of the
+StructuredText_ and Setext_ lightweight markup systems.
+
+reStructuredText is designed for extensibility for specific
+application domains. Its parser is a component of Docutils_.
+
+This document defines the goals_ of reStructuredText and provides a
+history_ of the project. It is written using the reStructuredText
+markup, and therefore serves as an example of its use. For a gentle
+introduction to using reStructuredText, please read `A
+ReStructuredText Primer`_. The `Quick reStructuredText`_ user
+reference is also useful. The `reStructuredText Markup
+Specification`_ is the definitive reference. There is also an
+analysis of the `Problems With StructuredText`_.
+
+ReStructuredText's web page is
+http://docutils.sourceforge.net/rst.html.
+
+.. _reStructuredText: http://docutils.sourceforge.net/rst.html
+.. _StructuredText:
+ http://www.zope.org/DevHome/Members/jim/StructuredTextWiki/FrontPage
+.. _Setext: http://docutils.sourceforge.net/mirror/setext.html
+.. _Docutils: http://docutils.sourceforge.net/
+.. _A ReStructuredText Primer: ../../user/rst/quickstart.html
+.. _Quick reStructuredText: ../../user/rst/quickref.html
+.. _reStructuredText Markup Specification: restructuredtext.html
+.. _Problems with StructuredText: ../../dev/rst/problems.html
+
+
+Goals
+=====
+
+The primary goal of reStructuredText_ is to define a markup syntax for
+use in Python docstrings and other documentation domains, that is
+readable and simple, yet powerful enough for non-trivial use. The
+intended purpose of the reStructuredText markup is twofold:
+
+- the establishment of a set of standard conventions allowing the
+ expression of structure within plaintext, and
+
+- the conversion of such documents into useful structured data
+ formats.
+
+The secondary goal of reStructuredText is to be accepted by the Python
+community (by way of being blessed by PythonLabs and the BDFL [#]_) as
+a standard for Python inline documentation (possibly one of several
+standards, to account for taste).
+
+.. [#] Python's creator and "Benevolent Dictator For Life",
+ Guido van Rossum.
+
+To clarify the primary goal, here are specific design goals, in order,
+beginning with the most important:
+
+1. Readable. The marked-up text must be easy to read without any
+ prior knowledge of the markup language. It should be as easily
+ read in raw form as in processed form.
+
+2. Unobtrusive. The markup that is used should be as simple and
+ unobtrusive as possible. The simplicity of markup constructs
+ should be roughly proportional to their frequency of use. The most
+ common constructs, with natural and obvious markup, should be the
+ simplest and most unobtrusive. Less common constructs, for which
+ there is no natural or obvious markup, should be distinctive.
+
+3. Unambiguous. The rules for markup must not be open for
+ interpretation. For any given input, there should be one and only
+ one possible output (including error output).
+
+4. Unsurprising. Markup constructs should not cause unexpected output
+ upon processing. As a fallback, there must be a way to prevent
+ unwanted markup processing when a markup construct is used in a
+ non-markup context (for example, when documenting the markup syntax
+ itself).
+
+5. Intuitive. Markup should be as obvious and easily remembered as
+ possible, for the author as well as for the reader. Constructs
+ should take their cues from such naturally occurring sources as
+ plaintext email messages, newsgroup postings, and text
+ documentation such as README.txt files.
+
+6. Easy. It should be easy to mark up text using any ordinary text
+ editor.
+
+7. Scalable. The markup should be applicable regardless of the length
+ of the text.
+
+8. Powerful. The markup should provide enough constructs to produce a
+ reasonably rich structured document.
+
+9. Language-neutral. The markup should apply to multiple natural (as
+ well as artificial) languages, not only English.
+
+10. Extensible. The markup should provide a simple syntax and
+ interface for adding more complex general markup, and custom
+ markup.
+
+11. Output-format-neutral. The markup will be appropriate for
+ processing to multiple output formats, and will not be biased
+ toward any particular format.
+
+The design goals above were used as criteria for accepting or
+rejecting syntax, or selecting between alternatives.
+
+It is emphatically *not* the goal of reStructuredText to define
+docstring semantics, such as docstring contents or docstring length.
+These issues are orthogonal to the markup syntax and beyond the scope
+of this specification.
+
+Also, it is not the goal of reStructuredText to maintain compatibility
+with StructuredText_ or Setext_. reStructuredText shamelessly steals
+their great ideas and ignores the not-so-great.
+
+Author's note:
+
+ Due to the nature of the problem we're trying to solve (or,
+ perhaps, due to the nature of the proposed solution), the above
+ goals unavoidably conflict. I have tried to extract and distill
+ the wisdom accumulated over the years in the Python Doc-SIG_
+ mailing list and elsewhere, to come up with a coherent and
+ consistent set of syntax rules, and the above goals by which to
+ measure them.
+
+ There will inevitably be people who disagree with my particular
+ choices. Some desire finer control over their markup, others
+ prefer less. Some are concerned with very short docstrings,
+ others with full-length documents. This specification is an
+ effort to provide a reasonably rich set of markup constructs in a
+ reasonably simple form, that should satisfy a reasonably large
+ group of reasonable people.
+
+ David Goodger (goodger@python.org), 2001-04-20
+
+.. _Doc-SIG: http://www.python.org/sigs/doc-sig/
+
+
+History
+=======
+
+reStructuredText_, the specification, is based on StructuredText_ and
+Setext_. StructuredText was developed by Jim Fulton of `Zope
+Corporation`_ (formerly Digital Creations) and first released in 1996.
+It is now released as a part of the open-source "Z Object Publishing
+Environment" (ZOPE_). Ian Feldman's and Tony Sanders' earlier Setext_
+specification was either an influence on StructuredText or, by their
+similarities, at least evidence of the correctness of this approach.
+
+I discovered StructuredText_ in late 1999 while searching for a way to
+document the Python modules in one of my projects. Version 1.1 of
+StructuredText was included in Daniel Larsson's pythondoc_. Although
+I was not able to get pythondoc to work for me, I found StructuredText
+to be almost ideal for my needs. I joined the Python Doc-SIG_
+(Documentation Special Interest Group) mailing list and found an
+ongoing discussion of the shortcomings of the StructuredText
+"standard". This discussion has been going on since the inception of
+the mailing list in 1996, and possibly predates it.
+
+I decided to modify the original module with my own extensions and
+some suggested by the Doc-SIG members. I soon realized that the
+module was not written with extension in mind, so I embarked upon a
+general reworking, including adapting it to the "re" regular
+expression module (the original inspiration for the name of this
+project). Soon after I completed the modifications, I discovered that
+StructuredText.py was up to version 1.23 in the ZOPE distribution.
+Implementing the new syntax extensions from version 1.23 proved to be
+an exercise in frustration, as the complexity of the module had become
+overwhelming.
+
+In 2000, development on StructuredTextNG_ ("Next Generation") began at
+`Zope Corporation`_ (then Digital Creations). It seems to have many
+improvements, but still suffers from many of the problems of classic
+StructuredText.
+
+I decided that a complete rewrite was in order, and even started a
+`reStructuredText SourceForge project`_ (now inactive). My
+motivations (the "itches" I aim to "scratch") are as follows:
+
+- I need a standard format for inline documentation of the programs I
+ write. This inline documentation has to be convertible to other
+ useful formats, such as HTML. I believe many others have the same
+ need.
+
+- I believe in the Setext/StructuredText idea and want to help
+ formalize the standard. However, I feel the current specifications
+ and implementations have flaws that desperately need fixing.
+
+- reStructuredText could form part of the foundation for a
+ documentation extraction and processing system, greatly benefitting
+ Python. But it is only a part, not the whole. reStructuredText is
+ a markup language specification and a reference parser
+ implementation, but it does not aspire to be the entire system. I
+ don't want reStructuredText or a hypothetical Python documentation
+ processor to die stillborn because of over-ambition.
+
+- Most of all, I want to help ease the documentation chore, the bane
+ of many a programmer.
+
+Unfortunately I was sidetracked and stopped working on this project.
+In November 2000 I made the time to enumerate the problems of
+StructuredText and possible solutions, and complete the first draft of
+a specification. This first draft was posted to the Doc-SIG in three
+parts:
+
+- `A Plan for Structured Text`__
+- `Problems With StructuredText`__
+- `reStructuredText: Revised Structured Text Specification`__
+
+__ http://mail.python.org/pipermail/doc-sig/2000-November/001239.html
+__ http://mail.python.org/pipermail/doc-sig/2000-November/001240.html
+__ http://mail.python.org/pipermail/doc-sig/2000-November/001241.html
+
+In March 2001 a flurry of activity on the Doc-SIG spurred me to
+further revise and refine my specification, the result of which you
+are now reading. An offshoot of the reStructuredText project has been
+the realization that a single markup scheme, no matter how well
+thought out, may not be enough. In order to tame the endless debates
+on Doc-SIG, a flexible `Docstring Processing System framework`_ needed
+to be constructed. This framework has become the more important of
+the two projects; reStructuredText_ has found its place as one
+possible choice for a single component of the larger framework.
+
+The project web site and the first project release were rolled out in
+June 2001, including posting the second draft of the spec [#spec-2]_
+and the first draft of PEPs 256, 257, and 258 [#peps-1]_ to the
+Doc-SIG. These documents and the project implementation proceeded to
+evolve at a rapid pace. Implementation history details can be found
+in the `project history file`_.
+
+In November 2001, the reStructuredText parser was nearing completion.
+Development of the parser continued with the addition of small
+convenience features, improvements to the syntax, the filling in of
+gaps, and bug fixes. After a long holiday break, in early 2002 most
+development moved over to the other Docutils components, the
+"Readers", "Writers", and "Transforms". A "standalone" reader
+(processes standalone text file documents) was completed in February,
+and a basic HTML writer (producing HTML 4.01, using CSS-1) was
+completed in early March.
+
+`PEP 287`_, "reStructuredText Standard Docstring Format", was created
+to formally propose reStructuredText as a standard format for Python
+docstrings, PEPs, and other files. It was first posted to
+comp.lang.python_ and the Python-dev_ mailing list on 2002-04-02.
+
+Version 0.4 of the reStructuredText__ and `Docstring Processing
+System`_ projects were released in April 2002. The two projects were
+immediately merged, renamed to "Docutils_", and a 0.1 release soon
+followed.
+
+.. __: `reStructuredText SourceForge project`_
+
+.. [#spec-2] The second draft of the spec:
+
+ - `An Introduction to reStructuredText`__
+ - `Problems With StructuredText`__
+ - `reStructuredText Markup Specification`__
+ - `Python Extensions to the reStructuredText Markup
+ Specification`__
+
+ __ http://mail.python.org/pipermail/doc-sig/2001-June/001858.html
+ __ http://mail.python.org/pipermail/doc-sig/2001-June/001859.html
+ __ http://mail.python.org/pipermail/doc-sig/2001-June/001860.html
+ __ http://mail.python.org/pipermail/doc-sig/2001-June/001861.html
+
+.. [#peps-1] First drafts of the PEPs:
+
+ - `PEP 256: Docstring Processing System Framework`__
+ - `PEP 258: DPS Generic Implementation Details`__
+ - `PEP 257: Docstring Conventions`__
+
+ Current working versions of the PEPs can be found in
+ http://docutils.sourceforge.net/docs/peps/, and official versions
+ can be found in the `master PEP repository`_.
+
+ __ http://mail.python.org/pipermail/doc-sig/2001-June/001855.html
+ __ http://mail.python.org/pipermail/doc-sig/2001-June/001856.html
+ __ http://mail.python.org/pipermail/doc-sig/2001-June/001857.html
+
+
+.. _Zope Corporation: http://www.zope.com
+.. _ZOPE: http://www.zope.org
+.. _reStructuredText SourceForge project:
+ http://structuredtext.sourceforge.net/
+.. _pythondoc: http://starship.python.net/crew/danilo/pythondoc/
+.. _StructuredTextNG:
+ http://www.zope.org/DevHome/Members/jim/StructuredTextWiki/StructuredTextNG
+.. _project history file: ../../../HISTORY.html
+.. _PEP 287: ../../peps/pep-0287.html
+.. _Docstring Processing System framework: ../../peps/pep-0256.html
+.. _comp.lang.python: news:comp.lang.python
+.. _Python-dev: http://mail.python.org/pipermail/python-dev/
+.. _Docstring Processing System: http://docstring.sourceforge.net/
+.. _master PEP repository: http://www.python.org/peps/
+
+\f
+..
+ Local Variables:
+ mode: indented-text
+ indent-tabs-mode: nil
+ sentence-end-double-space: t
+ fill-column: 70
+ End:
--- /dev/null
+.. -*- coding: utf-8 -*-
+
+=======================================
+ reStructuredText Markup Specification
+=======================================
+
+:Author: David Goodger
+:Contact: docutils-develop@lists.sourceforge.net
+:Revision: $Revision: 8407 $
+:Date: $Date: 2019-10-29 23:48:34 +0100 (Di, 29. Okt 2019) $
+:Copyright: This document has been placed in the public domain.
+
+.. Note::
+
+ This document is a detailed technical specification; it is not a
+ tutorial or a primer. If this is your first exposure to
+ reStructuredText, please read `A ReStructuredText Primer`_ and the
+ `Quick reStructuredText`_ user reference first.
+
+.. _A ReStructuredText Primer: ../../user/rst/quickstart.html
+.. _Quick reStructuredText: ../../user/rst/quickref.html
+
+
+reStructuredText_ is plaintext that uses simple and intuitive
+constructs to indicate the structure of a document. These constructs
+are equally easy to read in raw and processed forms. This document is
+itself an example of reStructuredText (raw, if you are reading the
+text file, or processed, if you are reading an HTML document, for
+example). The reStructuredText parser is a component of Docutils_.
+
+Simple, implicit markup is used to indicate special constructs, such
+as section headings, bullet lists, and emphasis. The markup used is
+as minimal and unobtrusive as possible. Less often-used constructs
+and extensions to the basic reStructuredText syntax may have more
+elaborate or explicit markup.
+
+reStructuredText is applicable to documents of any length, from the
+very small (such as inline program documentation fragments, e.g.
+Python docstrings) to the quite large (this document).
+
+The first section gives a quick overview of the syntax of the
+reStructuredText markup by example. A complete specification is given
+in the `Syntax Details`_ section.
+
+`Literal blocks`_ (in which no markup processing is done) are used for
+examples throughout this document, to illustrate the plaintext markup.
+
+
+.. contents::
+
+
+-----------------------
+ Quick Syntax Overview
+-----------------------
+
+A reStructuredText document is made up of body or block-level
+elements, and may be structured into sections. Sections_ are
+indicated through title style (underlines & optional overlines).
+Sections contain body elements and/or subsections. Some body elements
+contain further elements, such as lists containing list items, which
+in turn may contain paragraphs and other body elements. Others, such
+as paragraphs, contain text and `inline markup`_ elements.
+
+Here are examples of `body elements`_:
+
+- Paragraphs_ (and `inline markup`_)::
+
+ Paragraphs contain text and may contain inline markup:
+ *emphasis*, **strong emphasis**, `interpreted text`, ``inline
+ literals``, standalone hyperlinks (http://www.python.org),
+ external hyperlinks (Python_), internal cross-references
+ (example_), footnote references ([1]_), citation references
+ ([CIT2002]_), substitution references (|example|), and _`inline
+ internal targets`.
+
+ Paragraphs are separated by blank lines and are left-aligned.
+
+- Five types of lists:
+
+ 1. `Bullet lists`_::
+
+ - This is a bullet list.
+
+ - Bullets can be "*", "+", or "-".
+
+ 2. `Enumerated lists`_::
+
+ 1. This is an enumerated list.
+
+ 2. Enumerators may be arabic numbers, letters, or roman
+ numerals.
+
+ 3. `Definition lists`_::
+
+ what
+ Definition lists associate a term with a definition.
+
+ how
+ The term is a one-line phrase, and the definition is one
+ or more paragraphs or body elements, indented relative to
+ the term.
+
+ 4. `Field lists`_::
+
+ :what: Field lists map field names to field bodies, like
+ database records. They are often part of an extension
+ syntax.
+
+ :how: The field marker is a colon, the field name, and a
+ colon.
+
+ The field body may contain one or more body elements,
+ indented relative to the field marker.
+
+ 5. `Option lists`_, for listing command-line options::
+
+ -a command-line option "a"
+ -b file options can have arguments
+ and long descriptions
+ --long options can be long also
+ --input=file long options can also have
+ arguments
+ /V DOS/VMS-style options too
+
+ There must be at least two spaces between the option and the
+ description.
+
+- `Literal blocks`_::
+
+ Literal blocks are either indented or line-prefix-quoted blocks,
+ and indicated with a double-colon ("::") at the end of the
+ preceding paragraph (right here -->)::
+
+ if literal_block:
+ text = 'is left as-is'
+ spaces_and_linebreaks = 'are preserved'
+ markup_processing = None
+
+- `Block quotes`_::
+
+ Block quotes consist of indented body elements:
+
+ This theory, that is mine, is mine.
+
+ -- Anne Elk (Miss)
+
+- `Doctest blocks`_::
+
+ >>> print 'Python-specific usage examples; begun with ">>>"'
+ Python-specific usage examples; begun with ">>>"
+ >>> print '(cut and pasted from interactive Python sessions)'
+ (cut and pasted from interactive Python sessions)
+
+- Two syntaxes for tables_:
+
+ 1. `Grid tables`_; complete, but complex and verbose::
+
+ +------------------------+------------+----------+
+ | Header row, column 1 | Header 2 | Header 3 |
+ +========================+============+==========+
+ | body row 1, column 1 | column 2 | column 3 |
+ +------------------------+------------+----------+
+ | body row 2 | Cells may span |
+ +------------------------+-----------------------+
+
+ 2. `Simple tables`_; easy and compact, but limited::
+
+ ==================== ========== ==========
+ Header row, column 1 Header 2 Header 3
+ ==================== ========== ==========
+ body row 1, column 1 column 2 column 3
+ body row 2 Cells may span columns
+ ==================== ======================
+
+- `Explicit markup blocks`_ all begin with an explicit block marker,
+ two periods and a space:
+
+ - Footnotes_::
+
+ .. [1] A footnote contains body elements, consistently
+ indented by at least 3 spaces.
+
+ - Citations_::
+
+ .. [CIT2002] Just like a footnote, except the label is
+ textual.
+
+ - `Hyperlink targets`_::
+
+ .. _Python: http://www.python.org
+
+ .. _example:
+
+ The "_example" target above points to this paragraph.
+
+ - Directives_::
+
+ .. image:: mylogo.png
+
+ - `Substitution definitions`_::
+
+ .. |symbol here| image:: symbol.png
+
+ - Comments_::
+
+ .. Comments begin with two dots and a space. Anything may
+ follow, except for the syntax of footnotes/citations,
+ hyperlink targets, directives, or substitution definitions.
+
+
+----------------
+ Syntax Details
+----------------
+
+Descriptions below list "doctree elements" (document tree element
+names; XML DTD generic identifiers) corresponding to syntax
+constructs. For details on the hierarchy of elements, please see `The
+Docutils Document Tree`_ and the `Docutils Generic DTD`_ XML document
+type definition.
+
+
+Whitespace
+==========
+
+Spaces are recommended for indentation_, but tabs may also be used.
+Tabs will be converted to spaces. Tab stops are at every 8th column.
+
+Other whitespace characters (form feeds [chr(12)] and vertical tabs
+[chr(11)]) are converted to single spaces before processing.
+
+
+Blank Lines
+-----------
+
+Blank lines are used to separate paragraphs and other elements.
+Multiple successive blank lines are equivalent to a single blank line,
+except within literal blocks (where all whitespace is preserved).
+Blank lines may be omitted when the markup makes element separation
+unambiguous, in conjunction with indentation. The first line of a
+document is treated as if it is preceded by a blank line, and the last
+line of a document is treated as if it is followed by a blank line.
+
+
+Indentation
+-----------
+
+Indentation is used to indicate -- and is only significant in
+indicating -- block quotes, definitions (in definition list items),
+and local nested content:
+
+- list item content (multi-line contents of list items, and multiple
+ body elements within a list item, including nested lists),
+- the content of literal blocks, and
+- the content of explicit markup blocks.
+
+Any text whose indentation is less than that of the current level
+(i.e., unindented text or "dedents") ends the current level of
+indentation.
+
+Since all indentation is significant, the level of indentation must be
+consistent. For example, indentation is the sole markup indicator for
+`block quotes`_::
+
+ This is a top-level paragraph.
+
+ This paragraph belongs to a first-level block quote.
+
+ Paragraph 2 of the first-level block quote.
+
+Multiple levels of indentation within a block quote will result in
+more complex structures::
+
+ This is a top-level paragraph.
+
+ This paragraph belongs to a first-level block quote.
+
+ This paragraph belongs to a second-level block quote.
+
+ Another top-level paragraph.
+
+ This paragraph belongs to a second-level block quote.
+
+ This paragraph belongs to a first-level block quote. The
+ second-level block quote above is inside this first-level
+ block quote.
+
+When a paragraph or other construct consists of more than one line of
+text, the lines must be left-aligned::
+
+ This is a paragraph. The lines of
+ this paragraph are aligned at the left.
+
+ This paragraph has problems. The
+ lines are not left-aligned. In addition
+ to potential misinterpretation, warning
+ and/or error messages will be generated
+ by the parser.
+
+Several constructs begin with a marker, and the body of the construct
+must be indented relative to the marker. For constructs using simple
+markers (`bullet lists`_, `enumerated lists`_, footnotes_, citations_,
+`hyperlink targets`_, directives_, and comments_), the level of
+indentation of the body is determined by the position of the first
+line of text, which begins on the same line as the marker. For
+example, bullet list bodies must be indented by at least two columns
+relative to the left edge of the bullet::
+
+ - This is the first line of a bullet list
+ item's paragraph. All lines must align
+ relative to the first line. [1]_
+
+ This indented paragraph is interpreted
+ as a block quote.
+
+ Because it is not sufficiently indented,
+ this paragraph does not belong to the list
+ item.
+
+ .. [1] Here's a footnote. The second line is aligned
+ with the beginning of the footnote label. The ".."
+ marker is what determines the indentation.
+
+For constructs using complex markers (`field lists`_ and `option
+lists`_), where the marker may contain arbitrary text, the indentation
+of the first line *after* the marker determines the left edge of the
+body. For example, field lists may have very long markers (containing
+the field names)::
+
+ :Hello: This field has a short field name, so aligning the field
+ body with the first line is feasible.
+
+ :Number-of-African-swallows-required-to-carry-a-coconut: It would
+ be very difficult to align the field body with the left edge
+ of the first line. It may even be preferable not to begin the
+ body on the same line as the marker.
+
+
+Escaping Mechanism
+==================
+
+The character set universally available to plaintext documents, 7-bit
+ASCII, is limited. No matter what characters are used for markup,
+they will already have multiple meanings in written text. Therefore
+markup characters *will* sometimes appear in text **without being
+intended as markup**. Any serious markup system requires an escaping
+mechanism to override the default meaning of the characters used for
+the markup. In reStructuredText we use the backslash, commonly used
+as an escaping character in other domains.
+
+A backslash followed by any character (except whitespace characters
+in non-URI contexts)
+escapes that character. The escaped character represents the
+character itself, and is prevented from playing a role in any markup
+interpretation. The backslash is removed from the output. A literal
+backslash is represented by two backslashes in a row (the first
+backslash "escapes" the second, preventing it being interpreted in an
+"escaping" role).
+
+In non-URI contexts,
+backslash-escaped whitespace characters are removed from the document.
+This allows for character-level `inline markup`_.
+
+In URIs, backslash-escaped whitespace represents a single space.
+
+There are two contexts in which backslashes have no special meaning:
+literal blocks and inline literals. In these contexts, a single
+backslash represents a literal backslash, without having to double up.
+
+Please note that the reStructuredText specification and parser do not
+address the issue of the representation or extraction of text input
+(how and in what form the text actually *reaches* the parser).
+Backslashes and other characters may serve a character-escaping
+purpose in certain contexts and must be dealt with appropriately. For
+example, Python uses backslashes in strings to escape certain
+characters, but not others. The simplest solution when backslashes
+appear in Python docstrings is to use raw docstrings::
+
+ r"""This is a raw docstring. Backslashes (\) are not touched."""
+
+
+Reference Names
+===============
+
+`Reference names` identify elements for cross-referencing.
+
+.. Note:: References to a target position in external, generated documents
+ must use the auto-generated `identifier key`_ which may differ from the
+ `reference name` due to restrictions on identifiers/labels in the
+ output format.
+
+ .. _identifier key: ../doctree.html#identifier-keys
+
+Simple reference names are single words consisting of alphanumerics
+plus isolated (no two adjacent) internal hyphens, underscores,
+periods, colons and plus signs; no whitespace or other characters are
+allowed. Footnote labels (Footnotes_ & `Footnote References`_), citation
+labels (Citations_ & `Citation References`_), `interpreted text`_ roles,
+and some `hyperlink references`_ use the simple reference name syntax.
+
+Reference names using punctuation or whose names are phrases (two or
+more space-separated words) are called "phrase-references".
+Phrase-references are expressed by enclosing the phrase in backquotes
+and treating the backquoted text as a reference name::
+
+ Want to learn about `my favorite programming language`_?
+
+ .. _my favorite programming language: http://www.python.org
+
+Simple reference names may also optionally use backquotes.
+
+.. _`normalized reference names`:
+
+Reference names are whitespace-neutral and case-insensitive. When
+resolving reference names internally:
+
+- whitespace is normalized (one or more spaces, horizontal or vertical
+ tabs, newlines, carriage returns, or form feeds, are interpreted as
+ a single space), and
+
+- case is normalized (all alphabetic characters are converted to
+ lowercase).
+
+For example, the following `hyperlink references`_ are equivalent::
+
+ - `A HYPERLINK`_
+ - `a hyperlink`_
+ - `A
+ Hyperlink`_
+
+Hyperlinks_, footnotes_, and citations_ all share the same namespace
+for reference names. The labels of citations (simple reference names)
+and manually-numbered footnotes (numbers) are entered into the same
+database as other hyperlink names. This means that a footnote
+(defined as "``.. [1]``") which can be referred to by a footnote
+reference (``[1]_``), can also be referred to by a plain hyperlink
+reference (1_). Of course, each type of reference (hyperlink,
+footnote, citation) may be processed and rendered differently. Some
+care should be taken to avoid reference name conflicts.
+
+
+Document Structure
+==================
+
+Document
+--------
+
+Doctree element: document.
+
+The top-level element of a parsed reStructuredText document is the
+"document" element. After initial parsing, the document element is a
+simple container for a document fragment, consisting of `body
+elements`_, transitions_, and sections_, but lacking a document title
+or other bibliographic elements. The code that calls the parser may
+choose to run one or more optional post-parse transforms_,
+rearranging the document fragment into a complete document with a
+title and possibly other metadata elements (author, date, etc.; see
+`Bibliographic Fields`_).
+
+.. _document title:
+
+Specifically, there is no way to indicate a document title and
+subtitle explicitly in reStructuredText. [#]_ Instead, a lone top-level
+section title (see Sections_ below) can be treated as the document
+title. Similarly, a lone second-level section title immediately after
+the "document title" can become the document subtitle. The rest of
+the sections are then lifted up a level or two. See the `DocTitle
+transform`_ for details.
+
+.. [#] The `title`_ configuration setting can set a document title that does
+ not become part of the document body.
+
+.. _title: ../../user/config.html#title
+
+
+Sections
+--------
+
+Doctree elements: section, title.
+
+Sections are identified through their titles, which are marked up with
+adornment: "underlines" below the title text, or underlines and
+matching "overlines" above the title. An underline/overline is a
+single repeated punctuation character that begins in column 1 and
+forms a line extending at least as far as the right edge of the title
+text. Specifically, an underline/overline character may be any
+non-alphanumeric printable 7-bit ASCII character [#]_. When an
+overline is used, the length and character used must match the
+underline. Underline-only adornment styles are distinct from
+overline-and-underline styles that use the same character. There may
+be any number of levels of section titles, although some output
+formats may have limits (HTML has 6 levels).
+
+.. [#] The following are all valid section title adornment
+ characters::
+
+ ! " # $ % & ' ( ) * + , - . / : ; < = > ? @ [ \ ] ^ _ ` { | } ~
+
+ Some characters are more suitable than others. The following are
+ recommended::
+
+ = - ` : . ' " ~ ^ _ * + #
+
+Rather than imposing a fixed number and order of section title
+adornment styles, the order enforced will be the order as encountered.
+The first style encountered will be an outermost title (like HTML H1),
+the second style will be a subtitle, the third will be a subsubtitle,
+and so on.
+
+Below are examples of section title styles::
+
+ ===============
+ Section Title
+ ===============
+
+ ---------------
+ Section Title
+ ---------------
+
+ Section Title
+ =============
+
+ Section Title
+ -------------
+
+ Section Title
+ `````````````
+
+ Section Title
+ '''''''''''''
+
+ Section Title
+ .............
+
+ Section Title
+ ~~~~~~~~~~~~~
+
+ Section Title
+ *************
+
+ Section Title
+ +++++++++++++
+
+ Section Title
+ ^^^^^^^^^^^^^
+
+When a title has both an underline and an overline, the title text may
+be inset, as in the first two examples above. This is merely
+aesthetic and not significant. Underline-only title text may *not* be
+inset.
+
+A blank line after a title is optional. All text blocks up to the
+next title of the same or higher level are included in a section (or
+subsection, etc.).
+
+All section title styles need not be used, nor need any specific
+section title style be used. However, a document must be consistent
+in its use of section titles: once a hierarchy of title styles is
+established, sections must use that hierarchy.
+
+Each section title automatically generates a hyperlink target pointing
+to the section. The text of the hyperlink target (the "reference
+name") is the same as that of the section title. See `Implicit
+Hyperlink Targets`_ for a complete description.
+
+Sections may contain `body elements`_, transitions_, and nested
+sections.
+
+
+Transitions
+-----------
+
+Doctree element: transition.
+
+ Instead of subheads, extra space or a type ornament between
+ paragraphs may be used to mark text divisions or to signal
+ changes in subject or emphasis.
+
+ (The Chicago Manual of Style, 14th edition, section 1.80)
+
+Transitions are commonly seen in novels and short fiction, as a gap
+spanning one or more lines, with or without a type ornament such as a
+row of asterisks. Transitions separate other body elements. A
+transition should not begin or end a section or document, nor should
+two transitions be immediately adjacent.
+
+The syntax for a transition marker is a horizontal line of 4 or more
+repeated punctuation characters. The syntax is the same as section
+title underlines without title text. Transition markers require blank
+lines before and after::
+
+ Para.
+
+ ----------
+
+ Para.
+
+Unlike section title underlines, no hierarchy of transition markers is
+enforced, nor do differences in transition markers accomplish
+anything. It is recommended that a single consistent style be used.
+
+The processing system is free to render transitions in output in any
+way it likes. For example, horizontal rules (``<hr>``) in HTML output
+would be an obvious choice.
+
+
+Body Elements
+=============
+
+Paragraphs
+----------
+
+Doctree element: paragraph.
+
+Paragraphs consist of blocks of left-aligned text with no markup
+indicating any other body element. Blank lines separate paragraphs
+from each other and from other body elements. Paragraphs may contain
+`inline markup`_.
+
+Syntax diagram::
+
+ +------------------------------+
+ | paragraph |
+ | |
+ +------------------------------+
+
+ +------------------------------+
+ | paragraph |
+ | |
+ +------------------------------+
+
+
+Bullet Lists
+------------
+
+Doctree elements: bullet_list, list_item.
+
+A text block which begins with a "*", "+", "-", "•", "‣", or "⁃",
+followed by whitespace, is a bullet list item (a.k.a. "unordered" list
+item). List item bodies must be left-aligned and indented relative to
+the bullet; the text immediately after the bullet determines the
+indentation. For example::
+
+ - This is the first bullet list item. The blank line above the
+ first list item is required; blank lines between list items
+ (such as below this paragraph) are optional.
+
+ - This is the first paragraph in the second item in the list.
+
+ This is the second paragraph in the second item in the list.
+ The blank line above this paragraph is required. The left edge
+ of this paragraph lines up with the paragraph above, both
+ indented relative to the bullet.
+
+ - This is a sublist. The bullet lines up with the left edge of
+ the text blocks above. A sublist is a new list so requires a
+ blank line above and below.
+
+ - This is the third item of the main list.
+
+ This paragraph is not part of the list.
+
+Here are examples of **incorrectly** formatted bullet lists::
+
+ - This first line is fine.
+ A blank line is required between list items and paragraphs.
+ (Warning)
+
+ - The following line appears to be a new sublist, but it is not:
+ - This is a paragraph continuation, not a sublist (since there's
+ no blank line). This line is also incorrectly indented.
+ - Warnings may be issued by the implementation.
+
+Syntax diagram::
+
+ +------+-----------------------+
+ | "- " | list item |
+ +------| (body elements)+ |
+ +-----------------------+
+
+
+Enumerated Lists
+----------------
+
+Doctree elements: enumerated_list, list_item.
+
+Enumerated lists (a.k.a. "ordered" lists) are similar to bullet lists,
+but use enumerators instead of bullets. An enumerator consists of an
+enumeration sequence member and formatting, followed by whitespace.
+The following enumeration sequences are recognized:
+
+- arabic numerals: 1, 2, 3, ... (no upper limit).
+- uppercase alphabet characters: A, B, C, ..., Z.
+- lower-case alphabet characters: a, b, c, ..., z.
+- uppercase Roman numerals: I, II, III, IV, ..., MMMMCMXCIX (4999).
+- lowercase Roman numerals: i, ii, iii, iv, ..., mmmmcmxcix (4999).
+
+In addition, the auto-enumerator, "#", may be used to automatically
+enumerate a list. Auto-enumerated lists may begin with explicit
+enumeration, which sets the sequence. Fully auto-enumerated lists use
+arabic numerals and begin with 1. (Auto-enumerated lists are new in
+Docutils 0.3.8.)
+
+The following formatting types are recognized:
+
+- suffixed with a period: "1.", "A.", "a.", "I.", "i.".
+- surrounded by parentheses: "(1)", "(A)", "(a)", "(I)", "(i)".
+- suffixed with a right-parenthesis: "1)", "A)", "a)", "I)", "i)".
+
+While parsing an enumerated list, a new list will be started whenever:
+
+- An enumerator is encountered which does not have the same format and
+ sequence type as the current list (e.g. "1.", "(a)" produces two
+ separate lists).
+
+- The enumerators are not in sequence (e.g., "1.", "3." produces two
+ separate lists).
+
+It is recommended that the enumerator of the first list item be
+ordinal-1 ("1", "A", "a", "I", or "i"). Although other start-values
+will be recognized, they may not be supported by the output format. A
+level-1 [info] system message will be generated for any list beginning
+with a non-ordinal-1 enumerator.
+
+Lists using Roman numerals must begin with "I"/"i" or a
+multi-character value, such as "II" or "XV". Any other
+single-character Roman numeral ("V", "X", "L", "C", "D", "M") will be
+interpreted as a letter of the alphabet, not as a Roman numeral.
+Likewise, lists using letters of the alphabet may not begin with
+"I"/"i", since these are recognized as Roman numeral 1.
+
+The second line of each enumerated list item is checked for validity.
+This is to prevent ordinary paragraphs from being mistakenly
+interpreted as list items, when they happen to begin with text
+identical to enumerators. For example, this text is parsed as an
+ordinary paragraph::
+
+ A. Einstein was a really
+ smart dude.
+
+However, ambiguity cannot be avoided if the paragraph consists of only
+one line. This text is parsed as an enumerated list item::
+
+ A. Einstein was a really smart dude.
+
+If a single-line paragraph begins with text identical to an enumerator
+("A.", "1.", "(b)", "I)", etc.), the first character will have to be
+escaped in order to have the line parsed as an ordinary paragraph::
+
+ \A. Einstein was a really smart dude.
+
+Examples of nested enumerated lists::
+
+ 1. Item 1 initial text.
+
+ a) Item 1a.
+ b) Item 1b.
+
+ 2. a) Item 2a.
+ b) Item 2b.
+
+Example syntax diagram::
+
+ +-------+----------------------+
+ | "1. " | list item |
+ +-------| (body elements)+ |
+ +----------------------+
+
+
+Definition Lists
+----------------
+
+Doctree elements: definition_list, definition_list_item, term,
+classifier, definition.
+
+Each definition list item contains a term, optional classifiers, and a
+definition. A term is a simple one-line word or phrase. Optional
+classifiers may follow the term on the same line, each after an inline
+" : " (space, colon, space). A definition is a block indented
+relative to the term, and may contain multiple paragraphs and other
+body elements. There may be no blank line between a term line and a
+definition block (this distinguishes definition lists from `block
+quotes`_). Blank lines are required before the first and after the
+last definition list item, but are optional in-between. For example::
+
+ term 1
+ Definition 1.
+
+ term 2
+ Definition 2, paragraph 1.
+
+ Definition 2, paragraph 2.
+
+ term 3 : classifier
+ Definition 3.
+
+ term 4 : classifier one : classifier two
+ Definition 4.
+
+Inline markup is parsed in the term line before the classifier
+delimiter (" : ") is recognized. The delimiter will only be
+recognized if it appears outside of any inline markup.
+
+A definition list may be used in various ways, including:
+
+- As a dictionary or glossary. The term is the word itself, a
+ classifier may be used to indicate the usage of the term (noun,
+ verb, etc.), and the definition follows.
+
+- To describe program variables. The term is the variable name, a
+ classifier may be used to indicate the type of the variable (string,
+ integer, etc.), and the definition describes the variable's use in
+ the program. This usage of definition lists supports the classifier
+ syntax of Grouch_, a system for describing and enforcing a Python
+ object schema.
+
+Syntax diagram::
+
+ +----------------------------+
+ | term [ " : " classifier ]* |
+ +--+-------------------------+--+
+ | definition |
+ | (body elements)+ |
+ +----------------------------+
+
+
+Field Lists
+-----------
+
+Doctree elements: field_list, field, field_name, field_body.
+
+Field lists are used as part of an extension syntax, such as options
+for directives_, or database-like records meant for further
+processing. They may also be used for two-column table-like
+structures resembling database records (label & data pairs).
+Applications of reStructuredText may recognize field names and
+transform fields or field bodies in certain contexts. For examples,
+see `Bibliographic Fields`_ below, or the "image_" and "meta_"
+directives in `reStructuredText Directives`_.
+
+.. _field names:
+
+Field lists are mappings from *field names* to *field bodies*, modeled on
+RFC822_ headers. A field name may consist of any characters, but
+colons (":") inside of field names must be backslash-escaped
+when followed by whitespace.\ [#]_
+Inline markup is parsed in field names, but care must be taken when
+using `interpreted text`_ with explicit roles in field names: the role
+must be a suffix to the interpreted text. Field names are
+case-insensitive when further processed or transformed. The field
+name, along with a single colon prefix and suffix, together form the
+field marker. The field marker is followed by whitespace and the
+field body. The field body may contain multiple body elements,
+indented relative to the field marker. The first line after the field
+name marker determines the indentation of the field body. For
+example::
+
+ :Date: 2001-08-16
+ :Version: 1
+ :Authors: - Me
+ - Myself
+ - I
+ :Indentation: Since the field marker may be quite long, the second
+ and subsequent lines of the field body do not have to line up
+ with the first line, but they must be indented relative to the
+ field name marker, and they must line up with each other.
+ :Parameter i: integer
+
+The interpretation of individual words in a multi-word field name is
+up to the application. The application may specify a syntax for the
+field name. For example, second and subsequent words may be treated
+as "arguments", quoted phrases may be treated as a single argument,
+and direct support for the "name=value" syntax may be added.
+
+Standard RFC822_ headers cannot be used for this construct because
+they are ambiguous. A word followed by a colon at the beginning of a
+line is common in written text. However, in well-defined contexts
+such as when a field list invariably occurs at the beginning of a
+document (PEPs and email messages), standard RFC822 headers could be
+used.
+
+Syntax diagram (simplified)::
+
+ +--------------------+----------------------+
+ | ":" field name ":" | field body |
+ +-------+------------+ |
+ | (body elements)+ |
+ +-----------------------------------+
+
+.. [#] Up to Docutils 0.14, field markers were not recognized when
+ containing a colon.
+
+Bibliographic Fields
+````````````````````
+
+Doctree elements: docinfo, author, authors, organization, contact,
+version, status, date, copyright, field, topic.
+
+When a field list is the first non-comment element in a document
+(after the document title, if there is one), it may have its fields
+transformed to document bibliographic data. This bibliographic data
+corresponds to the front matter of a book, such as the title page and
+copyright page.
+
+Certain registered field names (listed below) are recognized and
+transformed to the corresponding doctree elements, most becoming child
+elements of the "docinfo" element. No ordering is required of these
+fields, although they may be rearranged to fit the document structure,
+as noted. Unless otherwise indicated below, each of the bibliographic
+elements' field bodies may contain a single paragraph only. Field
+bodies may be checked for `RCS keywords`_ and cleaned up. Any
+unrecognized fields will remain as generic fields in the docinfo
+element.
+
+The registered bibliographic field names and their corresponding
+doctree elements are as follows:
+
+- Field name "Author": author element.
+- "Authors": authors.
+- "Organization": organization.
+- "Contact": contact.
+- "Address": address.
+- "Version": version.
+- "Status": status.
+- "Date": date.
+- "Copyright": copyright.
+- "Dedication": topic.
+- "Abstract": topic.
+
+The "Authors" field may contain either: a single paragraph consisting
+of a list of authors, separated by ";" or "," (";" is checked first,
+so "Doe, Jane; Doe, John" will work.); multiple paragraphs (one per
+author); or a bullet list whose elements each contain a single
+paragraph per author. In some languages
+(e.g. Swedish), there is no singular/plural distinction between
+"Author" and "Authors", so only an "Authors" field is provided, and a
+single name is interpreted as an "Author". If a single name contains
+a comma, end it with a semicolon to disambiguate: ":Authors: Doe,
+Jane;".
+
+The "Address" field is for a multi-line surface mailing address.
+Newlines and whitespace will be preserved.
+
+The "Dedication" and "Abstract" fields may contain arbitrary body
+elements. Only one of each is allowed. They become topic elements
+with "Dedication" or "Abstract" titles (or language equivalents)
+immediately following the docinfo element.
+
+This field-name-to-element mapping can be replaced for other
+languages. See the `DocInfo transform`_ implementation documentation
+for details.
+
+Unregistered/generic fields may contain one or more paragraphs or
+arbitrary body elements.
+The field name is also used as a `"classes" attribute`_ value after being
+converted into a valid identifier form.
+
+
+RCS Keywords
+````````````
+
+`Bibliographic fields`_ recognized by the parser are normally checked
+for RCS [#]_ keywords and cleaned up [#]_. RCS keywords may be
+entered into source files as "$keyword$", and once stored under RCS or
+CVS [#]_, they are expanded to "$keyword: expansion text $". For
+example, a "Status" field will be transformed to a "status" element::
+
+ :Status: $keyword: expansion text $
+
+.. [#] Revision Control System.
+.. [#] RCS keyword processing can be turned off (unimplemented).
+.. [#] Concurrent Versions System. CVS uses the same keywords as RCS.
+
+Processed, the "status" element's text will become simply "expansion
+text". The dollar sign delimiters and leading RCS keyword name are
+removed.
+
+The RCS keyword processing only kicks in when the field list is in
+bibliographic context (first non-comment construct in the document,
+after a document title if there is one).
+
+
+Option Lists
+------------
+
+Doctree elements: option_list, option_list_item, option_group, option,
+option_string, option_argument, description.
+
+Option lists are two-column lists of command-line options and
+descriptions, documenting a program's options. For example::
+
+ -a Output all.
+ -b Output both (this description is
+ quite long).
+ -c arg Output just arg.
+ --long Output all day long.
+
+ -p This option has two paragraphs in the description.
+ This is the first.
+
+ This is the second. Blank lines may be omitted between
+ options (as above) or left in (as here and below).
+
+ --very-long-option A VMS-style option. Note the adjustment for
+ the required two spaces.
+
+ --an-even-longer-option
+ The description can also start on the next line.
+
+ -2, --two This option has two variants.
+
+ -f FILE, --file=FILE These two options are synonyms; both have
+ arguments.
+
+ /V A VMS/DOS-style option.
+
+There are several types of options recognized by reStructuredText:
+
+- Short POSIX options consist of one dash and an option letter.
+- Long POSIX options consist of two dashes and an option word; some
+ systems use a single dash.
+- Old GNU-style "plus" options consist of one plus and an option
+ letter ("plus" options are deprecated now, their use discouraged).
+- DOS/VMS options consist of a slash and an option letter or word.
+
+Please note that both POSIX-style and DOS/VMS-style options may be
+used by DOS or Windows software. These and other variations are
+sometimes used mixed together. The names above have been chosen for
+convenience only.
+
+The syntax for short and long POSIX options is based on the syntax
+supported by Python's getopt.py_ module, which implements an option
+parser similar to the `GNU libc getopt_long()`_ function but with some
+restrictions. There are many variant option systems, and
+reStructuredText option lists do not support all of them.
+
+Although long POSIX and DOS/VMS option words may be allowed to be
+truncated by the operating system or the application when used on the
+command line, reStructuredText option lists do not show or support
+this with any special syntax. The complete option word should be
+given, supported by notes about truncation if and when applicable.
+
+Options may be followed by an argument placeholder, whose role and
+syntax should be explained in the description text. Either a space or
+an equals sign may be used as a delimiter between options and option
+argument placeholders; short options ("-" or "+" prefix only) may omit
+the delimiter. Option arguments may take one of two forms:
+
+- Begins with a letter (``[a-zA-Z]``) and subsequently consists of
+ letters, numbers, underscores and hyphens (``[a-zA-Z0-9_-]``).
+- Begins with an open-angle-bracket (``<``) and ends with a
+ close-angle-bracket (``>``); any characters except angle brackets
+ are allowed internally.
+
+Multiple option "synonyms" may be listed, sharing a single
+description. They must be separated by comma-space.
+
+There must be at least two spaces between the option(s) and the
+description. The description may contain multiple body elements. The
+first line after the option marker determines the indentation of the
+description. As with other types of lists, blank lines are required
+before the first option list item and after the last, but are optional
+between option entries.
+
+Syntax diagram (simplified)::
+
+ +----------------------------+-------------+
+ | option [" " argument] " " | description |
+ +-------+--------------------+ |
+ | (body elements)+ |
+ +----------------------------------+
+
+
+Literal Blocks
+--------------
+
+Doctree element: literal_block.
+
+A paragraph consisting of two colons ("::") signifies that the
+following text block(s) comprise a literal block. The literal block
+must either be indented or quoted (see below). No markup processing
+is done within a literal block. It is left as-is, and is typically
+rendered in a monospaced typeface::
+
+ This is a typical paragraph. An indented literal block follows.
+
+ ::
+
+ for a in [5,4,3,2,1]: # this is program code, shown as-is
+ print a
+ print "it's..."
+ # a literal block continues until the indentation ends
+
+ This text has returned to the indentation of the first paragraph,
+ is outside of the literal block, and is therefore treated as an
+ ordinary paragraph.
+
+The paragraph containing only "::" will be completely removed from the
+output; no empty paragraph will remain.
+
+As a convenience, the "::" is recognized at the end of any paragraph.
+If immediately preceded by whitespace, both colons will be removed
+from the output (this is the "partially minimized" form). When text
+immediately precedes the "::", *one* colon will be removed from the
+output, leaving only one colon visible (i.e., "::" will be replaced by
+":"; this is the "fully minimized" form).
+
+In other words, these are all equivalent (please pay attention to the
+colons after "Paragraph"):
+
+1. Expanded form::
+
+ Paragraph:
+
+ ::
+
+ Literal block
+
+2. Partially minimized form::
+
+ Paragraph: ::
+
+ Literal block
+
+3. Fully minimized form::
+
+ Paragraph::
+
+ Literal block
+
+All whitespace (including line breaks, but excluding minimum
+indentation for indented literal blocks) is preserved. Blank lines
+are required before and after a literal block, but these blank lines
+are not included as part of the literal block.
+
+
+Indented Literal Blocks
+```````````````````````
+
+Indented literal blocks are indicated by indentation relative to the
+surrounding text (leading whitespace on each line). The minimum
+indentation will be removed from each line of an indented literal
+block. The literal block need not be contiguous; blank lines are
+allowed between sections of indented text. The literal block ends
+with the end of the indentation.
+
+Syntax diagram::
+
+ +------------------------------+
+ | paragraph |
+ | (ends with "::") |
+ +------------------------------+
+ +---------------------------+
+ | indented literal block |
+ +---------------------------+
+
+
+Quoted Literal Blocks
+`````````````````````
+
+Quoted literal blocks are unindented contiguous blocks of text where
+each line begins with the same non-alphanumeric printable 7-bit ASCII
+character [#]_. A blank line ends a quoted literal block. The
+quoting characters are preserved in the processed document.
+
+.. [#]
+ The following are all valid quoting characters::
+
+ ! " # $ % & ' ( ) * + , - . / : ; < = > ? @ [ \ ] ^ _ ` { | } ~
+
+ Note that these are the same characters as are valid for title
+ adornment of sections_.
+
+Possible uses include literate programming in Haskell and email
+quoting::
+
+ John Doe wrote::
+
+ >> Great idea!
+ >
+ > Why didn't I think of that?
+
+ You just did! ;-)
+
+Syntax diagram::
+
+ +------------------------------+
+ | paragraph |
+ | (ends with "::") |
+ +------------------------------+
+ +------------------------------+
+ | ">" per-line-quoted |
+ | ">" contiguous literal block |
+ +------------------------------+
+
+
+Line Blocks
+-----------
+
+Doctree elements: line_block, line. (New in Docutils 0.3.5.)
+
+Line blocks are useful for address blocks, verse (poetry, song
+lyrics), and unadorned lists, where the structure of lines is
+significant. Line blocks are groups of lines beginning with vertical
+bar ("|") prefixes. Each vertical bar prefix indicates a new line, so
+line breaks are preserved. Initial indents are also significant,
+resulting in a nested structure. Inline markup is supported.
+Continuation lines are wrapped portions of long lines; they begin with
+a space in place of the vertical bar. The left edge of a continuation
+line must be indented, but need not be aligned with the left edge of
+the text above it. A line block ends with a blank line.
+
+This example illustrates continuation lines::
+
+ | Lend us a couple of bob till Thursday.
+ | I'm absolutely skint.
+ | But I'm expecting a postal order and I can pay you back
+ as soon as it comes.
+ | Love, Ewan.
+
+This example illustrates the nesting of line blocks, indicated by the
+initial indentation of new lines::
+
+ Take it away, Eric the Orchestra Leader!
+
+ | A one, two, a one two three four
+ |
+ | Half a bee, philosophically,
+ | must, *ipso facto*, half not be.
+ | But half the bee has got to be,
+ | *vis a vis* its entity. D'you see?
+ |
+ | But can a bee be said to be
+ | or not to be an entire bee,
+ | when half the bee is not a bee,
+ | due to some ancient injury?
+ |
+ | Singing...
+
+Syntax diagram::
+
+ +------+-----------------------+
+ | "| " | line |
+ +------| continuation line |
+ +-----------------------+
+
+
+Block Quotes
+------------
+
+Doctree element: block_quote, attribution.
+
+A text block that is indented relative to the preceding text, without
+preceding markup indicating it to be a literal block or other content,
+is a block quote. All markup processing (for body elements and inline
+markup) continues within the block quote::
+
+ This is an ordinary paragraph, introducing a block quote.
+
+ "It is my business to know things. That is my trade."
+
+ -- Sherlock Holmes
+
+A block quote may end with an attribution: a text block beginning with
+"--", "---", or a true em-dash, flush left within the block quote. If
+the attribution consists of multiple lines, the left edges of the
+second and subsequent lines must align.
+
+Multiple block quotes may occur consecutively if terminated with
+attributions.
+
+ Unindented paragraph.
+
+ Block quote 1.
+
+ -- Attribution 1
+
+ Block quote 2.
+
+`Empty comments`_ may be used to explicitly terminate preceding
+constructs that would otherwise consume a block quote::
+
+ * List item.
+
+ ..
+
+ Block quote 3.
+
+Empty comments may also be used to separate block quotes::
+
+ Block quote 4.
+
+ ..
+
+ Block quote 5.
+
+Blank lines are required before and after a block quote, but these
+blank lines are not included as part of the block quote.
+
+Syntax diagram::
+
+ +------------------------------+
+ | (current level of |
+ | indentation) |
+ +------------------------------+
+ +---------------------------+
+ | block quote |
+ | (body elements)+ |
+ | |
+ | -- attribution text |
+ | (optional) |
+ +---------------------------+
+
+
+Doctest Blocks
+--------------
+
+Doctree element: doctest_block.
+
+Doctest blocks are interactive Python sessions cut-and-pasted into
+docstrings. They are meant to illustrate usage by example, and
+provide an elegant and powerful testing environment via the `doctest
+module`_ in the Python standard library.
+
+Doctest blocks are text blocks which begin with ``">>> "``, the Python
+interactive interpreter main prompt, and end with a blank line.
+Doctest blocks are treated as a special case of literal blocks,
+without requiring the literal block syntax. If both are present, the
+literal block syntax takes priority over Doctest block syntax::
+
+ This is an ordinary paragraph.
+
+ >>> print 'this is a Doctest block'
+ this is a Doctest block
+
+ The following is a literal block::
+
+ >>> This is not recognized as a doctest block by
+ reStructuredText. It *will* be recognized by the doctest
+ module, though!
+
+Indentation is not required for doctest blocks.
+
+
+Tables
+------
+
+Doctree elements: table, tgroup, colspec, thead, tbody, row, entry.
+
+ReStructuredText provides two syntaxes for delineating table cells:
+`Grid Tables`_ and `Simple Tables`_.
+
+As with other body elements, blank lines are required before and after
+tables. Tables' left edges should align with the left edge of
+preceding text blocks; if indented, the table is considered to be part
+of a block quote.
+
+Once isolated, each table cell is treated as a miniature document; the
+top and bottom cell boundaries act as delimiting blank lines. Each
+cell contains zero or more body elements. Cell contents may include
+left and/or right margins, which are removed before processing.
+
+
+Grid Tables
+```````````
+
+Grid tables provide a complete table representation via grid-like
+"ASCII art". Grid tables allow arbitrary cell contents (body
+elements), and both row and column spans. However, grid tables can be
+cumbersome to produce, especially for simple data sets. The `Emacs
+table mode`_ is a tool that allows easy editing of grid tables, in
+Emacs. See `Simple Tables`_ for a simpler (but limited)
+representation.
+
+Grid tables are described with a visual grid made up of the characters
+"-", "=", "|", and "+". The hyphen ("-") is used for horizontal lines
+(row separators). The equals sign ("=") may be used to separate
+optional header rows from the table body (not supported by the `Emacs
+table mode`_). The vertical bar ("|") is used for vertical lines
+(column separators). The plus sign ("+") is used for intersections of
+horizontal and vertical lines. Example::
+
+ +------------------------+------------+----------+----------+
+ | Header row, column 1 | Header 2 | Header 3 | Header 4 |
+ | (header rows optional) | | | |
+ +========================+============+==========+==========+
+ | body row 1, column 1 | column 2 | column 3 | column 4 |
+ +------------------------+------------+----------+----------+
+ | body row 2 | Cells may span columns. |
+ +------------------------+------------+---------------------+
+ | body row 3 | Cells may | - Table cells |
+ +------------------------+ span rows. | - contain |
+ | body row 4 | | - body elements. |
+ +------------------------+------------+---------------------+
+
+Some care must be taken with grid tables to avoid undesired
+interactions with cell text in rare cases. For example, the following
+table contains a cell in row 2 spanning from column 2 to column 4::
+
+ +--------------+----------+-----------+-----------+
+ | row 1, col 1 | column 2 | column 3 | column 4 |
+ +--------------+----------+-----------+-----------+
+ | row 2 | |
+ +--------------+----------+-----------+-----------+
+ | row 3 | | | |
+ +--------------+----------+-----------+-----------+
+
+If a vertical bar is used in the text of that cell, it could have
+unintended effects if accidentally aligned with column boundaries::
+
+ +--------------+----------+-----------+-----------+
+ | row 1, col 1 | column 2 | column 3 | column 4 |
+ +--------------+----------+-----------+-----------+
+ | row 2 | Use the command ``ls | more``. |
+ +--------------+----------+-----------+-----------+
+ | row 3 | | | |
+ +--------------+----------+-----------+-----------+
+
+Several solutions are possible. All that is needed is to break the
+continuity of the cell outline rectangle. One possibility is to shift
+the text by adding an extra space before::
+
+ +--------------+----------+-----------+-----------+
+ | row 1, col 1 | column 2 | column 3 | column 4 |
+ +--------------+----------+-----------+-----------+
+ | row 2 | Use the command ``ls | more``. |
+ +--------------+----------+-----------+-----------+
+ | row 3 | | | |
+ +--------------+----------+-----------+-----------+
+
+Another possibility is to add an extra line to row 2::
+
+ +--------------+----------+-----------+-----------+
+ | row 1, col 1 | column 2 | column 3 | column 4 |
+ +--------------+----------+-----------+-----------+
+ | row 2 | Use the command ``ls | more``. |
+ | | |
+ +--------------+----------+-----------+-----------+
+ | row 3 | | | |
+ +--------------+----------+-----------+-----------+
+
+
+Simple Tables
+`````````````
+
+Simple tables provide a compact and easy to type but limited
+row-oriented table representation for simple data sets. Cell contents
+are typically single paragraphs, although arbitrary body elements may
+be represented in most cells. Simple tables allow multi-line rows (in
+all but the first column) and column spans, but not row spans. See
+`Grid Tables`_ above for a complete table representation.
+
+Simple tables are described with horizontal borders made up of "=" and
+"-" characters. The equals sign ("=") is used for top and bottom
+table borders, and to separate optional header rows from the table
+body. The hyphen ("-") is used to indicate column spans in a single
+row by underlining the joined columns, and may optionally be used to
+explicitly and/or visually separate rows.
+
+A simple table begins with a top border of equals signs with one or
+more spaces at each column boundary (two or more spaces recommended).
+Regardless of spans, the top border *must* fully describe all table
+columns. There must be at least two columns in the table (to
+differentiate it from section headers). The top border may be
+followed by header rows, and the last of the optional header rows is
+underlined with '=', again with spaces at column boundaries. There
+may not be a blank line below the header row separator; it would be
+interpreted as the bottom border of the table. The bottom boundary of
+the table consists of '=' underlines, also with spaces at column
+boundaries. For example, here is a truth table, a three-column table
+with one header row and four body rows::
+
+ ===== ===== =======
+ A B A and B
+ ===== ===== =======
+ False False False
+ True False False
+ False True False
+ True True True
+ ===== ===== =======
+
+Underlines of '-' may be used to indicate column spans by "filling in"
+column margins to join adjacent columns. Column span underlines must
+be complete (they must cover all columns) and align with established
+column boundaries. Text lines containing column span underlines may
+not contain any other text. A column span underline applies only to
+one row immediately above it. For example, here is a table with a
+column span in the header::
+
+ ===== ===== ======
+ Inputs Output
+ ------------ ------
+ A B A or B
+ ===== ===== ======
+ False False False
+ True False True
+ False True True
+ True True True
+ ===== ===== ======
+
+Each line of text must contain spaces at column boundaries, except
+where cells have been joined by column spans. Each line of text
+starts a new row, except when there is a blank cell in the first
+column. In that case, that line of text is parsed as a continuation
+line. For this reason, cells in the first column of new rows (*not*
+continuation lines) *must* contain some text; blank cells would lead
+to a misinterpretation (but see the tip below). Also, this mechanism
+limits cells in the first column to only one line of text. Use `grid
+tables`_ if this limitation is unacceptable.
+
+.. Tip::
+
+ To start a new row in a simple table without text in the first
+ column in the processed output, use one of these:
+
+ * an empty comment (".."), which may be omitted from the processed
+ output (see Comments_ below)
+
+ * a backslash escape ("``\``") followed by a space (see `Escaping
+ Mechanism`_ above)
+
+Underlines of '-' may also be used to visually separate rows, even if
+there are no column spans. This is especially useful in long tables,
+where rows are many lines long.
+
+Blank lines are permitted within simple tables. Their interpretation
+depends on the context. Blank lines *between* rows are ignored.
+Blank lines *within* multi-line rows may separate paragraphs or other
+body elements within cells.
+
+The rightmost column is unbounded; text may continue past the edge of
+the table (as indicated by the table borders). However, it is
+recommended that borders be made long enough to contain the entire
+text.
+
+The following example illustrates continuation lines (row 2 consists
+of two lines of text, and four lines for row 3), a blank line
+separating paragraphs (row 3, column 2), text extending past the right
+edge of the table, and a new row which will have no text in the first
+column in the processed output (row 4)::
+
+ ===== =====
+ col 1 col 2
+ ===== =====
+ 1 Second column of row 1.
+ 2 Second column of row 2.
+ Second line of paragraph.
+ 3 - Second column of row 3.
+
+ - Second item in bullet
+ list (row 3, column 2).
+ \ Row 4; column 1 will be empty.
+ ===== =====
+
+
+Explicit Markup Blocks
+----------------------
+
+An explicit markup block is a text block:
+
+- whose first line begins with ".." followed by whitespace (the
+ "explicit markup start"),
+- whose second and subsequent lines (if any) are indented relative to
+ the first, and
+- which ends before an unindented line.
+
+Explicit markup blocks are analogous to bullet list items, with ".."
+as the bullet. The text on the lines immediately after the explicit
+markup start determines the indentation of the block body. The
+maximum common indentation is always removed from the second and
+subsequent lines of the block body. Therefore if the first construct
+fits in one line, and the indentation of the first and second
+constructs should differ, the first construct should not begin on the
+same line as the explicit markup start.
+
+Blank lines are required between explicit markup blocks and other
+elements, but are optional between explicit markup blocks where
+unambiguous.
+
+The explicit markup syntax is used for footnotes, citations, hyperlink
+targets, directives, substitution definitions, and comments.
+
+
+Footnotes
+`````````
+
+See also: `Footnote References`_.
+
+Doctree elements: footnote_, label_.
+
+Configuration settings:
+`footnote_references <footnote_references setting_>`_.
+
+.. _footnote: ../doctree.html#footnote
+.. _label: ../doctree.html#label
+.. _footnote_references setting:
+ ../../user/config.html#footnote-references-html4css1-writer
+
+Each footnote consists of an explicit markup start (".. "), a left
+square bracket, the footnote label, a right square bracket, and
+whitespace, followed by indented body elements. A footnote label can
+be:
+
+- a whole decimal number consisting of one or more digits,
+
+- a single "#" (denoting `auto-numbered footnotes`_),
+
+- a "#" followed by a simple reference name (an `autonumber label`_),
+ or
+
+- a single "*" (denoting `auto-symbol footnotes`_).
+
+The footnote content (body elements) must be consistently indented (by
+at least 3 spaces) and left-aligned. The first body element within a
+footnote may often begin on the same line as the footnote label.
+However, if the first element fits on one line and the indentation of
+the remaining elements differ, the first element must begin on the
+line after the footnote label. Otherwise, the difference in
+indentation will not be detected.
+
+Footnotes may occur anywhere in the document, not only at the end.
+Where and how they appear in the processed output depends on the
+processing system.
+
+Here is a manually numbered footnote::
+
+ .. [1] Body elements go here.
+
+Each footnote automatically generates a hyperlink target pointing to
+itself. The text of the hyperlink target name is the same as that of
+the footnote label. `Auto-numbered footnotes`_ generate a number as
+their footnote label and reference name. See `Implicit Hyperlink
+Targets`_ for a complete description of the mechanism.
+
+Syntax diagram::
+
+ +-------+-------------------------+
+ | ".. " | "[" label "]" footnote |
+ +-------+ |
+ | (body elements)+ |
+ +-------------------------+
+
+
+Auto-Numbered Footnotes
+.......................
+
+A number sign ("#") may be used as the first character of a footnote
+label to request automatic numbering of the footnote or footnote
+reference.
+
+The first footnote to request automatic numbering is assigned the
+label "1", the second is assigned the label "2", and so on (assuming
+there are no manually numbered footnotes present; see `Mixed Manual
+and Auto-Numbered Footnotes`_ below). A footnote which has
+automatically received a label "1" generates an implicit hyperlink
+target with name "1", just as if the label was explicitly specified.
+
+.. _autonumber label: `autonumber labels`_
+
+A footnote may specify a label explicitly while at the same time
+requesting automatic numbering: ``[#label]``. These labels are called
+_`autonumber labels`. Autonumber labels do two things:
+
+- On the footnote itself, they generate a hyperlink target whose name
+ is the autonumber label (doesn't include the "#").
+
+- They allow an automatically numbered footnote to be referred to more
+ than once, as a footnote reference or hyperlink reference. For
+ example::
+
+ If [#note]_ is the first footnote reference, it will show up as
+ "[1]". We can refer to it again as [#note]_ and again see
+ "[1]". We can also refer to it as note_ (an ordinary internal
+ hyperlink reference).
+
+ .. [#note] This is the footnote labeled "note".
+
+The numbering is determined by the order of the footnotes, not by the
+order of the references. For footnote references without autonumber
+labels (``[#]_``), the footnotes and footnote references must be in
+the same relative order but need not alternate in lock-step. For
+example::
+
+ [#]_ is a reference to footnote 1, and [#]_ is a reference to
+ footnote 2.
+
+ .. [#] This is footnote 1.
+ .. [#] This is footnote 2.
+ .. [#] This is footnote 3.
+
+ [#]_ is a reference to footnote 3.
+
+Special care must be taken if footnotes themselves contain
+auto-numbered footnote references, or if multiple references are made
+in close proximity. Footnotes and references are noted in the order
+they are encountered in the document, which is not necessarily the
+same as the order in which a person would read them.
+
+
+Auto-Symbol Footnotes
+.....................
+
+An asterisk ("*") may be used for footnote labels to request automatic
+symbol generation for footnotes and footnote references. The asterisk
+may be the only character in the label. For example::
+
+ Here is a symbolic footnote reference: [*]_.
+
+ .. [*] This is the footnote.
+
+A transform will insert symbols as labels into corresponding footnotes
+and footnote references. The number of references must be equal to
+the number of footnotes. One symbol footnote cannot have multiple
+references.
+
+The standard Docutils system uses the following symbols for footnote
+marks [#]_:
+
+- asterisk/star ("*")
+- dagger (HTML character entity "†", Unicode U+02020)
+- double dagger ("‡"/U+02021)
+- section mark ("§"/U+000A7)
+- pilcrow or paragraph mark ("¶"/U+000B6)
+- number sign ("#")
+- spade suit ("♠"/U+02660)
+- heart suit ("♥"/U+02665)
+- diamond suit ("♦"/U+02666)
+- club suit ("♣"/U+02663)
+
+.. [#] This list was inspired by the list of symbols for "Note
+ Reference Marks" in The Chicago Manual of Style, 14th edition,
+ section 12.51. "Parallels" ("||") were given in CMoS instead of
+ the pilcrow. The last four symbols (the card suits) were added
+ arbitrarily.
+
+If more than ten symbols are required, the same sequence will be
+reused, doubled and then tripled, and so on ("**" etc.).
+
+.. Note:: When using auto-symbol footnotes, the choice of output
+ encoding is important. Many of the symbols used are not encodable
+ in certain common text encodings such as Latin-1 (ISO 8859-1). The
+ use of UTF-8 for the output encoding is recommended. An
+ alternative for HTML and XML output is to use the
+ "xmlcharrefreplace" `output encoding error handler`__.
+
+__ ../../user/config.html#output-encoding-error-handler
+
+
+Mixed Manual and Auto-Numbered Footnotes
+........................................
+
+Manual and automatic footnote numbering may both be used within a
+single document, although the results may not be expected. Manual
+numbering takes priority. Only unused footnote numbers are assigned
+to auto-numbered footnotes. The following example should be
+illustrative::
+
+ [2]_ will be "2" (manually numbered),
+ [#]_ will be "3" (anonymous auto-numbered), and
+ [#label]_ will be "1" (labeled auto-numbered).
+
+ .. [2] This footnote is labeled manually, so its number is fixed.
+
+ .. [#label] This autonumber-labeled footnote will be labeled "1".
+ It is the first auto-numbered footnote and no other footnote
+ with label "1" exists. The order of the footnotes is used to
+ determine numbering, not the order of the footnote references.
+
+ .. [#] This footnote will be labeled "3". It is the second
+ auto-numbered footnote, but footnote label "2" is already used.
+
+
+Citations
+`````````
+
+See also: `Citation References`_.
+
+Doctree element: citation_
+
+.. _citation: ../doctree.html#citation
+
+Citations are identical to footnotes except that they use only
+non-numeric labels such as ``[note]`` or ``[GVR2001]``. Citation
+labels are simple `reference names`_ (case-insensitive single words
+consisting of alphanumerics plus internal hyphens, underscores, and
+periods; no whitespace). Citations may be rendered separately and
+differently from footnotes. For example::
+
+ Here is a citation reference: [CIT2002]_.
+
+ .. [CIT2002] This is the citation. It's just like a footnote,
+ except the label is textual.
+
+
+.. _hyperlinks:
+
+Hyperlink Targets
+`````````````````
+
+Doctree element: target_.
+
+.. _target: ../doctree.html#target
+
+These are also called _`explicit hyperlink targets`, to differentiate
+them from `implicit hyperlink targets`_ defined below.
+
+Hyperlink targets identify a location within or outside of a document,
+which may be linked to by `hyperlink references`_.
+
+Hyperlink targets may be named or anonymous. Named hyperlink targets
+consist of an explicit markup start (".. "), an underscore, the
+reference name (no trailing underscore), a colon, whitespace, and a
+link block::
+
+ .. _hyperlink-name: link-block
+
+Reference names are whitespace-neutral and case-insensitive. See
+`Reference Names`_ for details and examples.
+
+Anonymous hyperlink targets consist of an explicit markup start
+(".. "), two underscores, a colon, whitespace, and a link block; there
+is no reference name::
+
+ .. __: anonymous-hyperlink-target-link-block
+
+An alternate syntax for anonymous hyperlinks consists of two
+underscores, a space, and a link block::
+
+ __ anonymous-hyperlink-target-link-block
+
+See `Anonymous Hyperlinks`_ below.
+
+There are three types of hyperlink targets: internal, external, and
+indirect.
+
+1. _`Internal hyperlink targets` have empty link blocks. They provide
+ an end point allowing a hyperlink to connect one place to another
+ within a document. An internal hyperlink target points to the
+ element following the target. [#]_ For example::
+
+ Clicking on this internal hyperlink will take us to the target_
+ below.
+
+ .. _target:
+
+ The hyperlink target above points to this paragraph.
+
+ Internal hyperlink targets may be "chained". Multiple adjacent
+ internal hyperlink targets all point to the same element::
+
+ .. _target1:
+ .. _target2:
+
+ The targets "target1" and "target2" are synonyms; they both
+ point to this paragraph.
+
+ If the element "pointed to" is an external hyperlink target (with a
+ URI in its link block; see #2 below) the URI from the external
+ hyperlink target is propagated to the internal hyperlink targets;
+ they will all "point to" the same URI. There is no need to
+ duplicate a URI. For example, all three of the following hyperlink
+ targets refer to the same URI::
+
+ .. _Python DOC-SIG mailing list archive:
+ .. _archive:
+ .. _Doc-SIG: http://mail.python.org/pipermail/doc-sig/
+
+ An inline form of internal hyperlink target is available; see
+ `Inline Internal Targets`_.
+
+ .. [#] Works also, if the internal hyperlink target is "nested" at the
+ end of an indented text block. This behaviour allows setting targets
+ to individual list items (except the first, as a preceding internal
+ target applies to the list as a whole)::
+
+ * bullet list
+
+ .. _`second item`:
+
+ * second item, with hyperlink target.
+
+
+2. _`External hyperlink targets` have an absolute or relative URI or
+ email address in their link blocks. For example, take the
+ following input::
+
+ See the Python_ home page for info.
+
+ `Write to me`_ with your questions.
+
+ .. _Python: http://www.python.org
+ .. _Write to me: jdoe@example.com
+
+ After processing into HTML, the hyperlinks might be expressed as::
+
+ See the <a href="http://www.python.org">Python</a> home page
+ for info.
+
+ <a href="mailto:jdoe@example.com">Write to me</a> with your
+ questions.
+
+ An external hyperlink's URI may begin on the same line as the
+ explicit markup start and target name, or it may begin in an
+ indented text block immediately following, with no intervening
+ blank lines. If there are multiple lines in the link block, they
+ are concatenated. Any unescaped whitespace is removed (whitespace is
+ permitted to allow for line wrapping). The following external
+ hyperlink targets are equivalent::
+
+ .. _one-liner: http://docutils.sourceforge.net/rst.html
+
+ .. _starts-on-this-line: http://
+ docutils.sourceforge.net/rst.html
+
+ .. _entirely-below:
+ http://docutils.
+ sourceforge.net/rst.html
+
+ Escaped whitespace is preserved as intentional spaces, e.g.::
+
+ .. _reference: ../local\ path\ with\ spaces.html
+
+ If an external hyperlink target's URI contains an underscore as its
+ last character, it must be escaped to avoid being mistaken for an
+ indirect hyperlink target::
+
+ This link_ refers to a file called ``underscore_``.
+
+ .. _link: underscore\_
+
+ It is possible (although not generally recommended) to include URIs
+ directly within hyperlink references. See `Embedded URIs and Aliases`_
+ below.
+
+3. _`Indirect hyperlink targets` have a hyperlink reference in their
+ link blocks. In the following example, target "one" indirectly
+ references whatever target "two" references, and target "two"
+ references target "three", an internal hyperlink target. In
+ effect, all three reference the same thing::
+
+ .. _one: two_
+ .. _two: three_
+ .. _three:
+
+ Just as with `hyperlink references`_ anywhere else in a document,
+ if a phrase-reference is used in the link block it must be enclosed
+ in backquotes. As with `external hyperlink targets`_, the link
+ block of an indirect hyperlink target may begin on the same line as
+ the explicit markup start or the next line. It may also be split
+ over multiple lines, in which case the lines are joined with
+ whitespace before being normalized.
+
+ For example, the following indirect hyperlink targets are
+ equivalent::
+
+ .. _one-liner: `A HYPERLINK`_
+ .. _entirely-below:
+ `a hyperlink`_
+ .. _split: `A
+ Hyperlink`_
+
+ It is possible to include an alias directly within hyperlink
+ references. See `Embedded URIs and Aliases`_ below.
+
+If the reference name contains any colons, either:
+
+- the phrase must be enclosed in backquotes::
+
+ .. _`FAQTS: Computers: Programming: Languages: Python`:
+ http://python.faqts.com/
+
+- or the colon(s) must be backslash-escaped in the link target::
+
+ .. _Chapter One\: "Tadpole Days":
+
+ It's not easy being green...
+
+See `Implicit Hyperlink Targets`_ below for the resolution of
+duplicate reference names.
+
+Syntax diagram::
+
+ +-------+----------------------+
+ | ".. " | "_" name ":" link |
+ +-------+ block |
+ | |
+ +----------------------+
+
+
+Anonymous Hyperlinks
+....................
+
+The `World Wide Web Consortium`_ recommends in its `HTML Techniques
+for Web Content Accessibility Guidelines`_ that authors should
+"clearly identify the target of each link." Hyperlink references
+should be as verbose as possible, but duplicating a verbose hyperlink
+name in the target is onerous and error-prone. Anonymous hyperlinks
+are designed to allow convenient verbose hyperlink references, and are
+analogous to `Auto-Numbered Footnotes`_. They are particularly useful
+in short or one-off documents. However, this feature is easily abused
+and can result in unreadable plaintext and/or unmaintainable
+documents. Caution is advised.
+
+Anonymous `hyperlink references`_ are specified with two underscores
+instead of one::
+
+ See `the web site of my favorite programming language`__.
+
+Anonymous targets begin with ".. __:"; no reference name is required
+or allowed::
+
+ .. __: http://www.python.org
+
+As a convenient alternative, anonymous targets may begin with "__"
+only::
+
+ __ http://www.python.org
+
+The reference name of the reference is not used to match the reference
+to its target. Instead, the order of anonymous hyperlink references
+and targets within the document is significant: the first anonymous
+reference will link to the first anonymous target. The number of
+anonymous hyperlink references in a document must match the number of
+anonymous targets. For readability, it is recommended that targets be
+kept close to references. Take care when editing text containing
+anonymous references; adding, removing, and rearranging references
+require attention to the order of corresponding targets.
+
+
+Directives
+``````````
+
+Doctree elements: depend on the directive.
+
+Directives are an extension mechanism for reStructuredText, a way of
+adding support for new constructs without adding new primary syntax
+(directives may support additional syntax locally). All standard
+directives (those implemented and registered in the reference
+reStructuredText parser) are described in the `reStructuredText
+Directives`_ document, and are always available. Any other directives
+are domain-specific, and may require special action to make them
+available when processing the document.
+
+For example, here's how an image_ may be placed::
+
+ .. image:: mylogo.jpeg
+
+A figure_ (a graphic with a caption) may placed like this::
+
+ .. figure:: larch.png
+
+ The larch.
+
+An admonition_ (note, caution, etc.) contains other body elements::
+
+ .. note:: This is a paragraph
+
+ - Here is a bullet list.
+
+Directives are indicated by an explicit markup start (".. ") followed
+by the directive type, two colons, and whitespace (together called the
+"directive marker"). Directive types are case-insensitive single
+words (alphanumerics plus isolated internal hyphens, underscores,
+plus signs, colons, and periods; no whitespace). Two colons are used
+after the directive type for these reasons:
+
+- Two colons are distinctive, and unlikely to be used in common text.
+
+- Two colons avoids clashes with common comment text like::
+
+ .. Danger: modify at your own risk!
+
+- If an implementation of reStructuredText does not recognize a
+ directive (i.e., the directive-handler is not installed), a level-3
+ (error) system message is generated, and the entire directive block
+ (including the directive itself) will be included as a literal
+ block. Thus "::" is a natural choice.
+
+The directive block is consists of any text on the first line of the
+directive after the directive marker, and any subsequent indented
+text. The interpretation of the directive block is up to the
+directive code. There are three logical parts to the directive block:
+
+1. Directive arguments.
+2. Directive options.
+3. Directive content.
+
+Individual directives can employ any combination of these parts.
+Directive arguments can be filesystem paths, URLs, title text, etc.
+Directive options are indicated using `field lists`_; the field names
+and contents are directive-specific. Arguments and options must form
+a contiguous block beginning on the first or second line of the
+directive; a blank line indicates the beginning of the directive
+content block. If either arguments and/or options are employed by the
+directive, a blank line must separate them from the directive content.
+The "figure" directive employs all three parts::
+
+ .. figure:: larch.png
+ :scale: 50
+
+ The larch.
+
+Simple directives may not require any content. If a directive that
+does not employ a content block is followed by indented text anyway,
+it is an error. If a block quote should immediately follow a
+directive, use an empty comment in-between (see Comments_ below).
+
+Actions taken in response to directives and the interpretation of text
+in the directive content block or subsequent text block(s) are
+directive-dependent. See `reStructuredText Directives`_ for details.
+
+Directives are meant for the arbitrary processing of their contents,
+which can be transformed into something possibly unrelated to the
+original text. It may also be possible for directives to be used as
+pragmas, to modify the behavior of the parser, such as to experiment
+with alternate syntax. There is no parser support for this
+functionality at present; if a reasonable need for pragma directives
+is found, they may be supported.
+
+Directives do not generate "directive" elements; they are a *parser
+construct* only, and have no intrinsic meaning outside of
+reStructuredText. Instead, the parser will transform recognized
+directives into (possibly specialized) document elements. Unknown
+directives will trigger level-3 (error) system messages.
+
+Syntax diagram::
+
+ +-------+-------------------------------+
+ | ".. " | directive type "::" directive |
+ +-------+ block |
+ | |
+ +-------------------------------+
+
+
+Substitution Definitions
+````````````````````````
+
+Doctree element: substitution_definition.
+
+Substitution definitions are indicated by an explicit markup start
+(".. ") followed by a vertical bar, the substitution text, another
+vertical bar, whitespace, and the definition block. Substitution text
+may not begin or end with whitespace. A substitution definition block
+contains an embedded inline-compatible directive (without the leading
+".. "), such as "image_" or "replace_". For example::
+
+ The |biohazard| symbol must be used on containers used to
+ dispose of medical waste.
+
+ .. |biohazard| image:: biohazard.png
+
+It is an error for a substitution definition block to directly or
+indirectly contain a circular substitution reference.
+
+`Substitution references`_ are replaced in-line by the processed
+contents of the corresponding definition (linked by matching
+substitution text). Matches are case-sensitive but forgiving; if no
+exact match is found, a case-insensitive comparison is attempted.
+
+Substitution definitions allow the power and flexibility of
+block-level directives_ to be shared by inline text. They are a way
+to include arbitrarily complex inline structures within text, while
+keeping the details out of the flow of text. They are the equivalent
+of SGML/XML's named entities or programming language macros.
+
+Without the substitution mechanism, every time someone wants an
+application-specific new inline structure, they would have to petition
+for a syntax change. In combination with existing directive syntax,
+any inline structure can be coded without new syntax (except possibly
+a new directive).
+
+Syntax diagram::
+
+ +-------+-----------------------------------------------------+
+ | ".. " | "|" substitution text "| " directive type "::" data |
+ +-------+ directive block |
+ | |
+ +-----------------------------------------------------+
+
+Following are some use cases for the substitution mechanism. Please
+note that most of the embedded directives shown are examples only and
+have not been implemented.
+
+Objects
+ Substitution references may be used to associate ambiguous text
+ with a unique object identifier.
+
+ For example, many sites may wish to implement an inline "user"
+ directive::
+
+ |Michael| and |Jon| are our widget-wranglers.
+
+ .. |Michael| user:: mjones
+ .. |Jon| user:: jhl
+
+ Depending on the needs of the site, this may be used to index the
+ document for later searching, to hyperlink the inline text in
+ various ways (mailto, homepage, mouseover Javascript with profile
+ and contact information, etc.), or to customize presentation of
+ the text (include username in the inline text, include an icon
+ image with a link next to the text, make the text bold or a
+ different color, etc.).
+
+ The same approach can be used in documents which frequently refer
+ to a particular type of objects with unique identifiers but
+ ambiguous common names. Movies, albums, books, photos, court
+ cases, and laws are possible. For example::
+
+ |The Transparent Society| offers a fascinating alternate view
+ on privacy issues.
+
+ .. |The Transparent Society| book:: isbn=0738201448
+
+ Classes or functions, in contexts where the module or class names
+ are unclear and/or interpreted text cannot be used, are another
+ possibility::
+
+ 4XSLT has the convenience method |runString|, so you don't
+ have to mess with DOM objects if all you want is the
+ transformed output.
+
+ .. |runString| function:: module=xml.xslt class=Processor
+
+Images
+ Images are a common use for substitution references::
+
+ West led the |H| 3, covered by dummy's |H| Q, East's |H| K,
+ and trumped in hand with the |S| 2.
+
+ .. |H| image:: /images/heart.png
+ :height: 11
+ :width: 11
+ .. |S| image:: /images/spade.png
+ :height: 11
+ :width: 11
+
+ * |Red light| means stop.
+ * |Green light| means go.
+ * |Yellow light| means go really fast.
+
+ .. |Red light| image:: red_light.png
+ .. |Green light| image:: green_light.png
+ .. |Yellow light| image:: yellow_light.png
+
+ |-><-| is the official symbol of POEE_.
+
+ .. |-><-| image:: discord.png
+ .. _POEE: http://www.poee.org/
+
+ The "image_" directive has been implemented.
+
+Styles [#]_
+ Substitution references may be used to associate inline text with
+ an externally defined presentation style::
+
+ Even |the text in Texas| is big.
+
+ .. |the text in Texas| style:: big
+
+ The style name may be meaningful in the context of some particular
+ output format (CSS class name for HTML output, LaTeX style name
+ for LaTeX, etc), or may be ignored for other output formats (such
+ as plaintext).
+
+ .. @@@ This needs to be rethought & rewritten or removed:
+
+ Interpreted text is unsuitable for this purpose because the set
+ of style names cannot be predefined - it is the domain of the
+ content author, not the author of the parser and output
+ formatter - and there is no way to associate a style name
+ argument with an interpreted text style role. Also, it may be
+ desirable to use the same mechanism for styling blocks::
+
+ .. style:: motto
+ At Bob's Underwear Shop, we'll do anything to get in
+ your pants.
+
+ .. style:: disclaimer
+ All rights reversed. Reprint what you like.
+
+ .. [#] There may be sufficient need for a "style" mechanism to
+ warrant simpler syntax such as an extension to the interpreted
+ text role syntax. The substitution mechanism is cumbersome for
+ simple text styling.
+
+Templates
+ Inline markup may be used for later processing by a template
+ engine. For example, a Zope_ author might write::
+
+ Welcome back, |name|!
+
+ .. |name| tal:: replace user/getUserName
+
+ After processing, this ZPT output would result::
+
+ Welcome back,
+ <span tal:replace="user/getUserName">name</span>!
+
+ Zope would then transform this to something like "Welcome back,
+ David!" during a session with an actual user.
+
+Replacement text
+ The substitution mechanism may be used for simple macro
+ substitution. This may be appropriate when the replacement text
+ is repeated many times throughout one or more documents,
+ especially if it may need to change later. A short example is
+ unavoidably contrived::
+
+ |RST|_ is a little annoying to type over and over, especially
+ when writing about |RST| itself, and spelling out the
+ bicapitalized word |RST| every time isn't really necessary for
+ |RST| source readability.
+
+ .. |RST| replace:: reStructuredText
+ .. _RST: http://docutils.sourceforge.net/rst.html
+
+ Note the trailing underscore in the first use of a substitution
+ reference. This indicates a reference to the corresponding
+ hyperlink target.
+
+ Substitution is also appropriate when the replacement text cannot
+ be represented using other inline constructs, or is obtrusively
+ long::
+
+ But still, that's nothing compared to a name like
+ |j2ee-cas|__.
+
+ .. |j2ee-cas| replace::
+ the Java `TM`:super: 2 Platform, Enterprise Edition Client
+ Access Services
+ __ http://developer.java.sun.com/developer/earlyAccess/
+ j2eecas/
+
+ The "replace_" directive has been implemented.
+
+
+Comments
+````````
+
+Doctree element: comment.
+
+Arbitrary indented text may follow the explicit markup start and will
+be processed as a comment element. No further processing is done on
+the comment block text; a comment contains a single "text blob".
+Depending on the output formatter, comments may be removed from the
+processed output. The only restriction on comments is that they not
+use the same syntax as any of the other explicit markup constructs:
+substitution definitions, directives, footnotes, citations, or
+hyperlink targets. To ensure that none of the other explicit markup
+constructs is recognized, leave the ".." on a line by itself::
+
+ .. This is a comment
+ ..
+ _so: is this!
+ ..
+ [and] this!
+ ..
+ this:: too!
+ ..
+ |even| this:: !
+
+.. _empty comments:
+
+An explicit markup start followed by a blank line and nothing else
+(apart from whitespace) is an "_`empty comment`". It serves to
+terminate a preceding construct, and does **not** consume any indented
+text following. To have a block quote follow a list or any indented
+construct, insert an unindented empty comment in-between.
+
+Syntax diagram::
+
+ +-------+----------------------+
+ | ".. " | comment |
+ +-------+ block |
+ | |
+ +----------------------+
+
+
+Implicit Hyperlink Targets
+==========================
+
+Implicit hyperlink targets are generated by section titles, footnotes,
+and citations, and may also be generated by extension constructs.
+Implicit hyperlink targets otherwise behave identically to explicit
+`hyperlink targets`_.
+
+Problems of ambiguity due to conflicting duplicate implicit and
+explicit reference names are avoided by following this procedure:
+
+1. `Explicit hyperlink targets`_ override any implicit targets having
+ the same reference name. The implicit hyperlink targets are
+ removed, and level-1 (info) system messages are inserted.
+
+2. Duplicate implicit hyperlink targets are removed, and level-1
+ (info) system messages inserted. For example, if two or more
+ sections have the same title (such as "Introduction" subsections of
+ a rigidly-structured document), there will be duplicate implicit
+ hyperlink targets.
+
+3. Duplicate explicit hyperlink targets are removed, and level-2
+ (warning) system messages are inserted. Exception: duplicate
+ `external hyperlink targets`_ (identical hyperlink names and
+ referenced URIs) do not conflict, and are not removed.
+
+System messages are inserted where target links have been removed.
+See "Error Handling" in `PEP 258`_.
+
+The parser must return a set of *unique* hyperlink targets. The
+calling software (such as the Docutils_) can warn of unresolvable
+links, giving reasons for the messages.
+
+
+Inline Markup
+=============
+
+In reStructuredText, inline markup applies to words or phrases within
+a text block. The same whitespace and punctuation that serves to
+delimit words in written text is used to delimit the inline markup
+syntax constructs (see the `inline markup recognition rules`_ for
+details). The text within inline markup may not begin or end with
+whitespace. Arbitrary `character-level inline markup`_ is supported
+although not encouraged. Inline markup cannot be nested.
+
+There are nine inline markup constructs. Five of the constructs use
+identical start-strings and end-strings to indicate the markup:
+
+- emphasis_: "*"
+- `strong emphasis`_: "**"
+- `interpreted text`_: "`"
+- `inline literals`_: "``"
+- `substitution references`_: "|"
+
+Three constructs use different start-strings and end-strings:
+
+- `inline internal targets`_: "_`" and "`"
+- `footnote references`_: "[" and "]_"
+- `hyperlink references`_: "`" and "\`_" (phrases), or just a
+ trailing "_" (single words)
+
+`Standalone hyperlinks`_ are recognized implicitly, and use no extra
+markup.
+
+Inline markup recognition rules
+-------------------------------
+
+Inline markup start-strings and end-strings are only recognized if
+the following conditions are met:
+
+1. Inline markup start-strings must be immediately followed by
+ non-whitespace.
+
+2. Inline markup end-strings must be immediately preceded by
+ non-whitespace.
+
+3. The inline markup end-string must be separated by at least one
+ character from the start-string.
+
+4. Both, inline markup start-string and end-string must not be preceded by
+ an unescaped backslash (except for the end-string of `inline literals`_).
+ See `Escaping Mechanism`_ above for details.
+
+5. If an inline markup start-string is immediately preceded by one of the
+ ASCII characters ``' " < ( [ {`` or a similar
+ non-ASCII character [#openers]_, it must not be followed by the
+ corresponding closing character from ``' " ) ] } >`` or a similar non-ASCII
+ character [#closers]_. (For quotes, matching characters can be any of
+ the `quotation marks in international usage`_.)
+
+If the configuration setting `simple-inline-markup`_ is False (default),
+additional conditions apply to the characters "around" the
+inline markup:
+
+6. Inline markup start-strings must start a text block or be
+ immediately preceded by
+
+ * whitespace,
+ * one of the ASCII characters ``- : / ' " < ( [ {``
+ * or a similar non-ASCII punctuation character. [#pre-chars]_
+
+7. Inline markup end-strings must end a text block or be immediately
+ followed by
+
+ * whitespace,
+ * one of the ASCII characters ``- . , : ; ! ? \ / ' " ) ] } >``
+ * or a similar non-ASCII punctuation character. [#post-chars]_
+
+.. [#openers] `Unicode categories`_ `Ps` (Open), `Pi` (Initial quote),
+ or `Pf` (Final quote). [#uni-version]_
+.. [#closers] Unicode categories `Pe` (Close), `Pi` (Initial quote),
+ or `Pf` (Final quote). [#uni-version]_
+.. [#pre-chars] Unicode categories `Ps` (Open), `Pi` (Initial quote),
+ `Pf` (Final quote), `Pd` (Dash), or `Po` (Other). [#uni-version]_
+.. [#post-chars] Unicode categories `Pe` (Close), `Pi` (Initial quote),
+ `Pf` (Final quote), `Pd` (Dash), or `Po` (Other). [#uni-version]_
+
+.. [#uni-version] The category of some characters changed with the
+ development of the Unicode standard.
+ Docutils 0.13 uses `Unicode version 5.2.0`_.
+
+.. _Unicode categories:
+ http://www.unicode.org/Public/5.1.0/ucd/UCD.html#General_Category_Values
+.. _Unicode version 5.2.0: http://www.unicode.org/Public/5.2.0/
+.. _quotation marks in international usage:
+ http://en.wikipedia.org/wiki/Quotation_mark,_non-English_usage
+
+The inline markup recognition rules were devised to allow 90% of non-markup
+uses of "*", "`", "_", and "|" without escaping. For example, none of the
+following terms are recognized as containing inline markup strings:
+
+- 2 * x a ** b (* BOM32_* ` `` _ __ | (breaks rule 1)
+- || (breaks rule 3)
+- "*" '|' (*) [*] {*} <*>
+ ‘*’ ‚*‘ ‘*‚ ’*’ ‚*’
+ “*” „*“ “*„ ”*” „*”
+ »*« ›*‹ «*» »*» ›*› (breaks rule 5)
+- 2*x a**b O(N**2) e**(x*y) f(x)*f(y) a|b file*.*
+ __init__ __init__() (breaks rule 6)
+
+No escaping is required inside the following inline markup examples:
+
+- ``*2 * x *a **b *.txt*`` (breaks rule 2; renders as "*2 * x *a **b *.txt*")
+- ``*2*x a**b O(N**2) e**(x*y) f(x)*f(y) a*(1+2)*``
+ (breaks rule 7; renders as "*2*x a**b O(N**2) e**(x*y) f(x)*f(y) a*(1+2)*")
+
+It may be desirable to use `inline literals`_ for some of these anyhow,
+especially if they represent code snippets. It's a judgment call.
+
+The following terms *do* require either literal-quoting or escaping to avoid
+misinterpretation::
+
+ *4, class_, *args, **kwargs, `TeX-quoted', *ML, *.txt
+
+In most use cases, `inline literals`_ or `literal blocks`_ are the best
+choice (by default, this also selects a monospaced font). Alternatively, the
+inline markup characters can be escaped::
+
+ \*4, class\_, \*args, \**kwargs, \`TeX-quoted', \*ML, \*.txt
+
+
+For languages that don't use whitespace between words (e.g. Japanese or
+Chinese) it is recommended to set `simple-inline-markup`_ to True and
+eventually escape inline markup characters.
+The examples breaking rules 6 and 7 above show which constructs may need
+special attention.
+
+
+.. _simple-inline-markup: ../../user/config.html#simple-inline-markup
+
+
+Recognition order
+-----------------
+
+Inline markup delimiter characters are used for multiple constructs,
+so to avoid ambiguity there must be a specific recognition order for
+each character. The inline markup recognition order is as follows:
+
+- Asterisks: `Strong emphasis`_ ("**") is recognized before emphasis_
+ ("*").
+
+- Backquotes: `Inline literals`_ ("``"), `inline internal targets`_
+ (leading "_`", trailing "`"), are mutually independent, and are
+ recognized before phrase `hyperlink references`_ (leading "`",
+ trailing "\`_") and `interpreted text`_ ("`").
+
+- Trailing underscores: Footnote references ("[" + label + "]_") and
+ simple `hyperlink references`_ (name + trailing "_") are mutually
+ independent.
+
+- Vertical bars: `Substitution references`_ ("|") are independently
+ recognized.
+
+- `Standalone hyperlinks`_ are the last to be recognized.
+
+
+Character-Level Inline Markup
+-----------------------------
+
+It is possible to mark up individual characters within a word with
+backslash escapes (see `Escaping Mechanism`_ above). Backslash
+escapes can be used to allow arbitrary text to immediately follow
+inline markup::
+
+ Python ``list``\s use square bracket syntax.
+
+The backslash will disappear from the processed document. The word
+"list" will appear as inline literal text, and the letter "s" will
+immediately follow it as normal text, with no space in-between.
+
+Arbitrary text may immediately precede inline markup using
+backslash-escaped whitespace::
+
+ Possible in *re*\ ``Structured``\ *Text*, though not encouraged.
+
+The backslashes and spaces separating "re", "Structured", and "Text"
+above will disappear from the processed document.
+
+.. CAUTION::
+
+ The use of backslash-escapes for character-level inline markup is
+ not encouraged. Such use is ugly and detrimental to the
+ unprocessed document's readability. Please use this feature
+ sparingly and only where absolutely necessary.
+
+
+Emphasis
+--------
+
+Doctree element: emphasis.
+
+Start-string = end-string = "*".
+
+Text enclosed by single asterisk characters is emphasized::
+
+ This is *emphasized text*.
+
+Emphasized text is typically displayed in italics.
+
+
+Strong Emphasis
+---------------
+
+Doctree element: strong.
+
+Start-string = end-string = "**".
+
+Text enclosed by double-asterisks is emphasized strongly::
+
+ This is **strong text**.
+
+Strongly emphasized text is typically displayed in boldface.
+
+
+Interpreted Text
+----------------
+
+Doctree element: depends on the explicit or implicit role and
+processing.
+
+Start-string = end-string = "`".
+
+Interpreted text is text that is meant to be related, indexed, linked,
+summarized, or otherwise processed, but the text itself is typically
+left alone. Interpreted text is enclosed by single backquote
+characters::
+
+ This is `interpreted text`.
+
+The "role" of the interpreted text determines how the text is
+interpreted. The role may be inferred implicitly (as above; the
+"default role" is used) or indicated explicitly, using a role marker.
+A role marker consists of a colon, the role name, and another colon.
+A role name is a single word consisting of alphanumerics plus isolated
+internal hyphens, underscores, plus signs, colons, and periods;
+no whitespace or other characters are allowed. A role marker is
+either a prefix or a suffix to the interpreted text, whichever reads
+better; it's up to the author::
+
+ :role:`interpreted text`
+
+ `interpreted text`:role:
+
+Interpreted text allows extensions to the available inline descriptive
+markup constructs. To emphasis_, `strong emphasis`_, `inline
+literals`_, and `hyperlink references`_, we can add "title reference",
+"index entry", "acronym", "class", "red", "blinking" or anything else
+we want. Only pre-determined roles are recognized; unknown roles will
+generate errors. A core set of standard roles is implemented in the
+reference parser; see `reStructuredText Interpreted Text Roles`_ for
+individual descriptions. The role_ directive can be used to define
+custom interpreted text roles. In addition, applications may support
+specialized roles.
+
+In `field lists`_, care must be taken when using interpreted text with
+explicit roles in field names: the role must be a suffix to the
+interpreted text. The following are recognized as field list items::
+
+ :`field name`:code:: interpreted text with explicit role as suffix
+
+ :a `complex`:code:\ field name: a backslash-escaped space
+ is necessary
+
+The following are **not** recognized as field list items::
+
+ ::code:`not a field name`: paragraph with interpreted text
+
+ :code:`not a field name`: paragraph with interpreted text
+
+Edge cases::
+
+ :field\:`name`: interpreted text (standard role) requires
+ escaping the leading colon in a field name
+
+ :field:\`name`: not interpreted text
+
+
+Inline Literals
+---------------
+
+Doctree element: literal.
+
+Start-string = end-string = "``".
+
+Text enclosed by double-backquotes is treated as inline literals::
+
+ This text is an example of ``inline literals``.
+
+Inline literals may contain any characters except two adjacent
+backquotes in an end-string context (according to the recognition
+rules above). No markup interpretation (including backslash-escape
+interpretation) is done within inline literals.
+
+Line breaks are *not* preserved in inline literals. Although a
+reStructuredText parser will preserve runs of spaces in its output,
+the final representation of the processed document is dependent on the
+output formatter, thus the preservation of whitespace cannot be
+guaranteed. If the preservation of line breaks and/or other
+whitespace is important, `literal blocks`_ should be used.
+
+Inline literals are useful for short code snippets. For example::
+
+ The regular expression ``[+-]?(\d+(\.\d*)?|\.\d+)`` matches
+ floating-point numbers (without exponents).
+
+
+Hyperlink References
+--------------------
+
+Doctree element: reference.
+
+- Named hyperlink references:
+
+ - No start-string, end-string = "_".
+ - Start-string = "`", end-string = "\`_". (Phrase references.)
+
+- Anonymous hyperlink references:
+
+ - No start-string, end-string = "__".
+ - Start-string = "`", end-string = "\`__". (Phrase references.)
+
+Hyperlink references are indicated by a trailing underscore, "_",
+except for `standalone hyperlinks`_ which are recognized
+independently. The underscore can be thought of as a right-pointing
+arrow. The trailing underscores point away from hyperlink references,
+and the leading underscores point toward `hyperlink targets`_.
+
+Hyperlinks consist of two parts. In the text body, there is a source
+link, a reference name with a trailing underscore (or two underscores
+for `anonymous hyperlinks`_)::
+
+ See the Python_ home page for info.
+
+A target link with a matching reference name must exist somewhere else
+in the document. See `Hyperlink Targets`_ for a full description).
+
+`Anonymous hyperlinks`_ (which see) do not use reference names to
+match references to targets, but otherwise behave similarly to named
+hyperlinks.
+
+
+Embedded URIs and Aliases
+`````````````````````````
+
+A hyperlink reference may directly embed a target URI or (since
+Docutils 0.11) a hyperlink reference within angle brackets ("<...>")
+as follows::
+
+ See the `Python home page <http://www.python.org>`_ for info.
+
+ This `link <Python home page_>`_ is an alias to the link above.
+
+This is exactly equivalent to::
+
+ See the `Python home page`_ for info.
+
+ This link_ is an alias to the link above.
+
+ .. _Python home page: http://www.python.org
+ .. _link: `Python home page`_
+
+The bracketed URI must be preceded by whitespace and be the last text
+before the end string.
+
+With a single trailing underscore, the reference is named and the same
+target URI may be referred to again.
+With two trailing underscores, the reference and target are both
+anonymous, and the target cannot be referred to again. These are
+"one-off" hyperlinks. For example::
+
+ `RFC 2396 <http://www.rfc-editor.org/rfc/rfc2396.txt>`__ and `RFC
+ 2732 <http://www.rfc-editor.org/rfc/rfc2732.txt>`__ together
+ define the syntax of URIs.
+
+Equivalent to::
+
+ `RFC 2396`__ and `RFC 2732`__ together define the syntax of URIs.
+
+ __ http://www.rfc-editor.org/rfc/rfc2396.txt
+ __ http://www.rfc-editor.org/rfc/rfc2732.txt
+
+`Standalone hyperlinks`_ are treated as URIs, even if they end with an
+underscore like in the example of a Python function documentation::
+
+ `__init__ <http:example.py.html#__init__>`__
+
+If a target URI that is not recognized as `standalone hyperlink`_ happens
+to end with an underscore, this needs to be backslash-escaped to avoid
+being parsed as hyperlink reference. For example ::
+
+ Use the `source <parrots.txt\_>`__.
+
+creates an anonymous reference to the file ``parrots.txt_``.
+
+If the reference text happens to end with angle-bracketed text that is
+*not* a URI or hyperlink reference, at least one angle-bracket needs to
+be backslash-escaped or an escaped space should follow. For example, here
+are three references to titles describing a tag::
+
+ See `HTML Element: \<a>`_, `HTML Element: <b\> `_, and
+ `HTML Element: <c>\ `_.
+
+The reference text may also be omitted, in which case the URI will be
+duplicated for use as the reference text. This is useful for relative
+URIs where the address or file name is also the desired reference
+text::
+
+ See `<a_named_relative_link>`_ or `<an_anonymous_relative_link>`__
+ for details.
+
+.. CAUTION::
+
+ This construct offers easy authoring and maintenance of hyperlinks
+ at the expense of general readability. Inline URIs, especially
+ long ones, inevitably interrupt the natural flow of text. For
+ documents meant to be read in source form, the use of independent
+ block-level `hyperlink targets`_ is **strongly recommended**. The
+ embedded URI construct is most suited to documents intended *only*
+ to be read in processed form.
+
+
+Inline Internal Targets
+------------------------
+
+Doctree element: target.
+
+Start-string = "_`", end-string = "`".
+
+Inline internal targets are the equivalent of explicit `internal
+hyperlink targets`_, but may appear within running text. The syntax
+begins with an underscore and a backquote, is followed by a hyperlink
+name or phrase, and ends with a backquote. Inline internal targets
+may not be anonymous.
+
+For example, the following paragraph contains a hyperlink target named
+"Norwegian Blue"::
+
+ Oh yes, the _`Norwegian Blue`. What's, um, what's wrong with it?
+
+See `Implicit Hyperlink Targets`_ for the resolution of duplicate
+reference names.
+
+
+Footnote References
+-------------------
+
+See also: Footnotes_
+
+Doctree element: footnote_reference_.
+
+Configuration settings:
+`footnote_references <footnote_references setting_>`_,
+trim_footnote_reference_space_.
+
+.. _footnote_reference: ../doctree.html#footnote-reference
+.. _trim_footnote_reference_space:
+ ../../user/config.html#trim-footnote-reference-space
+
+Start-string = "[", end-string = "]_".
+
+Each footnote reference consists of a square-bracketed label followed
+by a trailing underscore. Footnote labels are one of:
+
+- one or more digits (i.e., a number),
+
+- a single "#" (denoting `auto-numbered footnotes`_),
+
+- a "#" followed by a simple reference name (an `autonumber label`_),
+ or
+
+- a single "*" (denoting `auto-symbol footnotes`_).
+
+For example::
+
+ Please RTFM [1]_.
+
+ .. [1] Read The Fine Manual
+
+`Inline markup recognition rules`_ may require whitespace in front of the
+footnote reference. To remove the whitespace from the output, use an
+escaped whitespace character (see `Escaping Mechanism`_) or set the
+trim_footnote_reference_space_ configuration setting. Leading whitespace
+is removed by default, if the `footnote_references setting`_ is
+"superscript".
+
+
+Citation References
+-------------------
+
+See also: Citations_
+
+Doctree element: citation_reference_.
+
+.. _citation_reference: ../doctree.html#citation_reference
+
+Start-string = "[", end-string = "]_".
+
+Each citation reference consists of a square-bracketed label followed
+by a trailing underscore. Citation labels are simple `reference
+names`_ (case-insensitive single words, consisting of alphanumerics
+plus internal hyphens, underscores, and periods; no whitespace).
+
+For example::
+
+ Here is a citation reference: [CIT2002]_.
+
+
+Substitution References
+-----------------------
+
+Doctree element: substitution_reference, reference.
+
+Start-string = "|", end-string = "|" (optionally followed by "_" or
+"__").
+
+Vertical bars are used to bracket the substitution reference text. A
+substitution reference may also be a hyperlink reference by appending
+a "_" (named) or "__" (anonymous) suffix; the substitution text is
+used for the reference text in the named case.
+
+The processing system replaces substitution references with the
+processed contents of the corresponding `substitution definitions`_
+(which see for the definition of "correspond"). Substitution
+definitions produce inline-compatible elements.
+
+Examples::
+
+ This is a simple |substitution reference|. It will be replaced by
+ the processing system.
+
+ This is a combination |substitution and hyperlink reference|_. In
+ addition to being replaced, the replacement text or element will
+ refer to the "substitution and hyperlink reference" target.
+
+.. _standalone hyperlink:
+
+Standalone Hyperlinks
+---------------------
+
+Doctree element: reference.
+
+No start-string or end-string.
+
+A URI (absolute URI [#URI]_ or standalone email address) within a text
+block is treated as a general external hyperlink with the URI itself
+as the link's text. For example::
+
+ See http://www.python.org for info.
+
+would be marked up in HTML as::
+
+ See <a href="http://www.python.org">http://www.python.org</a> for
+ info.
+
+Two forms of URI are recognized:
+
+1. Absolute URIs. These consist of a scheme, a colon (":"), and a
+ scheme-specific part whose interpretation depends on the scheme.
+
+ The scheme is the name of the protocol, such as "http", "ftp",
+ "mailto", or "telnet". The scheme consists of an initial letter,
+ followed by letters, numbers, and/or "+", "-", ".". Recognition is
+ limited to known schemes, per the `Official IANA Registry of URI
+ Schemes`_ and the W3C's `Retired Index of WWW Addressing Schemes`_.
+
+ The scheme-specific part of the resource identifier may be either
+ hierarchical or opaque:
+
+ - Hierarchical identifiers begin with one or two slashes and may
+ use slashes to separate hierarchical components of the path.
+ Examples are web pages and FTP sites::
+
+ http://www.python.org
+
+ ftp://ftp.python.org/pub/python
+
+ - Opaque identifiers do not begin with slashes. Examples are
+ email addresses and newsgroups::
+
+ mailto:someone@somewhere.com
+
+ news:comp.lang.python
+
+ With queries, fragments, and %-escape sequences, URIs can become
+ quite complicated. A reStructuredText parser must be able to
+ recognize any absolute URI, as defined in RFC2396_ and RFC2732_.
+
+2. Standalone email addresses, which are treated as if they were
+ absolute URIs with a "mailto:" scheme. Example::
+
+ someone@somewhere.com
+
+Punctuation at the end of a URI is not considered part of the URI,
+unless the URI is terminated by a closing angle bracket (">").
+Backslashes may be used in URIs to escape markup characters,
+specifically asterisks ("*") and underscores ("_") which are valid URI
+characters (see `Escaping Mechanism`_ above).
+
+.. [#URI] Uniform Resource Identifier. URIs are a general form of
+ URLs (Uniform Resource Locators). For the syntax of URIs see
+ RFC2396_ and RFC2732_.
+
+
+Units
+=====
+
+(New in Docutils 0.3.10.)
+
+All measures consist of a positive floating point number in standard
+(non-scientific) notation and a unit, possibly separated by one or
+more spaces.
+
+Units are only supported where explicitly mentioned in the reference
+manuals.
+
+
+Length Units
+------------
+
+The following length units are supported by the reStructuredText
+parser:
+
+* em (em unit, the element's font size)
+* ex (ex unit, x-height of the element’s font)
+* mm (millimeters; 1 mm = 1/1000 m)
+* cm (centimeters; 1 cm = 10 mm)
+* in (inches; 1 in = 2.54 cm = 96 px)
+* px (pixels, 1 px = 1/96 in) [#]_
+* pt (points; 1 pt = 1/72 in)
+* pc (picas; 1 pc = 1/6 in = 12 pt)
+
+This set corresponds to the `length units in CSS2`_ (a subset of `length
+units in CSS3`_).
+
+.. [#] In LaTeX, the default definition is 1 px = 1/72 in (cf. `How to
+ configure the size of a pixel`_ in the LaTeX writer documentation).
+
+The following are all valid length values: "1.5em", "20 mm", ".5in".
+
+Length values without unit are completed with a writer-dependent
+default (e.g. "px" with HTML, "pt" with `latex2e`). See the writer
+specific documentation in the `user doc`__ for details.
+
+.. _length units in CSS2:
+ http://www.w3.org/TR/CSS2/syndata.html#length-units
+.. _length units in CSS3:
+ http://www.w3.org/TR/css-values-3/#absolute-lengths
+.. _How to configure the size of a pixel:
+ ../../user/latex.html#size-of-a-pixel
+__ ../../user/
+
+
+Percentage Units
+----------------
+
+Percentage values have a percent sign ("%") as unit. Percentage
+values are relative to other values, depending on the context in which
+they occur.
+
+
+----------------
+ Error Handling
+----------------
+
+Doctree element: system_message, problematic.
+
+Markup errors are handled according to the specification in `PEP
+258`_.
+
+
+.. _reStructuredText: http://docutils.sourceforge.net/rst.html
+.. _Docutils: http://docutils.sourceforge.net/
+.. _The Docutils Document Tree: ../doctree.html
+.. _"classes" attribute: ../doctree.html#classes
+.. _Docutils Generic DTD: ../docutils.dtd
+.. _transforms:
+ http://docutils.sourceforge.net/docutils/transforms/
+.. _Grouch: http://www.mems-exchange.org/software/grouch/
+.. _RFC822: http://www.rfc-editor.org/rfc/rfc822.txt
+.. _DocTitle transform:
+.. _DocInfo transform:
+ http://docutils.sourceforge.net/docutils/transforms/frontmatter.py
+.. _getopt.py:
+ http://www.python.org/doc/current/lib/module-getopt.html
+.. _GNU libc getopt_long():
+ http://www.gnu.org/software/libc/manual/html_node/Getopt-Long-Options.html
+.. _doctest module:
+ http://www.python.org/doc/current/lib/module-doctest.html
+.. _Emacs table mode: http://table.sourceforge.net/
+.. _Official IANA Registry of URI Schemes:
+ http://www.iana.org/assignments/uri-schemes
+.. _Retired Index of WWW Addressing Schemes:
+ http://www.w3.org/Addressing/schemes.html
+.. _World Wide Web Consortium: http://www.w3.org/
+.. _HTML Techniques for Web Content Accessibility Guidelines:
+ http://www.w3.org/TR/WCAG10-HTML-TECHS/#link-text
+.. _image: directives.html#image
+.. _replace: directives.html#replace
+.. _meta: directives.html#meta
+.. _figure: directives.html#figure
+.. _admonition: directives.html#admonitions
+.. _role: directives.html#custom-interpreted-text-roles
+.. _reStructuredText Directives: directives.html
+.. _reStructuredText Interpreted Text Roles: roles.html
+.. _RFC2396: http://www.rfc-editor.org/rfc/rfc2396.txt
+.. _RFC2732: http://www.rfc-editor.org/rfc/rfc2732.txt
+.. _Zope: http://www.zope.com/
+.. _PEP 258: ../../peps/pep-0258.html
+
+\f
+..
+ Local Variables:
+ mode: indented-text
+ indent-tabs-mode: nil
+ sentence-end-double-space: t
+ fill-column: 70
+ End:
--- /dev/null
+=========================================
+ reStructuredText Interpreted Text Roles
+=========================================
+
+:Author: David Goodger
+:Contact: docutils-develop@lists.sourceforge.net
+:Revision: $Revision: 8398 $
+:Date: $Date: 2019-09-30 13:36:39 +0200 (Mo, 30. Sep 2019) $
+:Copyright: This document has been placed in the public domain.
+
+This document describes the interpreted text roles implemented in the
+reference reStructuredText parser.
+
+Interpreted text uses backquotes (`) around the text. An explicit
+role marker may optionally appear before or after the text, delimited
+with colons. For example::
+
+ This is `interpreted text` using the default role.
+
+ This is :title:`interpreted text` using an explicit role.
+
+A default role may be defined by applications of reStructuredText; it
+is used if no explicit ``:role:`` prefix or suffix is given. The
+"default default role" is `:title-reference:`_. It can be changed
+using the default-role_ directive.
+
+See the `Interpreted Text`_ section in the `reStructuredText Markup
+Specification`_ for syntax details. For details on the hierarchy of
+elements, please see `The Docutils Document Tree`_ and the `Docutils
+Generic DTD`_ XML document type definition. For interpreted text role
+implementation details, see `Creating reStructuredText Interpreted
+Text Roles`_.
+
+.. _"role" directive: directives.html#role
+.. _default-role: directives.html#default-role
+.. _Interpreted Text: restructuredtext.html#interpreted-text
+.. _reStructuredText Markup Specification: restructuredtext.html
+.. _The Docutils Document Tree: ../doctree.html
+.. _Docutils Generic DTD: ../docutils.dtd
+.. _Creating reStructuredText Interpreted Text Roles:
+ ../../howto/rst-roles.html
+
+
+.. contents::
+
+
+---------------
+ Customization
+---------------
+
+Custom interpreted text roles may be defined in a document with the
+`"role" directive`_. Customization details are listed with each role.
+
+.. _class:
+
+A ``class`` option is recognized by the "role" directive for most
+interpreted text roles. A description__ is provided in the `"role"
+directive`_ documentation.
+
+__ directives.html#role-class
+
+
+----------------
+ Standard Roles
+----------------
+
+``:emphasis:``
+==============
+
+:Aliases: None
+:DTD Element: emphasis
+:Customization:
+ :Options: class_.
+ :Content: None.
+
+Implements emphasis. These are equivalent::
+
+ *text*
+ :emphasis:`text`
+
+
+``:literal:``
+==============
+
+:Aliases: None
+:DTD Element: literal
+:Customization:
+ :Options: class_.
+ :Content: None.
+
+Implements inline literal text. These are equivalent::
+
+ ``text``
+ :literal:`text`
+
+Care must be taken with backslash-escapes though. These are *not*
+equivalent::
+
+ ``text \ and \ backslashes``
+ :literal:`text \ and \ backslashes`
+
+The backslashes in the first line are preserved (and do nothing),
+whereas the backslashes in the second line escape the following
+spaces.
+
+
+``:code:``
+==========
+
+:Aliases: None
+:DTD Element: literal
+:Customization:
+ :Options: class_, language
+ :Content: None.
+
+(New in Docutils 0.9.)
+
+The ``code`` role marks its content as code in a formal language.
+
+For syntax highlight of inline code, the `"role" directive`_ can be used to
+build custom roles with the code language specified in the "language"
+option.
+
+For example, the following creates a LaTeX-specific "latex" role::
+
+ .. role:: latex(code)
+ :language: latex
+
+Content of the new role is parsed and tagged by the Pygments_ syntax
+highlighter. See the `code directive`_ for more info on parsing and display
+of code in reStructuredText.
+
+In addition to "class_", the following option is recognized:
+
+``language`` : text
+ Name of the code's language.
+ See `supported languages and markup formats`_ for recognized values.
+
+.. _code directive: directives.html#code
+.. _Pygments: http://pygments.org/
+.. _supported languages and markup formats: http://pygments.org/languages/
+
+
+``:math:``
+==========
+
+:Aliases: None
+:DTD Element: math
+:Customization:
+ :Options: class_
+ :Content: None.
+
+(New in Docutils 0.8.)
+
+The ``math`` role marks its content as mathematical notation (inline
+formula).
+
+The input format is LaTeX math syntax without the “math delimiters“
+(``$ $``), for example::
+
+ The area of a circle is :math:`A_\text{c} = (\pi/4) d^2`.
+
+See the `math directive`_ (producing display formulas) for more info
+on mathematical notation in reStructuredText.
+
+.. _math directive: directives.html#math
+
+
+``:pep-reference:``
+===================
+
+:Aliases: ``:PEP:``
+:DTD Element: reference
+:Customization:
+ :Options: class_.
+ :Content: None.
+
+The ``:pep-reference:`` role is used to create an HTTP reference to a
+PEP (Python Enhancement Proposal). The ``:PEP:`` alias is usually
+used. For example::
+
+ See :PEP:`287` for more information about reStructuredText.
+
+This is equivalent to::
+
+ See `PEP 287`__ for more information about reStructuredText.
+
+ __ http://www.python.org/peps/pep-0287.html
+
+
+``:rfc-reference:``
+===================
+
+:Aliases: ``:RFC:``
+:DTD Element: reference
+:Customization:
+ :Options: class_.
+ :Content: None.
+
+The ``:rfc-reference:`` role is used to create an HTTP reference to an
+RFC (Internet Request for Comments). The ``:RFC:`` alias is usually
+used. For example::
+
+ See :RFC:`2822` for information about email headers.
+
+This is equivalent to::
+
+ See `RFC 2822`__ for information about email headers.
+
+ __ http://www.faqs.org/rfcs/rfc2822.html
+
+You can link to a specific section by saying ``:rfc:`number#anchor``` (new in
+Docutils 0.15).
+
+
+``:strong:``
+============
+
+:Aliases: None
+:DTD Element: strong
+:Customization:
+ :Options: class_.
+ :Content: None.
+
+Implements strong emphasis. These are equivalent::
+
+ **text**
+ :strong:`text`
+
+
+``:subscript:``
+===============
+
+:Aliases: ``:sub:``
+:DTD Element: subscript
+:Customization:
+ :Options: class_.
+ :Content: None.
+
+Implements subscripts.
+
+.. Tip::
+
+ Whitespace or punctuation is required around interpreted text, but
+ often not desired with subscripts & superscripts.
+ Backslash-escaped whitespace can be used; the whitespace will be
+ removed from the processed document::
+
+ H\ :sub:`2`\ O
+ E = mc\ :sup:`2`
+
+ In such cases, readability of the plain text can be greatly
+ improved with substitutions::
+
+ The chemical formula for pure water is |H2O|.
+
+ .. |H2O| replace:: H\ :sub:`2`\ O
+
+ See `the reStructuredText spec`__ for further information on
+ `character-level markup`__ and `the substitution mechanism`__.
+
+ __ restructuredtext.html
+ __ restructuredtext.html#character-level-inline-markup
+ __ restructuredtext.html#substitution-references
+
+
+``:superscript:``
+=================
+
+:Aliases: ``:sup:``
+:DTD Element: superscript
+:Customization:
+ :Options: class_.
+ :Content: None.
+
+Implements superscripts. See the tip in `:subscript:`_ above.
+
+
+``:title-reference:``
+=====================
+
+:Aliases: ``:title:``, ``:t:``.
+:DTD Element: title_reference
+:Customization:
+ :Options: class_.
+ :Content: None.
+
+The ``:title-reference:`` role is used to describe the titles of
+books, periodicals, and other materials. It is the equivalent of the
+HTML "cite" element, and it is expected that HTML writers will
+typically render "title_reference" elements using "cite".
+
+Since title references are typically rendered with italics, they are
+often marked up using ``*emphasis*``, which is misleading and vague.
+The "title_reference" element provides accurate and unambiguous
+descriptive markup.
+
+Let's assume ``:title-reference:`` is the default interpreted text
+role (see below) for this example::
+
+ `Design Patterns` [GoF95]_ is an excellent read.
+
+The following document fragment (pseudo-XML_) will result from
+processing::
+
+ <paragraph>
+ <title_reference>
+ Design Patterns
+
+ <citation_reference refname="gof95">
+ GoF95
+ is an excellent read.
+
+``:title-reference:`` is the default interpreted text role in the
+standard reStructuredText parser. This means that no explicit role is
+required. Applications of reStructuredText may designate a different
+default role, in which case the explicit ``:title-reference:`` role
+must be used to obtain a ``title_reference`` element.
+
+
+.. _pseudo-XML: ../doctree.html#pseudo-xml
+
+
+-------------------
+ Specialized Roles
+-------------------
+
+``raw``
+=======
+
+:Aliases: None
+:DTD Element: raw
+:Customization:
+ :Options: class_, format
+ :Content: None
+
+.. WARNING::
+
+ The "raw" role is a stop-gap measure allowing the author to bypass
+ reStructuredText's markup. It is a "power-user" feature that
+ should not be overused or abused. The use of "raw" ties documents
+ to specific output formats and makes them less portable.
+
+ If you often need to use "raw"-derived interpreted text roles or
+ the "raw" directive, that is a sign either of overuse/abuse or that
+ functionality may be missing from reStructuredText. Please
+ describe your situation in a message to the Docutils-users_ mailing
+ list.
+
+ .. _Docutils-users: ../../user/mailing-lists.html#docutils-user
+
+The "raw" role indicates non-reStructuredText data that is to be
+passed untouched to the Writer. It is the inline equivalent of the
+`"raw" directive`_; see its documentation for details on the
+semantics.
+
+.. _"raw" directive: directives.html#raw-directive
+
+The "raw" role cannot be used directly. The `"role" directive`_ must
+first be used to build custom roles based on the "raw" role. One or
+more formats (Writer names) must be provided in a "format" option.
+
+For example, the following creates an HTML-specific "raw-html" role::
+
+ .. role:: raw-html(raw)
+ :format: html
+
+This role can now be used directly to pass data untouched to the HTML
+Writer. For example::
+
+ If there just *has* to be a line break here,
+ :raw-html:`<br />`
+ it can be accomplished with a "raw"-derived role.
+ But the line block syntax should be considered first.
+
+.. Tip:: Roles based on "raw" should clearly indicate their origin, so
+ they are not mistaken for reStructuredText markup. Using a "raw-"
+ prefix for role names is recommended.
+
+In addition to "class_", the following option is recognized:
+
+``format`` : text
+ One or more space-separated output format names (Writer names).
--- /dev/null
+<!--
+===========================================================================
+ OASIS XML Exchange Table Model Declaration Module
+===========================================================================
+:Date: 1999-03-15
+-->
+
+<!-- This set of declarations defines the XML version of the Exchange
+ Table Model as of the date shown in the Formal Public Identifier
+ (FPI) for this entity.
+
+ This set of declarations may be referred to using a public external
+ entity declaration and reference as shown in the following three
+ lines:
+
+ <!ENTITY % calstblx
+ PUBLIC "-//OASIS//DTD XML Exchange Table Model 19990315//EN">
+ %calstblx;
+
+ If various parameter entities used within this set of declarations
+ are to be given non-default values, the appropriate declarations
+ should be given before calling in this package (i.e., before the
+ "%calstblx;" reference).
+-->
+
+<!-- The motivation for this XML version of the Exchange Table Model
+ is simply to create an XML version of the SGML Exchange Table
+ Model. By design, no effort has been made to "improve" the model.
+
+ This XML version incorporates the logical bare minimum changes
+ necessary to make the Exchange Table Model a valid XML DTD.
+-->
+
+<!-- The XML version of the Exchange Table Model differs from
+ the SGML version in the following ways:
+
+ The following parameter entities have been removed:
+
+ - tbl.table.excep, tbl.hdft.excep, tbl.row.excep, tbl.entry.excep
+ There are no exceptions in XML. The following normative statement
+ is made in lieu of exceptions: the exchange table model explicitly
+ forbids a table from occurring within another table. If the
+ content model of an entry includes a table element, then this
+ cannot be enforced by the DTD, but it is a deviation from the
+ exchange table model to include a table within a table.
+
+ - tbl.hdft.name, tbl.hdft.mdl, tbl.hdft.excep, tbl.hdft.att
+ The motivation for these elements was to change the table
+ header/footer elements. Since XML does not allow element declarations
+ to contain name groups, and the exchange table model does not
+ allow a table to contain footers, the continued presence of these
+ attributes seems unnecessary.
+
+ The following parameter entity has been added:
+
+ - tbl.thead.att
+ This entity parameterizes the attributes on thead. It replaces
+ the tbl.hdft.att parameter entity.
+
+ Other miscellaneous changes:
+
+ - Tag ommission indicators have been removed
+ - Comments have been removed from declarations
+ - NUMBER attributes have been changed to NMTOKEN
+ - NUTOKEN attributes have been to changed to NMTOKEN
+ - Removed the grouping characters around the content model
+ parameter entry for the 'entry' element. This is necessary
+ so that an entry can contain #PCDATA and be defined as an
+ optional, repeatable OR group beginning with #PCDATA.
+-->
+
+<!-- This entity includes a set of element and attribute declarations
+ that partially defines the Exchange table model. However, the model
+ is not well-defined without the accompanying natural language
+ description of the semantics (meanings) of these various elements,
+ attributes, and attribute values. The semantic writeup, also available
+ from SGML Open, should be used in conjunction with this entity.
+-->
+
+<!-- In order to use the Exchange table model, various parameter entity
+ declarations are required. A brief description is as follows:
+
+ ENTITY NAME WHERE USED WHAT IT IS
+
+ %yesorno In ATTLIST of: An attribute declared value
+ almost all elements for a "boolean" attribute
+
+ %paracon In content model of: The "text" (logical content)
+ <entry> of the model group for <entry>
+
+ %titles In content model of: The "title" part of the model
+ table element group for the table element
+
+ %tbl.table.name In declaration of: The name of the "table"
+ table element element
+
+ %tbl.table-titles.mdl In content model of: The model group for the title
+ table elements part of the content model for
+ table element
+
+ %tbl.table.mdl In content model of: The model group for the content
+ table elements model for table element,
+ often (and by default) defined
+ in terms of %tbl.table-titles.mdl
+ and tgroup
+
+ %tbl.table.att In ATTLIST of: Additional attributes on the
+ table element table element
+
+ %bodyatt In ATTLIST of: Additional attributes on the
+ table element table element (for backward
+ compatibility with the SGML
+ model)
+
+ %tbl.tgroup.mdl In content model of: The model group for the content
+ <tgroup> model for <tgroup>
+
+ %tbl.tgroup.att In ATTLIST of: Additional attributes on the
+4 <tgroup> <tgroup> element
+
+ %tbl.thead.att In ATTLIST of: Additional attributes on the
+ <thead> <thead> element
+
+ %tbl.tbody.att In ATTLIST of: Additional attributes on the
+ <tbody> <tbody> element
+
+ %tbl.colspec.att In ATTLIST of: Additional attributes on the
+ <colspec> <colspec> element
+
+ %tbl.row.mdl In content model of: The model group for the content
+ <row> model for <row>
+
+ %tbl.row.att In ATTLIST of: Additional attributes on the
+ <row> <row> element
+
+ %tbl.entry.mdl In content model of: The model group for the content
+ <entry> model for <entry>
+
+ %tbl.entry.att In ATTLIST of: Additional attributes on the
+ <entry> <entry> element
+
+ This set of declarations will use the default definitions shown below
+ for any of these parameter entities that are not declared before this
+ set of declarations is referenced.
+-->
+
+<!-- These definitions are not directly related to the table model, but are
+ used in the default CALS table model and may be defined elsewhere (and
+ prior to the inclusion of this table module) in the referencing DTD. -->
+
+<!ENTITY % yesorno 'NMTOKEN'> <!-- no if zero(s), yes if any other value -->
+<!ENTITY % titles 'title?'>
+<!ENTITY % paracon '#PCDATA'> <!-- default for use in entry content -->
+
+<!--
+The parameter entities as defined below change and simplify the CALS table
+model as published (as part of the Example DTD) in MIL-HDBK-28001. The
+resulting simplified DTD has support from the SGML Open vendors and is
+therefore more interoperable among different systems.
+
+These following declarations provide the Exchange default definitions
+for these entities. However, these entities can be redefined (by giving
+the appropriate parameter entity declaration(s) prior to the reference
+to this Table Model declaration set entity) to fit the needs of the
+current application.
+
+Note, however, that changes may have significant effect on the ability to
+interchange table information. These changes may manifest themselves
+in useability, presentation, and possible structure information degradation.
+-->
+
+<!ENTITY % tbl.table.name "table">
+<!ENTITY % tbl.table-titles.mdl "%titles;,">
+<!ENTITY % tbl.table-main.mdl "tgroup+">
+<!ENTITY % tbl.table.mdl "%tbl.table-titles.mdl; %tbl.table-main.mdl;">
+<!ENTITY % tbl.table.att "
+ pgwide %yesorno; #IMPLIED ">
+<!ENTITY % bodyatt "">
+<!ENTITY % tbl.tgroup.mdl "colspec*,thead?,tbody">
+<!ENTITY % tbl.tgroup.att "">
+<!ENTITY % tbl.thead.att "">
+<!ENTITY % tbl.tbody.att "">
+<!ENTITY % tbl.colspec.att "">
+<!ENTITY % tbl.row.mdl "entry+">
+<!ENTITY % tbl.row.att "">
+<!ENTITY % tbl.entry.mdl "(%paracon;)*">
+<!ENTITY % tbl.entry.att "">
+
+<!-- ===== Element and attribute declarations follow. ===== -->
+
+<!--
+ Default declarations previously defined in this entity and
+ referenced below include:
+ ENTITY % tbl.table.name "table"
+ ENTITY % tbl.table-titles.mdl "%titles;,"
+ ENTITY % tbl.table.mdl "%tbl.table-titles; tgroup+"
+ ENTITY % tbl.table.att "
+ pgwide %yesorno; #IMPLIED "
+-->
+
+<!ELEMENT %tbl.table.name; (%tbl.table.mdl;)>
+
+<!ATTLIST %tbl.table.name;
+ frame (top|bottom|topbot|all|sides|none) #IMPLIED
+ colsep %yesorno; #IMPLIED
+ rowsep %yesorno; #IMPLIED
+ %tbl.table.att;
+ %bodyatt;
+>
+
+<!--
+ Default declarations previously defined in this entity and
+ referenced below include:
+ ENTITY % tbl.tgroup.mdl "colspec*,thead?,tbody"
+ ENTITY % tbl.tgroup.att ""
+-->
+
+<!ELEMENT tgroup (%tbl.tgroup.mdl;) >
+
+<!ATTLIST tgroup
+ cols NMTOKEN #REQUIRED
+ colsep %yesorno; #IMPLIED
+ rowsep %yesorno; #IMPLIED
+ align (left|right|center|justify|char) #IMPLIED
+ %tbl.tgroup.att;
+>
+
+<!--
+ Default declarations previously defined in this entity and
+ referenced below include:
+ ENTITY % tbl.colspec.att ""
+-->
+
+<!ELEMENT colspec EMPTY >
+
+<!ATTLIST colspec
+ colnum NMTOKEN #IMPLIED
+ colname NMTOKEN #IMPLIED
+ colwidth CDATA #IMPLIED
+ colsep %yesorno; #IMPLIED
+ rowsep %yesorno; #IMPLIED
+ align (left|right|center|justify|char) #IMPLIED
+ char CDATA #IMPLIED
+ charoff NMTOKEN #IMPLIED
+ %tbl.colspec.att;
+>
+
+<!--
+ Default declarations previously defined in this entity and
+ referenced below include:
+ ENTITY % tbl.thead.att ""
+-->
+
+<!ELEMENT thead (row+)>
+
+<!ATTLIST thead
+ valign (top|middle|bottom) #IMPLIED
+ %tbl.thead.att;
+>
+
+<!--
+ Default declarations previously defined in this entity and
+ referenced below include:
+ ENTITY % tbl.tbody.att ""
+-->
+
+<!ELEMENT tbody (row+)>
+
+<!ATTLIST tbody
+ valign (top|middle|bottom) #IMPLIED
+ %tbl.tbody.att;
+>
+
+<!--
+ Default declarations previously defined in this entity and
+ referenced below include:
+ ENTITY % tbl.row.mdl "entry+"
+ ENTITY % tbl.row.att ""
+-->
+
+<!ELEMENT row (%tbl.row.mdl;)>
+
+<!ATTLIST row
+ rowsep %yesorno; #IMPLIED
+ valign (top|middle|bottom) #IMPLIED
+ %tbl.row.att;
+>
+
+
+<!--
+ Default declarations previously defined in this entity and
+ referenced below include:
+ ENTITY % paracon "#PCDATA"
+ ENTITY % tbl.entry.mdl "(%paracon;)*"
+ ENTITY % tbl.entry.att ""
+-->
+
+<!ELEMENT entry %tbl.entry.mdl;>
+
+<!ATTLIST entry
+ colname NMTOKEN #IMPLIED
+ namest NMTOKEN #IMPLIED
+ nameend NMTOKEN #IMPLIED
+ morerows NMTOKEN #IMPLIED
+ colsep %yesorno; #IMPLIED
+ rowsep %yesorno; #IMPLIED
+ align (left|right|center|justify|char) #IMPLIED
+ char CDATA #IMPLIED
+ charoff NMTOKEN #IMPLIED
+ valign (top|middle|bottom) #IMPLIED
+ %tbl.entry.att;
+>
--- /dev/null
+=====================
+ Docutils Transforms
+=====================
+
+:Author: David Goodger
+:Contact: docutils-develop@lists.sourceforge.net
+:Revision: $Revision: 7530 $
+:Date: $Date: 2012-10-16 14:40:36 +0200 (Di, 16. Okt 2012) $
+:Copyright: This document has been placed in the public domain.
+
+
+.. contents::
+
+Transforms change the document tree in-place, add to the tree, or prune it.
+Transforms resolve references and footnote numbers, process interpreted
+text, and do other context-sensitive processing. Each transform is a
+subclass of ``docutils.tranforms.Transform``.
+
+There are `transforms added by components`_, others (e.g.
+``parts.Contents``) are added by the parser, if a corresponding directive is
+found in the document.
+
+To add a transform, components (objects inheriting from
+Docutils.Component like Readers, Parsers, Writers, Input, Output) overwrite
+the ``get_transforms()`` method of their base class. After the Reader has
+finished processing, the Publisher calls
+``Transformer.populate_from_components()`` with a list of components and all
+transforms returned by the component's ``get_transforms()`` method are
+stored in a `transformer object` attached to the document tree.
+
+
+For more about transforms and the Transformer object, see also `PEP
+258`_. (The ``default_transforms()`` attribute of component classes mentioned
+there is deprecated. Use the ``get_transforms()`` method instead.)
+
+.. _PEP 258: ../peps/pep-0258.html#transformer
+
+
+Transforms Listed in Priority Order
+===================================
+
+Transform classes each have a default_priority attribute which is used by
+the Transformer to apply transforms in order (low to high). The default
+priority can be overridden when adding transforms to the Transformer object.
+
+
+============================== ============================ ========
+Transform: module.Class Added By Priority
+============================== ============================ ========
+misc.class "class" (d/p) 210
+
+references.Substitutions standalone (r), pep (r) 220
+
+references.PropagateTargets standalone (r), pep (r) 260
+
+frontmatter.DocTitle standalone (r) 320
+
+frontmatter.DocInfo standalone (r) 340
+
+frontmatter.SectSubTitle standalone (r) 350
+
+peps.Headers pep (r) 360
+
+peps.Contents pep (r) 380
+
+universal.StripClasses... Writer (w) 420
+
+references.AnonymousHyperlinks standalone (r), pep (r) 440
+
+references.IndirectHyperlinks standalone (r), pep (r) 460
+
+peps.TargetNotes pep (r) 520
+
+references.TargetNotes peps.TargetNotes (t/p) 0
+
+misc.CallBack peps.TargetNotes (t/p) 1
+
+references.TargetNotes "target-notes" (d/p) 540
+
+references.Footnotes standalone (r), pep (r) 620
+
+references.ExternalTargets standalone (r), pep (r) 640
+
+references.InternalTargets standalone (r), pep (r) 660
+
+parts.SectNum "sectnum" (d/p) 710
+
+parts.Contents "contents" (d/p), 720
+ peps.Contents (t/p)
+
+universal.StripComments Reader (r) 740
+
+peps.PEPZero peps.Headers (t/p) 760
+
+components.Filter "meta" (d/p) 780
+
+universal.Decorations Reader (r) 820
+
+misc.Transitions standalone (r), pep (r) 830
+
+universal.ExposeInternals Reader (r) 840
+
+references.DanglingReferences standalone (r), pep (r) 850
+
+universal.Messages Writer (w) 860
+
+universal.FilterMessages Writer (w) 870
+
+universal.SmartQuotes Parser 850
+
+universal.TestMessages DocutilsTestSupport 880
+
+writer_aux.Compound newlatex2e (w) 910
+
+writer_aux.Admonitions html4css1 (w), 920
+ latex2e (w)
+
+misc.CallBack n/a 990
+============================== ============================ ========
+
+Key:
+
+* (r): Reader
+* (w): Writer
+* (d): Directive
+* (t): Transform
+* (/p): Via a "pending" node
+
+
+Transform Priority Range Categories
+===================================
+
+==== ==== ================================================
+ Priority
+---------- ------------------------------------------------
+From To Category
+==== ==== ================================================
+ 0 99 immediate execution (added by another transform)
+ 100 199 very early (non-standard)
+ 200 299 very early
+ 300 399 early
+ 400 699 main
+ 700 799 late
+ 800 899 very late
+ 900 999 very late (non-standard)
+==== ==== ================================================
+
+
+Transforms added by components
+===============================
+
+
+readers.Reader:
+ | universal.Decorations,
+ | universal.ExposeInternals,
+ | universal.StripComments
+
+readers.ReReader:
+ None
+
+readers.standalone.Reader:
+ | references.Substitutions,
+ | references.PropagateTargets,
+ | frontmatter.DocTitle,
+ | frontmatter.SectionSubTitle,
+ | frontmatter.DocInfo,
+ | references.AnonymousHyperlinks,
+ | references.IndirectHyperlinks,
+ | references.Footnotes,
+ | references.ExternalTargets,
+ | references.InternalTargets,
+ | references.DanglingReferences,
+ | misc.Transitions
+
+readers.pep.Reader:
+ | references.Substitutions,
+ | references.PropagateTargets,
+ | references.AnonymousHyperlinks,
+ | references.IndirectHyperlinks,
+ | references.Footnotes,
+ | references.ExternalTargets,
+ | references.InternalTargets,
+ | references.DanglingReferences,
+ | misc.Transitions,
+ | peps.Headers,
+ | peps.Contents,
+ | peps.TargetNotes
+
+parsers.rst.Parser
+ universal.SmartQuotes
+
+writers.Writer:
+ | universal.Messages,
+ | universal.FilterMessages,
+ | universal.StripClassesAndElements
+
+writers.UnfilteredWriter
+ None
+
+writers.latex2e.Writer
+ writer_aux.Admonitions
+
+writers.html4css1.Writer:
+ writer_aux.Admonitions
+
+writers.odf_odt.Writer:
+ removes references.DanglingReferences
--- /dev/null
+slide-shows.s5.html: slide-shows.txt
+ rst2s5.py slide-shows.txt slide-shows.s5.html \
+ --config ../../tools/docutils.conf \
+ --overwrite-theme-files \
+ --link-stylesheet \
+ --no-generator --no-datestamp --no-source-link
+
+smartquotes.html: smartquotes.txt
+ rst2html.py smartquotes.txt smartquotes.html --smart-quotes=true
--- /dev/null
+========================
+ Docutils Configuration
+========================
+
+:Author: David Goodger
+:Contact: docutils-develop@lists.sourceforge.net
+:Revision: $Revision: 8412 $
+:Date: $Date: 2019-11-06 19:15:21 +0100 (Mi, 06. Nov 2019) $
+:Copyright: This document has been placed in the public domain.
+
+.. sidebar:: Docutils Security for Web Applications
+
+ For details about securing web applications, please see `Deploying
+ Docutils Securely <../howto/security.html>`_.
+
+.. contents::
+
+
+-------------------
+Configuration Files
+-------------------
+
+Configuration files are used for persistent customization; they can be
+set once and take effect every time you use a front-end tool.
+Configuration file settings override the built-in defaults, and
+command-line options override all.
+
+By default, Docutils checks the following places for configuration
+files, in the following order:
+
+1. ``/etc/docutils.conf``: This is a system-wide configuration file,
+ applicable to all Docutils processing on the system.
+
+2. ``./docutils.conf``: This is a project-specific configuration file,
+ located in the current directory. The Docutils front end has to be
+ executed from the directory containing this configuration file for
+ it to take effect (note that this may have nothing to do with the
+ location of the source files). Settings in the project-specific
+ configuration file will override corresponding settings in the
+ system-wide file.
+
+3. ``~/.docutils``: This is a user-specific configuration file,
+ located in the user's home directory. Settings in this file will
+ override corresponding settings in both the system-wide and
+ project-specific configuration files.
+
+If more than one configuration file is found, all will be read but
+later entries will override earlier ones. For example, a "stylesheet"
+entry in a user-specific configuration file will override a
+"stylesheet" entry in the system-wide file.
+
+The default implicit config file paths can be overridden by the
+``DOCUTILSCONFIG`` environment variable. ``DOCUTILSCONFIG`` should
+contain a colon-separated (semicolon-separated on Windows) sequence of
+config file paths to search for; leave it empty to disable implicit
+config files altogether. Tilde-expansion is performed on paths.
+Paths are interpreted relative to the current working directory.
+Empty path items are ignored.
+
+In addition, a configuration file may be explicitly specified with the
+"--config" command-line option. This configuration file is read after
+the three implicit ones listed above (or the ones defined by the
+``DOCUTILSCONFIG`` environment variable), and its entries will have
+priority.
+
+
+-------------------------
+Configuration File Syntax
+-------------------------
+
+Configuration files are UTF-8-encoded text files. The
+ConfigParser.py_ module from Python_'s standard library is used to
+read them. From its documentation:
+
+ The configuration file consists of sections, lead by a "[section]"
+ header and followed by "name: value" entries, with continuations
+ in the style of `RFC 822`_; "name=value" is also accepted. Note
+ that leading whitespace is removed from values. ... Lines
+ beginning with "#" or ";" are ignored and may be used to provide
+ comments.
+
+.. Note:: No format string interpolation is done.
+
+Configuration file entry names correspond to internal runtime
+settings. Underscores ("_") and hyphens ("-") can be used
+interchangably in entry names; hyphens are automatically converted to
+underscores.
+
+For on/off switch settings (_`booleans`), the following values are
+recognized:
+
+:On: "true", "yes", "on", "1"
+:Off: "false", "no", "off", "0", "" (no value)
+
+.. _list:
+
+List values can be comma- or colon-delimited.
+
+strip_classes_, strip_elements_with_classes_, stylesheet, and
+stylesheet_path use the comma as delimiter,
+whitespace around list values is stripped. ::
+
+ strip-classes: ham,eggs,
+ strip-elements-with-classes: sugar, salt, flour
+ stylesheet: html4css1.css,
+ math.css,
+ style with spaces.css
+ stylesheet-path: ../styles/my.css, ../styles/funny.css
+
+expose_internals_, ignore_ and prune_ use the colon as delimiter and do not
+strip whitespace::
+
+ expose_internals: b:c:d
+
+
+Example
+=======
+
+This is the contents of the ``tools/docutils.conf`` configuration file
+supplied with Docutils::
+
+ # These entries affect all processing:
+ [general]
+ source-link: yes
+ datestamp: %Y-%m-%d %H:%M UTC
+ generator: on
+
+ # These entries affect HTML output:
+ [html4css1 writer]
+ # Required for docutils-update, the website build system:
+ stylesheet-path: ../docutils/writers/html4css1/html4css1.css
+ embed-stylesheet: no
+ field-name-limit: 20
+
+Individual configuration sections and settings are described in the
+following section.
+
+
+-------------------------------------
+Configuration File Sections & Entries
+-------------------------------------
+
+Below are the Docutils runtime settings, listed by config file
+section. Any setting may be specified in any section, but only
+settings from active sections will be used. Sections correspond to
+Docutils components (module name or alias; section names are always in
+lowercase letters). Each `Docutils application`_ uses a specific set
+of components; corresponding configuration file sections are applied
+when the application is used. Configuration sections are applied in
+general-to-specific order, as follows:
+
+1. `[general]`_
+
+2. `[parsers]`_, parser dependencies, and the section specific to the
+ Parser used ("[... parser]"). Currently, only `[restructuredtext
+ parser]`_ is applicable.
+
+3. `[readers]`_, reader dependencies, and the section specific to the
+ Reader used ("[... reader]"). For example, `[pep reader]`_ depends
+ on `[standalone reader]`_.
+
+4. `[writers]`_, writer family ("[... writers]"; if applicable),
+ writer dependencies, and the section specific to the writer used
+ ("[... writer]"). For example, `[pep_html writer]`_ depends
+ on `[html4css1 writer]`_.
+
+5. `[applications]`_, application dependencies, and the section
+ specific to the Application (front-end tool) in use
+ ("[... application]").
+
+Since any setting may be specified in any section, this ordering
+allows component- or application-specific overrides of earlier
+settings. For example, there may be Reader-specific overrides of
+general settings; Writer-specific overrides of Parser settings;
+Application-specific overrides of Writer settings; and so on.
+
+If multiple configuration files are applicable, the process is
+completed (all sections are applied in the order given) for each one
+before going on to the next. For example, a "[pep_html writer]
+stylesheet" setting in an earlier configuration file would be
+overridden by an "[html4css1 writer] stylesheet" setting in a later
+file.
+
+Some knowledge of Python_ is assumed for some attributes.
+
+.. _ConfigParser.py:
+ http://www.python.org/doc/current/lib/module-ConfigParser.html
+.. _Python: http://www.python.org/
+.. _RFC 822: http://www.rfc-editor.org/rfc/rfc822.txt
+.. _Docutils application: tools.html
+
+
+[general]
+=========
+
+Settings in the "[general]" section are always applied.
+
+auto_id_prefix
+--------------
+
+Prefix prepended to all auto-generated `identifier keys` generated within
+the document, after id_prefix_. Ensure the value conforms to the
+restrictions on identifiers in the output format, as it is not subjected to
+the `identifier normalization`_.
+
+A trailing "%" is replaced with the tag name (new in Docutils 0.16).
+
+Default: "id" (`will change to "%" in future`__).
+Options: ``--auto-id-prefix`` (hidden, intended mainly for programmatic use).
+
+.. _identifier normalization:
+ ../ref/rst/directives.html#identifier-normalization
+__ ../../RELEASE-NOTES.html#future-changes
+
+datestamp
+---------
+
+Include a time/datestamp in the document footer. Contains a
+format string for Python's ``time.strftime``. See the `time
+module documentation`__.
+
+Default: None.
+Options: ``--date, -d, --time, -t, --no-datestamp``.
+
+Configuration file entry examples::
+
+ # Equivalent to --date command-line option, results in
+ # ISO 8601 extended format datestamp, e.g. "2001-12-21":
+ datestamp: %Y-%m-%d
+
+ # Equivalent to --time command-line option, results in
+ # date/timestamp like "2001-12-21 18:43 UTC":
+ datestamp: %Y-%m-%d %H:%M UTC
+
+ # Disables datestamp; equivalent to --no-datestamp:
+ datestamp:
+
+__ http://www.python.org/doc/current/lib/module-time.html
+
+debug
+-----
+
+Report debug-level system messages.
+
+Default: don't (None). Options: ``--debug, --no-debug``.
+
+dump_internals
+--------------
+
+At the end of processing, write all internal attributes of the
+document (``document.__dict__``) to stderr.
+
+Default: don't (None).
+Options: ``--dump-internals`` (hidden, for development use only).
+
+dump_pseudo_xml
+---------------
+
+At the end of processing, write the pseudo-XML representation of
+the document to stderr.
+
+Default: don't (None).
+Options: ``--dump-pseudo-xml`` (hidden, for development use only).
+
+dump_settings
+-------------
+
+At the end of processing, write all Docutils settings to stderr.
+
+Default: don't (None).
+Options: ``--dump-settings`` (hidden, for development use only).
+
+dump_transforms
+---------------
+
+At the end of processing, write a list of all transforms applied
+to the document to stderr.
+
+Default: don't (None).
+Options: ``--dump-transforms`` (hidden, for development use only).
+
+error_encoding
+--------------
+
+The text encoding for error output.
+
+Default: "ascii". Options: ``--error-encoding, -e``.
+
+error_encoding_error_handler
+----------------------------
+
+The error handler for unencodable characters in error output. See
+output_encoding_error_handler_ for acceptable values.
+
+Default: "backslashreplace"
+Options: ``--error-encoding-error-handler, --error-encoding, -e``.
+
+exit_status_level
+-----------------
+
+A system message level threshold; non-halting system messages at
+or above this level will produce a non-zero exit status at normal
+exit. Exit status is the maximum system message level plus 10 (11
+for INFO, etc.).
+
+Default: disabled (5). Options: ``--exit-status``.
+
+expose_internals
+----------------
+
+List_ of internal attribues to expose as external attributes (with
+"internal:" namespace prefix). To specify multiple attributes in
+configuration files, use colons to separate names; on the command
+line, the option may be used more than once.
+
+Default: don't (None).
+Options: ``--expose-internal-attribute`` (hidden, for development use only).
+
+footnote_backlinks
+------------------
+
+Enable or disable backlinks from footnotes_ and citations_ to their
+references.
+
+Default: enabled (True).
+Options: ``--footnote-backlinks, --no-footnote-backlinks``.
+
+generator
+---------
+
+Include a "Generated by Docutils" credit and link in the document footer.
+
+Default: off (None). Options: ``--generator, -g, --no-generator``.
+
+halt_level
+----------
+
+The threshold at or above which system messages are converted to
+exceptions, halting execution immediately. If `traceback`_ is set, the
+exception will propagate; otherwise, Docutils will exit.
+
+Default: severe (4). Options: ``--halt, --strict``.
+
+id_prefix
+---------
+
+Prefix prepended to all identifier keys generated within the document.
+Ensure the value conforms to the restrictions on identifiers in the output
+format, as it is not subjected to the `identifier normalization`_.
+See also auto_id_prefix_.
+
+Default: "" (empty).
+Options: ``--id-prefix`` (hidden, intended mainly for programmatic use).
+
+input_encoding
+--------------
+
+The text encoding for input.
+
+Default: auto-detect (None). Options: ``--input-encoding, -i``.
+
+input_encoding_error_handler
+----------------------------
+
+The error handler for undecodable characters in the input. Acceptable
+values include:
+
+strict
+ Raise an exception in case of an encoding error.
+replace
+ Replace malformed data with the official Unicode replacement
+ character, U+FFFD.
+ignore
+ Ignore malformed data and continue without further notice.
+
+Acceptable values are the same as for the "error" parameter of
+Python's ``unicode`` function; other values may be defined in
+applications or in future versions of Python.
+
+Default: "strict".
+Options: ``--input-encoding-error-handler, --input-encoding, -i``.
+
+language_code
+-------------
+
+Case-insensitive `language tag`_ as defined in `BCP 47`_.
+
+Sets the document language, also used for localized directive and
+role names as well as Docutils-generated text.
+
+A typical language identifier consists of a 2-letter language code
+from `ISO 639`_ (3-letter codes can be used if no 2-letter code
+exists). The language identifier can have an optional subtag,
+typically for variations based on country (from `ISO 3166`_
+2-letter country codes). Avoid subtags except where they add
+useful distinguishing information. Examples of language tags
+include "fr", "en-GB", "pt-br" (the same as "pt-BR"), and
+"de-1901" (German with pre-1996 spelling).
+
+The language of document parts can be specified with a
+"language-<language tag>" `class attribute`_, e.g.
+``.. class:: language-el-polyton`` for a quote in polytonic Greek.
+
+Default: English ("en"). Options: ``--language, -l``.
+
+.. _class attribute: ../ref/doctree.html#classes
+
+output_encoding
+---------------
+
+The text encoding for output.
+
+Default: "UTF-8". Options: ``--output-encoding, -o``.
+
+output_encoding_error_handler
+-----------------------------
+
+The error handler for unencodable characters in the output. Acceptable
+values include:
+
+strict
+ Raise an exception in case of an encoding error.
+replace
+ Replace malformed data with a suitable replacement marker,
+ such as "?".
+ignore
+ Ignore malformed data and continue without further notice.
+xmlcharrefreplace
+ Replace with the appropriate XML character reference, such as
+ "``†``".
+backslashreplace
+ Replace with backslashed escape sequences, such as "``\u2020``".
+
+Acceptable values are the same as for the "error" parameter of
+Python's ``encode`` string method; other values may be defined in
+applications or in future versions of Python.
+
+Default: "strict".
+Options: ``--output-encoding-error-handler, --output-encoding, -o``.
+
+record_dependencies
+-------------------
+
+Path to a file where Docutils will write a list of files that were
+required to generate the output, e.g. included files or embedded
+stylesheets [#dependencies]_. [#pwd]_ The format is one path per
+line with forward slashes as separator, the encoding is ``utf8``.
+
+Set to ``-`` in order to write dependencies to stdout.
+
+This option is particularly useful in conjunction with programs like
+``make`` using ``Makefile`` rules like::
+
+ ham.html: ham.txt $(shell cat hamdeps.txt)
+ rst2html.py --record-dependencies=hamdeps.txt ham.txt ham.html
+
+If the filesystem encoding differs from utf8, replace the ``cat``
+command with a call to a converter, e.g.::
+
+ $(shell iconv -f utf8 -t latin1 hamdeps.txt)
+
+Default: None. Option: ``--record-dependencies``.
+
+report_level
+------------
+
+Report system messages at or higher than <level>:
+
+1 info
+2 warning
+3 error
+4 severe
+5 none
+
+Default: warning (2).
+Options: ``--report, -r, --verbose, -v, --quiet, -q``.
+
+sectnum_xform
+-------------
+
+Enable or disable automatic section numbering by Docutils
+(docutils.transforms.parts.SectNum) associated with the `sectnum
+directive`_.
+
+If disabled, section numbers might be added to the output by the
+renderer (e.g. by LaTeX or via a CSS style definition).
+
+Default: enabled (True).
+Options: ``--section-numbering``, ``--no-section-numbering``.
+
+.. _sectnum directive: ../ref/rst/directives.html#sectnum
+
+source_link
+-----------
+
+Include a "View document source" link in the document footer. URL will
+be relative to the destination.
+
+Default: don't (None).
+Options: ``--source-link, -s, --no-source-link``.
+
+source_url
+----------
+
+An explicit URL for a "View document source" link, used verbatim.
+
+Default: compute if source_link (None).
+Options: ``--source-url, --no-source-link``.
+
+strict_visitor
+--------------
+
+When processing a document tree with the Visitor pattern, raise an
+error if a writer does not support a node type listed as optional. For
+transitional development use.
+
+Default: disabled (None).
+Option: ``--strict-visitor`` (hidden, for development use only).
+
+strip_classes
+-------------
+
+Comma-separated list_ of "classes" attribute values to remove from all
+elements in the document tree. The command line option may be used more
+than once.
+
+.. WARNING:: Potentially dangerous; use with caution.
+
+Default: disabled (None). Option: ``--strip-class``.
+
+strip_comments
+--------------
+
+Enable the removal of comment elements from the document tree.
+
+Default: disabled (None).
+Options: ``--strip-comments``, ``--leave-comments``.
+
+strip_elements_with_classes
+---------------------------
+
+Comma-separated list_ of "classes" attribute values;
+matching elements are removed from the document tree.
+The command line option may be used more than once.
+
+.. WARNING:: Potentially dangerous; use with caution.
+
+Default: disabled (None). Option: ``--strip-element-with-class``.
+
+title
+-----
+
+The `document title`_ as metadata, which does not become part of the
+document body. It overrides a document-supplied title. For
+example, in HTML output the metadata document title appears in the
+title bar of the browser window.
+
+Default: none. Option: ``--title``.
+
+.. _document title: ../ref/rst/restructuredtext.html#document-title
+
+toc_backlinks
+-------------
+
+Enable backlinks from section titles to table of contents entries
+("entry"), to the top of the TOC ("top"), or disable ("none").
+
+Default: "entry".
+Options: ``--toc-entry-backlinks, --toc-top-backlinks, --no-toc-backlinks``.
+
+traceback
+---------
+
+Enable Python tracebacks when halt-level system messages and other
+exceptions occur. Useful for debugging, and essential for issue
+reports. Exceptions are allowed to propagate, instead of being
+caught and reported (in a user-friendly way) by Docutils.
+
+Default: disabled (None) unless Docutils is run programmatically
+using the `Publisher Interface`_.
+Options: ``--traceback, --no-traceback``.
+
+.. _Publisher Interface: ../api/publisher.html
+
+warning_stream
+--------------
+
+Path to a file for the output of system messages (warnings). [#pwd]_
+
+Default: stderr (None). Options: ``--warnings``.
+
+
+[parsers]
+=========
+
+Docutils currently supports only one parser, for reStructuredText.
+
+
+[restructuredtext parser]
+-------------------------
+
+character_level_inline_markup
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Experimental setting to relax the `inline markup recognition rules`_
+requiring whitespace or punctuation around inline markup.
+
+Allows character level inline markup without escaped whithespace and is
+especially suited for langauges that do not use whitespace to separate words
+(e.g. Japanese, Chinese).
+
+.. WARNING:: Potentially dangerous; use with caution.
+
+ When changing this setting to "True", inline markup charactes in
+ URLs, names and formulas must be escaped to prevent recognition and
+ possible errors. Examples::
+
+ http://rST_for_all.html (hyperlinks to rST_ and for_)
+ x_2, inline_markup (hyperlinks to x_ and inline_)
+ 2*x (starts emphasised text)
+ a|b (starts a substitution reference)
+
+Default: disabled (False).
+Options: ``--character-level-inline-markup, --word-level-inline-markup``.
+
+New in Docutils 0.13.
+
+file_insertion_enabled
+~~~~~~~~~~~~~~~~~~~~~~
+
+Enable or disable directives that insert the contents of external
+files, such as the "include_" & "raw_". A "warning" system
+message (including the directive text) is inserted instead. (See
+also raw_enabled_ for another security-relevant setting.)
+
+Default: enabled (True).
+Options: ``--file-insertion-enabled, --no-file-insertion``.
+
+.. _include: ../ref/rst/directives.html#include
+.. _raw: ../ref/rst/directives.html#raw
+
+pep_references
+~~~~~~~~~~~~~~
+
+Recognize and link to standalone PEP references (like "PEP 258").
+
+Default: disabled (None); enabled (True) in PEP Reader.
+Options: ``--pep-references``.
+
+pep_base_url
+~~~~~~~~~~~~
+Base URL for PEP references.
+
+Default: "http://www.python.org/peps/".
+Option: ``--pep-base-url``.
+
+pep_file_url_template
+~~~~~~~~~~~~~~~~~~~~~
+
+Template for PEP file part of URL, interpolated with the PEP
+number and appended to pep_base_url_.
+
+Default: "pep-%04d". Option: ``--pep-file-url``.
+
+raw_enabled
+~~~~~~~~~~~
+
+Enable or disable the "raw_" directive. A "warning" system message
+(including the directive text) is inserted instead. (See also
+file_insertion_enabled_ for another security-relevant setting.)
+
+Default: enabled (True). Options: ``--raw-enabled, --no-raw``.
+
+rfc_references
+~~~~~~~~~~~~~~
+
+Recognize and link to standalone RFC references (like "RFC 822").
+
+Default: disabled (None); enabled (True) in PEP Reader.
+Options: ``--rfc-references``.
+
+rfc_base_url
+~~~~~~~~~~~~
+
+Base URL for RFC references.
+
+Default: "http://www.faqs.org/rfcs/". Option: ``--rfc-base-url``.
+
+smart_quotes
+~~~~~~~~~~~~
+
+Activate the experimental SmartQuotes_ transform to
+change straight quotation marks to typographic form. `Quote characters`_
+are selected according to the language of the current block element (see
+language_code_, smartquotes_locales_, and the `pre-defined quote sets`__).
+
+Also changes consecutive runs of hyphen-minus and full stops (``---``,
+``--``, ``...``) to em-dash, en-dash and ellipsis Unicode characters
+respectively.
+
+Supported values:
+
+booleans_ (yes/no)
+ Use smart quotes?
+
+alt (or "alternative")
+ Use alternative quote set (if defined for the language).
+
+Default: "no". Option: ``--smart-quotes``.
+
+New in Docutils 0.10.
+
+.. _SmartQuotes: smartquotes.html
+__ smartquotes.html#localization
+.. _quote characters:
+ http://en.wikipedia.org/wiki/Non-English_usage_of_quotation_marks
+
+
+smartquotes_locales
+~~~~~~~~~~~~~~~~~~~
+
+Typographical quotes used by the SmartQuotes_ transform.
+
+A comma-separated list_ with language tag and a set of four quotes (primary
+open/close, secondary open/close)smartquotes_locales. (If more than one
+character shall be used for a quote (e.g. padding in French quotes), a
+colon-separated list may be used.)
+
+Example:
+ Ensure a correct leading apostrophe in ``'s Gravenhage`` in Dutch (at the
+ cost of incorrect opening single quotes) and set French quotes to double
+ and single guillemets with inner padding::
+
+ smartquote-locales: nl: „”’’,
+ fr: « : »:‹ : ›
+
+Default: None. Option: ``--smartquotes-locales``.
+
+New in Docutils 0.14.
+
+syntax_highlight
+~~~~~~~~~~~~~~~~
+
+Token type names used by Pygments_ when parsing contents of the code_
+directive and role.
+
+Supported values:
+
+long
+ Use hierarchy of long token type names.
+short
+ Use short token type names. (For use with
+ `Pygments-generated stylesheets`_.)
+none
+ No code parsing. Use this to avoid the "Pygments not
+ found" warning when Pygments is not installed.
+
+Default: "long". Option: ``--syntax-highlight``.
+
+New in Docutils 0.9.
+
+.. _Pygments: http://pygments.org/
+.. _code: ../ref/rst/directives.html#code
+.. _Pygments-generated stylesheets:
+ http://pygments.org/docs/cmdline/#generating-styles
+
+tab_width
+~~~~~~~~~
+
+Number of spaces for hard tab expansion.
+
+Default: 8. Options: ``--tab-width``.
+
+trim_footnote_reference_space
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Remove spaces before `footnote references`_.
+
+Default: don't (None); may be overriden by a writer-specific
+footnote_references__ default though.
+
+Options: ``--trim-footnote-reference-space, --leave-footnote-reference-space``.
+
+__ `footnote_references [latex writers]`_
+
+
+[readers]
+=========
+
+
+[standalone reader]
+-------------------
+
+docinfo_xform
+~~~~~~~~~~~~~
+
+Enable or disable the `bibliographic field list`_ transform
+(docutils.transforms.frontmatter.DocInfo).
+
+Default: enabled (True). Options: ``--no-doc-info``.
+
+doctitle_xform
+~~~~~~~~~~~~~~
+
+Enable or disable the promotion of a lone top-level section title
+to `document title`_ (and subsequent section title to document
+subtitle promotion; docutils.transforms.frontmatter.DocTitle).
+
+Default: enabled (True). Options: ``--no-doc-title``.
+
+sectsubtitle_xform
+~~~~~~~~~~~~~~~~~~
+
+Enable or disable the promotion of the title of a lone subsection
+to a subtitle (docutils.transforms.frontmatter.SectSubTitle).
+
+Default: disabled (0). Options: ``--section-subtitles,
+--no-section-subtitles``.
+
+
+[pep reader]
+------------
+
+The `pep_references`_ and `rfc_references`_ settings
+(`[restructuredtext parser]`_) are set on by default.
+
+
+.. [python reader]
+ ---------------
+
+ Not implemented.
+
+
+[writers]
+=========
+
+[docutils_xml writer]
+---------------------
+
+.. Caution::
+
+ * In Python versions older than 2.7.3 and 3.2.3, the newlines_ and
+ indents_ options may adversely affect whitespace; use them only for
+ reading convenience (see http://bugs.python.org/issue4147).
+
+ * The XML declaration carries text encoding information. If the encoding
+ is not UTF-8 or ASCII and the XML declaration is missing, standard
+ tools may be unable to read the generated XML.
+
+doctype_declaration
+~~~~~~~~~~~~~~~~~~~
+
+Generate XML with a DOCTYPE declaration.
+
+Default: do (1). Options: ``--no-doctype``.
+
+indents
+~~~~~~~
+
+Generate XML with indents and newlines.
+
+Default: don't (None). Options: ``--indents``.
+
+newlines
+~~~~~~~~
+
+Generate XML with newlines before and after tags.
+
+Default: don't (None). Options: ``--newlines``.
+
+.. _xml_declaration [docutils_xml writer]:
+
+xml_declaration
+~~~~~~~~~~~~~~~
+
+Generate XML with an XML declaration. Also defined for the
+`HTML Writers`__.
+
+Default: do (1). Options: ``--no-xml-declaration``.
+
+__ `xml_declaration [html writers]`_
+
+
+[html writers]
+--------------
+
+.. _attribution [html writers]:
+
+attribution
+~~~~~~~~~~~
+
+Format for `block quote`_ attributions: one of "dash" (em-dash
+prefix), "parentheses"/"parens", or "none". Also defined for the
+`LaTeX Writers`__.
+
+Default: "dash". Options: ``--attribution``.
+
+__ attribution [latex writers]_
+
+cloak_email_addresses
+~~~~~~~~~~~~~~~~~~~~~
+
+Scramble email addresses to confuse harvesters. In the reference
+URI, the "@" will be replaced by %-escapes (as of RFC 1738). In
+the visible text (link text) of an email reference, the "@" and
+all periods (".") will be surrounded by ``<span>`` tags.
+Furthermore, HTML entities are used to encode these characters in
+order to further complicate decoding the email address. For
+example, "abc@example.org" will be output as::
+
+ <a class="reference" href="mailto:abc%40example.org">
+ abc<span>@</span>example<span>.</span>org</a>
+
+.. Note:: While cloaking email addresses will have little to no
+ impact on the rendering and usability of email links in most
+ browsers, some browsers (e.g. the ``links`` browser) may decode
+ cloaked email addresses incorrectly.
+
+Default: don't cloak (None). Option: ``--cloak-email-addresses``.
+
+compact_lists
+~~~~~~~~~~~~~
+
+Remove extra vertical whitespace between items of bullet lists and
+enumerated lists, when list items are all "simple" (i.e., items
+each contain one paragraph and/or one "simple" sublist only). The
+behaviour can be specified directly via "class" attributes (values
+"compact" and "open") in the document.
+
+Default: enabled (True).
+Options: ``--compact-lists, --no-compact-lists``.
+
+compact_field_lists
+~~~~~~~~~~~~~~~~~~~
+
+Remove extra vertical whitespace between items of `field lists`_ that
+are "simple" (i.e., all field bodies each contain at most one
+paragraph). The behaviour can be specified directly via "class"
+attributes (values "compact" and "open") in the document.
+
+Default: enabled (True).
+Options: ``--compact-field-lists, --no-compact-field-lists``.
+
+
+.. _embed_stylesheet [html writers]:
+
+embed_stylesheet
+~~~~~~~~~~~~~~~~
+
+Embed the stylesheet in the output HTML file. The stylesheet file
+must specified by the stylesheet_path__ setting and must be
+accessible during processing.
+Also defined for the `LaTeX Writers <embed_stylesheet [latex writers]_>`__.
+
+Default: enabled. Options: ``--embed-stylesheet,
+--link-stylesheet``.
+
+__ `stylesheet_path [html writers]`_
+
+
+.. _footnote_references [html writers]:
+
+footnote_references
+~~~~~~~~~~~~~~~~~~~
+
+Format for `footnote references`_, one of "superscript" or "brackets".
+Also defined for the `LaTeX Writers <footnote_references [latex writers]_>`__.
+
+Overrides [#override]_ trim_footnote_reference_space_, if
+applicable. [#footnote_space]_
+
+Default: "brackets". Option: ``--footnote-references``.
+
+initial_header_level
+~~~~~~~~~~~~~~~~~~~~
+
+The initial level for header elements. This does not affect the
+document title & subtitle; see doctitle_xform_.
+
+Default: 1 (for "<h1>"). Option: ``--initial-header-level``.
+
+
+math_output
+~~~~~~~~~~~
+
+The format of mathematical content (`math directive`_ and role) in
+the output document. Supported values are (case insensitive):
+
+:HTML:
+ Format math in standard HTML enhanced by CSS rules.
+ Requires the ``math.css`` stylesheet (in the system
+ `stylesheet directory <stylesheet_dirs [html writers]_>`_)
+
+ A `stylesheet_path <stylesheet_path [html writers]_>`_
+ can be appended after whitespace, the specified
+ stylesheet(s) will only be referenced or embedded, if required
+ (i.e. if there is mathematical content in the document).
+
+:MathJax:
+ Format math for display with MathJax_, a JavaScript-based math rendering
+ engine.
+
+ Pro:
+ Works across multiple browsers and platforms.
+
+ Large set of `supported LaTeX math commands and constructs`__
+
+ __ http://docs.mathjax.org/en/latest/tex.html#supported-latex-commands
+
+ Con:
+ Rendering requires JavaScript and an Internet connection or local
+ MathJax installation.
+
+ A URL pointing to a MathJax library should be appended after whitespace.
+ A warning is given if this is missing.
+
+ * It is recommended to install__ the MathJax library on the same
+ server as the rest of the deployed site files.
+
+ __ http://docs.mathjax.org/en/latest/installation.html
+
+ Example: Install the library at the top level of the web
+ server’s hierarchy in the directory ``MathJax`` and set::
+
+ math-output: mathjax /MathJax/MathJax.js
+
+ * The easiest way to use MathJax is to link directly to a public
+ installation. In that case, there is no need to install MathJax locally.
+
+ Downside: Downloads JavaScript code from a third-party site --- opens
+ the door to cross-site scripting attacs!
+
+ Example: MathJax.org recommends ``cdnjs.cloudflare.com``::
+
+ math-output: mathjax
+ https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.1/MathJax.js
+
+ See https://cdnjs.com/about and https://www.cloudflare.com/terms/ for
+ details and terms of use.
+
+ * Use a local MathJax installation on the *client* machine, e.g.::
+
+ math-output: MathJax file:/usr/share/javascript/mathjax/MathJax.js
+
+ This is the fallback if no URL is specified.
+
+:MathML:
+ Embed math content as presentational MathML_.
+
+ Pro:
+ The W3C recommendation for math on the web.
+
+ Self-contained documents (no JavaScript, no external downloads).
+
+ Con:
+ Docutil's latex2mathml converter supports only a small
+ subset of LaTeX syntax.
+
+ With the "html4css1" writer, the resulting HTML document does
+ not validate, as there is no DTD for `MathML + XHTML Transitional`.
+ However, MathML-enabled browsers will render it fine.
+
+ An external converter can be appended after whitespace, e.g.,
+ ``--math-output="MathML latexml"``:
+
+ blahtexml_
+ Fast conversion, support for many symbols and environments, but no
+ "align" (or other equation-aligning) environment. (C++)
+
+ LaTeXML_
+ Comprehensive macro support but very slow. (Perl)
+
+ TtM_
+ No "matrix", "align" and "cases" environments. Support may be removed.
+
+:LaTeX:
+ Include literal LaTeX code.
+
+ The failsave fallback.
+
+Default: writer dependent (see `[html4css1 writer]`_, `[html5 writer]`_).
+Option: ``--math-output``.
+
+New in Docutils 0.8.
+
+.. _math directive: ../ref/rst/directives.html#math
+.. _MathJax: http://www.mathjax.org/
+.. _MathPlayer: http://www.dessci.com/en/products/mathplayer/
+.. _MathML: http://www.w3.org/TR/MathML/
+.. _blahtexml: http://gva.noekeon.org/blahtexml/
+.. _LaTeXML: http://dlmf.nist.gov/LaTeXML/
+.. _TtM: http://hutchinson.belmont.ma.us/tth/mml/
+
+
+.. _stylesheet [html writers]:
+
+stylesheet
+~~~~~~~~~~
+
+A comma-separated list of CSS stylesheet URLs, used verbatim.
+Also defined for the `LaTeX Writer <stylesheet [latex writers]_>`__.
+
+Overrides also stylesheet-path__. [#override]_
+
+Default: None. Options: ``--stylesheet``.
+
+__ `stylesheet_path [html writers]`_
+
+
+.. _stylesheet_dirs [html writers]:
+
+stylesheet_dirs
+~~~~~~~~~~~~~~~
+
+A comma-separated list of directories where stylesheets can be found.
+Used by the stylesheet_path__ setting when expanding relative path arguments.
+
+Note: This setting defines a "search path" (similar to the PATH variable for
+executables). However, the term "path" is already used in the
+stylesheet_path__ setting with the meaning of a file location.
+
+__
+__ `stylesheet_path [html writers]`_
+
+Default: the working directory of the process at launch and the directory
+with default stylesheet files (writer and installation specific).
+Use the ``--help`` option to get the exact value.
+Option: ``--stylesheet-directories``.
+
+.. _stylesheet_path [html writers]:
+
+stylesheet_path
+~~~~~~~~~~~~~~~
+
+A comma-separated list of paths to CSS stylesheets. Relative paths are
+expanded if a matching file is found in the stylesheet_dirs__.
+If embed_stylesheet__ is False, paths are rewritten relative to the
+output HTML file. Also defined for the `LaTeX Writer`__.
+
+Also overrides "stylesheet". [#override]_
+Pass an empty string (to either "stylesheet" or "stylesheet_path") to
+deactivate stylesheet inclusion.
+
+Default: writer dependent (see `[html4css1 writer]`_, `[html5 writer]`_,
+[pep_html writer]_).
+Options: ``--stylesheet-path``.
+
+__ `embed_stylesheet [html writers]`_
+__ `stylesheet_path [latex writers]`_
+__ `stylesheet_dirs [html writers]`_
+
+
+.. _table_style [html writers]:
+
+table_style
+~~~~~~~~~~~
+
+Class value(s) added to all tables_.
+Also defined for the `LaTeX Writer`__.
+
+The default CSS sylesheet defines:
+
+borderless
+ No borders around the table.
+
+booktabs
+ Lines above and below the table and a thin line after the head.
+
+align-left, align-center, align-right
+ Align the tables
+
+colwidths-auto
+ Delegate the determination of table column widths to the backend
+ (Leave out the ``<colgroup>`` column specification.)
+
+ Cf. the `table directive`_.
+
+Default: "". Option: ``--table-style``.
+
+__ `table_style [latex writers]`_
+.. _table directive: ../ref/rst/directives.html#table
+
+
+.. _template [html writers]:
+
+template
+~~~~~~~~
+
+Path to template file, which must be encoded in UTF-8. [#pwd]_
+Also defined for the `LaTeX Writer`__.
+
+Default: "template.txt" in the docutils/writers/html4css1/
+directory (installed automatically; for the exact machine-specific
+path, use the ``--help`` option). Options: ``--template``.
+
+__ `template [latex writers]`_
+
+
+.. _xml_declaration [html writers]:
+
+xml_declaration
+~~~~~~~~~~~~~~~
+
+Generate XML with an XML declaration. Also defined for the
+`Docutils XML Writer`__.
+
+.. Caution:: The XML declaration carries text encoding information. If the
+ encoding is not UTF-8 or ASCII and the XML declaration is missing,
+ standard tools may be unable to read the generated XHTML.
+
+Default: do (1). Options: ``--no-xml-declaration``.
+
+__ `xml_declaration [docutils_xml writer]`_
+
+
+[html4css1 writer]
+~~~~~~~~~~~~~~~~~~
+
+The `HTML4/CSS1 Writer`_ generates output that conforms to the
+`XHTML 1 Transitional`_ specification.
+It shares all settings defined in the `[html writers]`_
+`configuration section`_.
+
+
+Writer specific defaults:
+
+math_output_
+ "MathML"
+
+`stylesheet_path <stylesheet_path [html writers]_>`_:
+ "html4css1.css"
+
+.. _HTML4/CSS1 Writer: html.html#html4css1
+.. _XHTML 1 Transitional: http://www.w3.org/TR/xhtml1/
+
+
+field_name_limit
+""""""""""""""""
+
+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. 0 indicates "no limit". See also option_limit_.
+
+Default: 14 (i.e. 14 characters). Option: ``--field-name-limit``.
+
+
+option_limit
+""""""""""""
+
+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. 0 indicates "no limit". See also
+field_name_limit_.
+
+Default: 14 (i.e. 14 characters). Option: ``--option-limit``.
+
+
+[html5 writer]
+~~~~~~~~~~~~~~
+
+The `HTML5 Writer`_ generates valid XML that is compatible with `HTML5`_.
+It shares all settings defined in the `[html writers]`_
+`configuration section`_.
+
+Writer specific defaults:
+
+`math_output`_
+ "MathML"
+
+`stylesheet_path <stylesheet_path [html writers]_>`_:
+ "minimal.css,plain.css"
+
+New in Docutils 0.13.
+
+.. _HTML5 Writer: html.html#html5-polyglot
+.. _HTML5: http://www.w3.org/TR/html5/
+
+
+[pep_html writer]
+~~~~~~~~~~~~~~~~~
+
+The PEP/HTML Writer derives from the HTML4/CSS1 Writer, and shares
+all settings defined in the `[html writers]`_ and `[html4css1 writer]`_
+`configuration sections`_.
+
+Writer specific defaults:
+
+`stylesheet_path <stylesheet_path [html writers]_>`__:
+ "pep.css"
+
+`template <template [html writers]_>`__:
+ ``docutils/writers/pep_html/template.txt`` in the installation
+ directory. For the exact machine-specific path, use the ``--help``
+ option.
+
+no_random
+"""""""""
+Do not use a random banner image. Mainly used to get predictable
+results when testing.
+
+Default: random enabled (None). Options: ``--no-random`` (hidden).
+
+pep_home
+""""""""
+
+Home URL prefix for PEPs.
+
+Default: current directory ("."). Options: ``--pep-home``.
+
+python_home
+"""""""""""
+Python's home URL.
+
+Default: parent directory (".."). Options: ``--python-home``.
+
+
+[s5_html writer]
+~~~~~~~~~~~~~~~~
+
+The S5/HTML Writer derives from the HTML4/CSS1 Writer, and shares
+all settings defined in the `[html writers]`_ and `[html4css1 writer]`_
+`configuration sections`_.
+
+Writer specific defaults:
+
+compact_lists_:
+ disable compact lists.
+
+template__:
+ ``docutils/writers/s5_html/template.txt`` in the installation
+ directory. For the exact machine-specific path, use the ``--help``
+ option.
+
+__ `template [html writers]`_
+
+
+hidden_controls
+"""""""""""""""
+
+Auto-hide the presentation controls in slideshow mode, or or keep
+them visible at all times.
+
+Default: auto-hide (1). Options: ``--hidden-controls``,
+``--visible-controls``.
+
+current_slide
+"""""""""""""
+
+Enable or disable the current slide indicator ("1/15").
+
+Default: disabled (None). Options: ``--current-slide``,
+``--no-current-slide``.
+
+overwrite_theme_files
+"""""""""""""""""""""
+
+Allow or prevent the overwriting of existing theme files in the
+``ui/<theme>`` directory. This has no effect if "theme_url_" is
+used.
+
+Default: keep existing theme files (None). Options:
+``--keep-theme-files``, ``--overwrite-theme-files``.
+
+theme
+"""""
+
+Name of an installed S5 theme, to be copied into a ``ui/<theme>``
+subdirectory, beside the destination file (output HTML). Note
+that existing theme files will not be overwritten; the existing
+theme directory must be deleted manually.
+Also overrides the "theme_url_" setting. [#override]_
+
+Default: "default". Option: ``--theme``.
+
+theme_url
+"""""""""
+
+The URL of an S5 theme directory. The destination file (output
+HTML) will link to this theme; nothing will be copied. Also overrides
+the "theme_" setting. [#override]_
+
+Default: None. Option: ``--theme-url``.
+
+view_mode
+"""""""""
+
+The initial view mode, either "slideshow" or "outline".
+
+Default: "slidewhow". Option: ``--view-mode``.
+
+.. ------------------------------------------------------------
+
+[latex writers]
+----------------
+
+Common settings for the `LaTeX writers`_
+`[latex2e writer]`_ and `[xetex writer]`_.
+
+.. _LaTeX writers: latex.html
+
+use_latex_toc
+~~~~~~~~~~~~~
+
+To get pagenumbers in the `table of contents`_, it
+must be generated by LaTeX. Usually latex must be run twice to get
+numbers correct.
+
+Default: on. Options: ``--use-latex-toc, --use-docutils-toc``.
+
+use_latex_docinfo
+~~~~~~~~~~~~~~~~~
+
+Attach author and date to the `document title`_
+instead of the `bibliographic fields`_.
+
+Default: off. Options: ``--use-latex-docinfo, --use-docutils-docinfo``.
+
+docutils_footnotes
+~~~~~~~~~~~~~~~~~~
+Use the Docutils-specific macros ``\DUfootnote`` and
+``\DUfootnotetext`` for footnotes_.
+
+Default: on. Option: ``--docutils-footnotes``.
+
+use_latex_citations
+~~~~~~~~~~~~~~~~~~~
+
+Use \cite for citations_ instead of a simulation with figure-floats.
+
+Default: off. Options: ``--use-latex-citations, --figure-citations``.
+
+use_latex_abstract
+~~~~~~~~~~~~~~~~~~
+
+Use LaTeX abstract environment for the document's abstract_.
+
+Default: off. Options: ``--use-latex-abstract, --topic-abstract``.
+
+hyperlink_color
+~~~~~~~~~~~~~~~
+
+Color of any hyperlinks embedded in text.
+
+* "0" or "false" disable coloring of links. (Links will be marked
+ by red boxes that are not printed),
+* "black" results in “invisible“ links,
+
+Set hyperref_options_ to "draft" to completely disable hyperlinking.
+
+Default: "blue". Option: ``--hyperlink-color``.
+
+hyperref_options
+~~~~~~~~~~~~~~~~
+
+Options for the `hyperref TeX package`_. If hyperlink_color_ is
+not "false", the expansion of ::
+
+ 'colorlinks=true,linkcolor=%s,urlcolor=%s' % (
+ hyperlink_color, self.hyperlink_color
+
+is prepended.
+
+Default: "". Option: ``--hyperref-options``.
+
+.. _hyperref TeX package: http://tug.org/applications/hyperref/
+
+documentclass
+~~~~~~~~~~~~~
+
+Specify LaTeX documentclass.
+
+Default: "article". Option: ``--documentclass``.
+
+documentoptions
+~~~~~~~~~~~~~~~
+
+Specify document options. Multiple options can be given, separated by
+commas.
+
+Default: "a4paper". Option: ``--documentoptions``.
+
+
+.. _embed_stylesheet [latex writers]:
+
+embed_stylesheet
+~~~~~~~~~~~~~~~~
+
+Embed the stylesheet(s) in the header of the output file. The
+stylesheets must be accessible during processing. Currently, this
+fails if the file is not available via the given path (i.e. the
+file is *not* searched in the `TeX input path`_).
+Also defined for the `HTML Writers`__ (with default *on*).
+
+Default: off. Options: ``--embed-stylesheet, --link-stylesheet``.
+
+__ `embed_stylesheet [html writers]`_
+
+.. _stylesheet [latex writers]:
+
+stylesheet
+~~~~~~~~~~
+
+A comma-separated list_ of style files.
+Also defined for the `HTML Writers`__.
+
+Overrides also stylesheet_path__. [#override]_
+
+If `embed_stylesheet`__ is False (default), the stylesheet files are
+referenced with ``\usepackage`` (extension ``.sty`` or no extension) or
+``\input`` (any other extension).
+
+LaTeX will search the specified files in the `TeX input path`_.
+
+Default: no stylesheet (""). Option: ``--stylesheet``.
+
+__ `stylesheet_path [latex writers]`_
+__ `embed_stylesheet [latex writers]`_
+__ `stylesheet [html writers]`_
+.. _TeX input path:
+ http://www.tex.ac.uk/cgi-bin/texfaq2html?label=what-TDS
+
+
+.. _stylesheet_dirs [latex writers]:
+
+stylesheet_dirs
+~~~~~~~~~~~~~~~
+
+A comma-separated list of directories where stylesheets can be found.
+Used by the stylesheet_path__ setting.
+
+Note: This setting defines a "search path" (similar to the PATH variable for
+executables). However, the term "path" is already used in the
+stylesheet_path__ setting with the meaning of a file location.
+
+__
+__ `stylesheet_path [latex writers]`_
+
+Default: the working directory of the process at launch and the directory
+with default stylesheet files (writer and installation specific).
+Use the ``--help`` option to get the exact value.
+Option: ``--stylesheet-directories``.
+
+.. _stylesheet_path [latex writers]:
+
+stylesheet_path
+~~~~~~~~~~~~~~~
+
+A comma-separated list of style files. Relative paths are expanded if a
+matching file is found in the stylesheet_dirs__.
+If embed_stylesheet__ is False, paths are rewritten relative to the
+output file path. Run ``latex`` from the directory containing
+the output file.
+
+The stylesheet__ option is preferred for files in the `TeX input path`_.
+
+Also defined for the
+`HTML Writers <stylesheet_path [html writers]_>`__.
+
+Also overrides stylesheet__. [#override]_
+
+Default: no stylesheet (""). Option: ``--stylesheet-path``.
+
+__ `stylesheet_dirs [latex writers]`_
+__ `embed_stylesheet [latex writers]`_
+__
+__ `stylesheet [latex writers]`_
+
+
+latex_preamble
+~~~~~~~~~~~~~~
+
+LaTeX code that will be inserted in the document preamble.
+Can be used to load packages with options or (re-) define LaTeX
+macros without writing a custom style file (new in Docutils 0.7).
+
+Default: writer dependent (see `[latex2e writer]`_, `[xetex writer]`_).
+Option: ``--latex-preamble``.
+
+.. _footnote_references [latex writers]:
+
+footnote_references
+~~~~~~~~~~~~~~~~~~~
+
+Format for `footnote references`_: one of "superscript" or
+"brackets". Also defined for the `HTML Writers`__.
+
+Overrides [#override]_ trim_footnote_reference_space_, if
+applicable [#footnote_space]_.
+
+Default: "superscript". Option: ``--footnote-references``.
+
+__ `footnote_references [html writers]`_
+
+.. _attribution [latex writers]:
+
+attribution
+~~~~~~~~~~~
+
+See `attribution [html writers]`_.
+
+compound_enumerators
+~~~~~~~~~~~~~~~~~~~~
+
+Enable or disable compound enumerators for nested `enumerated lists`_
+(e.g. "1.2.a.ii").
+
+Default: disabled (None).
+Options: ``--compound-enumerators``, ``--no-compound-enumerators``.
+
+literal_block_env
+~~~~~~~~~~~~~~~~~
+
+When possible\ [#]_, use the specified environment for `literal blocks`_.
+
+Default: "" (quoting of whitespace and special chars).
+Option: ``--literal-block-env``.
+
+.. [#] A literal-block element, when processed by a Docutils writer might
+ have it's origin in literal block following "::" or a
+ ``.. parsed-literal::`` directive.
+
+ A LaTeX verbatim environment is only usable if there is no other
+ markup contained in the literal-block.
+
+
+section_prefix_for_enumerators
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Enable or disable section ("." subsection ...) prefixes for
+compound enumerators. This has no effect unless
+`compound_enumerators`_ are enabled.
+
+Default: disabled (None).
+Options: ``--section-prefix-for-enumerators``,
+``--no-section-prefix-for-enumerators``.
+
+section_enumerator_separator
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The separator between section number prefix and enumerator for
+compound enumerated lists (see `compound_enumerators`_).
+
+Generally it isn't recommended to use both sub-sections and nested
+enumerated lists with compound enumerators. This setting avoids
+ambiguity in the situation where a section "1" has a list item
+enumerated "1.1", and subsection "1.1" has list item "1". With a
+separator of ".", these both would translate into a final compound
+enumerator of "1.1.1". With a separator of "-", we get the
+unambiguous "1-1.1" and "1.1-1".
+
+Default: "-". Option: ``--section-enumerator-separator``.
+
+.. _table_style [latex writers]:
+
+table_style
+~~~~~~~~~~~
+
+Specify the default style for tables_
+Also defined for the `HTML Writers`__.
+
+Supported values:
+
+standard
+ Borders around all cells.
+booktabs
+ A line above and below the table and one after the head.
+borderless
+ No borders.
+
+align-left, align-center, align-right
+ Align tables.
+
+colwidths-auto, colwidths-given
+ Default value for column width determination by
+ LaTeX or Docutils.
+ Override with the `table directive`_'s :widths: option.
+
+ .. warning::
+
+ ``colwidths-auto`` is only suited for tables with simple cell content.
+
+ LaTeX puts the content of auto-sized columns on one line (merging
+ paragraphs) and may fail with complex content.
+
+Default: "standard". Option: ``--table-style``.
+
+__ `table_style [html writers]`_
+
+
+.. _template [latex writers]:
+
+template
+~~~~~~~~
+
+Path [#pwd]_ to template file, which must be encoded in UTF-8.
+Also defined for the `HTML Writers`__.
+
+Default: writer dependent (see `[latex2e writer]`_, `[xetex writer]`_).
+Options: ``--template``.
+
+__ `template [html writers]`_
+
+
+[latex2e writer]
+~~~~~~~~~~~~~~~~
+
+The `LaTeX2e writer`_ generates a LaTeX source for compilation with 8-bit
+LaTeX (pdfTeX_). It shares all settings defined in the `[latex writers]`_
+`configuration section`_.
+
+.. _LaTeX2e writer: latex.html#latex2e-writer
+.. _pdfTeX: https://www.tug.org/applications/pdftex/
+.. _configuration section: `Configuration File Sections & Entries`_
+
+
+Writer Specific Defaults
+""""""""""""""""""""""""
+
+latex_preamble_
+ Load the "PDF standard fonts" (Times, Helvetica, Courier)::
+
+ \usepackage{mathptmx} % Times
+ \usepackage[scaled=.90]{helvet}
+ \usepackage{courier}
+
+template__
+ "default.tex" in the ``docutils/writers/latex2e/`` directory
+ (installed automatically).
+
+ __ `template [latex writers]`_
+
+
+font_encoding
+"""""""""""""
+
+Specify `LaTeX font encoding`_. Multiple options can be given, separated by
+commas. The last value becomes the document default.
+Possible values are "", "T1", "OT1", "LGR,T1" or any other combination of
+`LaTeX font encodings`_.
+
+Default: "T1". Option: ``--font-encoding``.
+
+.. _LaTeX font encoding: latex.html#font-encoding
+.. _LaTeX font encodings:
+ http://mirror.ctan.org/macros/latex/doc/encguide.pdf
+
+
+[xetex writer]
+~~~~~~~~~~~~~~
+
+The `XeTeX writer`_ generates a LaTeX source for compilation with `XeTeX or
+LuaTeX`_. It derives from the latex2e writer, and shares all settings
+defined in the `[latex writers]`_ and `[latex2e writer]`_ `configuration
+sections`_.
+
+.. _XeTeX writer: latex.html#xetex-writer
+.. _XeTeX or LuaTeX: https://texfaq.org/FAQ-xetex-luatex
+.. _configuration sections: `Configuration File Sections & Entries`_
+
+Writer Specific Defaults
+""""""""""""""""""""""""
+
+latex_preamble_:
+ Font setup for `Linux Libertine`_,::
+
+ % Linux Libertine (free, wide coverage, not only for Linux)
+ \setmainfont{Linux Libertine O}
+ \setsansfont{Linux Biolinum O}
+ \setmonofont[HyphenChar=None]{DejaVu Sans Mono}
+
+ The optional argument ``HyphenChar=None`` to the monospace font
+ prevents word hyphenation in literal text.
+
+.. _Linux Libertine: http://www.linuxlibertine.org/
+
+template__:
+ "xelatex.tex" in the ``docutils/writers/latex2e/`` directory
+ (installed automatically).
+
+ .. TODO: show full path with --help (like in the HTML writers) and
+ add the following line:
+ for the exact machine-specific path, use the ``--help`` option).
+
+ __ `template [latex writers]`_
+
+
+[odf_odt writer]
+----------------
+
+The following command line options are specific to ``odtwriter``:
+
+stylesheet
+~~~~~~~~~~
+
+Specify a stylesheet URL, used verbatim.
+
+Default: writers/odf_odt/styles.odt in the installation directory.
+
+odf-config-file
+~~~~~~~~~~~~~~~
+
+Specify a configuration/mapping file relative to the current working
+directory for additional ODF options. In particular, this file may
+contain a section named "Formats" that maps default style names to names
+to be used in the resulting output file allowing for adhering to external
+standards. For more info and the format of the configuration/mapping
+file, see the `Odt Writer for Docutils`_ document.
+
+cloak-email-addresses
+~~~~~~~~~~~~~~~~~~~~~
+
+Obfuscate email addresses to confuse harvesters while still
+keeping email links usable with standards-compliant browsers.
+
+no-cloak-email-addresses
+~~~~~~~~~~~~~~~~~~~~~~~~
+Do not obfuscate email addresses.
+
+table-border-thickness
+~~~~~~~~~~~~~~~~~~~~~~
+
+Specify the thickness of table borders in thousands of a cm.
+Default is 35.
+
+add-syntax-highlighting
+~~~~~~~~~~~~~~~~~~~~~~~
+
+Add syntax highlighting in literal code blocks.
+
+no-syntax-highlighting
+~~~~~~~~~~~~~~~~~~~~~~
+
+Do not add syntax highlighting in literal code blocks.
+(default)
+
+create-sections
+~~~~~~~~~~~~~~~
+
+Create sections for headers. (default)
+
+no-sections
+~~~~~~~~~~~
+
+Do not create sections for headers.
+
+create-links
+~~~~~~~~~~~~
+Create links.
+
+no-links
+~~~~~~~~
+
+Do not create links. (default)
+
+endnotes-end-doc
+~~~~~~~~~~~~~~~~
+
+Generate endnotes at end of document, not footnotes at bottom of page.
+
+no-endnotes-end-doc
+~~~~~~~~~~~~~~~~~~~
+
+Generate footnotes at bottom of page, not endnotes at end of
+document. (default)
+
+generate-list-toc
+~~~~~~~~~~~~~~~~~
+
+Generate a bullet list table of contents, not an
+ODF/``oowriter`` table of contents.
+
+generate-oowriter-toc
+~~~~~~~~~~~~~~~~~~~~~
+
+Generate an ODF/``oowriter`` table of contents, not a bullet
+list. (default) **Note:** ``odtwriter`` is not able to
+determine page numbers, so you will need to open the generated
+document in ``oowriter``, then right-click on the table of
+contents and select "Update" to insert page numbers.
+
+custom-odt-header
+~~~~~~~~~~~~~~~~~
+
+Specify the contents of a custom header line. For details about
+custom headers and about special field character sequences, see
+section "Custom header/footers: inserting page numbers, date,
+time, etc" in the `Odt Writer for Docutils`_ document for
+details.
+
+custom-odt-footer
+~~~~~~~~~~~~~~~~~
+
+Specify the contents of a custom footer line. For details about
+custom footers and about special field character sequences, see
+section "Custom header/footers: inserting page numbers, date,
+time, etc" in the `Odt Writer for Docutils`_ document for
+details.
+
+.. _Odt Writer for Docutils: odt.html
+
+
+[pseudoxml writer]
+------------------
+
+This writer does not define specific settings.
+
+
+[applications]
+==============
+
+[buildhtml application]
+-----------------------
+
+ignore
+~~~~~~
+
+List_ of wildcard (shell globing) patterns, specifying files to silently
+ignore. To specify multiple patterns, use colon-separated patterns (in
+configuration files or on the command line); on the command line, the
+option may also be used more than once.
+
+Default: none. Options: ``--ignore``.
+
+prune
+~~~~~
+
+List_ of directories not to process. To specify multiple
+directories, use colon-separated paths (in configuration files or
+on the command line); on the command line, the option may also be
+used more than once.
+
+Default: ['.hg', '.bzr', '.git', '.svn', 'CVS']. Options:
+``--prune``.
+
+recurse
+~~~~~~~
+
+Recursively scan subdirectories, or ignore subdirectories.
+
+Default: recurse (1). Options: ``--recurse, --local``.
+
+silent
+~~~~~~
+
+Work silently (no progress messages). Independent of
+"report_level".
+
+Default: show progress (None). Options: ``--silent``.
+
+
+[docfactory application]
+------------------------
+
+(To be completed.)
+
+
+Other Settings
+==============
+
+Command-Line Only
+-----------------
+
+These settings are only effective as command-line options; setting
+them in configuration files has no effect.
+
+config
+~~~~~~
+
+Path to a configuration file to read (if it exists). [#pwd]_
+Settings may override defaults and earlier settings. The config
+file is processed immediately. Multiple ``--config`` options may
+be specified; each will be processed in turn.
+
+Filesystem path settings contained within the config file will be
+interpreted relative to the config file's location (*not* relative
+to the current working directory).
+
+Default: None. Options: ``--config``.
+
+
+Internal Settings
+-----------------
+
+These settings are for internal use only; setting them in
+configuration files has no effect, and there are no corresponding
+command-line options.
+
+_config_files
+~~~~~~~~~~~~~
+
+List of paths of applied configuration files.
+
+Default: None. No command-line options.
+
+_directories
+~~~~~~~~~~~~
+
+(``buildhtml.py`` front end.) List of paths to source
+directories, set from positional arguments.
+
+Default: current working directory (None). No command-line
+options.
+
+_disable_config
+~~~~~~~~~~~~~~~
+
+Prevent standard configuration files from being read. For
+programmatic use only.
+
+Default: config files enabled (None). No command-line options.
+
+_destination
+~~~~~~~~~~~~
+
+Path to output destination, set from positional arguments.
+
+Default: stdout (None). No command-line options.
+
+_source
+~~~~~~~
+
+Path to input source, set from positional arguments.
+
+Default: stdin (None). No command-line options.
+
+
+.. _language tag: http://www.w3.org/International/articles/language-tags/
+.. _BCP 47: http://www.rfc-editor.org/rfc/bcp/bcp47.txt
+.. _ISO 639: http://www.loc.gov/standards/iso639-2/php/English_list.php
+.. _ISO 3166: http://www.iso.ch/iso/en/prods-services/iso3166ma/
+ 02iso-3166-code-lists/index.html
+
+.. [#pwd] Path relative to the working directory of the process at
+ launch.
+
+.. [#override] The overridden setting will automatically be set to
+ ``None`` for command-line options and config file settings. Client
+ programs which specify defaults that override other settings must
+ do the overriding explicitly, by assigning ``None`` to the other
+ settings.
+
+.. [#dependencies] Images are only added to the dependency list if the
+ reStructuredText parser extracted image dimensions from the file.
+
+.. [#footnote_space] The footnote space is trimmed if the reference
+ style is "superscript", and it is left if the reference style is
+ "brackets".
+
+ The overriding only happens if the parser supports the
+ trim_footnote_reference_space option.
+
+
+------------------------------
+Old-Format Configuration Files
+------------------------------
+
+Formerly, Docutils configuration files contained a single "[options]"
+section only. This was found to be inflexible, and in August 2003
+Docutils adopted the current component-based configuration file
+sections as described above. Docutils will still recognize the old
+"[options]" section, but complains with a deprecation warning.
+
+To convert existing config files, the easiest way is to change the
+section title: change "[options]" to "[general]". Most settings
+haven't changed. The only ones to watch out for are these:
+
+===================== =====================================
+Old-Format Setting New Section & Setting
+===================== =====================================
+pep_stylesheet [pep_html writer] stylesheet
+pep_stylesheet_path [pep_html writer] stylesheet_path
+pep_template [pep_html writer] template
+===================== =====================================
+
+.. References
+
+.. _abstract:
+.. _bibliographic field list:
+.. _bibliographic fields:
+ ../ref/rst/restructuredtext.html#bibliographic-fields
+.. _block quote: ../ref/rst/restructuredtext.html#block-quotes
+.. _citations: ../ref/rst/restructuredtext.html#citations
+.. _enumerated lists: ../ref/rst/restructuredtext.html#enumerated-lists
+.. _field lists: ../ref/rst/restructuredtext.html#field-lists
+.. _field names: ../ref/rst/restructuredtext.html#field-names
+.. _footnotes: ../ref/rst/restructuredtext.html#footnotes
+.. _footnote references: ../ref/rst/restructuredtext.html#footnote-references
+.. _inline markup recognition rules:
+ ../ref/rst/restructuredtext.html#inline-markup-recognition-rules
+.. _literal blocks: ../ref/rst/restructuredtext.html#literal-blocks
+.. _option lists: ../ref/rst/restructuredtext.html#option-lists
+.. _tables: ../ref/rst/restructuredtext.html#tables
+
+.. _table of contents: ../ref/rst/directives.html#contents
--- /dev/null
+==================================================================
+ Changes to the Docutils latex2e writer since version 0.5
+==================================================================
+
+A backwards compatibility style sheet
+*************************************
+
+:Author: Guenter Milde
+:Contact: docutils-develop@lists.sourceforge.net
+:Revision: $Revision: 7302 $
+:Date: $Date: 2012-01-03 20:23:53 +0100 (Di, 03. Jän 2012) $
+:Copyright: © 2009 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.
+
+:Abstract: This file documents changes and provides a style for best
+ possible compatibility to the behaviour of the `latex2e`
+ writer of Doctutils release 0.5.
+
+.. _2-Clause BSD license: http://www.spdx.org/licenses/BSD-2-Clause
+
+::
+
+ \NeedsTeXFormat{LaTeX2e}
+ \ProvidesPackage{docutils-05-compat}
+ [2009/03/26 v0.1 compatibility with rst2latex from Docutils 0.5]
+
+.. contents::
+ :depth: 3
+
+Usage
+=====
+
+* To get an (almost) identic look for your old documents,
+ place ``docutils-05-compat.sty`` in the TEXINPUT path (e.g.
+ the current work directory) and pass the
+ ``--stylesheet=docutils-05-compat`` option to ``rst2latex.py``.
+
+* To use your custom stylesheets without change, add them to the
+ compatibility style, e.g.
+ ``--stylesheet="docutils-05-compat,mystyle.tex``.
+
+.. tip:: As the changes include bug fixes that are partly reverted by this
+ style, it is recommended to adapt the stylesheets to the new version or
+ copy just the relevant parts of this style into them.
+
+Changes since 0.5
+=================
+
+Bugfixes
+--------
+
+* Newlines around comments, targets and references prevent run-together
+ paragraphs.
+
+ + An image directive with hyperlink reference or target did not start a
+ new paragraph (e.g. the first two image examples in
+ standalone_rst_latex.tex).
+
+ + Paragraphs were not separated if there was a (hyper) target definition
+ inbetween.
+
+ + Paragraphs did run together, if separated by a comment-paragraph in the
+ rst source.
+
+* Fixed missing and spurious internal links/targets.
+ Internal links now take you to the correct place.
+
+* Verbose and linked system messages.
+
+* `Figure and image alignment`_ now conforms to the rst definition.
+
+* Put `header and footer directive`__ content in \DUheader respective
+ \DUfooter macros (ignored by the default style/template).
+
+ (They were put inside hard-coded markup at the top/bottom of the document
+ without an option to get them on every page.)
+
+__ ../ref/rst/directives.html#document-header-footer
+
+* Render doctest blocks as literal blocks (fixes bug [1586058] doctest block
+ nested in admonition). I.e.
+
+ + indent doctest blocks by nesting in a quote environment. This is also
+ the rendering by the HTML writer (html4css2.css).
+ + apply the ``--literal-block-env`` setting also to doctest blocks.
+
+ .. warning::
+ (``--literal-block-env=verbatim`` and
+ ``--literal-block-env=lstlistings`` fail with literal or doctest
+ blocks nested in an admonition.
+
+* Two-way hyperlinked footnotes and support for symbol footnotes and
+ ``--footnote-references=brackets`` with ``--use-latex-footnotes``.
+
+* The packages `fixltx2e` (providing LaTeX patches and the \textsubscript
+ command) and `cmap` (including character maps in the generated PDF for
+ better search and copy-and-paste operations) are now always loaded
+ (configurable with custom templates_).
+
+Backwards compatibility:
+ "Bug for bug compatibility" is not provided.
+
+
+New configuration setting defaults
+----------------------------------
+
+- font-encoding: "T1" (formerly implicitely set by 'ae').
+- use-latex-toc: true (ToC with page numbers).
+- use-latex-footnotes: true (no mixup with figures).
+
+Backwards compatibility:
+ Reset to the former defaults with:
+
+ | font-encoding: ''
+ | use-latex-toc: False
+ | use-latex-footnotes: False
+
+ (in the config file) or the command line options:
+
+ ``--figure-footnotes --use-docutils-toc --font-encoding=''``
+
+
+Cleaner LaTeX source
+--------------------
+
+New features:
+ * Remove redundant "double protection" from the encoding of the "special
+ printing characters" and square brackets, e.g. ``\%`` instead of
+ ``{\%}``.
+ * Remove some spurious whitespace, e.g. ``\item [what:] -> \item[what:]``.
+ * Use conventional style for "named" macros, e.g. ``\dots{}`` instead of
+ ``{\dots}``
+
+Backwards compatibility:
+ Changes do not affect the output.
+
+
+LaTeX style sheets
+------------------
+
+New Feature:
+ LaTeX packages can be used as ``--stylesheet`` argument without
+ restriction.
+
+Implementation:
+ Use ``\usepackage`` if style sheet ends with ``.sty`` or has no
+ extension and ``\input`` else.
+
+Rationale:
+ while ``\input`` works with extension as well as without extension,
+ ``\usepackage`` expects the package name without extension. (The latex2e
+ writer will strip a ``.sty`` extension.)
+
+
+Backwards compatibility:
+ Up to Docutils 0.5, if no filename extension is given in the
+ ``stylesheet`` argument, ``.tex`` is assumed (by latex).
+
+ Since Docutils 0.6, a stylesheet without filename extension is assumed to
+ be a LaTeX package (``*.sty``) and referenced with the ``\usepackage``
+ command.
+
+.. important::
+ Always specify the extension if you want the style sheet to be
+ ``\input`` by LaTeX.
+
+
+Templates
+---------
+
+New Feature:
+ Advanced configuration via custom templates.
+
+Implementation:
+ A ``--template`` option and config setting allows specification of a
+ template file.
+
+See the `LaTeX writer documentation`__ for details.
+
+__ latex.html#templates
+
+
+Custom roles
+------------
+
+New Feature: failsave implementation
+ As with classes to HTML objects, class arguments are silently ignored if
+ there is no styling rule for this class in a custom style sheet.
+
+New Feature: custom roles based on standard roles
+ As class support needs to be handled by the LaTeX writer, this feature was
+ not present "automatically" (as in HTML). Modified visit/depart_*()
+ methods for the standard roles now call visit/depart_inline() if there are
+ class arguments to the node.
+
+Backwards compatibility:
+ The implementation is fully backwards compatible. (SVN versions 5742 to
+ 5861 contained an implementation that did not work with commands expecting
+ an argument.)
+
+Length units
+------------
+
+New Features:
+ 1. Add default unit if none given.
+ A poll on docutils-users favoured ``bp`` (Big Point: 1 bp = 1/72 in).
+
+ 2. Do not change ``px`` to ``pt``.
+
+ 3. Lengths specified in the document with unit "pt" will be written with
+ unit "bp" to the LaTeX source.
+
+Rationale:
+ 1. prevent LaTeX error "missing unit".
+
+ 2. ``px`` is a valid unit in pdftex since version 1.3.0 released on
+ 2005-02-04:
+
+ 1px defaults to 1bp (or 72dpi), but can be changed with the
+ ``\pdfpxdimen`` primitive.::
+
+ \pdfpxdimen=1in % 1 dpi
+ \divide\pdfpxdimen by 96 % 96 dpi
+
+ -- http://www.tug.org/applications/pdftex/NEWS
+
+ Modern TeX distributions use pdftex also for dvi generation (i.e.
+ ``latex`` actually calls ``pdftex`` with some options).
+
+ 3. In Docutils (as well as CSS) the unit symbol "pt" denotes the
+ `Postscript point` or `DTP point` while LaTeX uses "pt" for the `LaTeX
+ point`, which is unknown to Docutils and 0.3 % smaller.
+
+ The `DTP point` is available in LaTeX as "bp" (big point):
+
+ 1 pt = 1/72.25 in < 1 bp = 1/72 in
+
+
+Backwards compatibility:
+ Images with width specification in ``px`` come out slightly (0.3 %) larger:
+
+ 1 px = 1 bp = 1/72 in > 1 pt = 1/72.25 in
+
+ This can be reset with ::
+
+ \pdfpxdimen=1pt
+
+.. caution:: It is impossible to revert the change of lengths specified with
+ "pt" or without unit in a style sheet, however the 0.3 % change will be
+ imperceptible in most cases.
+
+.. admonition:: Error ``illegal unit px``
+
+ The unit ``px`` is not defined in "pure" LaTeX, but introduced by the
+ `pdfTeX` converter on 2005-02-04. `pdfTeX` is used in all modern LaTeX
+ distributions (since ca. 2006) also for conversion into DVI.
+
+ If you convert the LaTeX source with a legacy program, you might get the
+ error ``illegal unit px``.
+
+ If updating LaTeX is not an option, just remove the ``px`` from the length
+ specification. HTML/CSS will default to ``px`` while the `latexe2` writer
+ will add the fallback unit ``bp``.
+
+
+Font encoding
+-------------
+
+New feature:
+ Do not mix font-encoding and font settings: do not load the obsolete
+ `ae` and `aeguill` packages unless explicitely required via the
+ ``--stylesheet`` option.
+
+ :font-encoding = "": do not load `ae` and `aeguill`, i.e.
+
+ * do not change font settings,
+ * do not use the fontenc package
+ (implicitely loaded via `ae`),
+ * use LaTeX default font encoding (OT1)
+
+ :font-encoding = "OT1": load `fontenc` with ``\usepackage[OT1]{fontenc}``
+
+Example:
+ ``--font-encoding=LGR,T1`` becomes ``\usepackage[LGR,T1]{fontenc}``
+ (Latin, Latin-1 Supplement, and Greek)
+
+
+Backwards compatibility:
+ Load the ae and aeguill packages if fontenc is not used.
+
+.. tip:: Using `ae` is not recommended. A similar look (but better
+ implementation) can be achieved with the packages `lmodern`, `cmsuper`,
+ or `cmlgr` all providing Computer Modern look-alikes in vector format and
+ T1 encoding, e.g. ``--font-encoding=T1 --stylesheet=lmodern``.
+
+Sub- and superscript as text
+----------------------------
+
+New feature:
+ Set sub- and superscript role argument in text mode not as math.
+
+ Pass the role content to ``\textsubscript`` or ``\textsuperscript``.
+
+Backwards compatibility:
+ The old implementation set the role content in Math mode, where
+
+ * whitespace is ignored,
+ * a different command set and font setting scheme is active,
+ * Latin letters are typeset italic but numbers upright.
+
+ Although it is possible to redefine ``\textsubscript`` and
+ ``\textsuperscript`` to typeset the content in math-mode, this can lead to
+ errors with certain input and is therefore not done in this style sheet.
+
+.. tip:: To get italic subscripts, define and use in your document
+ `custom roles`_ like ``.. role:: sub(subscript)`` and
+ ``.. role:: super(superscript)`` and define the "role commands"::
+
+ \newcommand{\DUrolesub}{\itshape}
+ \newcommand{\DUrolesuper}{\itshape}
+
+ Alternatively, if you want all sub- and superscripts in italic, redefine
+ the macros::
+
+ %% \let\DUsup\textsubscript
+ %% \let\DUsuper\textsuperscript
+ %% \renewcommand*{\textsubscript}{\DUsub\itshape}
+ %% \renewcommand*{\textsuperscript}{\DUsuper\itshape}
+
+ This is not fully backwards compatible, as it will also set numbers in
+ italic shape and not ignore whitespace.
+
+Page layout
+-----------
+
+New features:
+ * Margins are configurable via the ``DIV=...`` document option.
+
+ * The ``\raggedbottom`` setting is no longer inserted into the document. It
+ is the default for article and report classes. If requested in combination
+ with a book class, it can be given in a custom style sheet.
+
+Backwards compatibility:
+ Up to version 0.5, use of `typearea` and a DIV setting of 12 were
+ hard-coded into the latex2e writer ::
+
+ \usepackage{typearea}
+ \typearea{12}
+
+ and the vertical alignment of lower boundary of the text area in book
+ classes disabled via ::
+
+ \raggedbottom
+
+
+ToC and section numbers
+-----------------------
+
+Better conformance to Docutils specifications.
+
+New feature:
+ * The "depth" argument of the "contents" and "sectnum" directives is
+ respected.
+
+ * section numbering independent of 'use-latex-toc':
+
+ + sections are only numbered if there is a "sectnum" directive in the
+ document
+
+ + section numbering by LaTeX if the "sectnum_xforms" config setting is
+ False.
+
+Backwards compatibility:
+
+ The previous behaviour was to always number sections if 'use-latex-toc' is
+ true, using the document class defaults. It cannot be restored
+ universally, the following code sets the default values of the "article"
+ document class::
+
+ \setcounter{secnumdepth}{3}
+ \setcounter{tocdepth}{3}
+
+.. TODO or not to do? (Back-compatibility problems)
+ * The default "depth" of the LaTeX-created ToC and the LaTeX section
+ numbering is increased to the number of supported section levels.
+
+New feature:
+ If 'use-latex-toc' is set, local tables of content are typeset using the
+ 'minitoc' package (instead of being ignored).
+
+Backwards compatibility:
+ Disable the creation of local ToCs (ignoring all special commands) by
+ replacing ``\usepackage{minitoc} with ``\usepackage{mtcoff}``.
+
+
+Default font in admonitions and sidebar
+---------------------------------------
+
+New feature:
+ Use default font in admonitions and sidebar.
+
+Backward compatibility:
+ See the fallback definitions for admonitions_, `topic title`_ and
+ `sidebar`_.
+
+
+Figure placement
+----------------
+
+New feature:
+ Use ``\floatplacement`` from the `float` package instead of
+ "hard-coded" optional argument for the global setting.
+
+ Default to ``\floatplacement{figure}{H}`` (here definitely). This
+ corresponds most closely to the source and HTML placement (principle of
+ least surprise).
+
+Backwards compatibility:
+ Set the global default back to the previous used value::
+
+ \usepackage{float}
+ \floatplacement{figure}{htbp} % here, top, bottom, extra-page
+
+
+Figure and image alignment
+--------------------------
+
+New features:
+
+a) Fix behaviour of 'align' argument to a figure (do not align figure
+ contents).
+
+ As the 'figwidth' argument is still ignored and the "natural width" of a
+ figure in LaTeX is 100% \textwidth, setting the 'align' argument of a
+ figure has currently no effect on the LaTeX output.
+
+b) Set default align of image in a figure to 'center'.
+
+c) Also center images that are wider than textwidth.
+
+d) Align images with class "align-[right|center|left]" (allows setting the
+ alignment of an image in a figure).
+
+Backwards compatibility:
+ There is no "automatic" way to reverse these changes via a style sheet.
+
+a) The alignment of the image can be set with the "align-left",
+ "align-center" and "align-right" class arguments.
+
+ As previously, the caption of a figure is aligned according to the
+ document class -- configurable with a style sheet using the "caption"
+ package.
+
+b) See a)
+
+c) Set the alignment of "oversized" images to "left" to get back the
+ old placement.
+
+Shorter preamble
+----------------
+
+New feature:
+ The document preamble is pruned to contain only relevant commands and
+ settings.
+
+Packages that are no longer required
+````````````````````````````````````
+
+The following packages where required in pre-0.5 versions and still loaded
+with version 0.5::
+
+ \usepackage{shortvrb}
+ \usepackage{amsmath}
+
+
+Packages that are conditionally loaded
+``````````````````````````````````````
+
+Additional to the `typearea` for `page layout`_, the following packages are
+only loaded if actually required by doctree elements:
+
+Tables
+^^^^^^
+
+Standard package for tables across several pages::
+
+ \usepackage{longtable}
+
+Extra space between text in tables and the line above them
+('array' is implicitely loaded by 'tabularx', see below)::
+
+ \usepackage{array}
+ \setlength{\extrarowheight}{2pt}
+
+Table cells spanning multiple rows::
+
+ \usepackage{multirow}
+
+Docinfo
+^^^^^^^
+
+One-page tables with auto-width columns::
+
+ \usepackage{tabularx}
+
+Images
+^^^^^^
+Include graphic files::
+
+ \usepackage{graphicx}
+
+Problematic, Sidebar
+^^^^^^^^^^^^^^^^^^^^
+Set text and/or background colour, coloured boxes with ``\colorbox``::
+
+ \usepackage{color}
+
+Floats for footnotes settings
+`````````````````````````````
+
+Settings for the use of floats for footnotes are only included if
+
+* the option "use-latex-footnotes" is False, and
+* there is at least one footnote in the document.
+
+::
+
+ % begin: floats for footnotes tweaking.
+ \setlength{\floatsep}{0.5em}
+ \setlength{\textfloatsep}{\fill}
+ \addtolength{\textfloatsep}{3em}
+ \renewcommand{\textfraction}{0.5}
+ \renewcommand{\topfraction}{0.5}
+ \renewcommand{\bottomfraction}{0.5}
+ \setcounter{totalnumber}{50}
+ \setcounter{topnumber}{50}
+ \setcounter{bottomnumber}{50}
+ % end floats for footnotes
+
+
+Special lengths, commands, and environments
+-------------------------------------------
+
+Removed definitions
+```````````````````
+
+admonition width
+^^^^^^^^^^^^^^^^
+The ``admonitionwith`` lenght is replaced by the more powerful
+``\DUadmonition`` command (see admonitions_).
+
+Backwards compatibility:
+ The default value (90 % of the textwidth) is unchanged.
+
+ To configure the admonition width, you must redefine the ``DUadmonition``
+ command instead of changing the ``admonitionwith`` length value.
+
+
+Renamed definitions (now conditional)
+`````````````````````````````````````
+
+The names for special doctree elements are now prefixed with ``DU``.
+
+Up to version 0.5, all definitions were included in the preamble (before the
+style sheet) of every document -- even if not used in the body. Since
+version 0.6, fallback definitions are included after the style sheet and
+only if required.
+
+Customization is done by an alternative definition in a style sheet with
+``\newcommand`` instead of the former ``\renewcommand``.
+
+The following code provides the old definitions and maps them (or their
+custom variants) to the new interface.
+
+docinfo width
+^^^^^^^^^^^^^
+::
+
+ \newlength{\docinfowidth}
+ \setlength{\docinfowidth}{0.9\textwidth}
+
+ \newlength{\DUdocinfowidth}
+ \AtBeginDocument{\setlength{\DUdocinfowidth}{\docinfowidth}}
+
+line block
+^^^^^^^^^^
+::
+
+ \newlength{\lineblockindentation}
+ \setlength{\lineblockindentation}{2.5em}
+ \newenvironment{lineblock}[1]
+ {\begin{list}{}
+ {\setlength{\partopsep}{\parskip}
+ \addtolength{\partopsep}{\baselineskip}
+ \topsep0pt\itemsep0.15\baselineskip\parsep0pt
+ \leftmargin#1}
+ \raggedright}
+ {\end{list}}
+
+ \newlength{\DUlineblockindent}
+ \AtBeginDocument{\setlength{\DUlineblockindent}{\lineblockindentation}}
+ \newenvironment{DUlineblock}[1]
+ {\begin{lineblock}{#1}}
+ {\end{lineblock}}
+
+local line width
+^^^^^^^^^^^^^^^^
+
+The ``\locallinewidth`` length for internal use in tables is replaced
+by ``\DUtablewidth``. It was never intended for customization::
+
+ \newlength{\locallinewidth}
+
+option lists
+^^^^^^^^^^^^
+::
+
+ \newcommand{\optionlistlabel}[1]{\bf #1 \hfill}
+ \newenvironment{optionlist}[1]
+ {\begin{list}{}
+ {\setlength{\labelwidth}{#1}
+ \setlength{\rightmargin}{1cm}
+ \setlength{\leftmargin}{\rightmargin}
+ \addtolength{\leftmargin}{\labelwidth}
+ \addtolength{\leftmargin}{\labelsep}
+ \renewcommand{\makelabel}{\optionlistlabel}}
+ }{\end{list}}
+
+ \newcommand{\DUoptionlistlabel}{\optionlistlabel}
+ \newenvironment{DUoptionlist}
+ {\begin{optionlist}{3cm}}
+ {\end{optionlist}}
+
+rubric
+^^^^^^
+Now less prominent (not bold, normal size) restore with::
+
+ \newcommand{\rubric}[1]{\subsection*{~\hfill {\it #1} \hfill ~}}
+ \newcommand{\DUrubric}[2][class-arg]{\rubric{#2}}
+
+title reference role
+^^^^^^^^^^^^^^^^^^^^
+::
+
+ \newcommand{\titlereference}[1]{\textsl{#1}}
+ \newcommand{\DUroletitlereference}[1]{\titlereference{#1}}
+
+
+New definitions
+```````````````
+
+New Feature:
+ Enable customization of some more Docutils elements with special commands
+
+ :admonition: ``DUadmonition`` command (replacing ``\admonitionwidth``),
+ :field list: ``DUfieldlist`` environment,
+ :legend: ``DUlegend`` environment,
+ :sidebar: ``\DUsidebar``, ``\DUtitle``, and
+ ``DUsubtitle`` commands,
+ :topic: ``\DUtopic`` and ``\DUtitle`` commands,
+ :transition: ``\DUtransition`` command.
+ :footnotes: ``\DUfootnotemark`` and ``\DUfootnotetext`` commands with
+ hyperlink support using the Docutils-provided footnote label.
+
+Backwards compatibility:
+ In most cases, the default definition corresponds to the previously used
+ construct. The following definitions restore the old behaviour in case of
+ changes.
+
+admonitions
+^^^^^^^^^^^
+Use sans-serif fonts::
+
+ \newcommand{\DUadmonition}[2][class-arg]{%
+ \begin{center}
+ \fbox{\parbox{0.9\textwidth}{\sffamily #2}}
+ \end{center}
+ }
+
+dedication
+^^^^^^^^^^
+Do not center::
+
+ \newcommand{\DUtopicdedication}[1]{#1}
+
+But center the title::
+
+ \newcommand*{\DUtitlededication}[1]{\centerline{\textbf{#1}}}
+
+sidebar
+^^^^^^^
+Use sans-serif fonts, a frame, and a darker shade of grey::
+
+ \providecommand{\DUsidebar}[2][class-arg]{%
+ \begin{center}
+ \sffamily
+ \fbox{\colorbox[gray]{0.80}{\parbox{0.9\textwidth}{#2}}}
+ \end{center}
+ }
+
+sidebar sub-title
+^^^^^^^^^^^^^^^^^
+Bold instead of emphasized::
+
+ \providecommand*{\DUsubtitlesidebar}[1]{\hspace*{\fill}\\
+ \textbf{#1}\smallskip}
+
+topic
+^^^^^
+No quote but normal text::
+
+ \newcommand{\DUtopic}[2][class-arg]{%
+ \ifcsname DUtopic#1\endcsname%
+ \csname DUtopic#1\endcsname{#2}%
+ \else
+ #2
+ \fi
+ }
+
+topic title
+^^^^^^^^^^^
+Title for "topics" (admonitions, sidebar).
+
+Larger font size::
+
+ \providecommand*{\DUtitletopic}[1]{\textbf{\large #1}\smallskip}
+
+transition
+^^^^^^^^^^
+Do not add vertical space after the transition. ::
+
+ \providecommand*{\DUtransition}[1][class-arg]{%
+ \hspace*{\fill}\hrulefill\hspace*{\fill}}
--- /dev/null
+.. -*- coding: utf-8 -*-
+
+========================================
+ Emacs Support for reStructuredText
+========================================
+
+:Authors: Stefan Merten <stefan@merten-home.de>, Martin Blais
+ <blais@furius.ca>
+:Version: ``rst.el`` V1.4.1
+:Abstract:
+
+ High-level description of the existing Emacs_ support for editing
+ reStructuredText_ text documents. Suggested setup code and usage
+ instructions are provided.
+
+.. contents::
+
+Introduction
+============
+
+reStructuredText_ is a syntax for simple text files that allows a
+tool set - docutils_ - to extract generic document structure. For
+people who use Emacs_, there is a package that adds a major mode that
+supports editing the syntax of reStructuredText_: ``rst.el``. This
+document describes the features it provides, and how to setup your
+Emacs_ to use them and how to invoke them.
+
+Installation
+============
+
+Emacs_ support for reStructuredText_ is implemented as an Emacs_ major
+mode (``rst-mode``) provided by the ``rst.el`` Emacs_ package.
+
+Emacs_ distributions contain ``rst.el`` since version V23.1. However,
+a significantly updated version of ``rst.el`` is contained in Emacs_
+V24.3. This document describes the version of ``rst.el`` contained in
+Emacs_ V24.3 and later versions. This version of ``rst.el`` has the
+internal version V1.4.1.
+
+If you have Emacs_ V24.3 or later you do not need to install anything
+to get reST support. If you have an Emacs_ between V23.1 and V24.2 you
+may use the version of ``rst.el`` installed with Emacs_ or install a
+more recent one locally_ (recommended). In other cases you need to
+install ``rst.el`` locally_ to get reST support.
+
+Checking situation
+------------------
+
+Here are some steps to check your situation:
+
+#. In Emacs_ switch to an empty buffer and try ::
+
+ M-x rst-mode
+
+ If this works you have ``rst.el`` installed somewhere. You can see
+ that it works if you find a string ``ReST`` in Emacs' modeline of
+ the current buffer. If this doesn't work you need to install
+ ``rst.el`` yourself locally_.
+
+#. In the buffer you just switched to ``rst-mode`` try ::
+
+ C-h v rst-version
+
+ If this fails you have a version of ``rst.el`` older than
+ V1.1.0. Either you have an old ``rst.el`` locally or you are using
+ an Emacs_ between V23.1 and V24.2. In this case it is recommended
+ that you install a more recent version of ``rst.el`` locally_.
+
+ You may also try ::
+
+ C-h v emacs-version
+
+ to find out your Emacs_ version.
+
+#. Check the version of ``rst.el``
+
+ The content of ``rst-version`` gives you the internal version of
+ ``rst.el``. The version contained in Emacs_ V24.3 and described here
+ is V1.4.0. If you have an older version you may or may not install
+ a more recent version of ``rst.el`` locally_.
+
+.. _locally:
+
+Local installation
+------------------
+
+If you decided to install locally please follow these steps.
+
+#. Download ``rst.el``
+
+ Download the most recent published version of ``rst.el`` from
+ http://sourceforge.net/p/docutils/code/HEAD/tree/trunk/docutils/tools/editors/emacs/rst.el
+
+#. Put ``rst.el`` to a directory in ``load-path``
+
+ Use ::
+
+ C-h v load-path
+
+ If in the resulting list you find a directory in your home
+ directory put ``rst.el`` in this directory.
+
+ Make sure the directory is one of the first entries in
+ ``load-path``. Otherwise a version of ``rst.el`` which came with
+ Emacs_ may be found before your local version.
+
+ In Emacs_ see the info node ``Init File Examples`` for more
+ information on how to set up your Emacs_ initialization
+ machinery. Try ::
+
+ C-h i
+ mEmacs<Return>
+ sInit File Examples<Return>
+
+#. Enable ``rst-mode``
+
+ Add the following to your Emacs_ initialization setup ::
+
+ (require 'rst)
+
+ After you restarted Emacs_ ``rst.el`` is loaded and ready to be
+ used.
+
+Switching ``rst-mode`` on
+-------------------------
+
+By default ``rst-mode`` is switched on for files ending in ``.rst`` or
+``.rest``. If in a buffer you want to switch ``rst-mode`` on manually
+use ::
+
+ M-x rst-mode
+
+If you want to use ``rst-mode`` in files with other extensions modify
+``auto-mode-alist`` to automatically turn it on whenever you visit
+reStructuredText_ documents::
+
+ (setq auto-mode-alist
+ (append '(("\\.txt\\'" . rst-mode)
+ ("\\.rst\\'" . rst-mode)
+ ("\\.rest\\'" . rst-mode)) auto-mode-alist))
+
+Put the extensions you want in the correct place in the example
+above. Add more lines if needed.
+
+If have local variables enabled (try ``C-h v enable-local-variables``
+to find out), you can also add the following at the top of your
+documents to trigger rst-mode::
+
+ .. -*- mode: rst -*-
+
+Or this at the end of your documents::
+
+ ..
+ Local Variables:
+ mode: rst
+ End:
+
+Key bindings
+============
+
+``rst-mode`` automatically binds several keys for invoking special
+functions for editing reStructuredText_. Since ``rst-mode`` contains a
+lot of functionality most key bindings consist of three
+keystrokes.
+
+Following the Emacs_ conventions for major modes the key bindings of
+``rst-mode`` start with ``C-c C-<letter>``. The second key stroke
+selects a group of key bindings:
+
+C-c C-a
+ Commands to adjust the section headers and work with the hierarchy
+ they build.
+
+C-c C-c
+ Commands to compile the current reStructuredText_ document to
+ various output formats.
+
+C-c C-l
+ Commands to work with lists of various kinds.
+
+C-c C-r
+ Commands to manipulate the current region.
+
+C-c C-t
+ Commands to create and manipulate a table of contents.
+
+At any stage of typing you may use ``C-h`` to get help on the
+available key bindings. I.e. ``C-c C-h`` gives you help on all key
+bindings while ``C-c C-r C-h`` gives you help on the commands for
+regions. This is handy if you forgot a certain key binding.
+
+Additional key bindings which have a certain meaning in other Emacs_
+modes are reused in ``rst-mode`` so you don't have to learn a
+different set of key bindings for editing reStructuredText_.
+
+In ``rst-mode`` try ::
+
+ C-h m
+
+to list all mode specific key bindings. Most of the key bindings are
+described in this tutorial.
+
+.. note:: The key bindings have been completely revamped in ``rst.el``
+ V1.0.0. This was necessary to make room for new
+ functionality. Some of the old bindings still work but give
+ a warning to use the new binding. In the output of ``C-h m``
+ these bindings show up as ``rst-deprecated-...``. The old
+ bindings will be removed completely in a later version.
+
+Section Adornments
+==================
+
+``rst-mode`` recognizes the section adornments building the section
+hierarchy of the document. Section adornments are the underlines or
+under- and overlines used to mark a section title. There are a couple
+of commands to work with section adornments. These commands are bound
+to key bindings starting with ``C-c C-a``.
+
+Adjusting a Section Title
+-------------------------
+
+There is a function that helps a great deal to maintain these
+adornments: ``rst-adjust`` (bound to ``C-c C-a C-a``, ``C-c C-=``, and
+``C-=``). This function is a Swiss army knife that can be invoked
+repeatedly and whose behavior depends on context:
+
+#. If there is an incomplete adornment, e.g. ::
+
+ My Section Title
+ ==
+
+ invocation will complete the adornment. It can also be used to
+ adjust the length of the existing adornment when you need to edit
+ the title.
+
+#. If there is no section adornment at all, by default an adornment of
+ the same level as the last encountered section level is added. You
+ can simply enter a few characters of the title and invoke the
+ function to create the section adornment.
+
+ The variable ``rst-new-adornment-down`` can be customized to create
+ one level lower adornments than the previous section title instead
+ of keeping the level.
+
+#. If there is already a section adornment, it is promoted one level
+ up. You can invoke it like this repeatedly to cycle the title
+ through the hierarchy of existing adornments.
+
+Invoking the function with a negative prefix argument, e.g. ``C--
+C-=``, will effectively reverse the direction of adornment cycling.
+To alternate between underline-only and over-and-under styles, you can
+use a regular prefix argument, e.g. ``C-u C-=``. See the
+documentation of ``rst-adjust`` for more description of the prefix
+arguments to alter the behavior of the function.
+
+Promoting and Demoting Many Sections
+------------------------------------
+
+When you are re-organizing the structure of a document, it can be
+useful to change the level of a number of section titles. The same
+key binding can be used to do that: if the region is active when the
+binding is invoked, all the section titles that are within the region
+are promoted accordingly (or demoted, with negative prefix argument).
+
+Redoing All the Adornments to Your Taste
+----------------------------------------
+
+If you open someone else's file and the adornments it contains are
+unfamiliar, you may want to readjust them to fit your own preferred
+hierarchy of adornments. This can be difficult to perform by hand.
+However, you can do this easily by invoking
+``rst-straighten-adornments`` (``C-c C-a C-s``), which operates on the
+entire buffer.
+
+Customizations for Adornments
+-----------------------------
+
+You can customize the variable ``rst-preferred-adornments`` to a list
+of the adornments that you like to use for documents.
+
+If you prefer adornments according to
+http://sphinx-doc.org/rest.html#sections you may customize it to end
+up with a value like this::
+
+ ((35 over-and-under 0) ; ?#
+ (42 over-and-under 0) ; ?*
+ (61 simple 0) ; ?=
+ (45 simple 0) ; ?-
+ (94 simple 0) ; ?^
+ (34 simple 0)) ; ?"
+
+This will become the default in a later version of ``rst.el``.
+
+If you set ``rst-preferred-adornments`` to nil resembling the empty
+list only the section adornment found in the buffer will be used.
+
+Viewing the Hierarchy of Section Adornments
+-------------------------------------------
+
+You can visualize the hierarchy of the section adornments in the
+current buffer by invoking ``rst-display-adornments-hierarchy``, bound
+on ``C-c C-a C-d``. A temporary buffer will appear with fake section
+titles rendered in the style of the current document. This can be
+useful when editing other people's documents to find out which section
+adornments correspond to which levels.
+
+Movement and Selection
+======================
+
+Movement and Selection for Sections
+-----------------------------------
+
+You can move the cursor between the different section titles by using
+the ``rst-backward-section`` (``C-M-a``) and ``rst-forward-section``
+(``C-M-e``). To mark the section that cursor lies in, use
+``rst-mark-section`` (``C-M-h``).
+
+The key bindings are modeled after other modes with similar
+functionality.
+
+Movements and Selection for Text Blocks
+---------------------------------------
+
+The understanding of reStructuredText_ of ``rst-mode`` is used to set
+all the variables influencing Emacs' understanding of paragraphs. Thus
+all operations on paragraphs work as usual. For instance
+``forward-paragraph`` (``M-}``) works as usual.
+
+Indenting and Filling
+=====================
+
+Indentation of text plays a major role in the syntax of
+reStructuredText_. It is tedious to maintain the indentation
+manually. ``rst-mode`` understands most of the structure of
+reStructuredText_ allowing for sophisticated indentation and filling
+support described in this section.
+
+Indenting Text Blocks
+---------------------
+
+``rst-mode`` supports indentation of text blocks by the command
+``rst-shift-region`` (``C-c C-r TAB``). Mark a region and use ``C-c
+C-r TAB`` to indent all blocks one tab to the right. Use ``M-- C-c C-r
+TAB`` to indent the region one tab to the left.
+
+You may use arbitrary prefix arguments such as ``M-2`` or ``M-- 2`` to
+determine the number of tabs you want to indent. A prefix of ``M-0``
+removes all indentation in the active region.
+
+A tab is an indentation making sense for the block at hand in
+reStructuredText_ syntax. In some cases the exact indentation depends
+on personal taste. You may customize a couple of variables ``M-x
+customize-group<RET> rst-indent<RET>`` to match your taste.
+
+Indenting Lines While Typing
+----------------------------
+
+In Emacs_ the ``TAB`` key is often used for indenting the current
+line. ``rst-mode`` implements this for the sophisticated indentation
+rules of reStructuredText_. Pressing ``TAB`` cycles through the
+possible tabs for the current line. In the same manner
+``newline-and-indent`` (``C-j``) indents the new line properly.
+
+This is very handy while writing lists. Consider this
+reStructuredText_ bullet list with the cursor at ``@``::
+
+ * Level 1
+
+ * Level 2@
+
+Type ``C-j`` twice to get this::
+
+ * Level 1
+
+ * Level 2
+
+ @
+
+Now you an enter text at this level, or start a new list item by
+typing another ``*``. Or you may type ``TAB`` to reduce the
+indentation once::
+
+ * Level 1
+
+ * Level 2
+
+ @
+
+Typing another ``TAB`` gets you to the first level::
+
+ * Level 1
+
+ * Level 2
+
+ @
+
+.. note:: Since Emacs_ V24.4 ``electric-indent-mode`` is globally on.
+ This breaks indentation in ``rst-mode`` and renders
+ ``rst-mode`` mostly useless. This is fixed in V1.4.1 of
+ ``rst-mode``.
+
+ A quick fix for older versions of ``rst.el`` is to add the
+ following line at the end of the ``(define-derived-mode
+ rst-mode ...`` block in your copy of ``rst.el``::
+
+ (setq electric-indent-inhibit t)
+
+ You may also install V1.4.1 or newer locally_.
+
+Filling
+-------
+
+``rst-mode`` understanding the indentation rules of reStructuredText_
+also supports filling paragraphs. Just use ``fill-paragraph``
+(``M-q``) as you do in other modes.
+
+Operating on Lists
+==================
+
+Lists are supported in various flavors in reStructuredText_.
+``rst-mode`` understands reStructuredText_ lists and offers some
+support for operating on lists. Key bindings for commands for
+operating on lists start with ``C-c C-l``.
+
+Please note that so far definition lists are not explicitly supported
+by ``rst-mode``.
+
+Bulleted and Enumerated Lists
+-----------------------------
+
+If you have a couple of plain lines you want to turn into an
+enumerated list you can invoke ``rst-enumerate-region`` (``C-c C-l
+C-e``). For example, the following region ::
+
+ Apples
+
+ Oranges
+
+ Bananas
+
+becomes ::
+
+ 1. Apples
+
+ 2. Oranges
+
+ 3. Bananas
+
+``rst-bullet-list-region`` (``C-c C-l C-b``) does the same, but
+results in a bullet list ::
+
+ * Apples
+
+ * Oranges
+
+ * Bananas
+
+By default, each paragraph starting on the leftmost line in the
+highlighted region will be taken to be a single list or enumeration
+item, for example, enumerating the following::
+
+ An apple a day
+ keeps the doctor away.
+
+ But oranges
+ are tastier than apples.
+
+ If you preferred bananas
+ you may be
+ a monkey.
+
+Will result in::
+
+ 1. An apple a day
+ keeps the doctor away.
+
+ 2. But oranges
+ are tastier than apples.
+
+ 3. If you preferred bananas
+ you may be
+ a monkey.
+
+If you would like to enumerate each of the lines, use a prefix
+argument on the preceding commands, e.g.::
+
+ Apples
+ Oranges
+ Bananas
+
+becomes::
+
+ * Apples
+ * Oranges
+ * Bananas
+
+Straightening Existing Bullet List Hierarchies
+----------------------------------------------
+
+If you invoke ``rst-straighten-bullets-region`` (``C-c C-l C-s``), the
+existing bullets in the active region will be replaced to reflect
+their respective level. This does not make a difference in the
+document structure that reStructuredText_ defines, but looks better
+in, for example, if all of the top-level bullet items use the
+character ``-``, and all of the 2nd level items use ``*``, etc.
+
+Inserting a List Item
+---------------------
+
+To start a new list you may invoke ``rst-insert-list`` (``C-c C-l
+C-i``). You may choose from an item style supported by
+reStructuredText_.
+
+You may also invoke ``rst-insert-list`` at the end of a list item. In
+this case it inserts a new line containing the markup for the a list
+item on the same level.
+
+Operating on Other Text Blocks
+==============================
+
+Creating and Removing Line Blocks
+---------------------------------
+
+To create line blocks, first select the region to convert and invoke
+``rst-line-block-region`` ``C-c C-r C-l``. For example, the following
+::
+
+ Apples
+ Oranges
+ Bananas
+
+becomes ::
+
+ | Apples
+ | Oranges
+ | Bananas
+
+This works even if the region is indented. To remove line blocks,
+select a region and invoke with a prefix argument.
+
+Commenting a Region of Text
+---------------------------
+
+``rst-mode`` understands reStructuredText_ comments. Use
+``comment-dwim`` (``M-;``) to work on comments as usual::
+
+ Apples
+ Oranges
+ Bananas
+
+becomes::
+
+ ..
+ Apples
+ Oranges
+ Bananas
+
+To remove a comment you have to tell this to ``comment-dwim``
+explicitly by using a prefix argument (``C-u M-;``).
+
+Please note that only indented comments are supported properly by the
+parts of ``comment-dwim`` working on regions.
+
+.. _Conversion:
+
+Converting Documents from Emacs
+===============================
+
+``rst-mode`` provides a number of functions for running documents
+being edited through the docutils tools. The key bindings for these
+commands start with ``C-c C-c``.
+
+The main generic function is ``rst-compile`` (``C-c C-c C-c``). It
+invokes a compilation command with the correct output name for the
+current buffer and then invokes Emacs' compile function. It also looks
+for the presence of a ``docutils.conf`` configuration file in the
+parent directories and adds it to the command line options. There is also
+``rst-compile-alt-toolset`` (``C-c C-c C-a``) in case you often need
+run your document in a second toolset.
+
+You can customize the commands being used by setting
+``rst-compile-primary-toolset`` and ``rst-compile-secondary-toolset``.
+
+Other commands are available for other formats:
+
+* ``rst-compile-pseudo-region`` (``C-c C-c C-x``)
+
+ When crafting documents, it is often convenient to view which data
+ structures docutils will parse them into. You can use to run the
+ active region through ``rst2pseudoxml.py`` and have the output
+ automatically be displayed in a new buffer.
+
+* ``rst-compile-pdf-preview`` (``C-c C-c C-p``)
+
+ Convert the current document to PDF and launch a viewer on the
+ results.
+
+* ``rst-compile-slides-preview`` (``C-c C-c C-s``): Convert the
+ current document to S5 slides and view in a web browser.
+
+Imenu Support
+=============
+
+Using Imenu
+-----------
+
+Emacs_ has a package called ``imenu``. ``rst-mode`` supports Imenu by
+adding a function to convert the structure of a reStructuredText_
+buffer to an Imenu index. Thus you can use invoke ``imenu`` (``M-x
+imenu``) to navigate through the section index or invoke
+``imenu-add-to-menubar`` (``M-x imenu-add-to-menubar``) to add an
+Imenu menu entry to Emacs' menu bar.
+
+Using which function
+--------------------
+
+As a side effect of Imenu support the ``which-func`` package is also
+supported. Invoke ``which-function-mode`` (``M-x
+which-function-mode``) to add the name of the current section to the
+mode line. This is especially useful if you navigate through documents
+with long sections which do not fit on a single screen.
+
+Using the Table of Contents
+===========================
+
+The sections in a reStructuredText_ document can be used to form a
+table of contents. ``rst-mode`` can work with such a table of contents
+in various forms. Key bindings for these commands start with ``C-c
+C-t``.
+
+Navigating Using the Table of Contents
+--------------------------------------
+
+When you are editing long documents, it can be a bit difficult to
+orient yourself in the structure of your text. To that effect, a
+function is provided that presents a hierarchically indented table of
+contents of the document in a temporary buffer, in which you can
+navigate and press ``Return`` to go to a specific section.
+
+Invoke ``rst-toc`` (``C-c C-t C-t``). It presents a temporary buffer
+that looks something like this::
+
+ Table of Contents:
+ Debugging Meta-Techniques
+ Introduction
+ Debugging Solution Patterns
+ Recognize That a Bug Exists
+ Subdivide and Isolate
+ Identify and Verify Assumptions
+ Use a Tool for Introspection
+ Change one thing at a time
+ Learn about the System
+ Understanding a bug
+ The Basic Steps in Debugging
+ Attitude
+ Bad Feelings
+ Good Feelings
+ References
+
+When you move the cursor to a section title and press ``RET`` or ``f``
+or click with ``button1`` on a section title, the temporary buffer
+disappears and you are left with the cursor positioned at the chosen
+section. Clicking with ``button2`` jumps to the respective section but
+keeps the toc buffer. You can use this to look at the various section
+headers quickly. Use ``q`` in this buffer to just quit it without
+moving the cursor in the original document. Use ``z`` to zap the
+buffer altogether.
+
+Inserting a Table of Contents
+-----------------------------
+
+Oftentimes in long text documents that are meant to be read directly,
+a table of contents is inserted at the beginning of the text. In
+reStructuredText_ documents, since the table of contents is
+automatically generated by the parser with the ``.. contents::``
+directive, people generally have not been adding an explicit table of
+contents to their source documents, and partly because it is too much
+trouble to edit and maintain.
+
+The Emacs_ support for reStructuredText_ provides a function to insert
+such a table of contents in your document. Since it is not meant to
+be part of the document text, you should place such a table of
+contents within a comment, so that it is ignored by the parser. This
+is the favored usage::
+
+ .. contents::
+ ..
+ 1 Introduction
+ 2 Debugging Solution Patterns
+ 2.1 Recognize That a Bug Exists
+ 2.2 Subdivide and Isolate
+ 2.3 Identify and Verify Assumptions
+ 2.4 Use a Tool for Introspection
+ 2.5 Change one thing at a time
+ 2.6 Learn about the System
+ 3 Understanding a bug
+ 4 The Basic Steps in Debugging
+ 5 Attitude
+ 5.1 Bad Feelings
+ 5.2 Good Feelings
+ 6 References
+
+Just place the cursor at the top-left corner where you want to insert
+the TOC and invoke the function ``rst-toc-insert`` with ``C-c C-t
+C-i``. The table of contents will display all the section titles that
+are under the location where the insertion occurs. This way you can
+insert local table of contents by placing them in the appropriate
+location.
+
+You can use a numeric prefix argument to limit the depth of rendering
+of the TOC.
+
+You can customize the look of the TOC by setting the values of the
+following variables: ``rst-toc-indent``, ``rst-toc-insert-style``,
+``rst-toc-insert-max-level``.
+
+Maintaining the Table of Contents Up-to-date
+--------------------------------------------
+
+One issue is that you will probably want to maintain the inserted
+table of contents up-to-date. ``rst-toc-update`` (``C-c C-t C-u``)
+will automatically update an inserted table of contents following a
+``.. contents::`` directive laid out like the example above.
+
+Syntax Highlighting via Font-Lock
+=================================
+
+``rst-mode`` provides syntax highlighting for nearly all to
+reStructuredText_ constructs.
+
+Use ``customize-group rst-faces`` to customize the faces used for
+font-locking.
+
+Customization
+=============
+
+Some aspects of ``rst-mode`` can be configured through the
+customization feature of Emacs_. Try ::
+
+ M-x customize-group<RETURN>rst
+
+for all customizations or use the respective menu entry. Those
+customizations which are useful for many people are described in this
+section.
+
+Customizing Section Title Formatting
+------------------------------------
+
+For a couple of things the reStructuredText_ syntax offers a choice of
+options on how to do things exactly. Some of these choices influence
+the operation of ``rst.el`` and thus can be configured. The
+customizations are contained in the ``rst-adjust`` group.
+
+Among these things is the exact layout of section adornments. In fact
+reStructuredText_ prescribes only the characters and how these
+characters must be used but the exact use of concrete adornments may
+be different in every source file. Using the customization option
+``rst-preferred-adornments`` you can tell ``rst-mode`` on the exact
+sequence of adornments you prefer to markup the different levels of
+sections headers.
+
+Finally the title text of over-and-under adornments may be indented in
+reStructuredText_. ``rst-default-indent`` tells ``rst-mode`` how many
+positions a over-and-under adornment should be indented when toggling
+from simple adornment and in case a consistent indentation throughout
+the whole buffer for such adornment is needed.
+
+Customizing Indentation
+-----------------------
+
+reStructuredText_ uses indentation a lot to signify a certain meaning.
+In some cases the exact amount of indentation is prescribed by the
+syntax while in some cases the exact indentation is not fixed. The
+customization group ``rst-indent`` allows to customize the amount of
+indentation in these cases.
+
+In field lists the content of a field needs to be indented relative to
+the field label. ``rst-indent-field`` tells ``rst-mode`` the amount of
+indentation to use for field content. A value of zero always indents
+according to the content after the field label.
+
+The indentation of literal blocks is controlled by
+``rst-indent-literal-normal`` and ``rst-indent-literal-minimized``.
+The first is used when the leading literal tag (``::``) appears alone
+on a line. The second is used when the minimized style is used where
+the literal tag follows some text.
+
+The indentation of comments is controlled by ``rst-indent-comment``.
+Of course this makes only sense for the indented comments of
+reStructuredText_.
+
+Customization option ``rst-indent-width`` gives the default
+indentation when there are no other hints on what amount of
+indentation to use.
+
+Customizing Faces
+-----------------
+
+The faces used for font-locking can be defined in the ``rst-faces``
+customization group. The customization options ending in ``-face`` are
+only there for backward compatibility so please leave them as they
+are.
+
+reStructuredText_ sets no limit on the nesting of sections. By default
+there are six levels of fontification defined. Section titles deeper
+than six level have no special fontification - only the adornments are
+fontified. The exact mapping from a level to a face is done by by
+``rst-adornment-faces-alist``, however. So if you need fontification
+deeper than six levels you may want to customize this option. You may
+also want to customize it if you like the general idea of section
+title fontification in ``rst-mode`` but for instance prefer a reversed
+order.
+
+Customizing Conversion
+----------------------
+
+Conversion_ can be customized by the customization options in the
+customization group ``rst-compile``.
+
+If some conversion does not work as expected please check
+the variable ``rst-compile-toolsets`` ::
+
+ M-x customize-option<RETURN>rst-compile-toolsets
+
+This variable defines the commands and other details used for
+conversion. In case of problems please check that the commands are
+either available or customize them to what is available in your
+environment.
+
+.. note:: There are some options in V1.4.1 of ``rst.el`` which should
+ be customization options but are not yet. Customization
+ support will be added in a later version.
+
+.. note:: Please note that there is a package ``rst2pdf`` based on the
+ ReportLab library. Please note that the command of this
+ package requires an additional ``-o`` for naming the output
+ file. This breaks the usual conventions employed by Docutils
+ tools. ``rst-mode`` V1.4.1 does not support this directly.
+
+Other Customizations
+--------------------
+
+``rst-preferred-bullets`` can be customized to hold your preferred set
+of bullets to use for bulleted lists.
+
+``rst-mode-hook`` is a normal major mode hook which may be customized.
+It is run if you enter ``rst-mode``.
+
+Related aspects
+===============
+
+This section covers some general aspects using Emacs_ for editing
+reStructuredText_ source. They are not directly related to
+``rst-mode`` but may enhance your experience.
+
+``text-mode`` Settings
+----------------------
+
+Consult the Emacs_ manual for more ``text-mode`` customizations. In
+particular, you may be interested in setting the following variables,
+functions and modes that pertain somewhat to ``text-mode``:
+
+* ``indent-tabs-mode``
+* ``colon-double-space``
+* ``sentence-end-double-space``
+* ``auto-fill-mode``
+* ``auto-mode-alist``
+
+Editing Tables: Emacs table mode
+--------------------------------
+
+You may want to check out `Emacs table mode`_ to create an edit
+tables, it allows creating ASCII tables compatible with
+reStructuredText_.
+
+.. _Emacs table mode: http://table.sourceforge.net/
+
+Character Processing
+--------------------
+
+Since reStructuredText punts on the issue of character processing,
+here are some useful resources for Emacs_ users in the Unicode world:
+
+* `xmlunicode.el and unichars.el from Norman Walsh
+ <http://nwalsh.com/emacs/xmlchars/index.html>`__
+
+* `An essay by Tim Bray, with example code
+ <http://www.tbray.org/ongoing/When/200x/2003/09/27/UniEmacs>`__
+
+* For Emacs_ users on Mac OS X, here are some useful useful additions
+ to your .emacs file.
+
+ - To get direct keyboard input of non-ASCII characters (like
+ "option-e e" resulting in "é" [eacute]), first enable the option
+ key by setting the command key as your meta key::
+
+ (setq mac-command-key-is-meta t) ;; nil for option key
+
+ Next, use one of these lines::
+
+ (set-keyboard-coding-system 'mac-roman)
+ (setq mac-keyboard-text-encoding kTextEncodingISOLatin1)
+
+ I prefer the first line, because it enables non-Latin-1 characters
+ as well (em-dash, curly quotes, etc.).
+
+ - To enable the display of all characters in the Mac-Roman charset,
+ first create a fontset listing the fonts to use for each range of
+ characters using charsets that Emacs_ understands::
+
+ (create-fontset-from-fontset-spec
+ "-apple-monaco-medium-r-normal--10-*-*-*-*-*-fontset-monaco,
+ ascii:-apple-monaco-medium-r-normal--10-100-75-75-m-100-mac-roman,
+ latin-iso8859-1:-apple-monaco-medium-r-normal--10-100-75-75-m-100-mac-roman,
+ mule-unicode-0100-24ff:-apple-monaco-medium-r-normal--10-100-75-75-m-100-mac-roman")
+
+ Latin-1 doesn't cover characters like em-dash and curly quotes, so
+ "mule-unicode-0100-24ff" is needed.
+
+ Next, use that fontset::
+
+ (set-frame-font "fontset-monaco")
+
+ - To enable cooperation between the system clipboard and the Emacs_
+ kill ring, add this line::
+
+ (set-clipboard-coding-system 'mac-roman)
+
+ Other useful resources are in `Andrew Choi's Emacs 21 for Mac OS X
+ FAQ <http://members.shaw.ca/akochoi-emacs/stories/faq.html>`__.
+
+Credits
+=======
+
+Part of the original code of ``rst.el`` has been written by Martin
+Blais and David Goodger and Wei-Wei Guo. The font-locking came from
+Stefan Merten.
+
+Most of the code has been modified, enhanced and extended by Stefan
+Merten who also is the current maintainer of ``rst.el``.
+
+.. _Emacs: http://www.gnu.org/software/emacs/emacs.html
+.. _reStructuredText: http://docutils.sf.net/rst.html
+.. _Docutils: http://docutils.sf.net/
+
+\f
+
+.. LocalWords: reST utf Merten Blais rst el docutils modeline emacs
+.. LocalWords: Init mEmacs sInit alist setq txt overlines RET nd py
+.. LocalWords: dwim conf toolset pseudoxml pdf Imenu imenu menubar
+.. LocalWords: func toc xmlunicode unichars eacute charset fontset
+.. LocalWords: kTextEncodingISOLatin charsets monaco ascii latin
+.. LocalWords: iso unicode Choi's Goodger Guo
+
+..
+ Local Variables:
+ mode: rst
+ indent-tabs-mode: nil
+ fill-column: 70
+ End:
--- /dev/null
+=====================
+Docutils HTML writers
+=====================
+
+.. contents::
+
+html
+----
+
+`html` is an alias for the default Docutils HTML writer.
+Currently, `html` is mapped to html4css1_.
+
+The target may change with the development of HTML, browsers, Docutils, and
+the web.
+
+* Use ``get_writer_by_name('html')`` or the rst2html.py_ front end, if you
+ want the output to be up-to-date automatically.
+
+* Use a specific writer name or front end, if you depend on stability of the
+ generated HTML code, e.g. because you use a custom style sheet or
+ post-processing that may break otherwise.
+
+
+html4css1
+---------
+
+:aliases: html4, html_
+:front-ends: rst2html4.py, rst2html.py_
+:config: `[html4css1 writer]`_
+
+The HTML Writer module, ``docutils/writers/html4css1.py``, was the first
+Docutils writer and up to release 0.13 the only official HTML writer.
+
+The output conforms to the `XHTML 1 Transitional`_ specification. It does
+not validate as `HTML 4.01 Transitional`_ due to the closing of empty tags
+required in XML but not allowed in HTML 4. However, the output follows the
+`HTML Compatibility Guidelines`_ for proper rendering on most HTML user
+agents.
+
+Correct rendering depends on a CSS_ style sheet. A reference style sheet,
+`html4css1.css`_, is provided and used by default.
+
+To support the `Internet Explorer` (with a market share of about 90% around
+2002, the time this writer was written), documents contain some hard-coded
+formatting hints and are tagged as "text/html" (instead of
+"application/xhtml+xml"). [#IE]_
+
+.. [#IE] Conformance to `CSS 2.1`_ has been added in IE 8 (2009), support
+ for XHTML in IE 9 (2011).
+
+.. _rst2html.py: tools.html#rst2html-py
+.. _[html4css1 writer]: config.html#html4css1-writer
+.. _html4css1.css: ../../docutils/writers/html4css1/html4css1.css
+
+pep_html
+~~~~~~~~
+
+:front-end: rstpep2html.py_
+:config: `[pep_html writer]`_
+
+This is a special writer for the generation of `Python Enhancement
+Proposals`_ (PEPs). It inherits from html4css1_ and adds some `PEP-specific
+options`_, a style sheet and template. The front-end uses also a specialised
+reader.
+
+.. _rstpep2html.py: tools.html#rstpep2html-py
+.. _PEP-specific options:
+.. _[pep_html writer]: config.html#pep-html-writer
+.. _Python Enhancement Proposals: https://www.python.org/dev/peps/
+
+s5_html
+~~~~~~~
+
+:alias: s5
+:front-end: rst2s5.py_
+:config: `[s5_html writer]`_
+
+The `s5` writer inherits from html4css1_. It produces XHTML for use with
+S5_, the “Simple Standards-based Slide Show System” by Eric Meyer. See
+`Easy Slide Shows With reST & S5`_ for details.
+
+.. _rst2s5.py: tools.html#rst2s5-py
+.. _[s5_html writer]: config.html#s5-html-writer
+.. _Easy Slide Shows With reST & S5: slide-shows.html
+.. _S5: http://meyerweb.com/eric/tools/s5/
+.. _theme: tools.html#themes
+
+
+html5_polyglot
+--------------
+
+:aliases: html5
+:front-end: rst2html5.py_
+:config: `[html5 writer]`_
+
+The ``html5_polyglot`` writer generates `polyglot HTML`_ [#]_ output, valid
+XML [#safetext]_ that is compatible with `HTML5`_. New features and elements
+will only be used if they are widely supported to make documents `viewable
+with any browser`_.
+
+There is no hard-coded formatting information in the HTML document. Correct
+rendering of elements not directly supported by HTML depends on a CSS_ style
+sheet. The provided style sheets minimal.css_ and plain.css_ define required
+and optional styling rules respectively. Adaption of the layout is possible
+with `custom style sheets`_. [#safetext]_
+
+New in Docutils 0.13
+
+.. [#] see also `Benefits of polyglot XHTML5`_
+.. [#safetext] The validity of raw HTML and custom stylesheets must be
+ ensured by the author (e.g. using `safe text content`_).
+
+.. _rst2html5.py: tools.html#rst2html5-py
+.. _[html5 writer]: config.html#html5-writer
+.. _minimal.css: ../../docutils/writers/html5_polyglot/minimal.css
+.. _plain.css: ../../docutils/writers/html5_polyglot/plain.css
+.. _custom style sheets: ../howto/html-stylesheets.html
+.. _viewable with any browser: http://www.anybrowser.org/campaign
+.. _Benefits of polyglot XHTML5: http://xmlplease.com/xhtml/xhtml5polyglot/
+.. _safe text content:
+ https://www.w3.org/TR/html-polyglot/#dfn-safe-text-content
+
+
+HTML writers in the sandbox
+---------------------------
+
+There are two more HTML writers in the sandbox_:
+
+.. _sandbox: ../dev/policies.html#the-sandbox
+
+xhtml11
+~~~~~~~
+:aliases: xhtml, html4strict
+:front-end: rst2xhtml.py
+:config: `[xhtml11 writer]`
+
+`XHTML 1.1`_ is the latest version of the XML based `extensible
+Hypertext Markup Language` with an official DTD.
+
+The `xhtml11 writer`_ lives in the Docutils sandbox_ since 2008. The output
+conforms to the strict requirements of `XHTML 1.1`_.
+
+.. _xhtml11 writer: ../../../sandbox/html4strict/README.html
+
+
+html4trans
+~~~~~~~~~~
+
+:front-end: rst2html_trans.py_
+
+The `HTML writer for lightweight browsers`_ lives in the Docutils sandbox
+(`sandbox/html4trans`_) since 2008. It removes the dependency on CSS. The
+output conforms to `XHTML 1 Transitional`_ and contains sufficient
+formatting information for rendering without style sheet. (Of course, this
+has some drawbacks_.)
+
+.. _HTML writer for lightweight browsers:
+ ../../../sandbox/html4trans/README.html
+.. _drawbacks: ../../../sandbox/html4trans/README.html#drawbacks
+.. _sandbox/html4trans: ../../../sandbox/html4trans
+.. _rst2html_trans.py: ../../../sandbox/html4trans/tools/rst2html_trans.py
+
+
+Overview
+--------
+
+=============== =========== ============== ================= ===========
+name alias(es) `front-end`_ HTML version CSS version
+=============== =========== ============== ================= ===========
+html4css1_ html4, rst2html4.py, `XHTML 1 `CSS 1`_
+ html_ rst2html.py Transitional`_
+
+pep_html_ .. rstpep2html.py `XHTML 1 `CSS 1`_
+ Transitional`_
+
+s5_html_ s5 rst2s5.py `XHTML 1 `CSS 1`_
+ Transitional`_
+
+html5_polyglot_ html5 rst2html5.py `HTML5`_ `CSS 3`_
+
+xhtml11_ xhtml, rst2xhtml.py `XHTML 1.1`_ `CSS 3`_
+ html4strict
+
+html4trans_ .. rst2html_trans `XHTML 1 no CSS
+ Transitional`_ required
+=============== =========== ============== ================= ===========
+
+
+References
+----------
+
+_`HTML5`
+ `HTML5, A vocabulary and associated APIs for HTML and XHTML`,
+ W3C Recommendation, 28 October 2014.
+ http://www.w3.org/TR/html5/
+
+_`XHTML 1.1`
+ `XHTML™ 1.1 - Module-based XHTML - Second Edition`,
+ W3C Recommendation, 23 November 2010.
+ http://www.w3.org/TR/xhtml11/
+
+_`XHTML 1 Transitional`
+ `Transitional version`_ of:
+ `XHTML™ 1.0 The Extensible HyperText Markup Language (Second
+ Edition)`, `A Reformulation of HTML 4 in XML 1.0`,
+ W3C Recommendation, 26 January 2000, revised 1 August 2002.
+ http://www.w3.org/TR/xhtml1/
+
+_`XHTML Basic`
+ `XHTML™ Basic 1.1 - Second Edition`,
+ W3C Recommendation, 23 November 2010.
+ http://www.w3.org/TR/xhtml-basic/
+
+.. _transitional version:
+ http://www.w3.org/TR/xhtml1/#a_dtd_XHTML-1.0-Transitional
+
+_`HTML 4.01 Transitional`
+ Transitional version of:
+ `HTML 4.01 Specification`, W3C Recommendation 24 December 1999.
+ http://www.w3.org/TR/html4/
+
+.. _`CSS 1`:
+
+_`CSS Level 1`:
+ The features defined in the `CSS1 specification`_, but using the syntax
+ and definitions in the `CSS 2.1`_ specification.
+
+_`CSS 2.1` `Cascading Style Sheets Level 2 Revision 1 (CSS 2.1) Specification`,
+ W3C Recommendation 07 June 2011.
+ http://www.w3.org/TR/CSS21/
+
+_`CSS 3`:
+ CSS Level 3 builds on CSS Level 2 module by module, using the CSS2.1
+ specification as its core.
+
+ Specifications: http://www.w3.org/Style/CSS/specs.en.html
+
+ Validator: http://jigsaw.w3.org/css-validator/
+
+.. other references
+ ----------------
+
+.. _HTML Compatibility Guidelines: http://www.w3.org/TR/xhtml1/#guidelines
+.. _CSS: http://www.w3.org/TR/CSS/
+.. _CSS1 specification: http://www.w3.org/TR/2008/REC-CSS1-20080411/
+.. _polyglot HTML: http://www.w3.org/TR/html-polyglot/
+
+ .. Beware. This specification is no longer in active maintenance and the
+ HTML Working Group does not intend to maintain it further.
+
+.. Appendix
+
+
+ On the question of Polyglot markup, there seems to be little
+ consensus. One line of argument suggests that, to the extent that it
+ is practical to obey the Robustness principle, it makes sense to do
+ so. That is, if you're generating HTML markup for the web, and you can
+ generate Polyglot markup that is also directly consumable as XML, you
+ should do so. Another line of argument suggests that even under the
+ most optimistic of projections, so tiny a fraction of the web will
+ ever be written in Polyglot that there's no practical benefit to
+ pursuing it as a general strategy for consuming documents from the
+ web. If you want to consume HTML content, use an HTML parser that
+ produces an XML-compatible DOM or event stream.
+
+ -- https://www.w3.org/TR/html-xml-tf-report/#conclusions
+
+ Further development
+
+ On 2016-05-25, David Goodger wrote:
+
+ > In addition, I'd actually like to see the HTML writer(s) with
+ > fully-parameterized classes, i.e. removing hard-coded *classes* as well as
+ > formatting. This way, any user who wants to (e.g.) write reST for use with
+ > Bootstrap can easily work around any naming conflicts.
+
+
+
+ Problems with html4css1 writer:
+
+ 1. Limiting ourself to CSS Level 1 requires use of hard-coded HTML
+ formatting to get all rST objects mapped to HTML.
+ Hard-coded HTML formatting is considered bad practice.
+
+ 2. Maths cannot be included in MathML format without rendering a
+ hmtl4css1-generated document invalid.
+
+ (XHTML 1.1. is the only member of the "HTML4 family" allowing embedding
+ of MathML. However, hard-coded HTML formatting prevents its use.)
+
+
+
+ Comparison of current HTML versions
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+ XHTML1.1
+ """"""""
+
+ +2 XML-based with official DTD
+ +1 allows processing with XML-tool-chain
+ +1 allows validating against the DTD
+
+ +1 writer exists (in sandbox) and in active use since 2008
+
+ -1 "old" format
+ -1 requires to work around restrictions lifted in HTML5
+ ("start" argument for enumerated lists, some tags in parsed literal)
+ which makes code and documents more complicated
+
+ HTML5
+ """""
+ +1 more recent
+ +1 simpler to write, less restrictions
+
+ +1 writer exists and in active use since 2015
+
+ +1 new page structure elements such as <main>, <section>, <article>,
+ <header>, <footer>, <aside>, <nav> and <figure>
+ provide better matches for the rst document model.
+
+ -1 new elements not yet supported by many browsers.
+
+ -2 no DTD
+ - no proper validation possible (there is an experimental validator)
+ - no standard interface to post-processing XML-tools
+
+ -1 two concurring definitions:
+ W3C standard and WHATWG "HTML Living Standard".
+
+.. _front-end: tools.html
--- /dev/null
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://web.resource.org/cc/"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:sodipodi="http://inkscape.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="1224.0000pt"
+ height="792.00000pt"
+ id="svg16130"
+ sodipodi:version="0.32"
+ inkscape:version="0.42"
+ sodipodi:docbase="/Users/david/projects/docutils/s5-branch/docs/user/images"
+ sodipodi:docname="rsp.svg"
+ inkscape:export-filename="/Users/david/projects/docutils/s5-branch/docs/user/images/rsp-empty.png"
+ inkscape:export-xdpi="90.000000"
+ inkscape:export-ydpi="90.000000">
+ <defs
+ id="defs16132">
+ <radialGradient
+ cx="64.960804"
+ cy="86.732626"
+ fx="64.394720"
+ fy="89.843742"
+ id="radialGradient1157"
+ r="4.6795605"
+ xlink:href="#linearGradient1125"
+ gradientTransform="scale(1.232968,0.811051)"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ id="linearGradient1147"
+ x1="30.807715"
+ x2="9.1659926"
+ xlink:href="#linearGradient1129"
+ y1="134.41771"
+ y2="128.61883"
+ gradientTransform="scale(2.035443,0.491293)"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ id="linearGradient1146"
+ x1="23.109005"
+ x2="23.655650"
+ xlink:href="#linearGradient1129"
+ y1="86.372661"
+ y2="75.530011"
+ gradientTransform="scale(1.564854,0.639037)"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ id="linearGradient1150"
+ x1="7.1055503"
+ x2="37.417715"
+ xlink:href="#linearGradient1152"
+ y1="148.97907"
+ y2="149.31015"
+ gradientTransform="scale(1.328405,0.752782)"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ id="linearGradient1152">
+ <stop
+ id="stop1153"
+ offset="0.00000000"
+ style="stop-color:#ffffff;stop-opacity:0.00000000;" />
+ <stop
+ id="stop1155"
+ offset="0.44302326"
+ style="stop-color:#ffffff;stop-opacity:0.46274510;" />
+ <stop
+ id="stop1154"
+ offset="1.0000000"
+ style="stop-color:#ffffff;stop-opacity:0.00000000;" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient1151"
+ x1="29.180973"
+ x2="12.077421"
+ xlink:href="#linearGradient1152"
+ y1="176.88234"
+ y2="176.49016"
+ gradientTransform="scale(1.503932,0.664924)"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ id="linearGradient1135"
+ x1="5.6004575"
+ x2="57.337623"
+ xlink:href="#linearGradient1136"
+ y1="125.70108"
+ y2="125.70108"
+ gradientTransform="scale(1.240748,0.805966)"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ id="linearGradient1129">
+ <stop
+ id="stop1130"
+ offset="0.00000000"
+ style="stop-color:#ffffff;stop-opacity:0.00000000;" />
+ <stop
+ id="stop1131"
+ offset="1.0000000"
+ style="stop-color:#ffffff;stop-opacity:0.64583331;" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient1128"
+ x1="76.620649"
+ x2="89.927438"
+ xlink:href="#linearGradient1129"
+ y1="79.202017"
+ y2="132.51965"
+ gradientTransform="scale(1.342210,0.745040)"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ id="linearGradient1133"
+ x1="95.959445"
+ x2="95.959445"
+ xlink:href="#linearGradient1125"
+ y1="96.280971"
+ y2="6.0312801"
+ gradientTransform="scale(1.356086,0.737416)"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ id="linearGradient1136">
+ <stop
+ id="stop1137"
+ offset="0.00000000"
+ style="stop-color:#000000;stop-opacity:1.0000000;" />
+ <stop
+ id="stop1138"
+ offset="1.0000000"
+ style="stop-color:#454545;stop-opacity:1.0000000;" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient1145"
+ x1="26.716417"
+ x2="57.535761"
+ xlink:href="#linearGradient1136"
+ y1="72.512797"
+ y2="104.12337"
+ gradientTransform="scale(1.435519,0.696612)"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ id="linearGradient1125">
+ <stop
+ id="stop1126"
+ offset="0.00000000"
+ style="stop-color:#979797;stop-opacity:1.0000000;" />
+ <stop
+ id="stop1163"
+ offset="0.35050300"
+ style="stop-color:#fafafa;stop-opacity:1.0000000;" />
+ <stop
+ id="stop1164"
+ offset="0.36050299"
+ style="stop-color:#9f9f9f;stop-opacity:1.0000000;" />
+ <stop
+ id="stop1127"
+ offset="1.0000000"
+ style="stop-color:#ffffff;stop-opacity:1.0000000;" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient1134"
+ x1="66.560545"
+ x2="26.091148"
+ xlink:href="#linearGradient1125"
+ y1="135.98955"
+ y2="85.436682"
+ gradientTransform="scale(1.892867,0.528299)"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ id="linearGradient1243">
+ <stop
+ id="stop1244"
+ offset="0.00000000"
+ style="stop-color:#000000;stop-opacity:0.19791667;" />
+ <stop
+ id="stop1245"
+ offset="1.0000000"
+ style="stop-color:#000000;stop-opacity:0.00000000;" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient1149"
+ x1="508.22840"
+ x2="505.28565"
+ xlink:href="#linearGradient1243"
+ y1="556.37391"
+ y2="107.87502"
+ gradientTransform="scale(1.347706,0.742001)"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1243"
+ id="linearGradient16217"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="scale(1.347706,0.742001)"
+ x1="508.22840"
+ y1="556.37391"
+ x2="505.28565"
+ y2="107.87502" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1243"
+ id="linearGradient16219"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="scale(1.347706,0.742001)"
+ x1="508.22840"
+ y1="556.37391"
+ x2="505.28565"
+ y2="107.87502" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1243"
+ id="linearGradient16221"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="scale(1.347706,0.742001)"
+ x1="508.22840"
+ y1="556.37391"
+ x2="505.28565"
+ y2="107.87502" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1243"
+ id="linearGradient16223"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="scale(1.347706,0.742001)"
+ x1="508.22840"
+ y1="556.37391"
+ x2="505.28565"
+ y2="107.87502" />
+ </defs>
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="0.52132701"
+ inkscape:cx="650.00000"
+ inkscape:cy="497.00000"
+ inkscape:document-units="px"
+ inkscape:current-layer="layer7"
+ showgrid="true"
+ inkscape:grid-bbox="false"
+ inkscape:grid-points="false"
+ gridspacingx="5.0000000px"
+ gridspacingy="5.0000000px"
+ gridtolerance="2.5000000px"
+ inkscape:window-width="920"
+ inkscape:window-height="603"
+ inkscape:window-x="20"
+ inkscape:window-y="73" />
+ <metadata
+ id="metadata16135">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ inkscape:label="base"
+ inkscape:groupmode="layer"
+ id="layer1"
+ style="display:inline">
+ <g
+ id="g17404"
+ transform="translate(100.0000,-75.00000)"
+ style="stroke:none;stroke-opacity:1.0000000">
+ <rect
+ ry="38.000000"
+ rx="38.000000"
+ style="fill:#ffffff;fill-opacity:0.14999999;stroke:none;stroke-opacity:1.0000000"
+ id="rrect19"
+ width="1100.0000"
+ height="844.00000"
+ x="0.0000000"
+ y="146.00000" />
+ <rect
+ ry="36.000000"
+ rx="36.000000"
+ style="fill:#ffffff;fill-opacity:0.099999972;stroke:none;stroke-opacity:1.0000000"
+ id="rrect18"
+ width="1096.0000"
+ height="840.00000"
+ x="2.0000000"
+ y="148.00000" />
+ <rect
+ ry="34.000000"
+ rx="34.000000"
+ style="fill:#ffffff;fill-opacity:0.099999972;stroke:none;stroke-opacity:1.0000000"
+ id="rrect17"
+ width="1092.0000"
+ height="836.00000"
+ x="4.0000000"
+ y="150.00000" />
+ <rect
+ ry="32.000000"
+ rx="32.000000"
+ style="fill:#ffffff;fill-opacity:0.099999972;stroke:none;stroke-opacity:1.0000000"
+ id="rrect16"
+ width="1088.0000"
+ height="832.00000"
+ x="6.0000000"
+ y="152.00000" />
+ <rect
+ ry="30.000000"
+ rx="30.000000"
+ style="fill:#ffffff;fill-opacity:0.099999972;stroke:none;stroke-opacity:1.0000000"
+ id="rrect15"
+ width="1084.0000"
+ height="828.00000"
+ x="8.0000000"
+ y="154.00000" />
+ <rect
+ ry="28.000000"
+ rx="28.000000"
+ style="fill:#ffffff;fill-opacity:0.099999972;stroke:none;stroke-opacity:1.0000000"
+ id="rrect14"
+ width="1080.0000"
+ height="824.00000"
+ x="10.000000"
+ y="156.00000" />
+ <rect
+ ry="26.000000"
+ rx="26.000000"
+ style="fill:#ffffff;fill-opacity:0.099999972;stroke:none;stroke-opacity:1.0000000"
+ id="rrect13"
+ width="1076.0000"
+ height="820.00000"
+ x="12.000000"
+ y="158.00000" />
+ <rect
+ ry="24.000000"
+ rx="24.000000"
+ style="fill:#ffffff;fill-opacity:0.099999972;stroke:none;stroke-opacity:1.0000000"
+ id="rrect12"
+ width="1072.0000"
+ height="816.00000"
+ x="14.000000"
+ y="160.00000" />
+ <rect
+ ry="22.000000"
+ rx="22.000000"
+ style="fill:#ffffff;fill-opacity:0.099999972;stroke:none;stroke-opacity:1.0000000"
+ id="rrect11"
+ width="1068.0000"
+ height="812.00000"
+ x="16.000000"
+ y="162.00000" />
+ <rect
+ ry="20.000000"
+ rx="20.000000"
+ style="fill:#ffffff;fill-opacity:0.099999972;stroke:none;stroke-opacity:1.0000000"
+ id="rrect10"
+ width="1064.0000"
+ height="808.00000"
+ x="18.000000"
+ y="164.00000" />
+ <rect
+ ry="18.000000"
+ rx="18.000000"
+ style="fill:#ffffff;fill-opacity:0.099999972;stroke:none;stroke-opacity:1.0000000"
+ id="rrect9"
+ width="1060.0000"
+ height="804.00000"
+ x="20.000000"
+ y="166.00000" />
+ <rect
+ ry="16.000000"
+ rx="16.000000"
+ style="fill:#ffffff;fill-opacity:0.099999972;stroke:none;stroke-opacity:1.0000000"
+ id="rrect8"
+ width="1056.0000"
+ height="800.00000"
+ x="22.000000"
+ y="168.00000" />
+ <rect
+ ry="14.000000"
+ rx="14.000000"
+ style="fill:#ffffff;fill-opacity:0.11999995;stroke:none;stroke-opacity:1.0000000"
+ id="rrect7"
+ width="1052.0000"
+ height="796.00000"
+ x="24.000000"
+ y="170.00000" />
+ <rect
+ ry="12.000000"
+ rx="12.000000"
+ style="fill:#ffffff;fill-opacity:0.14000000;stroke:none;stroke-opacity:1.0000000"
+ id="rrect6"
+ width="1048.0000"
+ height="792.00000"
+ x="26.000000"
+ y="172.00000" />
+ <rect
+ ry="10.000000"
+ rx="10.000000"
+ style="fill:#ffffff;fill-opacity:0.15999998;stroke:none;stroke-opacity:1.0000000"
+ id="rrect5"
+ width="1044.0000"
+ height="788.00000"
+ x="28.000000"
+ y="174.00000" />
+ <rect
+ ry="8.0000000"
+ rx="8.0000000"
+ style="fill:#ffffff;fill-opacity:0.17999996;stroke:none;stroke-opacity:1.0000000"
+ id="rrect4"
+ width="1040.0000"
+ height="784.00000"
+ x="30.000000"
+ y="176.00000" />
+ <rect
+ ry="6.0000000"
+ rx="6.0000000"
+ style="fill:#ffffff;fill-opacity:0.20000000;stroke:none;stroke-opacity:1.0000000"
+ id="rrect3"
+ width="1036.0000"
+ height="780.00000"
+ x="32.000000"
+ y="178.00000" />
+ <rect
+ ry="4.0000000"
+ rx="4.0000000"
+ style="fill:#ffffff;fill-opacity:0.21999998;stroke:none;stroke-opacity:1.0000000"
+ id="rrect2"
+ width="1032.0000"
+ height="776.00000"
+ x="34.000000"
+ y="180.00000" />
+ <rect
+ ry="2.0000000"
+ rx="2.0000000"
+ style="fill:#ffffff;fill-opacity:0.49999997;stroke:none;stroke-opacity:1.0000000"
+ id="rrect1"
+ width="1028.0000"
+ height="772.00000"
+ x="36.000000"
+ y="182.00000" />
+ <rect
+ style="fill:#ffffff;fill-opacity:1.0000000;stroke:none;stroke-width:2.0000000;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-dasharray:none;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000"
+ id="rect7529"
+ width="1024.0000"
+ height="768.00000"
+ x="38.000000"
+ y="184.00000" />
+ </g>
+ </g>
+ <g
+ inkscape:groupmode="layer"
+ id="layer6"
+ inkscape:label="cuts"
+ style="display:inline">
+ <g
+ style="display:inline"
+ id="g17268"
+ transform="matrix(3.955288,0.000000,0.000000,3.955288,-1133.851,-788.5280)">
+ <g
+ transform="matrix(-1.028194e-2,1.033891e-2,-1.033891e-2,-1.028194e-2,587.3686,366.0048)"
+ style="fill:#00ff00;fill-opacity:1.0000000;stroke:#000000;stroke-width:47.034168;stroke-miterlimit:4.0000000;stroke-dasharray:none;stroke-opacity:1.0000000"
+ id="g17126">
+ <path
+ style="fill:#00ff00;fill-opacity:1.0000000;stroke:#000000;stroke-width:47.034168;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-dasharray:none;stroke-opacity:1.0000000"
+ sodipodi:nodetypes="ccccc"
+ id="path17128"
+ d="M 7602.2995,10592.638 L 6351.2995,11841.638 L 7603.2995,9842.6385 L 8851.2995,11843.638 L 7602.2995,10592.638 z " />
+ </g>
+ <path
+ id="text17130"
+ d="M 346.56856,325.28003 C 346.01656,325.52003 345.34456,325.66403 344.48056,325.66403 C 342.70456,325.66403 341.26456,324.51203 341.26456,322.35203 C 341.24056,320.43204 342.48856,319.06403 344.40856,319.06403 C 345.36856,319.06403 346.01656,319.23203 346.44856,319.42403 L 347.02456,316.71203 C 346.25656,316.42403 345.20056,316.25603 344.24056,316.25603 C 339.87256,316.25603 337.52056,319.06404 337.52056,322.49603 C 337.52056,326.19203 339.94456,328.52003 343.73656,328.52003 C 345.12856,328.52003 346.35256,328.28003 347.00056,327.96803 L 346.56856,325.28003 M 360.08468,316.52003 L 356.43668,316.52003 L 356.43668,323.50403 C 356.43668,323.81603 356.38868,324.08003 356.29268,324.29603 C 356.07668,324.87203 355.47668,325.56803 354.46868,325.56803 C 353.17269,325.56803 352.62068,324.53603 352.62068,322.83203 L 352.62068,316.52003 L 348.97268,316.52003 L 348.97268,323.40803 C 348.97268,327.03203 350.70069,328.52003 353.10068,328.52003 C 355.21268,328.52003 356.31669,327.32003 356.77268,326.60003 L 356.84468,326.60003 L 357.01268,328.25603 L 360.18068,328.25603 C 360.13268,327.27204 360.08468,326.02403 360.08468,324.48803 L 360.08468,316.52003 M 363.54031,314.31203 L 363.54031,316.52003 L 361.98031,316.52003 L 361.98031,319.20803 L 363.54031,319.20803 L 363.54031,324.03203 C 363.54031,325.68803 363.87631,326.81603 364.54831,327.51203 C 365.14831,328.11203 366.13231,328.52003 367.30831,328.52003 C 368.31631,328.52003 369.20431,328.37603 369.66031,328.20803 L 369.63631,325.44803 C 369.30031,325.52003 369.06031,325.54403 368.55631,325.54403 C 367.47631,325.54403 367.11631,324.89603 367.11631,323.48003 L 367.11631,319.20803 L 369.73231,319.20803 L 369.73231,316.52003 L 367.11631,316.52003 L 367.11631,313.32803 L 363.54031,314.31203 M 371.17681,327.68003 C 372.06481,328.16003 373.43281,328.52003 374.96881,328.52003 C 378.32881,328.52003 380.03281,326.91203 380.03281,324.70403 C 380.00881,323.00004 379.09681,321.84803 376.86481,321.10403 C 375.42481,320.60003 374.96881,320.31203 374.96881,319.73603 C 374.96881,319.16003 375.47281,318.80003 376.36081,318.80003 C 377.34481,318.80003 378.37681,319.18403 378.90481,319.44803 L 379.52881,316.95203 C 378.80881,316.59203 377.60881,316.25603 376.24081,316.25603 C 373.33681,316.25603 371.46481,317.91204 371.46481,320.12003 C 371.44081,321.48803 372.37681,322.83203 374.82481,323.62403 C 376.16881,324.08003 376.52881,324.36803 376.52881,324.99203 C 376.52881,325.59203 376.07281,325.95203 374.96881,325.95203 C 373.88881,325.95203 372.49681,325.49603 371.82481,325.08803 L 371.17681,327.68003"
+ style="font-size:24.000000px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:center;line-height:125.00000%;writing-mode:lr-tb;text-anchor:middle;fill:#007f00;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000pt;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Myriad" />
+ </g>
+ </g>
+ <g
+ inkscape:groupmode="layer"
+ id="layer5"
+ inkscape:label="scissors"
+ style="display:inline">
+ <g
+ style="display:inline"
+ transform="matrix(-0.261242,0.531875,-0.531875,-0.261243,609.4123,269.4384)"
+ id="g834">
+ <path
+ transform="matrix(-0.974540,0.224211,0.224211,0.974540,434.7533,-39.90828)"
+ style="font-size:12.000000px;fill:#dadadb;fill-rule:evenodd;stroke:#000000;stroke-width:10.000006;stroke-linejoin:round;stroke-dasharray:none"
+ id="path693"
+ d="M 130.58000,19.228100 C 131.42800,19.228100 283.20600,268.51700 283.20600,268.51700 C 283.20600,268.51700 237.41800,294.80300 238.26600,294.80300 C 239.11400,294.80300 112.77400,100.62900 130.58000,19.228100 z " />
+ <path
+ style="font-size:12.000000px;fill:#1f1f61;fill-opacity:1.0000000;fill-rule:evenodd;stroke:#000000;stroke-width:10.000000;stroke-linejoin:bevel;stroke-dasharray:none"
+ id="path596"
+ d="M 267.36640,300.28500 C 267.36640,300.28500 221.96450,419.33820 230.36720,437.01870 C 230.00410,447.80450 196.57070,496.47240 174.95750,496.94460 C 156.32120,498.11630 95.023300,483.45520 104.85110,423.19450 C 116.53670,361.19710 166.80670,382.68650 186.68190,380.35660 C 206.55780,378.02600 240.34010,301.17560 216.89540,284.78780 C 243.06010,291.66780 266.70660,302.06270 267.36640,300.28500 z M 178.01080,388.46270 C 110.22310,370.58330 97.043850,476.92290 157.42350,483.15570 C 225.11850,486.03500 224.54920,396.02940 178.01080,388.46270 z " />
+ <path
+ transform="matrix(0.984591,0.174877,-0.174877,0.984591,41.27270,-35.37063)"
+ style="font-size:12.000000px;fill:#dadadb;fill-rule:evenodd;stroke:#000000;stroke-width:9.9999933;stroke-linejoin:bevel;stroke-dasharray:none"
+ id="path674"
+ d="M 130.58000,19.228100 C 131.42800,19.228100 283.20600,268.51700 283.20600,268.51700 C 283.20600,268.51700 237.41800,294.80300 238.26600,294.80300 C 239.11400,294.80300 112.77400,100.62900 130.58000,19.228100 z " />
+ <path
+ transform="translate(161.5948,57.16911)"
+ style="font-size:12.000000px;fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:6.2500000;stroke-dasharray:none"
+ sodipodi:nodetypes="ccc"
+ id="path710"
+ d="M 81.400500,200.68300 C 66.137900,201.53100 63.594200,225.27300 81.400500,226.12100 C 98.359000,225.27300 98.359200,200.68300 81.400500,200.68300 z " />
+ <path
+ transform="translate(161.5948,57.16911)"
+ style="font-size:12.000000px;fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:6.2500000;stroke-dasharray:none"
+ id="path711"
+ d="M 69.529600,209.16300 C 71.225500,209.16300 86.488100,224.42500 86.488100,224.42500" />
+ <path
+ transform="translate(161.5948,57.16911)"
+ style="font-size:12.000000px;fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:6.2500000;stroke-dasharray:none"
+ sodipodi:nodetypes="cc"
+ id="path712"
+ d="M 76.313000,203.22700 C 77.160900,203.22700 92.423500,218.49000 92.423500,218.49000" />
+ <path
+ style="font-size:12.000000px;fill:#e6ffff;fill-opacity:0.75000000;fill-rule:evenodd;stroke-width:1.0000000pt"
+ sodipodi:nodetypes="cccc"
+ id="path717"
+ d="M 311.59912,21.282200 C 312.44712,21.282200 250.54912,207.82500 250.54912,207.82500 C 250.54912,207.82500 257.17737,220.62188 259.72037,219.77388 C 262.26437,218.92588 318.38312,30.609400 311.59912,21.282200 z " />
+ <path
+ transform="translate(-3.750000,3.750000)"
+ style="font-size:12.000000px;fill-opacity:0.31851897;fill-rule:evenodd;stroke-width:1.0000000pt"
+ sodipodi:nodetypes="ccccc"
+ id="path718"
+ d="M 236.85900,262.03100 L 240.39000,257.08300 L 256.63200,272.60800 L 252.68100,276.70800 L 236.85900,262.03100 z " />
+ <path
+ style="font-size:12.000000px;fill:#1f1f61;fill-opacity:1.0000000;fill-rule:evenodd;stroke:#000000;stroke-width:10.000000;stroke-linejoin:bevel;stroke-dasharray:none"
+ id="path590"
+ d="M 319.25070,379.53570 C 386.05280,358.26700 404.56760,463.80860 344.57810,473.07250 C 277.11370,479.35530 273.15220,389.43500 319.25070,379.53570 z M 225.57020,295.96700 C 225.57020,295.96700 276.90680,412.58430 269.40450,430.66530 C 270.31010,441.41910 306.15060,488.34270 327.76030,487.72650 C 346.43190,487.95870 406.91430,470.23100 394.06590,410.54120 C 379.27480,349.21050 330.15000,373.20280 310.18270,371.87620 C 290.21460,370.54890 252.60710,295.49620 275.19730,277.94910 C 249.41200,286.13730 226.31860,297.70920 225.57020,295.96700 z " />
+ </g>
+ </g>
+ <g
+ inkscape:groupmode="layer"
+ id="layer4"
+ inkscape:label="breaks"
+ style="display:inline">
+ <g
+ style="display:inline"
+ id="g17263"
+ transform="matrix(3.955288,0.000000,0.000000,3.955288,-654.3060,-855.6644)">
+ <g
+ transform="matrix(0.000000,1.458120e-2,1.458120e-2,0.000000,167.9907,189.6206)"
+ style="fill:#00ff00;fill-opacity:1.0000000;stroke:#000000;stroke-width:47.034168;stroke-miterlimit:4.0000000;stroke-dasharray:none;stroke-opacity:1.0000000"
+ id="g2604">
+ <path
+ style="fill:#00ff00;fill-opacity:1.0000000;stroke:#000000;stroke-width:47.034168;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-dasharray:none;stroke-opacity:1.0000000"
+ sodipodi:nodetypes="ccccc"
+ id="path2606"
+ d="M 7601.0000,11063.000 L 6350.0000,12312.000 L 7602.0000,10313.000 L 8850.0000,12314.000 L 7601.0000,11063.000 z " />
+ </g>
+ <path
+ id="text17114"
+ d="M 299.55643,273.07213 C 299.55643,274.39213 299.50843,275.80813 299.46043,276.57613 L 302.55643,276.57613 L 302.70043,274.94413 L 302.74843,274.94413 C 303.56443,276.33613 304.90843,276.84013 306.27643,276.84013 C 308.96443,276.84013 311.62843,274.72813 311.62843,270.50413 C 311.65243,266.90413 309.61243,264.57613 306.80443,264.57613 C 305.17243,264.57613 303.94843,265.22413 303.25243,266.23213 L 303.20443,266.23213 L 303.20443,259.53613 L 299.55643,259.53613 L 299.55643,273.07213 M 303.20443,269.85613 C 303.20443,269.61613 303.22843,269.40013 303.27643,269.18413 C 303.51643,268.12813 304.42843,267.38413 305.41243,267.38413 C 307.11643,267.38413 307.93243,268.82413 307.93243,270.64813 C 307.93243,272.76013 306.97243,273.96013 305.41243,273.96013 C 304.35643,273.96013 303.51643,273.19213 303.27643,272.23213 C 303.22843,272.04013 303.20443,271.82413 303.20443,271.58413 L 303.20443,269.85613 M 313.90018,276.57613 L 317.54818,276.57613 L 317.54818,270.64813 C 317.54818,270.33613 317.57218,270.07213 317.62018,269.83213 C 317.86018,268.68013 318.77218,267.98413 320.11618,267.98413 C 320.52418,267.98413 320.81218,268.03213 321.12418,268.08013 L 321.12418,264.64813 C 320.86018,264.60013 320.69218,264.57613 320.35618,264.57613 C 319.20418,264.57613 317.78818,265.29613 317.18818,267.02413 L 317.09218,267.02413 L 316.94818,264.84013 L 313.82818,264.84013 C 313.90018,265.84813 313.92418,266.97613 313.92418,268.70413 L 313.90018,276.57613 M 333.40881,271.87213 C 333.45681,271.58413 333.52881,271.03213 333.52881,270.40813 C 333.52881,267.50413 332.08880,264.55213 328.29681,264.55213 C 324.24081,264.55213 322.36881,267.84013 322.36881,270.81613 C 322.36881,274.51213 324.64881,276.81613 328.63281,276.81613 C 330.21681,276.81613 331.68081,276.57613 332.88081,276.07213 L 332.40081,273.60013 C 331.41681,273.93613 330.40881,274.10413 329.16081,274.10413 C 327.45681,274.10413 325.96881,273.38413 325.84881,271.84813 L 333.40881,271.87213 M 325.82481,269.35213 C 325.92081,268.39213 326.54481,266.97613 328.10481,266.97613 C 329.76081,266.97613 330.14481,268.48813 330.14481,269.35213 L 325.82481,269.35213 M 345.46506,269.64013 C 345.46506,266.88013 344.24105,264.57613 340.32906,264.57613 C 338.19306,264.57613 336.58506,265.17613 335.76906,265.63213 L 336.44106,267.96013 C 337.20906,267.50413 338.48106,267.09613 339.68106,267.09613 C 341.48106,267.09613 341.81706,267.98413 341.81706,268.60813 L 341.81706,268.75213 C 337.66506,268.75213 334.92906,270.19213 334.92906,273.24013 C 334.92906,275.11213 336.34506,276.84013 338.72106,276.84013 C 340.11306,276.84013 341.31306,276.33613 342.08106,275.40013 L 342.15306,275.40013 L 342.36906,276.57613 L 345.65706,276.57613 C 345.51306,275.92813 345.46506,274.84813 345.46506,273.74413 L 345.46506,269.64013 M 341.93706,272.30413 C 341.93706,272.52013 341.91306,272.73613 341.86506,272.92813 C 341.62506,273.67213 340.85706,274.27213 339.96906,274.27213 C 339.15306,274.27213 338.52906,273.81613 338.52906,272.88013 C 338.52906,271.48813 340.01706,271.03213 341.93706,271.03213 L 341.93706,272.30413 M 352.00131,259.53613 L 348.35331,259.53613 L 348.35331,276.57613 L 352.00131,276.57613 L 352.00131,272.92813 L 352.91331,271.75213 L 355.76931,276.57613 L 360.25731,276.57613 L 355.45731,269.59213 L 359.65731,264.84013 L 355.26531,264.84013 L 352.88931,268.39213 C 352.60131,268.82413 352.31331,269.30413 352.04931,269.80813 L 352.00131,269.80813 L 352.00131,259.53613 M 360.71256,276.00013 C 361.60056,276.48013 362.96856,276.84013 364.50456,276.84013 C 367.86455,276.84013 369.56856,275.23213 369.56856,273.02413 C 369.54456,271.32013 368.63256,270.16813 366.40056,269.42413 C 364.96056,268.92013 364.50456,268.63213 364.50456,268.05613 C 364.50456,267.48013 365.00856,267.12013 365.89656,267.12013 C 366.88056,267.12013 367.91256,267.50413 368.44056,267.76813 L 369.06456,265.27213 C 368.34456,264.91213 367.14456,264.57613 365.77656,264.57613 C 362.87256,264.57613 361.00056,266.23213 361.00056,268.44013 C 360.97656,269.80813 361.91256,271.15213 364.36056,271.94413 C 365.70456,272.40013 366.06456,272.68813 366.06456,273.31213 C 366.06456,273.91213 365.60856,274.27213 364.50456,274.27213 C 363.42456,274.27213 362.03256,273.81613 361.36056,273.40813 L 360.71256,276.00013"
+ style="font-size:24.000000px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:center;line-height:125.00000%;writing-mode:lr-tb;text-anchor:middle;fill:#007f00;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000pt;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Myriad" />
+ </g>
+ </g>
+ <g
+ inkscape:groupmode="layer"
+ id="layer3"
+ inkscape:label="rock"
+ style="display:inline">
+ <g
+ style="display:inline"
+ transform="matrix(0.708388,0.000000,0.000000,0.708388,768.4189,171.0555)"
+ id="g2067">
+ <path
+ sodipodi:nodetypes="cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc"
+ id="path10"
+ d="M 149.15160,130.25073 L 138.01458,125.99417 L 132.85423,131.15452 L 127.69388,137.17493 L 120.81341,144.91545 L 113.07289,154.37609 L 105.33236,163.83673 L 97.591837,173.29738 L 89.851312,183.61808 L 82.970845,194.79883 L 76.090379,205.11953 L 70.069971,215.44023 L 64.909621,224.04082 L 61.469388,232.64140 L 58.889213,240.38192 L 58.889213,246.40233 L 60.609329,250.70262 L 66.629738,257.58309 L 73.510204,263.60350 L 82.110787,269.62391 L 90.711370,275.64431 L 100.17201,280.80466 L 108.77259,285.96501 L 117.37318,291.98542 L 124.25364,296.28571 L 129.41399,300.58601 L 132.85423,304.02624 L 135.43440,306.60641 L 138.01458,308.32653 L 140.59475,310.04665 L 144.03499,311.76676 L 150.05539,314.34694 L 156.93586,316.92711 L 165.53644,319.50729 L 195.63848,318.64723 L 201.65889,318.64723 L 208.53936,318.64723 L 216.27988,319.50729 L 224.02041,320.36735 L 230.90087,321.22741 L 236.06122,323.80758 L 241.22157,325.52770 L 248.10204,325.52770 L 254.98251,325.52770 L 261.86297,324.66764 L 268.74344,322.94752 L 275.62391,321.22741 L 281.64431,318.64723 L 286.80466,316.92711 L 291.10496,314.34694 L 295.40525,310.90671 L 298.84548,306.60641 L 303.14577,302.30612 L 306.58601,298.00583 L 310.02624,293.70554 L 312.60641,291.12536 L 315.18659,290.26531 L 318.62682,290.26531 L 322.92711,289.40525 L 328.94752,287.68513 L 334.96793,285.10496 L 340.98834,283.38484 L 346.14869,280.80466 L 349.58892,279.08455 L 351.30904,277.36443 L 356.78718,268.76385 L 364.48397,254.32361 L 363.12536,245.36152 L 359.04956,237.80175 L 362.48980,236.94169 L 365.93003,234.36152 L 368.51020,230.92128 L 371.09038,225.76093 L 373.67055,221.46064 L 375.39067,218.02041 L 376.25073,215.44023 L 377.11079,214.58017 L 365.93003,182.75802 L 364.20991,181.03790 L 361.62974,176.73761 L 357.32945,171.57726 L 352.16910,164.69679 L 347.00875,158.67638 L 342.70845,153.51603 L 333.79008,153.06414 L 329.62682,149.89505 L 322.92711,148.35569 L 320.03207,145.27697 L 315.64140,143.64723 L 312.97085,142.01749 L 308.94169,139.52769 L 304.14285,137.62682 L 299.34403,135.63557 L 295.22449,130.56560 L 290.24490,127.71429 L 286.80466,123.41399 L 284.22449,119.97376 L 282.50437,117.39359 L 281.64431,116.53353 L 239.50146,101.91254 L 238.64140,101.91254 L 236.06122,101.05248 L 231.76093,100.19242 L 227.46064,99.332362 L 222.30029,98.472303 L 218.00000,98.472303 L 213.69971,98.472303 L 211.11953,98.472303 L 181.51020,124.82216 L 149.15160,130.25073 z "
+ style="fill:#b5abab;fill-opacity:1.0000000" />
+ <path
+ sodipodi:nodetypes="cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc"
+ id="path1333"
+ d="M 272.27930,110.03646 L 278.00000,110.00000 L 281.00000,109.00000 L 285.00000,109.00000 L 288.00000,109.00000 L 290.00000,113.00000 L 293.00000,116.00000 L 295.00000,119.00000 L 298.00000,123.00000 L 300.00000,126.00000 L 302.00000,130.00000 L 303.00000,134.00000 L 303.00000,138.00000 L 302.00000,139.00000 L 302.00000,139.00000 L 301.00000,140.00000 L 301.00000,140.00000 L 297.00000,137.00000 L 293.00000,135.00000 L 290.00000,132.00000 L 287.00000,129.00000 L 284.00000,128.00000 L 280.00000,127.00000 L 277.00000,126.00000 L 273.00000,126.00000 L 270.00000,125.00000 L 266.00000,125.00000 L 262.00000,125.00000 L 259.00000,125.00000 L 254.00000,122.00000 L 249.00000,119.00000 L 245.00000,116.00000 L 240.00000,112.00000 L 235.00000,110.00000 L 230.00000,108.00000 L 225.00000,109.00000 L 219.00000,111.00000 L 214.00000,113.00000 L 209.00000,116.00000 L 204.00000,119.00000 L 199.00000,122.00000 L 194.00000,125.00000 L 190.00000,129.00000 L 186.00000,134.00000 L 183.00000,139.00000 L 177.00000,141.00000 L 171.00000,143.00000 L 164.00000,143.00000 L 157.00000,143.00000 L 150.00000,144.00000 L 143.00000,145.00000 L 137.00000,147.00000 L 131.00000,151.00000 L 129.00000,153.00000 L 127.00000,155.00000 L 125.00000,158.00000 L 124.00000,161.00000 L 117.00000,167.00000 L 111.00000,174.00000 L 106.00000,181.00000 L 101.00000,188.00000 L 96.000000,195.00000 L 92.000000,203.00000 L 87.000000,211.00000 L 81.000000,218.00000 L 78.000000,225.00000 L 74.000000,231.00000 L 70.000000,238.00000 L 69.000000,246.00000 L 74.000000,250.00000 L 79.000000,254.00000 L 83.000000,259.00000 L 88.000000,263.00000 L 93.000000,267.00000 L 97.000000,272.00000 L 102.00000,276.00000 L 107.00000,280.00000 L 111.00000,284.00000 L 116.00000,287.00000 L 121.00000,291.00000 L 126.00000,294.00000 L 132.00000,296.00000 L 138.00000,299.00000 L 144.00000,301.00000 L 150.00000,302.00000 L 155.00000,302.00000 L 159.00000,302.00000 L 164.00000,302.00000 L 168.00000,302.00000 L 172.00000,302.00000 L 176.00000,301.00000 L 180.00000,300.00000 L 184.00000,297.00000 L 188.00000,296.00000 L 191.00000,296.00000 L 193.00000,297.00000 L 196.00000,300.00000 L 198.00000,302.00000 L 201.00000,304.00000 L 204.00000,306.00000 L 207.00000,306.00000 L 211.00000,308.00000 L 214.00000,309.00000 L 218.00000,310.00000 L 222.00000,311.00000 L 226.00000,312.00000 L 230.00000,312.00000 L 233.00000,313.00000 L 237.00000,314.00000 L 240.00000,314.00000 L 244.00000,314.00000 L 246.00000,314.00000 L 249.00000,313.00000 L 252.00000,312.00000 L 255.00000,311.00000 L 258.00000,311.00000 L 261.00000,311.00000 L 267.00000,308.00000 L 273.00000,305.00000 L 279.00000,301.00000 L 285.00000,296.00000 L 290.00000,291.00000 L 296.00000,287.00000 L 302.00000,282.00000 L 308.00000,278.00000 L 312.00000,277.00000 L 316.00000,276.00000 L 321.00000,276.00000 L 325.00000,275.00000 L 329.00000,275.00000 L 334.00000,275.00000 L 338.00000,274.00000 L 343.00000,274.00000 L 344.00000,272.00000 L 346.00000,270.00000 L 349.00000,268.00000 L 351.00000,265.00000 L 354.00000,263.00000 L 356.00000,259.00000 L 357.00000,256.00000 L 359.00000,253.00000 L 357.00000,248.00000 L 355.00000,244.00000 L 353.00000,239.00000 L 352.00000,234.00000 L 355.00000,231.00000 L 359.00000,228.00000 L 363.00000,226.00000 L 366.00000,222.00000 L 363.00000,217.00000 L 359.00000,212.00000 L 355.00000,206.00000 L 354.00000,200.00000 L 356.00000,192.00000 L 358.00000,183.00000 L 358.00000,175.00000 L 354.00000,167.00000 L 352.00000,165.00000 L 349.00000,163.00000 L 347.00000,161.00000 L 344.00000,160.00000 L 341.00000,159.00000 L 338.00000,158.00000 L 335.00000,158.00000 L 332.00000,158.00000 L 330.00000,156.00000 L 328.00000,154.00000 L 327.00000,153.00000 L 327.00000,150.00000 L 329.00000,149.00000 L 335.00000,150.00000 L 342.00000,151.00000 L 349.00000,152.00000 L 355.00000,154.00000 L 361.00000,156.00000 L 367.00000,160.00000 L 371.00000,164.00000 L 374.00000,171.00000 L 374.00000,178.00000 L 373.00000,186.00000 L 372.00000,193.00000 L 375.00000,200.00000 L 379.00000,204.00000 L 382.00000,208.00000 L 386.00000,212.00000 L 388.00000,216.00000 L 389.00000,216.00000 L 389.00000,217.00000 L 389.00000,218.00000 L 389.00000,219.00000 L 389.00000,219.00000 L 391.00000,219.00000 L 391.00000,224.00000 L 390.00000,227.00000 L 388.00000,230.00000 L 385.00000,233.00000 L 382.00000,235.00000 L 378.00000,238.00000 L 375.00000,240.00000 L 373.00000,243.00000 L 372.00000,249.00000 L 372.00000,254.00000 L 370.00000,259.00000 L 367.00000,264.00000 L 365.00000,269.00000 L 362.00000,274.00000 L 358.00000,279.00000 L 353.00000,283.00000 L 348.00000,286.00000 L 343.00000,289.00000 L 338.00000,292.00000 L 332.00000,293.00000 L 328.00000,293.00000 L 325.00000,294.00000 L 321.00000,296.00000 L 319.00000,298.00000 L 317.00000,302.00000 L 315.00000,305.00000 L 313.00000,308.00000 L 311.00000,312.00000 L 308.00000,315.00000 L 306.00000,318.00000 L 302.00000,321.00000 L 299.00000,322.00000 L 295.00000,324.00000 L 291.00000,325.00000 L 288.00000,327.00000 L 284.00000,329.00000 L 276.00000,330.00000 L 267.00000,332.00000 L 259.00000,333.00000 L 250.00000,333.00000 L 242.00000,333.00000 L 233.00000,333.00000 L 225.00000,332.00000 L 217.00000,329.00000 L 212.00000,328.00000 L 207.00000,327.00000 L 202.00000,325.00000 L 197.00000,324.00000 L 192.00000,323.00000 L 187.00000,323.00000 L 182.00000,324.00000 L 178.00000,326.00000 L 168.00000,325.00000 L 158.00000,322.00000 L 149.00000,317.00000 L 140.00000,312.00000 L 131.00000,306.00000 L 123.00000,301.00000 L 115.00000,295.00000 L 108.00000,291.00000 L 105.00000,289.00000 L 102.00000,286.00000 L 98.000000,284.00000 L 94.000000,283.00000 L 90.000000,281.00000 L 86.000000,279.00000 L 83.000000,277.00000 L 79.000000,275.00000 L 75.000000,272.00000 L 71.000000,269.00000 L 66.000000,266.00000 L 62.000000,263.00000 L 58.000000,260.00000 L 54.000000,256.00000 L 51.000000,251.00000 L 49.000000,247.00000 L 51.000000,238.00000 L 54.000000,229.00000 L 58.000000,221.00000 L 63.000000,213.00000 L 85.000000,179.00000 L 89.000000,173.00000 L 94.000000,167.00000 L 99.000000,162.00000 L 104.00000,156.00000 L 108.00000,151.00000 L 113.00000,146.00000 L 117.00000,141.00000 L 121.00000,135.00000 L 125.00000,132.00000 L 128.00000,129.00000 L 132.00000,126.00000 L 135.00000,123.00000 L 139.00000,121.00000 L 143.00000,119.00000 L 148.00000,118.00000 L 152.00000,117.00000 L 157.00000,117.00000 L 162.00000,117.00000 L 167.00000,117.00000 L 172.00000,117.00000 L 176.00000,117.00000 L 181.00000,115.00000 L 185.00000,113.00000 L 189.00000,110.00000 L 192.00000,107.00000 L 196.00000,105.00000 L 200.00000,102.00000 L 203.00000,99.000000 L 207.00000,96.000000 L 210.00000,94.000000 L 214.00000,92.000000 L 219.00000,91.000000 L 221.00000,89.000000 L 223.00000,88.000000 L 227.00000,89.000000 L 230.00000,89.000000 L 234.00000,89.000000 L 237.00000,91.000000 L 241.00000,92.000000 L 244.00000,95.000000 L 247.00000,97.000000 L 250.00000,100.00000 L 253.00000,103.00000 L 257.03646,105.51823 L 262.08918,108.23892"
+ style="fill:#000000" />
+ <path
+ sodipodi:nodetypes="ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc"
+ style="fill:#645858;fill-opacity:1.0000000"
+ d="M 289.76968,176.61808 L 294.76968,177.61808 L 298.76968,178.61808 L 303.76968,179.61808 L 308.76968,180.61808 L 312.76968,182.61808 L 316.76968,184.61808 L 320.76968,186.61808 L 322.88387,187.07485 L 323.76968,189.55120 L 325.24603,192.02754 L 322.76968,193.61808 L 320.88387,193.01571 L 319.76968,193.61808 L 316.76968,193.61808 L 313.58860,194.38970 L 311.00000,195.69680 L 307.54519,197.77551 L 303.00583,200.85423 L 298.46647,201.08455 L 293.92711,197.23616 L 287.84840,196.69680 L 283.30904,197.46648 L 279.53936,196.46648 L 275.76968,193.69680 L 269.32070,193.78135 L 264.55102,194.01167 L 259.78134,194.70263 L 256.55102,193.85423 L 252.62974,193.46648 L 245.24198,195.69680 L 240.70262,196.38776 L 235.62391,196.84840 L 230.31487,199.61808 L 225.77551,203.69680 L 218.92711,207.23616 L 213.16327,211.85423 L 206.31487,213.16327 L 201.23615,211.93295 L 193.84840,210.70263 L 187.99806,205.86607 L 181.57290,203.02154 L 174.66149,202.84239 L 166.45481,204.08455 L 159.37609,206.62391 L 151.06495,208.38970 L 147.76968,206.79916 L 144.29333,204.91335 L 142.58860,202.02754 L 141.58860,199.14173 L 142.47441,196.07485 L 146.76968,196.61808 L 151.76968,194.61808 L 156.76968,191.61808 L 161.76968,189.61808 L 165.76968,187.61808 L 170.76968,185.61808 L 175.76968,182.61808 L 180.76968,180.61808 L 183.76968,180.61808 L 187.76968,179.61808 L 190.76968,180.61808 L 193.76968,181.61808 L 196.76968,182.61808 L 198.76968,183.61808 L 201.76968,185.61808 L 204.76968,188.61808 L 208.76968,187.61808 L 212.76968,184.61808 L 215.76968,180.61808 L 217.76968,176.61808 L 221.76968,174.61808 L 225.76968,172.61808 L 229.76968,169.61808 L 233.76968,167.61808 L 237.76968,165.61808 L 242.76968,163.61808 L 246.76968,161.61808 L 250.76968,159.61808 L 256.76968,160.61808 L 261.76968,162.61808 L 265.76968,165.61808 L 269.76968,169.61808 L 274.76968,173.61808 L 278.76968,175.61808 L 283.76968,177.61808 L 289.76968,176.61808 z "
+ id="path2065" />
+ <path
+ id="path16"
+ d="M 289.00000,172.00000 L 294.00000,173.00000 L 298.00000,174.00000 L 303.00000,175.00000 L 308.00000,176.00000 L 312.00000,178.00000 L 316.00000,180.00000 L 320.00000,182.00000 L 323.00000,186.00000 L 323.00000,187.00000 L 323.00000,188.00000 L 322.00000,189.00000 L 321.00000,190.00000 L 319.00000,189.00000 L 316.00000,189.00000 L 314.00000,188.00000 L 311.00000,188.00000 L 308.00000,188.00000 L 305.00000,188.00000 L 303.00000,188.00000 L 300.00000,188.00000 L 296.00000,187.00000 L 293.00000,187.00000 L 290.00000,188.00000 L 287.00000,188.00000 L 284.00000,189.00000 L 281.00000,189.00000 L 278.00000,188.00000 L 275.00000,186.00000 L 272.00000,184.00000 L 268.00000,181.00000 L 264.00000,178.00000 L 260.00000,176.00000 L 256.00000,174.00000 L 252.00000,173.00000 L 247.00000,173.00000 L 243.00000,174.00000 L 239.00000,177.00000 L 235.00000,180.00000 L 232.00000,183.00000 L 229.00000,186.00000 L 228.00000,185.00000 L 226.00000,188.00000 L 223.00000,191.00000 L 221.00000,193.00000 L 218.00000,195.00000 L 215.00000,196.00000 L 212.00000,198.00000 L 210.00000,200.00000 L 207.00000,202.00000 L 204.00000,201.00000 L 202.00000,200.00000 L 199.00000,200.00000 L 197.00000,198.00000 L 194.00000,197.00000 L 192.00000,195.00000 L 190.00000,193.00000 L 189.00000,191.00000 L 185.00000,190.00000 L 182.00000,190.00000 L 178.00000,191.00000 L 174.00000,192.00000 L 150.00000,202.00000 L 147.00000,201.00000 L 145.00000,200.00000 L 143.00000,198.00000 L 142.00000,196.00000 L 142.00000,195.00000 L 146.00000,192.00000 L 151.00000,190.00000 L 156.00000,187.00000 L 161.00000,185.00000 L 165.00000,183.00000 L 170.00000,181.00000 L 175.00000,178.00000 L 180.00000,176.00000 L 183.00000,176.00000 L 187.00000,175.00000 L 190.00000,176.00000 L 193.00000,177.00000 L 196.00000,178.00000 L 198.00000,179.00000 L 201.00000,181.00000 L 204.00000,184.00000 L 208.00000,183.00000 L 212.00000,180.00000 L 215.00000,176.00000 L 217.00000,172.00000 L 221.00000,170.00000 L 225.00000,168.00000 L 229.00000,165.00000 L 233.00000,163.00000 L 237.00000,161.00000 L 242.00000,159.00000 L 246.00000,157.00000 L 250.00000,155.00000 L 256.00000,156.00000 L 261.00000,158.00000 L 265.00000,161.00000 L 269.00000,165.00000 L 274.00000,169.00000 L 278.00000,171.00000 L 283.00000,173.00000 L 289.00000,172.00000 z "
+ style="fill:#000000" />
+ </g>
+ </g>
+ <g
+ inkscape:groupmode="layer"
+ id="layer8"
+ inkscape:label="covers"
+ style="display:inline">
+ <g
+ id="g17273"
+ transform="matrix(3.955288,0.000000,0.000000,3.955288,155.1671,-915.1278)">
+ <g
+ id="g17118"
+ style="fill:#00ff00;fill-opacity:1.0000000;stroke:#000000;stroke-width:47.034168;stroke-miterlimit:4.0000000;stroke-dasharray:none;stroke-opacity:1.0000000"
+ transform="matrix(1.274278e-2,7.087528e-3,-7.087528e-3,1.274278e-2,147.7444,148.5166)">
+ <path
+ d="M 7601.0000,11063.000 L 6350.0000,12312.000 L 7602.0000,10313.000 L 8850.0000,12314.000 L 7601.0000,11063.000 z "
+ id="path17120"
+ sodipodi:nodetypes="ccccc"
+ style="fill:#00ff00;fill-opacity:1.0000000;stroke:#000000;stroke-width:47.034168;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-dasharray:none;stroke-opacity:1.0000000" />
+ </g>
+ <path
+ id="text17122"
+ d="M 187.95573,356.23294 C 187.40374,356.47294 186.73173,356.61694 185.86773,356.61694 C 184.09174,356.61694 182.65173,355.46494 182.65173,353.30494 C 182.62773,351.38494 183.87574,350.01694 185.79573,350.01694 C 186.75573,350.01694 187.40374,350.18494 187.83573,350.37694 L 188.41173,347.66494 C 187.64374,347.37694 186.58773,347.20894 185.62773,347.20894 C 181.25974,347.20894 178.90773,350.01694 178.90773,353.44894 C 178.90773,357.14493 181.33174,359.47294 185.12373,359.47294 C 186.51573,359.47294 187.73974,359.23294 188.38773,358.92094 L 187.95573,356.23294 M 195.83186,359.47294 C 198.95186,359.47294 201.99986,357.50493 201.99986,353.23294 C 201.99986,349.68094 199.59986,347.20894 196.02386,347.20894 C 192.23186,347.20894 189.73586,349.63294 189.73586,353.42494 C 189.73586,357.21693 192.37586,359.47294 195.80786,359.47294 L 195.83186,359.47294 M 195.85586,356.85694 C 194.31986,356.85694 193.47986,355.34494 193.47986,353.35294 C 193.47986,351.60094 194.15186,349.82494 195.87986,349.82494 C 197.53586,349.82494 198.20786,351.60094 198.20786,353.32894 C 198.20786,355.44094 197.31986,356.85694 195.87986,356.85694 L 195.85586,356.85694 M 202.98798,347.47294 L 207.25998,359.20894 L 210.90798,359.20894 L 215.27598,347.47294 L 211.43598,347.47294 L 209.92398,352.92094 C 209.65999,353.92894 209.46798,354.81694 209.27598,355.77694 L 209.20398,355.77694 C 209.01199,354.84094 208.81998,353.90494 208.53198,352.92094 L 206.94798,347.47294 L 202.98798,347.47294 M 227.30711,354.50494 C 227.35511,354.21694 227.42711,353.66494 227.42711,353.04094 C 227.42711,350.13694 225.98711,347.18494 222.19511,347.18494 C 218.13911,347.18494 216.26711,350.47294 216.26711,353.44894 C 216.26711,357.14493 218.54711,359.44894 222.53111,359.44894 C 224.11511,359.44894 225.57911,359.20894 226.77911,358.70494 L 226.29911,356.23294 C 225.31511,356.56894 224.30711,356.73694 223.05911,356.73694 C 221.35511,356.73694 219.86711,356.01694 219.74711,354.48094 L 227.30711,354.50494 M 219.72311,351.98494 C 219.81911,351.02494 220.44311,349.60894 222.00311,349.60894 C 223.65911,349.60894 224.04311,351.12094 224.04311,351.98494 L 219.72311,351.98494 M 229.59536,359.20894 L 233.24336,359.20894 L 233.24336,353.28094 C 233.24336,352.96894 233.26736,352.70494 233.31536,352.46494 C 233.55536,351.31294 234.46736,350.61694 235.81136,350.61694 C 236.21936,350.61694 236.50736,350.66494 236.81936,350.71294 L 236.81936,347.28094 C 236.55536,347.23294 236.38736,347.20894 236.05136,347.20894 C 234.89936,347.20894 233.48336,347.92894 232.88336,349.65694 L 232.78736,349.65694 L 232.64336,347.47294 L 229.52336,347.47294 C 229.59536,348.48094 229.61936,349.60894 229.61936,351.33694 L 229.59536,359.20894 M 238.06398,358.63294 C 238.95198,359.11294 240.31999,359.47294 241.85598,359.47294 C 245.21598,359.47294 246.91998,357.86494 246.91998,355.65694 C 246.89598,353.95294 245.98398,352.80094 243.75198,352.05694 C 242.31199,351.55294 241.85598,351.26494 241.85598,350.68894 C 241.85598,350.11294 242.35999,349.75294 243.24798,349.75294 C 244.23198,349.75294 245.26399,350.13694 245.79198,350.40094 L 246.41598,347.90494 C 245.69599,347.54494 244.49598,347.20894 243.12798,347.20894 C 240.22399,347.20894 238.35198,348.86494 238.35198,351.07294 C 238.32798,352.44094 239.26399,353.78494 241.71198,354.57694 C 243.05598,355.03294 243.41598,355.32094 243.41598,355.94494 C 243.41598,356.54494 242.95998,356.90494 241.85598,356.90494 C 240.77599,356.90494 239.38398,356.44894 238.71198,356.04094 L 238.06398,358.63294"
+ style="font-size:24.000000px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:center;line-height:125.00000%;writing-mode:lr-tb;text-anchor:middle;fill:#007f00;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000pt;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Myriad" />
+ </g>
+ </g>
+ <g
+ inkscape:groupmode="layer"
+ id="layer7"
+ inkscape:label="paper"
+ style="display:inline">
+ <g
+ style="display:inline"
+ id="g17136"
+ transform="matrix(3.955288,0.000000,0.000000,3.955288,-708.3488,-857.6103)">
+ <path
+ sodipodi:nodetypes="cccccccc"
+ d="M 390.34708,372.49332 L 332.34539,427.86139 L 272.20460,392.33038 L 341.37790,339.74173 L 378.06120,351.10999 C 379.20468,351.78631 380.06344,352.64698 380.62363,353.61296 L 390.84522,371.30530 C 391.02046,371.60027 390.83244,372.00903 390.34708,372.49332 z "
+ style="fill:#ffff19;fill-opacity:1.0000000;stroke:#000000;stroke-width:1.6000000;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-dasharray:none;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000"
+ id="path12105" />
+ <path
+ id="path12107"
+ style="fill:#bebe12;fill-opacity:1.0000000;stroke:#000000;stroke-width:1.6000000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-dasharray:none;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000;display:inline"
+ d="M 390.84798,371.31968 C 390.67230,371.01421 390.16897,370.87309 389.44281,370.86931 L 380.40026,370.92353 L 380.40026,370.92353 L 381.40039,356.76032 C 381.45531,355.66353 381.19370,354.58394 380.62363,353.61296 L 390.84798,371.31968 z "
+ sodipodi:nodetypes="ccccccc" />
+ </g>
+ </g>
+</svg>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://web.resource.org/cc/"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://inkscape.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="595.27559pt"
+ height="841.88976pt"
+ id="svg5904"
+ sodipodi:version="0.32"
+ inkscape:version="0.42"
+ sodipodi:docbase="/Users/david/projects/docutils/s5-branch/docs/user/images"
+ sodipodi:docname="s5-files.svg"
+ inkscape:export-filename="/Users/david/projects/docutils/s5-branch/docs/user/images/s5-files.png"
+ inkscape:export-xdpi="100.00000"
+ inkscape:export-ydpi="100.00000">
+ <defs
+ id="defs5906">
+ <marker
+ inkscape:stockid="Arrow1Mstart"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="Arrow1Mstart"
+ style="overflow:visible">
+ <path
+ sodipodi:nodetypes="ccccc"
+ id="path10526"
+ d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none"
+ transform="scale(0.4)" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow1Lstart"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="Arrow1Lstart"
+ style="overflow:visible">
+ <path
+ sodipodi:nodetypes="ccccc"
+ id="path10529"
+ d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none"
+ transform="scale(0.8)" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow2Mend"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="Arrow2Mend"
+ style="overflow:visible;">
+ <path
+ sodipodi:nodetypes="cccc"
+ id="path10518"
+ style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
+ d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+ transform="scale(0.6) rotate(180) translate(-5,0)" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow2Mstart"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="Arrow2Mstart"
+ style="overflow:visible">
+ <path
+ sodipodi:nodetypes="cccc"
+ id="path10509"
+ style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round"
+ d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+ transform="scale(0.6) translate(-5,0)" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow2Lend"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="Arrow2Lend"
+ style="overflow:visible;">
+ <path
+ sodipodi:nodetypes="cccc"
+ id="path10521"
+ style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
+ d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+ transform="scale(1.1) rotate(180) translate(-5,0)" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow2Lstart"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="Arrow2Lstart"
+ style="overflow:visible">
+ <path
+ sodipodi:nodetypes="cccc"
+ id="path10512"
+ style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round"
+ d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+ transform="scale(1.1) translate(-5,0)" />
+ </marker>
+ </defs>
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="1.0050485"
+ inkscape:cx="359.99999"
+ inkscape:cy="345.00000"
+ inkscape:document-units="px"
+ inkscape:current-layer="layer1"
+ inkscape:window-width="1161"
+ inkscape:window-height="810"
+ inkscape:window-x="51"
+ inkscape:window-y="22"
+ showgrid="true"
+ inkscape:grid-bbox="true"
+ inkscape:grid-points="true"
+ gridspacingx="5.0000000px"
+ gridspacingy="5.0000000px"
+ gridtolerance="2.0000000px" />
+ <metadata
+ id="metadata5909">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ inkscape:label="Layer 1"
+ inkscape:groupmode="layer"
+ id="layer1"
+ style="display:inline">
+ <g
+ id="g15792">
+ <g
+ transform="translate(-5.000000,-55.00000)"
+ id="g13828"
+ style="stroke:#000000;stroke-opacity:1.0000000;stroke-linejoin:round;stroke-linecap:round">
+ <g
+ id="g13761"
+ style="stroke:#000000;stroke-opacity:1.0000000;stroke-linejoin:round;stroke-linecap:round">
+ <path
+ style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:3.1250000;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000"
+ d="M 451.84175,542.36220 L 490.47866,542.36220"
+ id="path13719" />
+ <path
+ style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:3.1250000;stroke-linecap:round;stroke-linejoin:round;marker-start:url(#Arrow1Mstart);stroke-miterlimit:4.0000000;stroke-opacity:1.0000000"
+ d="M 515.00000,597.36220 L 491.83836,597.36220"
+ id="path13721" />
+ <path
+ style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:3.1250000;stroke-linecap:round;stroke-linejoin:round;marker-start:url(#Arrow1Mstart);stroke-miterlimit:4.0000000;stroke-opacity:1.0000000"
+ d="M 515.00000,487.36218 L 491.83836,487.36218"
+ id="path13723" />
+ <path
+ id="path13725"
+ d="M 491.83836,487.36218 L 491.83836,597.36220 L 491.83836,707.36218"
+ style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:3.1250000;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000" />
+ <path
+ id="path13757"
+ d="M 515.00000,707.36218 L 491.83836,707.36218"
+ style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:3.1250000;stroke-linecap:round;stroke-linejoin:round;marker-start:url(#Arrow1Mstart);stroke-miterlimit:4.0000000;stroke-opacity:1.0000000" />
+ </g>
+ <g
+ id="g13695"
+ style="stroke:#000000;stroke-opacity:1.0000000;stroke-linejoin:round;stroke-linecap:round">
+ <path
+ id="path10755"
+ d="M 451.84175,982.36220 L 490.47866,982.36220"
+ style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:3.1250000;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000" />
+ <path
+ id="path13691"
+ d="M 515.00000,1037.3622 L 491.83836,1037.3622"
+ style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:3.1250000;stroke-linecap:round;stroke-linejoin:round;marker-start:url(#Arrow1Mstart);stroke-miterlimit:4.0000000;stroke-opacity:1.0000000" />
+ <path
+ id="path13689"
+ d="M 515.00000,927.36218 L 491.83836,927.36218"
+ style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:3.1250000;stroke-linecap:round;stroke-linejoin:round;marker-start:url(#Arrow1Mstart);stroke-miterlimit:4.0000000;stroke-opacity:1.0000000" />
+ <path
+ id="path13687"
+ d="M 491.83836,1037.3622 L 491.83836,927.36218"
+ style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:3.1250000;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000" />
+ </g>
+ <g
+ id="g13174"
+ style="stroke:#000000;stroke-opacity:1.0000000;stroke-linejoin:round;stroke-linecap:round">
+ <path
+ id="path9672"
+ d="M 205.00000,762.36217 L 275.47323,762.36217"
+ style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:3.1250000;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000" />
+ <path
+ id="path13150"
+ d="M 325.12023,762.36218 L 276.91055,762.36218"
+ style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:3.1250000;stroke-linecap:round;stroke-linejoin:round;marker-start:url(#Arrow1Mstart);stroke-miterlimit:4.0000000;stroke-opacity:1.0000000" />
+ <path
+ id="path13148"
+ d="M 325.12023,872.36218 L 276.91055,872.36218"
+ style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:3.1250000;stroke-linecap:round;stroke-linejoin:round;marker-start:url(#Arrow1Mstart);stroke-miterlimit:4.0000000;stroke-opacity:1.0000000" />
+ <path
+ id="path13146"
+ d="M 325.12023,982.36218 L 276.91055,982.36218"
+ style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:3.1250000;stroke-linecap:round;stroke-linejoin:round;marker-start:url(#Arrow1Mstart);stroke-miterlimit:4.0000000;stroke-opacity:1.0000000" />
+ <path
+ id="path13156"
+ d="M 325.12023,542.36218 L 276.91055,542.36218"
+ style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:3.1250000;stroke-linecap:round;stroke-linejoin:round;marker-start:url(#Arrow1Mstart);stroke-miterlimit:4.0000000;stroke-opacity:1.0000000" />
+ <path
+ id="path13154"
+ d="M 276.91055,982.36218 L 276.91055,542.36218"
+ style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:3.1250000;stroke-linecap:round;stroke-linejoin:round;marker-start:none;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000" />
+ <path
+ id="path13144"
+ d="M 325.12023,652.36218 L 276.91055,652.36218"
+ style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:3.1250000;stroke-linecap:round;stroke-linejoin:round;marker-start:url(#Arrow1Mstart);stroke-miterlimit:4.0000000;stroke-opacity:1.0000000" />
+ </g>
+ </g>
+ <g
+ transform="translate(-5.000000,-55.00000)"
+ id="g13805"
+ style="stroke:#000000;stroke-opacity:1.0000000">
+ <g
+ style="stroke:#000000;stroke-opacity:1.0000000"
+ id="g13533"
+ transform="translate(-160.0000,215.0000)">
+ <g
+ id="g13262"
+ transform="translate(522.7639,-102.4046)"
+ style="stroke:#000000;stroke-opacity:1.0000000">
+ <path
+ sodipodi:nodetypes="ccccccccc"
+ d="M 286.53987,344.38881 L 259.95853,330.91154 C 258.50529,330.17714 256.87802,329.76853 255.16608,329.76765 L 167.23608,329.76678 L 167.23608,329.76678 L 167.23608,419.76678 L 287.23608,419.76678 L 287.22985,346.10313 C 287.20953,345.21142 286.98750,344.61022 286.53987,344.38881 z "
+ style="fill:#ffffff;fill-opacity:1.0000000;stroke:#000000;stroke-width:3.7500000;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-dasharray:none;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000"
+ id="path13264" />
+ <path
+ sodipodi:nodetypes="ccccccc"
+ d="M 286.55635,344.40356 C 286.09815,344.17032 285.49622,344.35102 284.82132,344.84280 L 276.51509,351.08392 L 276.51509,351.08392 L 263.72436,334.02075 C 262.71303,332.71478 261.42576,331.64498 259.95853,330.91154 L 286.55635,344.40356 z "
+ style="fill:#a6a6a6;fill-opacity:1.0000000;stroke:#000000;stroke-width:3.0000000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-dasharray:none;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000;display:inline"
+ id="path13266" />
+ </g>
+ <text
+ sodipodi:linespacing="100.00000%"
+ id="text9098"
+ y="266.27817"
+ x="748.73212"
+ style="font-size:24.000011px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:center;line-height:100.00000%;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1.0000000;stroke:#000000;stroke-width:0.0000000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-dasharray:none;stroke-opacity:1.0000000;font-family:Myriad"
+ xml:space="preserve"><tspan
+ y="266.27817"
+ x="748.73212"
+ id="tspan9100"
+ sodipodi:role="line">s5-core</tspan><tspan
+ id="tspan9102"
+ y="290.27818"
+ x="748.73212"
+ sodipodi:role="line">.css</tspan></text>
+ </g>
+ <g
+ style="stroke:#000000;stroke-opacity:1.0000000"
+ id="g13541"
+ transform="translate(-160.0000,215.0000)">
+ <g
+ style="stroke:#000000;stroke-opacity:1.0000000"
+ transform="translate(522.7639,7.595400)"
+ id="g13276">
+ <path
+ id="path13278"
+ style="fill:#ffffff;fill-opacity:1.0000000;stroke:#000000;stroke-width:3.7500000;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-dasharray:none;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000"
+ d="M 286.53987,344.38881 L 259.95853,330.91154 C 258.50529,330.17714 256.87802,329.76853 255.16608,329.76765 L 167.23608,329.76678 L 167.23608,329.76678 L 167.23608,419.76678 L 287.23608,419.76678 L 287.22985,346.10313 C 287.20953,345.21142 286.98750,344.61022 286.53987,344.38881 z "
+ sodipodi:nodetypes="ccccccccc" />
+ <path
+ id="path13280"
+ style="fill:#a6a6a6;fill-opacity:1.0000000;stroke:#000000;stroke-width:3.0000000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-dasharray:none;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000;display:inline"
+ d="M 286.55635,344.40356 C 286.09815,344.17032 285.49622,344.35102 284.82132,344.84280 L 276.51509,351.08392 L 276.51509,351.08392 L 263.72436,334.02075 C 262.71303,332.71478 261.42576,331.64498 259.95853,330.91154 L 286.55635,344.40356 z "
+ sodipodi:nodetypes="ccccccc" />
+ </g>
+ <text
+ sodipodi:linespacing="100.00000%"
+ id="text9104"
+ y="377.05817"
+ x="749.49524"
+ style="font-size:24.000011px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:center;line-height:100.00000%;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1.0000000;stroke:#000000;stroke-width:0.0000000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-dasharray:none;stroke-opacity:1.0000000;font-family:Myriad"
+ xml:space="preserve"><tspan
+ y="377.05817"
+ x="749.49524"
+ id="tspan9106"
+ sodipodi:role="line">framing</tspan><tspan
+ id="tspan9108"
+ y="401.05818"
+ x="749.49524"
+ sodipodi:role="line">.css</tspan></text>
+ </g>
+ <g
+ style="stroke:#000000;stroke-opacity:1.0000000"
+ id="g13549"
+ transform="translate(-160.0000,215.0000)">
+ <g
+ style="stroke:#000000;stroke-opacity:1.0000000"
+ transform="translate(522.7639,117.5954)"
+ id="g13290">
+ <path
+ id="path13292"
+ style="fill:#ffffff;fill-opacity:1.0000000;stroke:#000000;stroke-width:3.7500000;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-dasharray:none;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000"
+ d="M 286.53987,344.38881 L 259.95853,330.91154 C 258.50529,330.17714 256.87802,329.76853 255.16608,329.76765 L 167.23608,329.76678 L 167.23608,329.76678 L 167.23608,419.76678 L 287.23608,419.76678 L 287.22985,346.10313 C 287.20953,345.21142 286.98750,344.61022 286.53987,344.38881 z "
+ sodipodi:nodetypes="ccccccccc" />
+ <path
+ id="path13294"
+ style="fill:#a6a6a6;fill-opacity:1.0000000;stroke:#000000;stroke-width:3.0000000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-dasharray:none;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000;display:inline"
+ d="M 286.55635,344.40356 C 286.09815,344.17032 285.49622,344.35102 284.82132,344.84280 L 276.51509,351.08392 L 276.51509,351.08392 L 263.72436,334.02075 C 262.71303,332.71478 261.42576,331.64498 259.95853,330.91154 L 286.55635,344.40356 z "
+ sodipodi:nodetypes="ccccccc" />
+ </g>
+ <text
+ transform="scale(1.075185,0.930073)"
+ sodipodi:linespacing="100.00000%"
+ id="text9110"
+ y="522.89044"
+ x="696.86365"
+ style="font-size:25.804459px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:center;line-height:100.00000%;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1.0000000;stroke:#000000;stroke-width:0.0000000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-dasharray:none;stroke-opacity:1.0000000;font-family:Myriad"
+ xml:space="preserve"><tspan
+ y="522.89044"
+ x="696.86365"
+ id="tspan9112"
+ sodipodi:role="line">pretty</tspan><tspan
+ id="tspan9114"
+ y="548.69490"
+ x="696.86365"
+ sodipodi:role="line">.css</tspan></text>
+ </g>
+ </g>
+ <g
+ transform="translate(-5.000000,-55.00000)"
+ id="g13701"
+ style="stroke:#000000;stroke-opacity:1.0000000">
+ <g
+ style="stroke:#000000;stroke-opacity:1.0000000"
+ id="g13617"
+ transform="translate(-150.0000,240.0000)">
+ <g
+ id="g13322"
+ transform="translate(512.7639,312.5954)"
+ style="stroke:#000000;stroke-opacity:1.0000000">
+ <path
+ sodipodi:nodetypes="ccccccccc"
+ d="M 286.53987,344.38881 L 259.95853,330.91154 C 258.50529,330.17714 256.87802,329.76853 255.16608,329.76765 L 167.23608,329.76678 L 167.23608,329.76678 L 167.23608,419.76678 L 287.23608,419.76678 L 287.22985,346.10313 C 287.20953,345.21142 286.98750,344.61022 286.53987,344.38881 z "
+ style="fill:#ffffff;fill-opacity:1.0000000;stroke:#000000;stroke-width:3.7500000;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-dasharray:none;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000"
+ id="path13324" />
+ <path
+ sodipodi:nodetypes="ccccccc"
+ d="M 286.55635,344.40356 C 286.09815,344.17032 285.49622,344.35102 284.82132,344.84280 L 276.51509,351.08392 L 276.51509,351.08392 L 263.72436,334.02075 C 262.71303,332.71478 261.42576,331.64498 259.95853,330.91154 L 286.55635,344.40356 z "
+ style="fill:#a6a6a6;fill-opacity:1.0000000;stroke:#000000;stroke-width:3.0000000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-dasharray:none;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000;display:inline"
+ id="path13326" />
+ </g>
+ <text
+ sodipodi:linespacing="100.00000%"
+ id="text9122"
+ y="682.05817"
+ x="740.27032"
+ style="font-size:24.000011px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:center;line-height:100.00000%;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1.0000000;stroke:#000000;stroke-width:0.0000000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-dasharray:none;stroke-opacity:1.0000000;font-family:Myriad"
+ xml:space="preserve"><tspan
+ y="682.05817"
+ x="740.27033"
+ id="tspan9124"
+ sodipodi:role="line">iepngfix</tspan><tspan
+ id="tspan9126"
+ y="706.05818"
+ x="740.27032"
+ sodipodi:role="line">.htc</tspan></text>
+ </g>
+ <g
+ style="stroke:#000000;stroke-opacity:1.0000000"
+ id="g13609"
+ transform="translate(-150.0000,240.0000)">
+ <g
+ style="stroke:#000000;stroke-opacity:1.0000000"
+ transform="translate(512.7639,422.5954)"
+ id="g13336">
+ <path
+ id="path13338"
+ style="fill:#ffffff;fill-opacity:1.0000000;stroke:#000000;stroke-width:3.7500000;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-dasharray:none;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000"
+ d="M 286.53987,344.38881 L 259.95853,330.91154 C 258.50529,330.17714 256.87802,329.76853 255.16608,329.76765 L 167.23608,329.76678 L 167.23608,329.76678 L 167.23608,419.76678 L 287.23608,419.76678 L 287.22985,346.10313 C 287.20953,345.21142 286.98750,344.61022 286.53987,344.38881 z "
+ sodipodi:nodetypes="ccccccccc" />
+ <path
+ id="path13340"
+ style="fill:#a6a6a6;fill-opacity:1.0000000;stroke:#000000;stroke-width:3.0000000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-dasharray:none;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000;display:inline"
+ d="M 286.55635,344.40356 C 286.09815,344.17032 285.49622,344.35102 284.82132,344.84280 L 276.51509,351.08392 L 276.51509,351.08392 L 263.72436,334.02075 C 262.71303,332.71478 261.42576,331.64498 259.95853,330.91154 L 286.55635,344.40356 z "
+ sodipodi:nodetypes="ccccccc" />
+ </g>
+ <text
+ sodipodi:linespacing="100.00000%"
+ id="text9116"
+ y="790.57019"
+ x="739.14758"
+ style="font-size:24.000011px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:center;line-height:100.00000%;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1.0000000;stroke:#000000;stroke-width:0.0000000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-dasharray:none;stroke-opacity:1.0000000;font-family:Myriad"
+ xml:space="preserve"><tspan
+ y="790.57019"
+ x="739.14758"
+ id="tspan9118"
+ sodipodi:role="line">blank</tspan><tspan
+ id="tspan9120"
+ y="814.57020"
+ x="739.14758"
+ sodipodi:role="line">.gif</tspan></text>
+ </g>
+ </g>
+ <g
+ transform="translate(-5.000000,-55.00000)"
+ id="g13768"
+ style="stroke:#000000;stroke-opacity:1.0000000">
+ <g
+ style="stroke:#000000;stroke-opacity:1.0000000"
+ id="g12998"
+ transform="translate(140.0000,160.0000)">
+ <g
+ id="g12960"
+ transform="translate(32.76392,117.5954)"
+ style="stroke:#000000;stroke-opacity:1.0000000">
+ <path
+ sodipodi:nodetypes="ccccccccc"
+ d="M 286.53987,344.38881 L 259.95853,330.91154 C 258.50529,330.17714 256.87802,329.76853 255.16608,329.76765 L 167.23608,329.76678 L 167.23608,329.76678 L 167.23608,419.76678 L 287.23608,419.76678 L 287.22985,346.10313 C 287.20953,345.21142 286.98750,344.61022 286.53987,344.38881 z "
+ style="fill:#ffffff;fill-opacity:1.0000000;stroke:#000000;stroke-width:3.7500000;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-dasharray:none;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000"
+ id="path12962" />
+ <path
+ sodipodi:nodetypes="ccccccc"
+ d="M 286.55635,344.40356 C 286.09815,344.17032 285.49622,344.35102 284.82132,344.84280 L 276.51509,351.08392 L 276.51509,351.08392 L 263.72436,334.02075 C 262.71303,332.71478 261.42576,331.64498 259.95853,330.91154 L 286.55635,344.40356 z "
+ style="fill:#a6a6a6;fill-opacity:1.0000000;stroke:#000000;stroke-width:3.0000000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-dasharray:none;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000;display:inline"
+ id="path12964" />
+ </g>
+ <text
+ sodipodi:linespacing="100.00000%"
+ id="text9080"
+ y="486.96219"
+ x="259.42813"
+ style="font-size:24.000011px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:center;line-height:100.00000%;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1.0000000;stroke:#000000;stroke-width:0.0000000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-dasharray:none;stroke-opacity:1.0000000;font-family:Myriad"
+ xml:space="preserve"><tspan
+ y="486.96219"
+ x="259.42813"
+ id="tspan9082"
+ sodipodi:role="line">outline</tspan><tspan
+ id="tspan9084"
+ y="510.96220"
+ x="259.42813"
+ sodipodi:role="line">.css</tspan></text>
+ </g>
+ <g
+ style="stroke:#000000;stroke-opacity:1.0000000"
+ id="g13006"
+ transform="translate(140.0000,160.0000)">
+ <g
+ id="g12972"
+ transform="translate(32.76392,227.5954)"
+ style="stroke:#000000;stroke-opacity:1.0000000">
+ <path
+ sodipodi:nodetypes="ccccccccc"
+ d="M 286.53987,344.38881 L 259.95853,330.91154 C 258.50529,330.17714 256.87802,329.76853 255.16608,329.76765 L 167.23608,329.76678 L 167.23608,329.76678 L 167.23608,419.76678 L 287.23608,419.76678 L 287.22985,346.10313 C 287.20953,345.21142 286.98750,344.61022 286.53987,344.38881 z "
+ style="fill:#ffffff;fill-opacity:1.0000000;stroke:#000000;stroke-width:3.7500000;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-dasharray:none;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000"
+ id="path12974" />
+ <path
+ sodipodi:nodetypes="ccccccc"
+ d="M 286.55635,344.40356 C 286.09815,344.17032 285.49622,344.35102 284.82132,344.84280 L 276.51509,351.08392 L 276.51509,351.08392 L 263.72436,334.02075 C 262.71303,332.71478 261.42576,331.64498 259.95853,330.91154 L 286.55635,344.40356 z "
+ style="fill:#a6a6a6;fill-opacity:1.0000000;stroke:#000000;stroke-width:3.0000000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-dasharray:none;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000;display:inline"
+ id="path12976" />
+ </g>
+ <text
+ xml:space="preserve"
+ style="font-size:24.000011px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:center;line-height:100.00000%;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1.0000000;stroke:#000000;stroke-width:0.0000000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-dasharray:none;stroke-opacity:1.0000000;font-family:Myriad"
+ x="259.34225"
+ y="596.96216"
+ id="text9284"
+ sodipodi:linespacing="100.00000%"><tspan
+ sodipodi:role="line"
+ id="tspan9290"
+ x="259.34226"
+ y="596.96216">print</tspan><tspan
+ sodipodi:role="line"
+ id="tspan9292"
+ x="259.34225"
+ y="620.96217">.css</tspan></text>
+ </g>
+ <g
+ style="stroke:#000000;stroke-opacity:1.0000000"
+ id="g13014"
+ transform="translate(140.0000,160.0000)">
+ <g
+ style="stroke:#000000;stroke-opacity:1.0000000"
+ transform="translate(32.76392,337.5954)"
+ id="g12978">
+ <path
+ id="path12980"
+ style="fill:#ffffff;fill-opacity:1.0000000;stroke:#000000;stroke-width:3.7500000;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-dasharray:none;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000"
+ d="M 286.53987,344.38881 L 259.95853,330.91154 C 258.50529,330.17714 256.87802,329.76853 255.16608,329.76765 L 167.23608,329.76678 L 167.23608,329.76678 L 167.23608,419.76678 L 287.23608,419.76678 L 287.22985,346.10313 C 287.20953,345.21142 286.98750,344.61022 286.53987,344.38881 z "
+ sodipodi:nodetypes="ccccccccc" />
+ <path
+ id="path12982"
+ style="fill:#a6a6a6;fill-opacity:1.0000000;stroke:#000000;stroke-width:3.0000000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-dasharray:none;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000;display:inline"
+ d="M 286.55635,344.40356 C 286.09815,344.17032 285.49622,344.35102 284.82132,344.84280 L 276.51509,351.08392 L 276.51509,351.08392 L 263.72436,334.02075 C 262.71303,332.71478 261.42576,331.64498 259.95853,330.91154 L 286.55635,344.40356 z "
+ sodipodi:nodetypes="ccccccc" />
+ </g>
+ <text
+ xml:space="preserve"
+ style="font-size:24.000011px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:center;line-height:100.00000%;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1.0000000;stroke:#000000;stroke-width:0.0000000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-dasharray:none;stroke-opacity:1.0000000;font-family:Myriad"
+ x="259.56012"
+ y="706.32617"
+ id="text12043"
+ sodipodi:linespacing="100.00000%"><tspan
+ sodipodi:role="line"
+ id="tspan12045"
+ x="259.56012"
+ y="706.32617">opera</tspan><tspan
+ sodipodi:role="line"
+ x="259.56012"
+ y="730.32618"
+ id="tspan12047">.css</tspan></text>
+ </g>
+ <g
+ style="stroke:#000000;stroke-opacity:1.0000000"
+ id="g13022"
+ transform="translate(140.0000,160.0000)">
+ <g
+ id="g12984"
+ transform="translate(32.76392,447.5954)"
+ style="stroke:#000000;stroke-opacity:1.0000000">
+ <path
+ sodipodi:nodetypes="ccccccccc"
+ d="M 286.53987,344.38881 L 259.95853,330.91154 C 258.50529,330.17714 256.87802,329.76853 255.16608,329.76765 L 167.23608,329.76678 L 167.23608,329.76678 L 167.23608,419.76678 L 287.23608,419.76678 L 287.22985,346.10313 C 287.20953,345.21142 286.98750,344.61022 286.53987,344.38881 z "
+ style="fill:#ffffff;fill-opacity:1.0000000;stroke:#000000;stroke-width:3.7500000;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-dasharray:none;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000"
+ id="path12986" />
+ <path
+ sodipodi:nodetypes="ccccccc"
+ d="M 286.55635,344.40356 C 286.09815,344.17032 285.49622,344.35102 284.82132,344.84280 L 276.51509,351.08392 L 276.51509,351.08392 L 263.72436,334.02075 C 262.71303,332.71478 261.42576,331.64498 259.95853,330.91154 L 286.55635,344.40356 z "
+ style="fill:#a6a6a6;fill-opacity:1.0000000;stroke:#000000;stroke-width:3.0000000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-dasharray:none;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000;display:inline"
+ id="path12988" />
+ </g>
+ <text
+ sodipodi:linespacing="100.00000%"
+ id="text9092"
+ y="816.30219"
+ x="259.32312"
+ style="font-size:24.000011px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:center;line-height:100.00000%;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1.0000000;stroke:#000000;stroke-width:0.0000000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-dasharray:none;stroke-opacity:1.0000000;font-family:Myriad"
+ xml:space="preserve"><tspan
+ y="816.30219"
+ x="259.32312"
+ id="tspan9094"
+ sodipodi:role="line">slides</tspan><tspan
+ id="tspan9096"
+ y="840.30220"
+ x="259.32312"
+ sodipodi:role="line">.js</tspan></text>
+ </g>
+ <g
+ style="stroke:#000000;stroke-opacity:1.0000000"
+ id="g12990"
+ transform="translate(140.0000,160.0000)">
+ <g
+ style="stroke:#000000;stroke-opacity:1.0000000"
+ transform="translate(32.76392,7.595403)"
+ id="g12886">
+ <path
+ id="path2125"
+ style="fill:#ffffff;fill-opacity:1.0000000;stroke:#000000;stroke-width:3.7500000;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-dasharray:none;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000"
+ d="M 286.53987,344.38881 L 259.95853,330.91154 C 258.50529,330.17714 256.87802,329.76853 255.16608,329.76765 L 167.23608,329.76678 L 167.23608,329.76678 L 167.23608,419.76678 L 287.23608,419.76678 L 287.22985,346.10313 C 287.20953,345.21142 286.98750,344.61022 286.53987,344.38881 z "
+ sodipodi:nodetypes="ccccccccc" />
+ <path
+ id="path2168"
+ style="fill:#a6a6a6;fill-opacity:1.0000000;stroke:#000000;stroke-width:3.0000000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-dasharray:none;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000;display:inline"
+ d="M 286.55635,344.40356 C 286.09815,344.17032 285.49622,344.35102 284.82132,344.84280 L 276.51509,351.08392 L 276.51509,351.08392 L 263.72436,334.02075 C 262.71303,332.71478 261.42576,331.64498 259.95853,330.91154 L 286.55635,344.40356 z "
+ sodipodi:nodetypes="ccccccc" />
+ </g>
+ <text
+ transform="scale(1.003177,0.996833)"
+ sodipodi:linespacing="100.00000%"
+ id="text9074"
+ y="378.15045"
+ x="258.4964"
+ style="font-size:24.117754px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:center;line-height:100.00000%;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1.0000000;stroke:#000000;stroke-width:0.0000000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-dasharray:none;stroke-opacity:1.0000000;font-family:Myriad"
+ xml:space="preserve"><tspan
+ y="378.15045"
+ x="258.49640"
+ id="tspan9076"
+ sodipodi:role="line">slides</tspan><tspan
+ id="tspan9078"
+ y="402.26821"
+ x="258.49640"
+ sodipodi:role="line">.css</tspan></text>
+ </g>
+ </g>
+ <g
+ id="g14176">
+ <g
+ style="stroke:#000000;stroke-opacity:1.0000000"
+ id="g13130"
+ transform="translate(0.000000,-54.99999)">
+ <path
+ sodipodi:nodetypes="ccccccccc"
+ d="M 209.99815,696.86669 L 210.00000,852.36217 L 75.000000,852.36217 L 75.000000,672.36217 L 75.000000,672.36217 L 161.90250,672.36347 C 164.47041,672.36479 166.91132,672.97771 169.09117,674.07931 L 208.96319,694.29521 C 209.63463,694.62733 209.96767,695.52913 209.99815,696.86669 z "
+ style="fill:#ffffff;fill-opacity:1.0000000;stroke:#000000;stroke-width:3.7500000;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-dasharray:none;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000"
+ id="path12105" />
+ <path
+ id="path12107"
+ style="fill:#a6a6a6;fill-opacity:1.0000000;stroke:#000000;stroke-width:3.7500000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-dasharray:none;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000;display:inline"
+ d="M 208.98791,694.31734 C 208.30060,693.96748 207.39771,694.23853 206.38536,694.97620 L 193.92602,704.33788 L 193.92602,704.33788 L 174.73992,678.74312 C 173.22293,676.78417 171.29202,675.17947 169.09117,674.07931 L 208.98791,694.31734 z "
+ sodipodi:nodetypes="ccccccc" />
+ </g>
+ <text
+ xml:space="preserve"
+ style="font-size:36.814487px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:center;line-height:100.00000%;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1.0000000;stroke:#000000;stroke-width:0.0000000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-dasharray:none;stroke-opacity:1.0000000;font-family:Myriad"
+ x="146.13911"
+ y="695.62231"
+ id="text9058"
+ sodipodi:linespacing="100.00000%"
+ transform="scale(0.997872,1.002133)"><tspan
+ sodipodi:role="line"
+ x="146.13911"
+ y="695.62231"
+ id="tspan9128"><tspan
+ id="tspan14172"
+ style="font-size:36.814487px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:center;line-height:99.999976%;writing-mode:lr-tb;text-anchor:middle;stroke:#000000;stroke-width:0.0000000;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000;font-family:Myriad" />*.html</tspan><tspan
+ sodipodi:role="line"
+ x="146.13912"
+ y="732.43680"
+ id="tspan14174">output</tspan></text>
+ </g>
+ </g>
+ </g>
+ <g
+ inkscape:groupmode="layer"
+ id="layer2"
+ inkscape:label="2"
+ style="display:inline" />
+</svg>
--- /dev/null
+================================
+ Generating LaTeX with Docutils
+================================
+
+:Author: Engelbert Gruber, Guenter Milde
+:Contact: docutils-develop@lists.sourceforge.net
+:Revision: $Revision: 8413 $
+:Date: $Date: 2019-11-13 14:45:43 +0100 (Mi, 13. Nov 2019) $
+:Copyright: This document has been placed in the public domain.
+:Abstract: This document covers topics specific to Docutils' LaTeX_ export.
+
+.. contents::
+.. sectnum::
+
+
+LaTeX
+=====
+
+LaTeX__, is a document preparation system for high-quality typesetting. It
+is most often used for medium-to-large technical or scientific documents but
+it can be used for almost any form of publishing. There exists a wide
+selecton of `LaTeX Documentation on the net`_ and `books on LaTeX and
+related topics`_. For an introduction to LaTeX see, e.g., `LaTeX2e for
+authors`_.
+
+__ http://www.latex-project.org/
+.. _LaTeX2e for authors:
+ http://www.latex-project.org/guides/usrguide.pdf
+.. _LaTeX Documentation on the net:
+ http://www.latex-project.org/guides/
+.. _books on LaTeX and related topics:
+ http://www.latex-project.org/guides/books.html
+
+
+.. _LaTeX packages:
+
+LaTeX document classes and packages
+-----------------------------------
+
+Unlike HTML with CSS, LaTeX uses one common language for markup and style
+definitions. Separation of content and style is realized by collecting style
+definitions in LaTeX classes and packages, or the
+`document preamble <LaTeX preamble_>`_.
+
+LaTeX document classes and packages (similar to Python modules or C
+libraries) provide means to extend or modify the LaTeX language by
+redefining macros or providing new ones.
+
+Using the `document class`_ and `style sheet`_ configuration options, you
+can select from a *huge* selection of classes and packages (standard as well
+as user contributed) coming with your TeX distribution or available at
+CTAN_ as well as custom style sheets.
+
+.. _CTAN: http://www.ctan.org
+
+
+Docutils specific LaTeX macros
+------------------------------
+
+Some Docutils objects have no LaTeX counterpart, they will be typeset
+using a Docutils specific LaTeX *macro* (command, environment, or
+length) to allow customization. By convention, special macros use the
+prefix ``\DU``\ [#]_.
+
+The generated LaTeX documents should be kept processable by a standard LaTeX
+installation. Therefore fallback definitions are included after the `custom
+style sheets`_, if a macro is required in the document.
+
+* Custom `style sheets`_ can define alternative implementations with
+ ``\newcommand``, ``\newenvironment``, and ``\newlength`` followed by
+ ``\setlength``.
+
+* Definitions with `raw LaTeX`_ are part of the document body. Use
+ ``\def``, ``\renewcommand`` or ``\renewenvironment``, and ``\setlength``.
+
+See the test output standalone_rst_latex.tex_ for an example of the fallback
+definitions and their use in the document.
+
+.. [#] DU for Documentation Utilities = Docutils
+
+
+Length units
+------------
+
+LaTeX supports all `length units`_ defined for Docutils plus the
+following less common units:
+
+:pt: typewriter's (or LaTeX) point (1 pt = 1/72.27 in)
+:dd: didôt (1 dd = 1238/1157 pt)
+:cc: cîcero (1 cc = 12 dd)
+:sp: scaled point (1sp = 1/65536pt)
+
+.. attention:: Different definitions of the unit "pt"!
+
+ * In Docutils (as well as CSS) the unit symbol "pt" denotes the
+ `Postscript point` or `DTP point`.
+
+ * LaTeX uses "pt" for the `LaTeX point`, which is unknown to Docutils and
+ 0.3 % smaller.
+
+ * The `DTP point` is available in LaTeX as "bp" (big point):
+
+ 1 pt = 1/72.25 in < 1 bp = 1/72 in
+
+ Lengths specified in the document with unit "pt" will be given the
+ unit "bp" in the LaTeX source.
+
+ In `raw LaTeX`_ and `custom style sheets`_, the `DTP point` must be
+ specified as "bp", while "pt" is interpreted as `LaTeX point`.
+
+The default length unit (added by Docutils to length specifications
+without unit) is the "DTP point".
+
+.. _length units: ../ref/rst/restructuredtext.html#length-units
+
+
+PDF generation
+==============
+
+In most cases, LaTeX code is not the desired end-format of the document.
+LaTeX offers many ways to generate PDF documents from the LaTeX
+source, including:
+
+_`pdflatex`
+ Generates a PDF document directly from the LaTeX file.
+ Export your document with the _`LaTeX2e writer` (writer
+ name "``latex``", frontend tool rst2latex.py_).
+
+_`xelatex` or _`lualatex`
+ The `XeTeX`_ and LuaTeX_ engines work with input files in UTF-8 encoding
+ and system fonts. Export your document with the _`XeTeX writer` (writer
+ name "``xetex``", frontend tool rst2xetex.py_).
+
+You may need to call latex two or three times to get internal references
+correct.
+
+.. _documentoptions: config.html#documentoptions
+.. _xetex: http://tug.org/xetex/
+.. _luatex: http://luatex.org/
+.. _rst2latex.py: tools.html#rst2latex-py
+.. _rst2xetex.py: tools.html#rst2xetex-py
+
+_`rubber`
+ The Rubber__ wrapper for LaTeX and friends can be used to automatically
+ run all programs the required number of times and delete "spurious" files.
+ This includes processing bibliographic references or indices, as well as
+ compilation or conversion of figures.
+
+__ https://launchpad.net/rubber/
+
+
+Configuration
+=============
+
+.. contents:: :local:
+
+.. _option:
+
+Options/Settings
+----------------
+
+Options can be specified as
+
+* command-line options, or
+
+* configuration settings.
+
+Run ``rst2latex.py --help`` to get a list of available options;
+see `Docutils Configuration`_ for details.
+
+.. _Docutils Configuration:
+ config.html
+
+Classes
+-------
+
+The `"classes" attribute`_ is one of the common attributes, shared by all
+Docutils elements.
+In HTML, the common use is to provide selection criteria for style rules in
+CSS stylesheets. As there is no comparable framework for LaTeX, Docutils
+emulates some of this behaviour via `Docutils specific LaTeX macros`_.
+Due to LaTeX limitations, class arguments are ignored for
+some elements (e.g. a rubric_).
+
+*Inline elements*
+ are handled via the ``\DUrole{}`` macro that calls the optional styling
+ command ``\DUrole«classargument»`` with one argument (the role content).
+ See `custom interpreted text roles`_.
+
+*Block level elements*
+ are wrapped in "class environments":
+ ``\begin{DUclass}`` calls the optional styling command
+ ``\DUCLASS«classargument»{}``, ``\end{DUclass}`` tries
+ ``\endDUCLASS«classargument»``.
+
+Customization is done by defining matching macros or environments.
+
+Example 1:
+ Use small caps font inside elements with class value "custom".
+
+ *Inline elements*
+ The LaTeX function ``\textsc`` sets the argument in small caps::
+
+ \newcommand{\DUrolecustom}[1]{\textsc{#1}}
+
+ *Block-level elements*
+ The LaTeX directive (macro without argument) ``\scshape`` switches to
+ the small caps font. Its effect is confined to the wrapper ``DUclass``
+ environment::
+
+ \newcommand*{\DUCLASScustom}{\scshape}
+
+Example 2:
+ It is even possible to locally redefine other LaTeX macros, e.g. to
+ turn bullet lists with class value "enumerateitems" into enumerated
+ lists::
+
+ \newcommand*{\DUCLASSenumerateitems}{%
+ \renewenvironment{itemize}{\begin{enumerate}}%
+ {\end{enumerate}}%
+ }
+
+.. rubric:: Notes
+
+* Class arguments may contain numbers and hyphens, which need special
+ treatment in LaTeX command names (see `class directive`_). The commands
+ ``\csname`` and ``\endcsname`` or the special command ``\@namedef`` can
+ help with the definition of corresponding macros or environments, e.g.::
+
+ \expandafter\newcommand\csname gg1\endcsname{Definition of gg1.}
+
+ or ::
+
+ \makeatletter
+ \@namedef{DUadmonitionadmonition-test}{…}
+ \makeatother
+
+* Elements can have multiple class arguments. In contrast to HTML/CSS, the
+ order of the class arguments cannot be ignored in LaTeX
+
+* For "historical reasons", class handling differs for some elements and
+ class values:
+
+ * The special macros ``\DUadmonition``, ``\DUtitle``, and ``\DUtopic`` are
+ written with a comma separated list of class values as optional
+ argument. See http://www.ctan.org/topic/keyval for LaTeX packages that
+ help parsing value lists.
+
+ See the sections on admonitions_, titles_, and the `topic element`_ for
+ customization examples.
+
+ * Class argument values starting with ``align-`` are transformed to
+ "align" argument values. Class argument values starting with
+ ``language-`` set the elements language property.
+
+ * The table element recognizes some special class values. See section
+ table_.
+
+.. _"classes" attribute: ../ref/doctree.html#classes
+
+
+LaTeX code
+----------
+
+Custom LaTeX code can be placed in `style sheets`_, the
+`LaTeX preamble`_, the document body (`raw LaTeX`_), or custom templates_.
+
+The functional tests that come with Docutils, can serve as example.
+
+input:
+ standalone_rst_latex.txt_ (includes files from `tests/functional/input/data`_)
+expected output:
+ standalone_rst_latex.tex_
+
+.. _standalone_rst_latex.txt:
+ https://sf.net/p/docutils/code/HEAD/tree/trunk/docutils/test/functional/input/standalone_rst_latex.txt
+.. _tests/functional/input/data:
+ https://sf.net/p/docutils/code/HEAD/tree/trunk/docutils/test/functional/input/data
+.. _standalone_rst_latex.tex:
+ https://sf.net/p/docutils/code/HEAD/tree/trunk/docutils/test/functional/expected/standalone_rst_latex.tex?format=raw
+
+
+.. _style sheet:
+.. _custom style sheets:
+
+Style sheets
+````````````
+
+A common way of LaTeX customization is the preparation of custom style
+sheets, either as simple files with LaTeX code snippets or as home-made
+`LaTeX packages`_ (see the clsguide_ for an introduction on LaTeX
+package writing).
+
+Options:
+ stylesheet_
+
+ It is possible to specify multiple style sheets and mix `LaTeX
+ packages`_ with custom style sheets.
+
+You cannot specify package options with the stylesheet_ setting. If
+you need to pass options to the package, use the ``\usepackage``
+command in the `LaTeX preamble`_ or a custom style sheet.
+
+Example 1:
+ Select Latin Modern fonts with the `lmodern` package::
+
+ --stylesheet=lmodern
+
+Example 2:
+ Use the `preamble.tex` home-made custom style sheet together with
+ the package `kerkis` (Bookman fonts)::
+
+ --stylesheet=kerkis,preamble.tex
+
+Example 3:
+ Select Palatino fonts with old-style numbers and true small-caps
+ with the LaTeX command ::
+
+ \usepackage[osf,sc]{mathpazo}
+
+ in the `LaTeX preamble`_ or `custom style sheets`_.
+
+Stylesheet Repository
+ There is a `repository of user-contributed style sheets`_ in the
+ Docutils Sandbox_.
+
+.. _clsguide:
+ http://mirror.ctan.org/macros/latex/doc/clsguide.pdf
+.. _stylesheet:
+ config.html#stylesheet-latex2e-writer
+.. _embed-stylesheet:
+ config.html#embed-stylesheet-latex2e-writer
+.. _repository of user-contributed style sheets:
+ ../../../sandbox/stylesheets/
+.. _sandbox: ../../../sandbox/
+
+
+LaTeX preamble
+``````````````
+
+Configuration by LaTeX code in the document preamble is also possible
+without a separate stylesheet. This way, packages can be loaded with
+options or commands re-defined without the need to create a separate
+file (new in Docutils 0.7).
+
+Option:
+ latex-preamble_
+
+Default:
+ used for `font setup`_
+
+Example:
+ To use the better looking ``txtt`` font for monospaced text define the
+ latex-preamble_ setting in a configuration file::
+
+ latex-preamble: \renewcommand{\ttdefault}{txtt}
+ \usepackage{mathptmx} % Times
+ \usepackage[scaled=.92]{helvet} % Helvetica
+
+.. _latex-preamble:
+ config.html#latex-preamble
+.. _PDF standard fonts:
+ http://en.wikipedia.org/wiki/PDF#Standard_Type_1_Fonts
+.. _Linux Libertine:
+ http://www.linuxlibertine.org/index.php?id=1&L=1
+
+
+Templates
+`````````
+
+Some customizations require commands at places other than the insertion
+point of stylesheets or depend on the deletion/replacement of parts of the
+document. This can be done via a custom template. See the `publisher
+documentation`_ for a description of the document parts available in a
+template file.
+
+Option:
+ template_
+
+In addition to the 'default.tex' template, the latex writer directory
+contains the alternative 'titlepage.tex'.
+
+Example:
+ Print a title page including docinfo, dedication, and abstract::
+
+ --template=titlepage.tex
+
+.. _publisher documentation: ../api/publisher.html
+.. _template: config.html#template-latex2e-writer
+
+
+Raw LaTeX
+`````````
+
+By means of the `raw directive`_ or a derived `custom role`_, one can
+give commands directly to LaTeX. These can be both, styling as well as
+printing commands.
+
+Example:
+ Math formula::
+
+ .. raw:: latex
+
+ \[x^3 + 3x^2a + 3xa^2 + a^3,\]
+
+ (Drawback: the formula will be invisible in other output formats. Better
+ use the `math directive`_)
+
+Most LaTeX code examples also work as raw LaTeX inside the document.
+An exception are commands that need to be given in the document
+preamble (e.g. package loading with ``\usepackage``, which can be
+achieved with the ``--style-sheet`` or ``--latex-preamble`` command
+line options instead). Remember to use *re-defining* commands for
+customizing `Docutils specific LaTeX macros`_ with raw LaTeX.
+
+Example:
+ Define the transition command as page break::
+
+ .. raw:: latex
+
+ \renewcommand*{\DUtransition}{\pagebreak[4]}
+
+See also:
+ * Defining a macro for a `custom role`_.
+ * Forcing `page breaks`_.
+
+.. _raw directive:
+ ../ref/rst/directives.html#raw
+.. _math directive:
+ ../ref/rst/directives.html#math
+
+
+
+How to configure the ...
+========================
+
+admonitions
+-----------
+
+Admonitions__ are specially marked "topics" that can appear anywhere an
+ordinary body element can.
+
+__ ../ref/rst/directives.html#admonitions
+
+Command:
+ ``\DUadmonition``
+
+Default:
+ Typeset in a frame (90 % of text width).
+
+The admonition title is typeset with the ``\DUtitle`` command which also
+takes a class argument. See `titles`_
+
+Example 1:
+ A lighter layout without the frame::
+
+ \newcommand{\DUadmonition}[2][class-arg]{%
+ % try \DUadmonition#1{#2}:
+ \ifcsname DUadmonition#1\endcsname%
+ \csname DUadmonition#1\endcsname{#2}%
+ \else
+ \begin{quote}
+ #2
+ \end{quote}
+ \fi
+ }
+
+ The first part of this definition acts as a "dispatcher". This way it is
+ possible to define a special handling of `specific admonitions`_ based on
+ the "class" argument.
+
+.. _specific admonitions:
+ ../ref/rst/directives.html#specific-admonitions
+
+Example 2:
+ Print admonitions in the margin::
+
+ \newcommand{\DUadmonition}[2][class-arg]{\marginpar{#2}}
+
+ Make sure there is enough space to fit the note.
+ See also the marginnote_ package.
+
+Example 3:
+ Use the ``.. note::`` admonition for a margin note::
+
+ \newcommand{\DUadmonitionnote}[1]{\marginpar{#1}}
+
+ Make sure there is enough space to fit the note.
+
+.. _marginnote:
+ http://mirror.ctan.org/help/Catalogue/entries/marginnote.html
+
+
+.. _custom role:
+
+custom interpreted text roles
+-----------------------------
+
+The rst `role directive`_ allows defining custom `text roles`_ that mark
+parts of inline text (spans) with class arguments (see section classes_).
+
+Commands:
+ ``\DUrole``: dispatcher command
+
+ ``\DUrole«classargument»``: optional styling command with 1 argument (the
+ role content).
+
+Default:
+ The default definition of ``\DUrole{«classargument»}{}`` calls the macro
+ named ``\DUrole«classargument»{}`` if it is defined and silently ignores
+ this class argument if not.
+
+Example 1:
+ Typeset text in small caps::
+
+ .. role:: smallcaps
+
+ :smallcaps:`Fourier` transformation
+
+ This is transformed to the LaTeX code::
+
+ \DUrole{smallcaps}{Fourier} transformation
+
+ The definition ::
+
+ \newcommand{\DUrolesmallcaps}{\textsc}
+
+ as `raw LaTeX`_ or in the custom `style sheet`_ will give the expected
+ result (if the text font_ supports small caps).
+
+Example 2:
+ Subscript text in normal size and *italic* shape::
+
+ .. role:: sub(subscript)
+
+ As "sub" inherits from the standard "subscript" role, the LaTeX macro
+ only needs to set the size and shape::
+
+ \newcommand{\DUrolesub}{\normalsize\itshape}
+
+Example 3:
+ A role with several classes and a converted class name::
+
+ .. role:: custom4
+ :class: argI argII arg_3
+
+ is translated to the nested commands::
+
+ \DUrole{argi}{\DUrole{argii}{\DUrole{arg-3}{<content>}}}
+
+ With the definitions::
+
+ \newcommand{\DUroleargi}[1]{\textsc}
+ \newcommand{\DUroleargii}[1]{{\large #1}}
+ \makeatletter
+ \@namedef{DUrolearg-3}{\textbf}
+ \makeatother
+
+ in a `style sheet`_\ [#]_ or as `raw LaTeX`_ in the document source,
+ text styled with ``:custom4:`large bold small-caps``` will be typeset
+ accordingly.
+
+.. [#] Leave out the ``\makeatletter`` - ``\makeatother`` pair if the style
+ sheet is a LaTeX package (``*.sty``).
+
+.. _role directive:
+ ../ref/rst/directives.html#role
+
+.. _text roles:
+ ../ref/rst/roles.html
+
+.. _class directive:
+ ../ref/rst/directives.html#class
+
+definition lists
+----------------
+
+ReStructuredText `definition lists`__ correspond to HTML ``<dl>`` list
+objects.
+
+Environment:
+ ``description``: LaTeX standard environment
+
+Command:
+ ``\descriptionlabel``: styling macro for the description term
+
+Default:
+ bold label text, hanging indent
+
+Example:
+ A non-bold label can be achieved with::
+
+ \renewcommand\descriptionlabel[1]{\hspace\labelsep \normalfont #1}
+
+__ ../ref/rst/restructuredtext.html#definition-lists
+
+
+document class
+--------------
+
+There are hundreds of LaTeX document classes installed by modern
+LaTeX distributions, provided by publishers, or available at CTAN_.
+
+Popular document classes:
+ * article, report, book: standard document classes
+ * scrartcl, scrrprt, scrbook: KOMA-script_ classes
+ * memoir_: highly configurable class for larger documents
+
+Option:
+ documentclass_
+
+.. _KOMA-script:
+ http://mirror.ctan.org/help/Catalogue/entries/koma-script.html
+.. _memoir:
+ http://mirror.ctan.org/help/Catalogue/entries/memoir.html
+.. _documentclass:
+ config.html#documentclass
+
+
+document info
+-------------
+
+Content of the `bibliographic fields`__ at the top of a document.
+By default, docinfo items are typeset as a table.
+
+Options:
+ use-latex-docinfo_, use-latex-abstract_
+
+Length:
+ ``\DUdocinfowidth``: the width for the `docinfo` table.
+
+Default:
+ 90 % of text width: ``0.9\textwidth``
+
+Example:
+ set to 70 % of text width::
+
+ \newlength{\DUdocinfowidth}
+ \setlength{\DUdocinfowidth}{0.7\textwidth}
+
+__ ../ref/rst/restructuredtext.html#bibliographic-fields
+
+.. _use-latex-docinfo:
+ config.html#use-latex-docinfo
+.. _use-latex-abstract:
+ config.html#use-latex-abstract
+
+
+document title
+--------------
+
+A lone top-level section title is (usually) transformed to the document title
+(see `section structure`_).
+
+The format of the document title is defined by the `document class`_. The
+"article" document class uses an in-page title and the "report" and "book"
+classes write a separate title page. See the `TeX FAQ`_ on how to customize
+the `style of document titles`_.
+
+The default title page shows only title and subtitle, date and author
+are shown in the `document info`_ table.
+
+Options:
+ use-latex-docinfo_
+
+ ``--template=titlepage.tex`` Put docinfo and abstract into the title page.
+ A separate title page is used also with the "abstract" document class.
+
+.. _section structure: rst/quickref.html#section-structure
+.. _TeX FAQ: http://www.tex.ac.uk/faq
+.. _style of document titles:
+ http://www.tex.ac.uk/cgi-bin/texfaq2html?label=titlsty
+
+
+field lists
+-----------
+
+`Field lists`__ may be used as generic two-column table constructs in
+documents.
+
+Environment:
+ ``DUfieldlist``
+
+Default:
+ Indented description list.
+
+Example:
+ Use a description list customized with enumitem_::
+
+ \usepackage{enumitem}
+ \newenvironment{DUfieldlist}%
+ {\description[font=,style=sameline,leftmargin=8em]}
+ {\enddescription}
+ }
+
+ The `KOMA-script`_ classes provide a similar environment under the name
+ `labeling`.
+
+.. _enumitem:
+ http://mirror.ctan.org/help/Catalogue/entries/enumitem.html
+
+__ ../ref/rst/restructuredtext.html#field-lists
+
+
+figure and table captions
+-------------------------
+
+The caption_ package provides many ways to customise the captions in
+floating environments like figure and table.
+
+The chngcntr_ package helps to configure the numbering of figure and table
+caption numberings.
+
+Some document classes (e.g. KOMA-script_) provide additional configuration.
+Also see the related `LaTeX FAQ entry`__
+
+Example
+ ::
+
+ \usepackage{caption}
+ \captionsetup{justification=raggedleft,singlelinecheck=false}
+
+.. _caption:
+ http://mirror.ctan.org/help/Catalogue/entries/caption.html
+.. _chngcntr:
+ http://mirror.ctan.org/help/Catalogue/entries/chngcntr.html
+__ http://www.tex.ac.uk/cgi-bin/texfaq2html?label=running-nos
+
+
+figure placement
+----------------
+
+Figures_ might be typeset at the place of definition (default) or "float"
+to a suitable place at the top or bottom of a page. This is implemented
+using the float_ package.
+
+Command:
+ ``\floatplacement``
+
+The placement setting is valid from the point of definition until the next
+``\floatplacement`` command or the end of the document. See float.pdf_ for
+details.
+
+Default:
+ ``\floatplacement{figure}{H}`` (here definitely). This corresponds most
+ closely to the source and HTML placement (principle of least surprise).
+
+Example 1:
+ In a custom `style sheet`_, set the default to let LaTeX find a suitable
+ place for figure floats::
+
+ \usepackage{float}
+ \floatplacement{figure}{htbp} % here, top, bottom, extra-page
+
+Example 2:
+ To move all following figures to the top or bottom of the page write in
+ the document source::
+
+ .. raw:: latex
+
+ \floatplacement{figure}{tb}
+
+.. _figures: ../ref/rst/directives.html#figure
+.. _float:
+ http://mirror.ctan.org/help/Catalogue/entries/float.html
+.. _float.pdf:
+ http://mirror.ctan.org/macros/latex/contrib/float/float.pdf
+
+.. _font setup:
+
+font
+----
+
+The selected text font influences the *look*, the *feel*,
+and the *readability* of the document (cf.
+http://www.csarven.ca/web-typography).
+Selecting a suitable font also solves the problem with `bad looking
+PDF output`_.
+
+Font selection is one of the main differences between LaTeX and XeTeX/LuaTeX:
+
+LaTeX
+ cannot use the fonts of the operating system directly but needs
+ specially installed fonts with additional supporting files.
+
+XeTeX/LuaTeX
+ can use system fonts and provides access to the full feature set of
+ modern OpenType_ fonts.
+
+.. _OpenType: http://en.wikipedia.org/wiki/OpenType
+
+The default font setup is done in the latex-preamble_:
+
+LaTeX
+ `PDF standard fonts`_ (Times, Helvetica, Courier)
+
+XeTeX/LuaTeX
+ `Linux Libertine`_, a free, high quality alternative to Times with a
+ wide coverage of glyphs, styles, and OpenType features.
+
+ Despite its name, Linux Libertine can be used on any operating
+ system that can handle OpenType fonts.
+
+Alternative fonts can be selected by
+
+LaTeX
+ a) specifying the corresponding LaTeX package(s) as argument to the
+ stylesheet_ option_ or with the ``\usepackage`` LaTeX command.
+
+ * packages can be combined,
+ * passing options to a package is only possible in a `style sheet`_
+ or the `LaTeX preamble`_.
+
+ b) changing the font-default macros ``\rmdefault``, ``\sfdefault``
+ and/or ``\ttdefault`` in a custom `style sheet`_, the `LaTeX
+ preamble`_ or `raw LaTeX`_.
+
+ Example 1:
+ Use `Latin Modern`_. `LaTeX code`_::
+
+ \usepackage{lmodern}
+
+ Command line argument::
+
+ --stylesheet=lmodern
+
+ Example 2:
+ The _`Times/Helvetica/Courier` `PDF standard fonts`_ are
+ selected by the LaTeX code [#]_::
+
+ \usepackage{mathptmx} % Times for serif and math
+ \usepackage[scaled=.90]{helvet} % downscaled Helvetica for sans serif
+ \usepackage{courier} % Courier for teletype (mono-space)
+
+ Since Docutils 0.7, this is the default value of the
+ `latex-preamble`_ option.
+
+ .. [#] When generating PDF-files from LaTeX, the `PDF standard
+ fonts`_ do not need to be embedded in the document. While this
+ results in smaller files, the actually used fonts on screen and in
+ print might differ! (For details see, e.g., the testflow_ package
+ documentation.)
+
+
+ Example 3:
+ Use the teletype font from the txfonts_ package. As there is no
+ package for this, we re-define the font macro with the `LaTeX code`_::
+
+ \renewcommand{\ttdefault}{txtt}
+
+
+XeTeX/LuaTeX
+ using the macros of the fontspec_ package. Use some font-viewer or
+ -manager (e.g. fontmatrix_) to find out the correct names of the
+ fonts on your system.
+
+ Example:
+ DejaVu_, very wide coverage, screen optimized. As this font
+ runs wide, add ``DIV=10`` to the `documentoptions`_::
+
+ \setmainfont{DejaVu Serif}
+ \setsansfont{DejaVu Sans}
+ \setmonofont[HyphenChar=None]{DejaVu Sans Mono}
+
+.. _fontspec: http://mirror.ctan.org/help/Catalogue/entries/fontspec.html
+.. _fontmatrix: http://fontmatrix.net/
+.. _DejaVu: http://dejavu-fonts.org/
+.. _documentoptions: config.html#documentoptions
+
+choice of suitable fonts
+````````````````````````
+
+High quality free fonts suitable for use with XeTeX/LuaTeX are, e.g., listed
+at `Good Libre Fonts`_, `25 Best Free Quality Fonts`_ and the update
+`19 More Free Quality Fonts`_.
+
+The `LaTeX Font Catalogue`_ provides information and examples for a wide
+range of fonts available for use with LaTeX. Here is just a selection:
+
+a) The `Latin Modern`_ (LM) fonts are extended outline versions of the
+ standard TeX font Computer Modern (CM).
+
+ +1 simple invocation: ``--stylesheet=lmodern``
+
+ +1 keeps the traditional TeX "look and feel":
+
+ +1 generally accepted as high quality CM replacement,
+ +1 comprehensive math support,
+ +1 including optical sizes,
+ +1 compatible with extensions made to match CM,
+ -1 modern types are hard to read at low (screen) resolutions.
+
+ -1 not part of a minimal standard TeX installation
+
+b) CM-Super_ is another outline CM replacement.
+
+ +1 simple invocation: modern LaTeX distributions use CM-Super
+ automatically instead of CM if it is installed.
+
+ -1 said to be of inferior quality compared to LM.
+
+ -1 not part of a minimal standard TeX installation,
+ bigger download size than Latin Modern (64 MB).
+
+c) `Bera`_ (Bitstream Vera)
+
+ +1 simple invocation: ``--stylesheet=bera``
+
+ +1 optimized for on-screen viewing with goot hinting
+
+ -1 not part of a minimal standard TeX installation
+
+d) PSNFSS_ Postscript fonts
+
+ +1 part of every standard TeX installation
+
+ +1 smaller PDF/Postscript document size if standard fonts are not
+ embedded
+
+ -1 restricted set of glyphs in the free versions [#]_
+
+ -1 different fonts for roman, sans-serif and typewriter fonts.
+
+ -1 invocation somewhat more complex, as several packages are
+ required for a complete font set, sometimes including package
+ options.
+
+ Roman (serif) PSNFSS fonts:
+
+ Bookman
+ good legibility but very wide.
+
+ Charter
+ bread-and-butter type optimized for printing on low-resolution
+ printers
+
+ New Century Schoolbook
+ good legibility but very wide.
+
+ Palatino
+ +1 recommended by font experts
+ +1 good LaTeX support including matching math fonts, small caps,
+ old-style figures
+ -1 bad rendering in xpdf viewer (auto-hinting leads to different
+ x-hight for different characters at some magnifications)
+ (this is fixed in recent versions).
+
+ Times
+ +1 the serif `PDF Standard Font`_,
+ -1 overused and quite narrow (devised for multi-column layouts).
+
+ Utopia
+ recommended by font experts
+
+
+ .. table:: Font packages for standard Postscript fonts
+ (cf. `Using common Postscript fonts with LaTeX`_)
+
+ ========= ============ ============= ============= =========
+ Package Roman Sans Serif Typewriter Math
+ ========= ============ ============= ============= =========
+ (none) CM Roman CM Sans Serif CM Typewriter CM Math
+
+ mathpazo Palatino Palatino
+
+ mathptmx Times Times
+
+ helvet Helvetica
+
+ avant Avant Garde
+
+ courier Courier
+
+ chancery Zapf
+ Chancery
+
+ bookman Bookman Avant Garde Courier
+
+ newcent New Century Avant Garde Courier
+ Schoolbook
+
+ charter Charter
+
+ utopia Utopia
+
+ fourier Utopia Fourier
+ ========= ============ ============= ============= =========
+
+.. [#] Extended versions of the standard Postscript fonts including
+ accented chars, as well as real small-caps
+ and old-style numbers are available with the `TeX Gyre`_ bundle
+ which is part of, e.g., `TeX Live`_.
+
+
+.. _LaTeX Font Catalogue:
+ http://www.tug.dk/FontCatalogue/
+.. _Latin Modern:
+ http://mirror.ctan.org/help/Catalogue/entries/lm.html
+.. _CM-Super:
+ http://mirror.ctan.org/help/Catalogue/entries/cm-super.html
+.. _bera:
+ http://mirror.ctan.org/help/Catalogue/entries/bera.html
+.. _TeX Gyre: http://www.gust.org.pl/projects/e-foundry/tex-gyre
+.. _PSNFSS:
+ http://mirror.ctan.org/help/Catalogue/entries/psnfss.html
+.. _Using common PostScript fonts with LaTeX:
+ http://mirror.ctan.org/macros/latex/required/psnfss/psnfss2e.pdf
+.. _TeX Live: http://tug.org/texlive/
+.. _txfonts:
+ http://mirror.ctan.org/help/Catalogue/entries/txfonts.html
+.. _PDF Standard Font:
+ http://en.wikipedia.org/wiki/PDF#Standard_Type_1_Fonts
+.. _testflow:
+ http://www.tex.ac.uk/tex-archive/help/Catalogue/entries/testflow.html
+.. _Good Libre Fonts:
+ http://typophile.com/node/18207
+.. _25 Best Free Quality Fonts:
+ http://www.alvit.de/blog/article/20-best-license-free-official-fonts
+.. _19 More Free Quality Fonts:
+ http://www.smashingmagazine.com/2006/10/11/17-more-free-quality-fonts/
+
+
+font encoding
+-------------
+
+LaTeX font encodings are described in detail in the encguide_ which is
+part of the LaTeX base documentation.
+
+Option:
+ font-encoding_
+
+Default:
+ "T1"
+
+Example 1:
+ Use the (obsolete) LaTeX default encoding "OT1"::
+
+ --font-encoding=OT1
+
+ or (without loading the fontenc_ package)::
+
+ --font-encoding=""
+
+ This will improve the look on screen with the default Computer Modern
+ fonts at the expense of problems with `search and text extraction`_
+ The recommended way is to select a T1-encoded "Type 1" (vector)
+ font, for example `Latin Modern`_
+
+Example 2:
+ Support for characters in the Unicode blocks Latin, Latin-1 Supplement,
+ and Greek together with a T1-encoded "Type 1" (vector) font, for example
+ `Latin Modern`_::
+
+ --font-encoding=LGR,T1 --stylesheet=lmodern
+
+.. _encguide:
+ http://mirror.ctan.org/macros/latex/doc/encguide.pdf
+.. _font-encoding:
+ config.html#font-encoding
+.. _fontenc:
+ http://mirror.ctan.org/help/Catalogue/entries/fontenc.html
+
+
+font size
+---------
+
+Add font size in points to the document options, e.g.
+``--documentoptions=12``, use e.g. the document classes provided by
+extsizes_ for values other than [10,11,12].
+
+.. _extsizes:
+ http://mirror.ctan.org/help/Catalogue/entries/extsizes.html
+
+
+footnotes
+---------
+
+By default, footnotes are set with Docutils-specific wrappers around
+the standard ``\footnotemark`` and ``\footnotetext`` commands. You
+can configure the footnote layout similar to standard LaTeX footnotes
+in a custom `style sheet`_ or the `LaTeX preamble`_.
+
+Further configuration is possible by alternative definitions of
+``\DUfootnotemark`` and ``\DUfootnotetext``
+
+Example 1:
+ Set footnote text with a hanging indent.
+
+ * This is the default with KOMA-script_ classes, e.g::
+
+ --documentclass=scrartcl
+
+ (for further configuration, see the `KOMA-script Guide`_),
+
+ * with package footmisc_::
+
+ \usepackage[hang]{footmisc}
+ \setlength{\footnotemargin}{0em}
+
+ (play with the ``\footnotemargin`` setting),
+
+ * redefine ``\DUfootnotetext`` inserting `\hangindent`::
+
+ \newcommand{\DUfootnotetext}[4]{%
+ \begingroup%
+ \renewcommand{\thefootnote}{%
+ \protect\raisebox{1em}{\protect\hypertarget{#1}{}}%
+ \protect\hyperlink{#2}{#3}}%
+ \footnotetext{\hangindent=2em #4}%
+ \endgroup%
+ }
+
+ (adapt the ``\hangindent`` value).
+
+Example 2:
+ Footnote marks in normal font size, not superscript::
+
+ \usepackage{scrextend} % not required with KOMA-script document classes
+ \deffootnote{1em}{1em}{\thefootnotemark\ }
+
+ (See the `KOMA-script Guide`_ for details and other options.)
+
+Example 3:
+ Place the footnote text where it appears in the source document (instead
+ of at the page bottom). This can be used to get the effect of endnotes
+ (needs the hanging_ package)::
+
+ \usepackage{hanging}
+ \newcommand{\DUfootnotetext}[4]{%
+ \par\noindent\raisebox{1em}{\hypertarget{#1}{}}%
+ \hyperlink{#2}{#3}%
+ \hangpara{\parindent}{1}#4%
+ }
+
+.. _footmisc:
+ http://mirror.ctan.org/help/Catalogue/entries/footmisc.html
+.. _hanging:
+ http://mirror.ctan.org/help/Catalogue/entries/hanging.html
+
+
+hyphenation
+-----------
+
+The amount of hyphenation is influenced by ``\hyphenpenalty``, setting it to
+10000 almost prevents hyphenation. As this produces lines with more space
+between words one should increase Latex's ``\tolerance`` for this.
+
+Example:
+ ::
+
+ \hyphenpenalty=5000
+ \tolerance=1000
+
+
+hyperlinks
+----------
+
+Options:
+ hyperlink-color_, hyperref-options_
+
+Hyperlinks are realized using the hyperref_ package. As it re-defines many
+standard LaTeX macros, this package is loaded last, *after* the style
+sheets.
+
+However, you can load hyperref before a package that requires its
+presence in a `style sheet`_ or the `LaTeX preamble`_ (see example
+below). This will ignore options set with hyperlink-color_ and
+hyperref-options_.
+
+URLs are typeset with the "url" package (loaded implicitely by "hyperref").
+The font of URLs can be defined with the ``\urlstyle`` command. Valid
+arguments are
+
+:same: normal text font, Docutils default,
+:tt: teletype (monospaced), LaTeX default,
+:rm: roman,
+:sf: sans serif
+
+Example:
+ Custom loading of the hyperref package also switches to
+ the LaTeX default (monospaced fonts for URLs). Reset to use the text
+ font::
+
+ \usepackage[unicode,colorlinks=true,linkcolor=green]{hyperref}
+ \urlstyle{same}
+
+See also `non-breaking hyperlinks`_.
+
+.. _hyperlink-color:
+ config.html#hyperlink-color
+.. _hyperref-options:
+ config.html#hyperref-options
+
+
+disable hyperlinks
+``````````````````
+
+To suppress the hyper-linking completely (e.g. for printing or to
+avoid clashes with other packages), set hyperref-options_ to "draft"
+or load the "nohyperref" package that comes with the "hyperref"
+bundle.
+
+Option:
+ ``--hyperref-options=draft``
+
+`LaTeX code`_::
+
+ \usepackage{nohyperref,url}
+ \urlstyle{same}
+
+.. _hyperref:
+ http://mirror.ctan.org/help/Catalogue/entries/hyperref.html
+
+line blocks
+-----------
+
+In `line blocks`__, newlines and leading whitespace are respected.
+
+Environment:
+ ``DUlineblock``: special list environment for line blocks
+
+Length:
+ ``\DUlineblockindent``: indentation of indented lineblock parts.
+
+Default:
+ 2.5 times the font hight: ``2.5em``
+
+Example:
+ set to the paragraph indentation::
+
+ \newlength{\DUlineblockindent}
+ \setlength{\DUlineblockindent}{\parindent}
+
+__ ../ref/rst/restructuredtext.html#line-blocks
+
+
+line spacing
+------------
+
+Commands:
+ ``\linespread``: for small adjustments
+
+ ``\singlespacing``, ``\onehalfspacing``, and ``\doublespacing``: from
+ package `setspace`
+
+Example 1:
+ Get document wide double spacing::
+
+ \usepackage{setspace}
+ \doublespacing
+
+Example 2:
+ Increase line spacing by five percent for better readability::
+
+ \linespread{1.05}
+
+
+literal blocks
+--------------
+
+No markup processing is done within a `literal block`__. It is left as-is,
+and is typically rendered in a monospaced typeface
+
+Option:
+ literal-block-env_
+
+Example:
+
+ ``--literal-block-env=lstlisting``
+
+ The ``lstlisting`` environment is highly configurable (as documented in
+ listings.pdf_) and provides syntax highlight for many programming languages,
+ for instance ::
+
+ \renewcommand{\ttdefault}{txtt}
+ \lstset{language=Python, morekeywords=[1]{yield}}
+ \lstloadlanguages{Python}
+ \lstset{
+ basicstyle=\ttfamily,
+ keywordstyle=\bfseries,
+ commentstyle=\rmfamily\itshape,
+ stringstyle=\slshape,
+ }
+ \lstset{showstringspaces=false}
+ \lstset{columns=fullflexible,
+ basewidth={0.5em,0.4em}}
+
+ and to get LaTeX syntax highlight for a code block with "listings"::
+
+ \lstloadlanguages{[LaTeX]TeX} % comma separated list of languages
+ \newcommand{\DUCLASSlatex}{\lstset{language=[LaTeX]TeX}}
+
+ The indentation of literal blocks can be reset with ::
+
+ \lstset{resetmargins=true}
+
+ and/or configured with e. g.::
+
+ \lstset{xleftmargin=-2em}
+
+__ ../ref/rst/restructuredtext.html#literal-blocks
+.. _literal-block-env:
+ config.html#literal-block-env
+.. _listings.pdf:
+ http://mirror.ctan.org/macros/latex/contrib/listings/listings.pdf
+
+
+lists
+-----
+
+Remove extra vertical whitespace between items of bullet lists and
+enumerated lists.
+
+Example:
+ Pass the class argument "compact" to the list::
+
+ .. class:: compact
+
+ * first item
+ * second item
+
+ The following lines for the `LaTeX preamble`_ use the enumitem_ package to
+ remove spacing from all lists with class argument "compact"::
+
+ \usepackage{enumitem}
+ \newcommand*{\DUCLASScompact}{\setlist{noitemsep}}
+
+
+list of figures/tables
+----------------------
+
+Docutils does not support lists of figures or tables.
+
+However, with LaTeX, they can be generated using `raw LaTeX`_ in the
+document source.
+
+Commands:
+ ``\listoffigures``: a list of figures
+
+ ``\listoftables``: a list of tables
+
+Example:
+ ::
+
+ .. raw:: latex
+
+ \listoffigures
+
+
+option list
+-----------
+
+`Option lists`__ are two-column lists of command-line options and
+descriptions, documenting a program's options.
+
+Environment:
+ ``DUoptionlist``: environment for option lists,
+
+Command:
+ ``\DUoptionlistlabel``: set appearance of the options
+
+Example:
+ set command options with a bold monospace font::
+
+ \newcommand{\DUoptionlistlabel}{\texttt{\textbf{#1}} \hfill}
+
+__ ../ref/rst/restructuredtext.html#option-lists
+
+
+page breaks
+-----------
+
+* Page breaks before top-level sections are the default with a
+ documentclass that provides "chapters", e.g. "book", "memoir" or
+ "scrbook".
+
+* Redefining the \section or \section* command in a
+ style sheet is possible too.
+
+* `Raw LaTeX`_ or a `custom role`_ can be used.
+
+* The transition element can be re-defined to produce a page break,
+
+Commands
+ ``\newpage``: hard pagebreak at exactly this position
+
+ ``\pagebreak[2]``: recommended page break after line end (precedence 1...4)
+
+Example:
+ Define the transition command as page break with the `LaTeX code`_::
+
+ \newcommand*{\DUtransition}{\pagebreak[4]}
+
+ (use ``\renewcommand`` with `raw LaTeX`_).
+
+page layout
+-----------
+
+By default, paper size and margin settings are determined by the document
+class.
+
+The following packages help to configure the page layout:
+
+a) The `typearea`_ package (part of the `KOMA-script`_ bundle) calculates a
+ *good* page layout (based on rules and recommendations of typography
+ experts).
+
+ See the `KOMA-Script Guide`_ for details on what is a *good* layout and
+ how this is achieved.
+
+b) The `geometry`_ package is recommended if you have to follow guidelines
+ with fixed values for the margins.
+ For details see the `geometry manual`_.
+
+Example 1:
+ Let `typearea` determine the type area with ``DIV=calc`` in the
+ documentoptions::
+
+ --documentoptions='a4paper,DIV=calc'
+
+ The ``DIV`` option can also be specified, like ``DIV=10``. It defines how
+ "crowded" a page will be: larger values mean larger text area (at the
+ expense of readability).
+
+Example 2:
+ `LaTeX code`_ to set margins with the geometry_ package::
+
+ \usepackage{geometry}
+ \geometry{hmargin={3cm,0.8in},height=8in}
+ \geometry{height=10in}.
+
+.. _typearea:
+ http://mirror.ctan.org/help/Catalogue/entries/typearea.html
+.. _KOMA-Script Guide:
+ http://mirror.ctan.org/macros/latex/contrib/koma-script/scrguien.pdf
+.. _geometry:
+ http://mirror.ctan.org/help/Catalogue/entries/geometry.html
+.. _geometry manual:
+ http://mirror.ctan.org/macros/latex/contrib/geometry/geometry.pdf
+
+
+page headers and footers
+------------------------
+
+With the fancyhdr_ package or the `KOMA-script`_ classes, you can define
+custom page head- and foot-lines.
+
+The `"header" and "footer" directives`_ save their content in the macros
+``\DUheader`` rsp. ``\DUfooter``. The macros can be used in LaTeX code and
+will be replaced by LaTeX with the content of the directives.
+
+Example:
+ `LaTeX code`_ to place left-aligned "header" and "footer" on every
+ page with fancyhdr_::
+
+ \usepackage{fancyhdr}
+ \fancyhead[L]{\DUheader}
+ \fancyfoot{} % reset
+ \fancyfoot[L]{\DUfooter}
+ \pagestyle{fancy}
+
+
+.. _fancyhdr: http://www.ctan.org/pkg/fancyhdr
+.. _"header" and "footer" directives: ../ref/rst/directives.html#header
+
+
+page numbering
+--------------
+
+Example:
+ Number pages by chapter (using the chappg_ package)::
+
+ \usepackage{chappg}
+
+ See the `chappg documentation`_ for details.
+
+.. _chappg:
+ http://mirror.ctan.org/help/Catalogue/entries/chappg.html
+.. _chappg documentation:
+ http://mirror.ctan.org/macros/latex/contrib/chappg/chappg.pdf
+
+
+paper size
+----------
+
+Paper geometry can be changed using ``--documentoptions`` or with the
+`geometry`_ package.
+
+`LaTeX code`_::
+
+ \usepackage{geometry}
+ \geometry{OPTIONLIST}
+
+Default:
+ a4paper
+
+Some possibilities:
+
+* a4paper, b3paper, letterpaper, executivepaper, legalpaper
+* landscape, portrait, twoside.
+
+Example:
+ Choose A5 pager in landscape orientation with command line argument::
+
+ --documentoptions=a5paper,landscape
+
+ The same with LaTeX commands in the `style sheet`_::
+
+ \usepackage{geometry}
+ \geometry{a5paper,landscape}
+
+ For details see the `geometry manual`_.
+
+paragraph indent
+----------------
+
+Default (in most document classes):
+ Indent the first line in a paragraph unless it is the first line of a
+ chapter, section, subsection, or subsubsection.
+
+Example 1:
+ To set paragraph indentation to zero but add a vertical space between
+ load the `parskip` package with the command line argument::
+
+ --stylesheet=parskip
+
+ or in a custom `style sheet`_ with::
+
+ \usepackage{parskip}
+
+Example 2:
+ To suppress the indentation of a specific paragraph, you may give it the
+ class "noindent" with, e.g. ::
+
+ .. class:: noindent
+
+ This paragraph should not be indented.
+
+ and define the `custom role`_ command::
+
+ \newcommand{\DUrolenoindent}[1]{\noindent #1}
+
+rubric
+------
+
+A rubric__ is like an informal heading that doesn't correspond to the
+document's structure.
+
+Command:
+ ``\DUrubric``
+
+Default:
+ subsubsection style (unnumbered), italic
+
+Example1:
+ Set centred and red::
+
+ \newcommand*{\DUrubric}[1]{%
+ \subsubsection*{\centerline{\color{red}#1}}}
+
+.. note::
+ Class attribute values are ignored because the "classes_ wrapper"
+ interferes with LaTeX's formatting (spacing/indendation) of text following
+ a section heading. Consider using a `topic element`_ or a container_.
+
+__ ../ref/rst/directives.html#rubric
+.. _container: ../ref/rst/directives.html#container
+
+section numbering
+-----------------
+
+Sections are numbered if there is a `sectnum directive`_ in the document.
+
+Option: sectnum_xform_
+ ``--section-numbering``, ``--no-section-numbering``
+
+If sectnum_xform_ is False, section numbers are generated by LaTeX. In this
+case the "prefix" and "suffix" arguments of the `sectnum directive`_ are
+ignored. The section number style is determined by the `document class`_
+and can be configured in a LaTeX `style sheet`_, e.g.::
+
+ \setcounter{secnumdepth}{5}
+
+.. note:: The LaTeX name is 'secnumdepth' (whithout 't').
+
+.. _sectnum directive: ../ref/rst/directives.html#sectnum
+.. _sectnum_xform: config.html#sectnum-xform
+
+
+sidebar
+-------
+
+Sidebars__ are like miniature, parallel documents that occur inside other
+documents, providing related or reference material. They can be likened to
+super-footnotes; their content is outside of the flow of the document's main
+text.
+
+Command:
+ ``DUsidebar``
+
+Default:
+ Box with grey background.
+
+Example:
+ Use margin notes::
+
+ \newcommand{\DUsidebar}[1]{\marginpar{\flushleft #1}}
+
+ * Make sure the margin is wide enough to hold the note.
+ * This fails with some constructs inside the `side bar` and where
+ \marginpar cannot be used, e.g., inside floats, footnotes, or in frames
+ made with the framed package (see marginnote_).
+
+__ http://docutils.sf.net/docutils/docs/ref/rst/directives.html#sidebar
+
+size of a pixel
+---------------
+
+The *physical size* of a pixel depends on the resolution of the output
+device and is usually specified in *dots per inch* (DPI).
+
+The *length unit* "px" is defined by the output format. For LaTeX, it is
+`defined in pdfTeX and LuaTeX`__ (the `xetex` writer emulates this
+definition).
+
+Default:
+ 72 DPI, i.e. 1 px = 1/72 in. [#]_
+
+Example:
+ Set the value to match the CSS definition
+ with the `LaTeX code`_::
+
+ \pdfpxdimen=1in
+ \divide\pdfpxdimen by 96 % 1/96 inch
+
+.. [#] The `CSS length unit ``px```_ defaults to 1/96 inch.
+
+__ http://tex.stackexchange.com/questions/41370/
+ what-are-the-possible-dimensions-sizes-units-latex-understands
+.. _CSS length unit ``px``: http://www.w3.org/TR/css-values-3/#px
+.. _reference pixel: http://www.w3.org/TR/css-values-3/#reference-pixel
+
+table
+-----
+
+A pre-configured table style can be globally selected via the table-style_
+setting or set for individual tables via a `class directive`_ or the class
+option of the `table directive`_.
+
+.. _table-style: config.html#table-style-latex-writers
+.. _table directive: ../ref/rst/directives.html#table
+
+topic element
+-------------
+
+A topic_ is like a block quote with a title, or a self-contained section
+with no subsections. Topics and rubrics can be used at places where a
+`section title`_ is not allowed (e.g. inside a directive).
+
+Example:
+ Use a standard paragraph for a topic::
+
+ \newcommand{\DUCLASStopic}{%
+ \renewenvironment{quote}{}{}%
+ }
+
+.. _topic: ../ref/rst/directives.html#topic
+.. _section title: ../ref/rst/restructuredtext.html#sections
+
+
+titles
+------
+
+The titles of admonitions_, sidebar_, and `topic element`_ are defined with
+the ``\DUtitle`` command that also takes a "class" argument.
+
+Example 1:
+ a centered and somewhat larger title for topcis::
+
+ \newcommand*{\DUtitletopic}[1]{\subsection*{\centering #1}
+
+Example 2:
+ a right-pointing hand as title for the "attention" directive::
+
+ \usepackage{pifont}
+ \newcommand{\DUtitleattention}[1]{\ding{43}}
+
+ The title argument is "swallowed" by the command.
+ To have both, hand and title use::
+
+ \usepackage{pifont}
+ \newcommand{\DUtitleattention}[1]{\ding{43} #1}
+
+
+table of contents
+-----------------
+
+A `contents directive`_ is replaced by a table of contents (ToC).
+
+Option: use-latex-toc_
+ ``--use-latex-toc``, ``--use-docutils-toc``
+
+With use-latex-toc (default since release 0.6):
+
+* The ToC is generated by LaTeX (via the ``\tableofcontents`` command).
+
+ The layout depends on the choosen document class and can be configured in
+ a custom `style sheet`_ (see e.g. the `KOMA-Script Guide`_ for the
+ `KOMA-script`_ classes).
+
+* The depth of the ToC and PDF-bookmarks can be configured
+
+ + with the "depth" argument of the `contents directive`_, or
+
+ + in a style sheet with e.g. ``\setcounter{tocdepth}{5}``.
+
+* Local ToCs are done with the minitoc_ package. See the `minitoc
+ documentation`_ for the numerous configuration options.
+
+.. note::
+ Minitoc supports local ToCs only at "part" and top section level
+ ("chapter" or "section"). Local `contents` directives at lower levels
+ are ignored (a warning is issued).
+
+ This is an intended feature of the minitoc_ package. If you really
+ require local ToCs at lower level, turn off the use-latex-toc_ option.
+
+.. _use-latex-toc: config.html#use-latex-toc
+.. _contents directive: ../ref/rst/directives.html#contents
+.. _minitoc:
+ http://mirror.ctan.org/help/Catalogue/entries/minitoc.html
+.. _minitoc documentation:
+ http://mirror.ctan.org/macros/latex/contrib/minitoc/minitoc.pdf
+
+
+title reference role
+--------------------
+
+`Title reference`_ is the default `default role`_ for `interpreted text`_.
+
+Command:
+ ``\DUroletitlereference``
+
+Default:
+ use slanted font (``\textsl``)
+
+Example:
+ set title references with a bold monospace font::
+
+ \newcommand{\DUroletitlereference}[1]{\texttt{\textbf{#1}}}
+
+.. _title reference:
+ ../ref/rst/roles.html#title-reference
+.. _default role:
+ ../ref/rst/directives.html#setting-the-default-interpreted-text-role
+.. _interpreted text:
+ ../ref/rst/restructuredtext.html#interpreted-text
+
+
+text encoding
+-------------
+
+The encoding of the LaTeX source file is Docutils' *output* encoding
+but LaTeX' *input* encoding.
+
+Option: output-encoding_
+ ``--output-encoding=OUTPUT-ENCODING``
+
+Default:
+ "utf8"
+
+Example:
+ Encode the LaTeX source file with the ISO `latin-1` (west european)
+ 8-bit encoding (the default in Docutils versions up to 0.6.)::
+
+ --output-encoding=latin-1
+
+Note:
+ LaTeX comes with two options for UTF-8 support,
+
+ :utf8: by the standard `inputenc`_ package with only limited coverage
+ (mainly accented characters).
+
+ :utf8x: supported by the `ucs`_ package covers a wider range of Unicode
+ characters than does "utf8". It is, however, a non-standard
+ extension and no longer developed.
+
+ Currently (in version 0.6), "utf8" is used if the output-encoding is
+ any of "utf_8", "U8", "UTF", or "utf8".
+
+.. with utf8x:
+ If LaTeX issues a Warning about unloaded/unknown characters adding ::
+
+ \PreloadUnicodePage{n}
+
+ (where *n* is the Unicode page-number) to the style sheet might help.
+
+.. _LaTeX Unicode: http://www.unruh.de/DniQ/latex/unicode/
+.. _output-encoding: config.html#output-encoding
+.. _inputenc:
+ http://mirror.ctan.org/help/Catalogue/entries/inputenc.html
+.. _ucs:
+ http://mirror.ctan.org/help/Catalogue/entries/unicode.html
+
+
+transition element
+------------------
+
+Transitions__ are commonly seen in novels and short fiction, as a gap
+spanning one or more lines, marking text divisions or signaling changes in
+subject, time, point of view, or emphasis.
+
+Command:
+ ``\DUtransition``
+
+Default:
+ A horizontal line, 1/3 of text width
+
+Example 1:
+ Use three stars::
+
+ \newcommand*{\DUtransition}{\centering{}*\quad*\quad*}
+
+ Alternatively use the more elaborated version in `transition-stars.sty`_.
+
+Example 2:
+ If paragraphs are separated by indentation, you can simply use a vertical
+ space::
+
+ \newcommand*{\DUtransition}{\vspace{2ex}}
+
+__ http://docutils.sf.net/docutils/docs/ref/rst/restructuredtext.html#transitions
+
+.. _transition-stars.sty: ../../../sandbox/stylesheets/transition-stars.sty
+
+
+Changes
+=======
+
+* The Docutils HISTORY_ lists all changes during the history of docutils.
+ Important changes are summarized in the RELEASE-NOTES_.
+
+* docutils-05-compat.sty_ is a `style sheet`_ that provides best possible
+ backwards compatibility with release 0.5.
+
+.. _HISTORY: ../../HISTORY.html
+.. _RELEASE-NOTES: ../../RELEASE-NOTES.html
+.. _docutils-05-compat: docutils-05-compat.sty.html
+.. _docutils-05-compat.sty:
+ ../../docutils/writers/latex2e/docutils-05-compat.sty
+
+
+Problems
+========
+
+Troubleshooting
+---------------
+
+Bad looking PDF output
+``````````````````````
+
+ What I am looking for when I try Docutils is if the PDF files I can get
+ are of high quality. Unfortunaltely that never is the case.
+
+ So am I just stupid or is there a way to get really high quality pdf from
+ Docutils?
+
+Make sure the default font is not a bitmap font.
+
+There is `Latin Modern`_ if you like the look of the standard font on paper,
+but want nice pdf. Or select something else like Times, Palatino, ... via
+configuration `options/settings`_. See font_ and font-encoding_.
+
+
+footnote mark and text at different pages
+`````````````````````````````````````````
+
+Docutils stores the footnote text in a separate node, at the position where
+it is specified in the input document. With the default settings, the
+footnote is put at the bottom of the page where the footnote text is located,
+maybe far away from the footnote mark (see e.g. `<rst/demo.txt>`_).
+
+To get footnote mark and text at the same page, keep footnote mark and
+footnote text close together!
+
+
+non-breaking hyperlinks
+```````````````````````
+
+If you convert with ``latex`` (as opposed to ``pdflatex``), hyperlinks will
+not wrap and sometimes stick into the margin.
+
+Wrong:
+ ::
+
+ \usepackage[breaklinks=true]{hyperref}
+
+ "breaklinks" is an internal option that indicates whether the chosen
+ driver can handle split links. (It might work to *disable* link breaking.)
+
+Right:
+ Use one of the following:
+
+ a) compile with pdflatex_,
+
+ b) use the package breakurl_,
+
+ c) (for printout) `disable hyperlinks`_ using the package "nohyperref".
+
+See also the `Link text doesn’t break at end line`_ LaTeX FAQ entry.
+
+.. _breakurl:
+ http://mirror.ctan.org/help/Catalogue/entries/breakurl.html
+
+.. _Link text doesn’t break at end line:
+ http://www.tex.ac.uk/cgi-bin/texfaq2html?label=breaklinks
+
+
+Glyph not defined in PD1 encoding
+`````````````````````````````````
+
+If a section title or other link contains non-Latin (e.g. Cyrillic)
+characters, the LaTeX log contains lots of warnings like::
+
+ Package hyperref Warning: Glyph not defined in PD1 encoding,
+ (hyperref) removing `\CYRZ' on input line 6.
+ ...
+
+This can be solved with the "unicode" hyperref_option_ setting::
+
+ --hyperref-option=unicode
+
+(works also with non-unicode input/output encoding (e.g. "koi8r" or
+"latin1"). Newer versions of hyperref default to "unicode=true" if the
+document language is "russian".
+
+.. _hyperref_option: config.html#stylesheet-latex2e-writer
+
+
+image inclusion
+```````````````
+
+Images__ are included in LaTeX with the help of the `graphicx` package. The
+supported file formats depend on the used driver:
+
+* pdflatex_ and xelatex_ work with PNG, JPG, or PDF, but **not EPS**.
+* Standard latex_ can include **only EPS** graphics, no other format.
+* latex + dvipdfmx works with EPS and JPG (add 'dvipdfmx' to the
+ documentoptions_ and 'bmpsize' to the stylesheet_ setting).
+
+If PDF-image inclusion in PDF files fails, specifying
+``--graphicx-option=pdftex`` or ``--graphicx-option=auto`` might help.
+
+For details see grfguide.pdf_.
+
+The Rubber_ wrapper can be used for automatic image conversion.
+
+Docutils expects an URI as pointer to the image file. The latex writer
+transforms this URI to a local path. By default, LaTeX does not accept
+spaces and more than one dot in the filename. If using "traditional"
+filenames is not an option, adding grffile_ to the `style sheets`_
+can help.
+
+__ ../ref/rst/directives.html#images
+.. _grfguide.pdf:
+ http://mirror.ctan.org/macros/latex/required/graphics/grfguide.pdf
+.. _grffile:
+ http://mirror.ctan.org/help/Catalogue/entries/grffile.html
+
+
+
+Why are my images too big?
+``````````````````````````
+
+HTML-browsers use the actual screen resolution (usually around
+100 DPI).
+
+The CSS specification suggests:
+
+ It is recommended that the reference pixel be the visual angle of one
+ pixel on a device with a pixel density of 96 DPI and a distance from the
+ reader of an arm's length.
+
+ -- http://www.w3.org/TR/CSS2/syndata.html#length-units
+
+This is why pixmap images without size specification or objects with a size
+specified in ``px`` tend to come too large in the PDF.
+
+Solution:
+ Specify the image size in fixed units (``pt``, ``cm``, ``in``) or
+ configure the `size of a pixel`_ (length unit px).
+
+Error ``illegal unit px``
+`````````````````````````
+
+If you convert the LaTeX source with a legacy program, you might get this
+error.
+
+The unit "px" was introduced by the `pdfTeX` converter on 2005-02-04.
+`pdfTeX` is used also for conversion into DVI format in all modern LaTeX
+distributions (since ca. 2006).
+
+If updating LaTeX is not an option, just remove the "px" from the length
+specification. HTML/CSS will default to "px" while the `latexe2` writer
+will add the fallback unit "bp".
+
+Error ``Symbol \textcurrency not provided`` ...
+```````````````````````````````````````````````
+
+The currency sign (\\u00a4) is not supported by all fonts (some have
+an Euro sign at its place). You might see an error like::
+
+ ! Package textcomp Error: Symbol \textcurrency not provided by
+ (textcomp) font family ptm in TS1 encoding.
+ (textcomp) Default family used instead.
+
+(which in case of font family "ptm" is a false positive). Add either
+
+:warn: turn the error in a warning, use the default symbol (bitmap), or
+:force,almostfull: use the symbol provided by the font at the users
+ risk,
+
+to the document options or use a different font package.
+
+Search and text extraction
+``````````````````````````
+
+Search for text that contains characters outside the ASCII range (e.g.
+umlauts) might fail. See font_ and `font encoding`_ (as well as
+`Searching PDF files`_ for background information).
+
+It may help to load the `cmap` package (via `style sheets`_ or the custom
+`LaTeX preamble`_ (see also `Proper use of cmap and mmmap`_).
+
+.. _Searching PDF files:
+ http://www.tex.ac.uk/cgi-bin/texfaq2html?label=srchpdf
+
+.. _Proper use of cmap and mmmap:
+ https://tex.stackexchange.com/questions/64409/proper-use-of-cmap-and-mmap
+
+Unicode box drawing and block characters
+````````````````````````````````````````
+
+The easiest solution is to use xelatex_ for `PDF generation`_.
+
+With "traditional" TeX engines (e.g. pdflatex_):
+
+- Generate LaTeX code with `output-encoding`_ "utf-8".
+
+- Add the pmboxdraw_ package to the `style sheets`_.
+ (For shaded boxes also add the `color` package.)
+
+Unfortunately, this defines only a subset of the characters
+(see pmboxdraw.pdf_ for a list).
+
+.. _pmboxdraw:
+ http://mirror.ctan.org/help/Catalogue/entries/pmboxdraw.html
+
+.. _pmboxdraw.pdf:
+ http://mirror.ctan.org/macros/latex/contrib/oberdiek/pmboxdraw.pdf
+
+Bugs and open issues
+--------------------
+
+Open to be fixed or open to discussion.
+
+See also the entries in the `Docutils TODO list`_,
+the BUGS_ documentation and the `SourceForge Bug Tracker`_.
+
+.. _Docutils TODO list: ../dev/todo.html#latex-writer
+.. _bugs: ../../BUGS.html
+.. _SourceForge Bug Tracker:
+ http://sf.net/tracker/?group_id=38414&atid=422030
+
+
+Footnotes and citations
+```````````````````````
+
+Initially both were implemented using figure floats, because hyperlinking
+back and forth seemed to be impossible. Later the `figure` directive was
+added that puts images into figure floats.
+
+This results in footnotes, citations, and figures possibly being mixed at
+page foot.
+
+Workaround:
+ Select footnote and citation handling with the docutils-footnotes_ and
+ use-latex-citations_ options.
+
+If ``use-latex-citations`` is used, a bibliography is inserted right at
+the end of the document. *This should be customizable*.
+
+If ``use-latex-citations`` is used adjacent citation references (separated
+only by a single space or a newline) are combined to a single citation
+group, i.e. ``[cite1]_ [cite2]_`` results in ``\cite{cite1,cite2}``.
+The appearance in the output can be configured in a `style sheet`_.
+
+.. _docutils-footnotes: config.html#docutils-footnotes
+.. _use-latex-citations: config.html#use-latex-citations
+
+
+Tables
+``````
+
+* reST-documents line length is assumed to be 80 characters. The
+ *tablewidth* is set relative to this value. If someone produces documents
+ with line length of 132 this will lead to suboptimal results.
+
+ You may use the `:width:` option to manually set the table column widths.
+
+* Table: multicol cells are always left aligned.
+
+* Table cells with both multirow and multicolumn are currently not possible.
+
+* literal-blocks in table cells:
+
+ - If verbatim or flushleft is used one gets vertical space above and below.
+ - This is bad for the topmost paragraph in a cell, therefore the writer
+ uses raggedright.
+ - Ragged right fails on followup paragraphs as the vertical space would be
+ missing.
+
+* ``--table-style=booktabs``, ``..class:: booktab``: `booktabs` version
+ 1.00 does not work with `longtable`. This is solved in newer versions
+ (current is 2005/04/14 v1.61803).
+
+
+Figures
+```````
+
+* Figures are always as wide as the containing text. The "figwidth" argument
+ is currently not supported. As a consequence, the "align" argument has no
+ effect.
+
+* Wrapping text around figures is currently not supported. (Requires the
+ `wrapfig`_ package.)
+
+.. _wrapfig:
+ http://mirror.ctan.org/help/Catalogue/entries/wrapfig.html
+
+
+Miscellaneous
+`````````````
+
+* Pdfbookmark level 4 (and greater) does not work (might be settable but
+ complicated).
+
+* Hyperlinks are not hyphenated; this leads to bad spacing. See
+ docs/user/rst/demo.txt 2.14 directives.
+
+* Pagestyle headings does not work, when sections are starred. Use LaTeX for
+ the section numbering with the `options/settings`_
+ ``--no-section-numbers`` (command line) or ``sectnum_xform: False``
+ (config file).
--- /dev/null
+=====================
+ Docutils_ Link List
+=====================
+
+:Author: Lea Wiemann, the Docutils team
+:Contact: docutils-develop@lists.sourceforge.net
+:Revision: $Revision: 8025 $
+:Date: $Date: 2017-02-06 15:35:40 +0100 (Mo, 06. Feb 2017) $
+:Copyright: This document has been placed in the public domain.
+
+.. title:: Docutils Links
+
+.. contents::
+
+This document contains links users of Docutils and reStructuredText
+may find useful. Many of the projects
+listed here are hosted in the `Docutils Sandbox`_. If you have
+something to publish, you can get write access, too!
+
+The most current version of this link list can always be found at
+http://docutils.sourceforge.net/docs/user/links.html.
+
+.. _Docutils: http://docutils.sourceforge.net/
+.. _Docutils Sandbox: http://docutils.sf.net/sandbox/README.html
+
+
+Editors
+-------
+
+Advanced text editors with reStructuredText support, IDEs, and docutils GUIs:
+
+* Emacs `rst mode <http://docutils.sf.net/tools/editors/emacs>`__.
+
+* `Vim <http://www.vim.org/index.php>`__:
+
+ - `reStructuredText syntax highlighting mode
+ <http://www.vim.org/scripts/script.php?script_id=973>`__,
+
+ - `VST <http://www.vim.org/scripts/script.php?script_id=1334>`__ (Vim
+ reStructuredText) plugin for Vim7 with folding.
+
+ - `VOoM <http://www.vim.org/scripts/script.php?script_id=2657>`__
+ plugin for Vim that emulates two-pane outliner with
+ support for reStructuredText (since version 4.0b2).
+
+ - `Riv: Take notes in rst <https://github.com/Rykka/riv.vim>`__ Vim
+ plugin to take notes in reStructured text.
+
+* `JED <http://www.jedsoft.org/jed/>`__ programmers editor with
+ `rst mode <http://jedmodes.sf.net/mode/rst/>`__
+
+* `reStructuredText editor plug-in for Eclipse`__
+
+ __ http://resteditor.sf.net/
+
+* Gnome's gedit offers syntax highlighting and a reST preview pane.
+
+ Latest version of the plugin is available from `bittner @ github`_
+ (See also: `Gedit third party plugins`__).
+
+ __ https://wiki.gnome.org/Apps/Gedit/ThirdPartyPlugins-v3.8
+
+ .. _bittner @ github: https://github.com/bittner/gedit-reST-plugin
+
+* A BBEdit_/TextWrangler `language module`__ for editing reST documents.
+
+ .. _BBEdit: https://en.wikipedia.org/wiki/BBEdit
+ __ http://ericfromcanada.bitbucket.org/
+
+* Gunnar Schwant's DocFactory_ is a wxPython GUI application for
+ Docutils.
+
+* ReSTedit_ by Bill Bumgarner is a Docutils GUI for Mac OS X.
+
+* Leo_ is an outliner_, written in Python using PyQt. It can be used as IDE
+ for literal programming, as a filing cabinet holding any kind of data and
+ as `document editor`__ with outlines containing reStructuredText markup.
+
+ .. _outliner: http://en.wikipedia.org/wiki/Outliner
+ __ http://leoeditor.com/tutorial-rst3.html
+
+* `NoTex <https://notex.ch>`_ is a browser-based reStructuredText editor
+ with syntax highlighting and PDF/HTML export functionality using Sphinx.
+
+* `rsted <https://github.com/anru/rsted>`_ is a "simple online editor for
+ reStructuredText on Flask". You can try it on http://rst.ninjs.org/
+
+.. _DocFactory: http://docutils.sf.net/sandbox/gschwant/docfactory/doc/
+.. _ReSTedit: http://www.friday.com/bbum/index.php?s=restedit
+.. _Leo: http://leoeditor.com/
+
+
+Export
+------
+
+Convert reStructuredText to other formats:
+
+PDF
+```
+
+* `rst2pdf (reportlab)
+ <http://rst2pdf.googlecode.com>`_ is a tool to go
+ directly from reStructuredText to PDF, via `reportlab
+ <http://www.reportlab.org/rl_toolkit.html>`_. No LaTeX installation is
+ required.
+
+* `rst2pdf (pdflatex)
+ <http://docutils.sourceforge.net/sandbox/blais/rst2pdf/>`_ by Martin Blais
+ is a minimal front end producing LaTeX, compiling the LaTeX file, getting
+ the produced output to the destination location and finally deleting all
+ the messy temporary files that this process generates.
+
+* `rst2pdf (rubber)
+ <http://docutils.sf.net/sandbox/rst2pdf/README.html>`_ is
+ a front end for the generation of PDF documents from a reStructuredText
+ source via LaTeX in one step cleaning up intermediate files. It uses the
+ `rubber <http://iml.univ-mrs.fr/~beffara/soft/rubber/>`_ Python wrapper
+ for LaTeX and friends.
+
+* ``py.rest`` from the Codespeak `py Lib scripts`_ converts
+ reStructuredText files to HTML and PDF (cleaning up the intermediate
+ latex files). Similar to ``buildhtml.py``, it looks recursively for
+ .txt files in the given PATHS.
+
+* rlpdf_ is another PDF Writer based on ReportLabs.
+
+* RinohType_ is a pure Python PDF Writer based on a document template and a
+ style sheet (beta).
+
+.. _py Lib scripts: http://codespeak.net/py/dist/bin.html
+.. _rlpdf: http://docutils.sf.net/sandbox/dreamcatcher/rlpdf/
+.. _RinohType: http://pypi.python.org/pypi/RinohType/0.2.1
+
+OpenOffice
+``````````
+
+* Since version 0.5, the odtwriter_ by Dave Kuhlman is part of the Docutils_
+ core.
+
+.. _odtwriter: http://docutils.sf.net/docs/user/odt.html
+
+
+website generators and HTML variants
+````````````````````````````````````
+
+* The Sphinx_ Python Documentation Generator by Georg Brandl was originally
+ created to translate the `Python documentation`_, and is now `used by
+ <http://sphinx.pocoo.org/examples.html>`__ a wide choice of projects.
+
+ It can generate complete web sites (interlinked and indexed HTML pages),
+ ePub, PDF, and others [#]_ from a set of rst source files.
+
+ .. [#] see http://sphinx-doc.org/config.html#options-for-epub-output
+ .. _Sphinx: http://sphinx.pocoo.org/
+
+* The Nikola_ static site generator, uses reStructuredText by
+ default.
+
+ .. _nikola: http://getnikola.com/
+
+* Pelican_ is a static site generator (mainly for blogs). Articles/pages can
+ be written in reStructuredText or Markdown\ [#markdown]_ format.
+
+ .. _pelican: http://docs.getpelican.com
+
+* tinkerer_ is a static bloggin framework based on Sphinx_.
+
+ .. _tinkerer: http://tinkerer.me
+
+* rst2ht_ by Oliver Rutherfurd, converts reStructuredText to an .ht
+ template, for use with ht2html_.
+
+ .. _rst2ht: http://www.rutherfurd.net/articles/rst-ht2html.html
+ .. _ht2html: http://ht2html.sourceforge.net/
+
+* htmlnav_ by Gunnar Schwant, is an HTML writer which supports navigation
+ bars.
+
+ .. _htmlnav: http://docutils.sf.net/sandbox/gschwant/htmlnav/
+
+* rest2web_, by Michael Foord, is a tool for creating web sites with
+ reStructuredText.
+
+ .. _rest2web: http://www.voidspace.org.uk/python/rest2web/
+
+* rst2chm_ by Oliver Rutherfurd, generates Microsoft HTML Help files from
+ reStructuredText files.
+
+ .. _rst2chm: http://www.rutherfurd.net/software/rst2chm/
+
+* `html4strict <http://docutils.sf.net/sandbox/html4strict/>`__
+ produces XHTML that strictly conforms to the XHTML 1.0 specification.
+
+* `html4trans <http://docutils.sf.net/sandbox/html4trans/>`__
+ produces XHTML conforming to the version 1.0 Transitional DTD that
+ contains enough formatting information to be viewed by a lightweight HTML
+ browser without CSS support.
+
+* A `simple HTML writer`_ by Bill Bumgarner that doesn't rely on CSS
+ (stylesheets).
+
+ .. _simple HTML writer: http://docutils.sf.net/sandbox/bbum/DocArticle/
+
+ePub
+````
+
+* The `rst2epub`_ project by Robert Wierschke converts simple
+ reStructuredText doucments into valid epub files.
+
+ .. simple but well structured with classes/modules for epub components,
+ and a standard ``setup.py`` installation file.
+
+* rst2epub2_ by Matt Harrison includes the epublib (originally by Tim
+ Tambin) and a rst2epub.py executable for the conversion.
+
+* Sphinx_ provides ePub as output option, too.
+
+.. _rst2epub: https://bitbucket.org/wierob/rst2epub
+.. _rst2epub2: https://github.com/mattharrison/rst2epub2
+
+
+Others
+``````
+
+* Pandoc_ is a document converter that can write Markdown\ [#markdown]_,
+ reStructuredText, HTML, LaTeX, RTF, DocBook XML, and S5.
+
+* restxsl_ by Michael Alyn Miller, lets you transform reStructuredText
+ documents into XML/XHTML files using XSLT stylesheets.
+
+* An `XSLT script`__ by Ladislav Lhotka enables reStructuredText annotations
+ to be included in RELAG NG XML schemas.
+
+ __ http://www.cesnet.cz/doc/techzpravy/2006/rngrest/
+
+* `DocBook Writer`_ by Oliver Rutherfurd.
+
+* Nabu_, written by Martin Blais, is a publishing system which
+ extracts information from reStructuredText documents and stores it
+ in a database. Python knowledge is required to write extractor
+ functions (see `Writing an Extractor`_) and to retrieve the data
+ from the database again.
+
+* The `pickle writer`_ by Martin Blais pickles the document tree to a binary
+ string. Later unpickling will allow you to publish with other Writers.
+
+* The `Texinfo Writer`_, by Jon Waltman converts reStructuredText to
+ Texinfo, the documentation format used by the GNU project and the
+ Emacs text editor. Texinfo can be used to produce multiple output
+ formats, including HTML, PDF, and Info.
+
+* For `confluence CMS`_ see https://github.com/netresearch/rst2confluence.
+
+* Deploying into wikis might be aided by deploy-rst_.
+
+.. _Pandoc: http://sophos.berkeley.edu/macfarlane/pandoc/
+.. _restxsl: http://www.strangeGizmo.com/products/restxsl/
+.. _DocBook Writer: http://docutils.sf.net/sandbox/oliverr/docbook/
+.. _Nabu: http://furius.ca/nabu/
+.. _Writing an Extractor: http://furius.ca/nabu/doc/nabu-extractor.html
+.. _pickle writer: http://docutils.sf.net/sandbox/blais/pickle_writer/
+.. _Texinfo Writer: http://docutils.sf.net/sandbox/texinfo-writer/README.html
+.. _confluence CMS: http://www.atlassian.com/software/confluence
+.. _deploy-rst: https://github.com/netresearch/deploy-rst
+
+
+Import
+------
+
+Convert other formats to reStructuredText:
+
+* recommonmark_ is a Markdown\ [#markdown]_ (CommonMark_) parser for docutils.
+
+* sxw2rest_, by Trent W. Buck, converts StarOffice XML Writer (SXW)
+ files to reStructuredText.
+
+* xml2rst_, an XSLT stylesheet written by Stefan Merten, converts XML
+ dumps of the document tree (e.g. created with rst2xml.py) back to
+ reStructuredText.
+
+* xhtml2rest_, written by Antonios Christofides, is a simple utility
+ to convert XHTML to reStructuredText.
+
+* DashTable_ by Gustav Klopp converts HTML tables into reStructuredText.
+ Colspan and Rowspan supported!
+
+ .. _DashTable: https://github.com/gustavklopp/DashTable
+
+* Sphinx_ includes a `LaTeX to Rst converter
+ <http://svn.python.org/projects/doctools/converter/>`__ in its source code
+ (trimmed to importing the old Python docs).
+
+* Pandoc_ can read Markdown\ [#markdown]_ and (subsets of) HTML, and LaTeX and export to
+ (amongst others) reStructuredText.
+
+* PySource_, by Tony Ibbs, is an experimental Python source Reader.
+ There is some related code in David Goodger's sandbox
+ (pysource_reader_) and a `Python Source Reader`_ document.
+
+.. [#markdown]
+ `Markdown <http://daringfireball.net/projects/markdown/syntax>`__ is
+ another lightwight markup language. See also documentation on `Common
+ markup for Markdown and reStructuredText`_.
+
+.. _recommonmark: https://github.com/rtfd/recommonmark
+.. _CommonMark: http://commonmark.org/
+.. _sxw2rest: http://twb.ath.cx/~twb/darcs/sxw2rest/
+.. _xml2rst: http://www.merten-home.de/FreeSoftware/xml2rst/index.html
+.. _xhtml2rest: http://docutils.sf.net/sandbox/wiemann/xhtml2rest/
+.. _PySource: http://docutils.sf.net/sandbox/tibs/pysource/
+.. _pysource_reader: http://docutils.sf.net/sandbox/davidg/pysource_reader/
+.. _Python Source Reader: http://docutils.sf.net/docs/dev/pysource.html
+.. _Common markup for Markdown and reStructuredText:
+ https://gist.github.com/dupuy/1855764
+
+
+Extensions
+----------
+
+Extend the reStructuredText syntax or the features of Docutils.
+More extensions are in the `Docutils Sandbox`_.
+
+* Beni Cherniavsky has written a generic `preprocessing module`_ for
+ roles and/or directives and built preprocessors for TeX math for
+ both LaTeX and HTML output on top of it.
+
+* Beni Cherniavsky maintains a Makefile_ for driving Docutils, hoping
+ to handle everything one might do with Docutils.
+
+* The `ASCII art to SVG converter`_ (aafigure) developed by
+ Chris Liechti can parse ASCII art images, embedded in reST documents and
+ output an image. This would mean that simple illustrations could be
+ embedded as ASCII art in the reST source and still look nice when
+ converted to e.g. HTML
+
+* zot4rst_ by Erik Hetzner is an extension that allows users to write reST
+ documents using citations from a Zotero_ library.
+
+* Quick and easy publishing reStructuredText source files as blog posts
+ on blogger.com is possible with `rst2blogger`_ .
+
+.. _preprocessing module: http://docutils.sf.net/sandbox/cben/rolehack/
+.. _Makefile: http://docutils.sf.net/sandbox/cben/make/
+.. _ASCII art to SVG converter:
+ http://docutils.sf.net/sandbox/cliechti/aafigure/
+.. _zot4rst: http://e6h.org/~egh/hg/zotero-plain
+.. _Zotero: http://www.zotero.org/
+.. _rst2blogger: https://github.com/dhellmann/rst2blogger#readme
+
+
+Related Applications
+--------------------
+
+Applications using docutils/reStructuredText and helper applications.
+
+* For Wikis, please see the `FAQ entry about Wikis`_.
+
+* For Blogs (Weblogs), please see the `FAQ entry about Blogs`_.
+
+* `Project Gutenberg`_ uses a customized version of Docutils with it's own
+ xetex- and nroff-writer and epub generator.
+
+.. _FAQ entry about Wikis: http://docutils.sf.net/FAQ.html
+ #are-there-any-wikis-that-use-restructuredtext-syntax
+.. _FAQ entry about Blogs: http://docutils.sf.net/FAQ.html
+ #are-there-any-weblog-blog-projects-that-use-restructuredtext-syntax
+.. _Project Gutenberg: http://www.gutenberg.org
+
+
+Tools
+`````
+
+* rstcheck_ Checks syntax of reStructuredText and code blocks nested within
+ it. (Using the Sphinx syntax "code-block" for the "code" directive.)
+
+ .. _rstcheck: https://pypi.python.org/pypi/rstcheck
+
+* restview_ is a viewer for ReStructuredText documents.
+
+ Pass the name of a ReStructuredText document to restview, and it will
+ launch a web server on localhost:random-port and open a web browser. It
+ will also watch for changes in that file and automatically reload and
+ rerender it. This is very convenient for previewing a document while
+ you're editing it.
+
+ .. _restview: http://mg.pov.lt/restview/
+
+
+Development
+```````````
+
+* Sphinx_ extends the ReStructuredText syntax to better support the
+ documentation of Software (and other) *projects* (but other documents
+ can be written with it too).
+
+ Since version 2.6, the `Python documentation`_ is based on
+ reStructuredText and Sphinx.
+
+* Trac_, a project management and bug/issue tracking system, supports
+ `using reStructuredText
+ <http://trac.edgewall.org/wiki/WikiRestructuredText>`__ as an
+ alternative to wiki markup.
+
+* PyLit_ provides a bidirectional text <--> code converter for *literate
+ programming with reStructuredText*.
+
+* If you are developing a Qt app, rst2qhc_ lets you generate the whole help
+ automatically from reStructuredText. That includes keywords, TOC,
+ multiple manuals per project, filters, project file, collection project
+ file, and more.
+
+.. _Python documentation: http://docs.python.org/
+.. _Trac: http://trac.edgewall.org/
+.. _PyLit: http://repo.or.cz/pylit.git
+.. _rst2qhc: http://rst2qhc.googlecode.com
+
+
+CMS Systems
+```````````
+
+* Plone_ and Zope_ both support reStructuredText markup.
+* ZReST_, by Richard Jones, is a "ReStructuredText Document for Zope_"
+ application that is complete and ready to install.
+
+.. _Plone: http://plone.org/
+.. _Zope: http://www.zope.org/
+.. _ZReST: http://docutils.sf.net/sandbox/richard/ZReST/
+
+
+Presentations
+`````````````
+
+* rst2html5_ transform restructuredtext documents to html5 + twitter's
+ bootstrap css, deck.js or reveal.js
+
+* landslide_ generates HTML5 slideshows from markdown, ReST, or textile.
+
+* `native support for S5 <slide-shows.s5.html>`_.
+
+* The `PythonPoint interface`_ by Richard Jones produces PDF
+ presentations using ReportLabs' PythonPoint_.
+
+* rst2beamer_ generates a LaTeX source that uses the `Beamer` document class.
+ Can be converted to PDF slides with pdfLaTeX/XeLaTeX/LuaLaTeX.
+
+* InkSlide_ quick and easy presentations using Inkscape_. InkSlide uses
+ reStructuredText for markup, although it renders only a subset of rst.
+
+* rst2outline_ translates a reStructuredText document to a plain text
+ outline. This can then be transformed to PowerPoint.
+
+* Pandoc_ can also be used to produce slides, as shown in this
+ `Pandoc Slides Demo`_
+
+.. _PythonPoint: http://www.reportlab.org/python_point.html
+.. _PythonPoint interface: http://docutils.sf.net/sandbox/richard/pythonpoint/
+.. _rst2beamer: http://docutils.sf.net/sandbox/rst2beamer/
+.. _Inkscape: http://inkscape.org/
+.. _InkSlide: http://wiki.inkscape.org/wiki/index.php/InkSlide
+.. _rst2html5: https://github.com/marianoguerra/rst2html5
+.. _landslide: https://github.com/adamzap/landslide
+.. _rst2outline: http://docutils.sf.net/sandbox/rst2outline/
+.. _Pandoc Slides Demo:
+ http://johnmacfarlane.net/pandoc/demo/example9/producing-slide-shows-with-pandoc
--- /dev/null
+=========================
+ Docutils_ Mailing Lists
+=========================
+
+:Author: Lea Wiemann
+:Contact: docutils-develop@lists.sourceforge.net
+:Revision: $Revision: 8111 $
+:Date: $Date: 2017-06-10 22:35:01 +0200 (Sa, 10. Jun 2017) $
+:Copyright: This document has been placed in the public domain.
+
+
+.. Gmane went down 2016 and is only partially restored.
+ http://home.gmane.org/2016/08/29/next-steps-gmane/
+
+.. raw:: html
+
+ <div class="sidebar">
+ <p class="first sidebar-title">Search the list archives</p>
+ <form method="get" action="https://sourceforge.net/p/docutils/mailman/search/">
+ <p style="margin-bottom: 3px;"><input type="text" name="q" style="width: 100%;" /></p>
+ <p>Search in <select name="mail_list">
+ <option value="all">all mailing lists</option>
+ <option value="docutils-users">Docutils-users</option>
+ <option value="docutils-develop">Docutils-develop</option>
+ <option value="docutils-checkins">Docutils-checkins</option>
+ </select></p>
+ <p class="last"><input type="submit" value="Search" /></p>
+ </form>
+ </div>
+
+All discussion about Docutils takes place on mailing lists.
+
+There are four different lists with traffic related to Docutils.
+For an oversight, see https://sourceforge.net/p/docutils/mailman/.
+If unsure, use the **Docutils-users** mailing list:
+
+
+Docutils-users
+--------------
+
+The `Docutils-users mailing list`_ is a place to discuss any issues
+related to the usage of Docutils and reStructuredText. (Please be
+sure to check the FAQ_ first.)
+
+There are several possibilities to **read and post** messages on the
+mailing lists; use the one you feel most comfortable with.
+
+* Using an `email subscription`__. This is the traditional way; you
+ will receive all messages sent to the mailing list via email.
+
+ __ `docutils-users mailing list`_
+
+.. * Using Gmane's `web interface`__. To post a message, click "post" or
+ "followup" in the drop-down menu on the right. (Gmane also has a
+ complete **archive** of the mailing list; use the search form at the
+ top of this page to search it.)
+
+ __ http://news.gmane.org/gmane.text.docutils.user
+
+* Use a newsreader with Gmane's `NNTP interface`__
+ (gmane.text.docutils.user on news.gmane.org).
+
+ __ nntp://news.gmane.org/gmane.text.docutils.user
+
+* **If you do not wish to subscribe,** you can also just send an email
+ message with your question or comment to
+ Docutils-users@lists.sourceforge.net.
+
+ Note in your message that you are not subscribed (to make sure that you
+ receive copies [CCs] of any replies) or check for answers in the
+ `Docutils-users Archives`_.
+
+The first time you post a message without being subscribed (also when
+posting via Gmane), you will receive an automatic response with the subject
+"Your message to Docutils-users awaits moderator approval"; this is done to
+prevent spam to the mailing lists. Your message will usually be approved
+within a few hours. To avoid duplicates, please do not resend your message
+using a different email address. After your first message has been
+approved, your email address will be added to the whitelist and future
+messages will be posted to the mailing list without moderation.
+
+To see the collection of prior postings to the list, visit the
+`Docutils-users Archives`_.
+
+
+Docutils-develop
+----------------
+
+Discussions about developing and extending Docutils take place on the
+`Docutils-develop mailing list`_.
+
+You can access this list via `email subscription`__ or news__
+(gmane.text.docutils.devel); the posting address is
+Docutils-develop@lists.sourceforge.net.
+
+To see the collection of prior postings to the list, visit the
+`Docutils-develop Archives`__.
+
+__ `Docutils-develop mailing list`_
+__ nntp://news.gmane.org/gmane.text.docutils.devel
+__ http://sourceforge.net/mailarchive/forum.php?forum_name=docutils-develop
+
+Docutils-checkins
+-----------------
+
+All check-ins to the `Subversion repository`_ cause a "check-in email"
+to the `Docutils-checkins list`_. In order to stay informed about
+current development, developers are advised to monitor this mailing
+list.
+
+This mailing list is for reading only; please direct any discussion
+about the check-ins to Docutils-develop. (For your convenience, the
+Reply-To header of all check-in emails points to Docutils-develop.)
+
+This mailing list is accessible via `email subscription`__ or
+news__ (gmane.text.docutils.cvs) as well.
+
+If you are using an email subscription and you would prefer to only
+receive check-in messages for changes that affect the main Docutils
+distribution (i.e. ``trunk/docutils/*``), go to the `list options`_
+page and select the "Docutils core" topic.
+
+__ `Docutils-checkins list`_
+__ nntp://news.gmane.org/gmane.text.docutils.cvs
+.. _list options: http://lists.sf.net/lists/options/docutils-checkins
+
+Doc-SIG
+-------
+
+The "Python Documentation Special Interest Group" (`Doc-SIG`_) mailing list
+is occasionally used to discuss the usage of Docutils for Python
+documentation.
+
+This mailing list can be accessed via `email subscription`__ or
+news__ (gmane.comp.python.documentation) as well. You must be
+subscribed in order to post messages to this mailing list.
+
+__ `Doc-SIG`_
+__ nntp://news.gmane.org/gmane.comp.python.documentation
+
+
+.. _Docutils-users mailing list:
+ http://lists.sourceforge.net/lists/listinfo/docutils-users
+.. _Docutils-users Archives:
+ http://sourceforge.net/mailarchive/forum.php?forum_name=docutils-users
+.. _Docutils-develop mailing list:
+ http://lists.sourceforge.net/lists/listinfo/docutils-develop
+.. _Docutils-develop Archives:
+ http://sourceforge.net/mailarchive/forum.php?forum_name=docutils-develop
+.. _Docutils-checkins list:
+ http://lists.sourceforge.net/lists/listinfo/docutils-checkins
+.. _Doc-SIG:
+ http://mail.python.org/mailman/listinfo/doc-sig
+
+.. _Subversion repository: ../dev/repository.html
+.. _Docutils: http://docutils.sourceforge.net/
+.. _FAQ: ../../FAQ.html
--- /dev/null
+==============================
+ manpage writer for Docutils_
+==============================
+
+:Author: Engelbert Gruber
+:Contact: docutils-develop@lists.sourceforge.net
+:Revision: $Revision: 7302 $
+:Date: $Date: 2012-01-03 20:23:53 +0100 (Di, 03. Jän 2012) $
+:Copyright: This document has been placed in the public domain.
+
+This tries to explore the posibilities to generate man-pages from
+reStructuredText. Man pages are the way for Unix systems to provide
+help to the user. GNU does this with (TeX)info-pages.
+
+Module information
+''''''''''''''''''
+
+Unix man page belong into a numbered section, 1 is user commands, 8 contains
+administrator commands, the headlines of all manpages are collected into a
+database, queryable with the programm ``apropos``, therefore the headline
+should contain a short text describing into which group this command belongs.
+
+These informations are collected from title, subtitle and the docinfo.
+
+Also man pages have a defined set of sections, that are more or less
+mandatory, see References_.
+
+man pages look like::
+
+ man(1) Man Pager Utils man(1)
+
+ NAME
+ man - an interface to the on-line reference manuals
+
+ SYNOPSIS
+ man [-c|-w|-tZT device] [-adhu7V] [-m system[,...]] [-L locale]
+
+in roff formatting::
+
+ .TH man 1 "14 May 2001" "2.3.19" "Manual pager utils"
+ .SH NAME
+ man \- an interface to the on-line reference manuals
+ .SH SYNOPSIS
+ .\" The general command line
+ .B man
+ .RB [\| \-c \||\| \-w \||\| \-tZT
+ .IR device \|]
+
+This means we have
+
+* a title "man"
+* a subtitle "an interface to the on-line reference manuals"
+* a manual section "1"
+* a manual group "Manual pager utils"
+* a date "14 May 2001"
+* a version "2.3.19"
+
+References
+''''''''''
+
+man pages from section 7, ``man`` and ``man-pages``.
+
+.. [LMHT] Linux Man Page Howto.
+
+Conventions
+'''''''''''
+
+* man pages have a special structure and organization. From the manpage
+ to *man*::
+
+ The table below shows the section numbers of the manual followed by the
+ types of pages they contain.
+
+ 1 Executable programs or shell commands
+ 2 System calls (functions provided by the kernel)
+ 3 Library calls (functions within program libraries)
+ 4 Special files (usually found in /dev)
+ 5 File formats and conventions eg /etc/passwd
+ 6 Games
+ 7 Miscellaneous (including macro packages and conven-
+ tions), e.g. man(7), groff(7)
+ 8 System administration commands (usually only for root)
+ 9 Kernel routines [Non standard]
+
+ A manual page consists of several parts.
+
+ They may be labelled NAME, SYNOPSIS, DESCRIPTION, OPTIONS, FILES,
+ SEE ALSO, BUGS, and AUTHOR.
+
+ The following conventions apply to the SYNOPSIS section and can be used
+ as a guide in other sections.
+
+ bold text type exactly as shown.
+ italic text replace with appropriate argument.
+ [-abc] any or all arguments within [ ] are optional.
+ -a|-b options delimited by | cannot be used together.
+ argument ... argument is repeatable.
+ [expression] ... entire expression within [ ] is repeatable.
+
+ The command or function illustration is a pattern that should match all
+ possible invocations. In some cases it is advisable to illustrate sev-
+ eral exclusive invocations as is shown in the SYNOPSIS section of this
+ manual page.
+
+* new lines in general.
+
+ Consecutive blank lines are merged by the viewer but not on printouts.
+ So one has to be cautious. This is most disturbing when printing
+ postscript.
+
+ .. NOTE::
+
+ 1. Roff requests only work when at line start.
+ 2. But consecutive blank lines are merged by the viewer but not on
+ printouts.
+
+ So try the rule start new lines in ``visit_``-functions, but only if
+ necessary. E.g. ``field-names`` are already on a new line because of
+ docutils structure.
+
+* Indentation, left margin:
+
+ - The writer includes two macros ``.INDENT`` and ``.UNINDENT`` that
+ keep track of the indentation in roff-code, for line-blocks python
+ keeps track of it. WHAT should be the preferred way ?
+
+ But standard macros like ``.PP`` might reset it.
+
+ - Why do ``.RE`` and ``.RS`` not work?
+
+ .. Note::
+ Current indent is in register ``.i``.
+
+* [LMHT]_ Filenames are always in italics, except in the SYNOPSIS section,
+ use::
+
+ .I /usr/include/stdio.h
+
+ and::
+
+ .B #include <stdio.h>
+
+* Tables are possible, via the external processor tbl, although one should
+ avoid them.
+
+Open issues
+'''''''''''
+
+* How to typeset command/manpage names in text.
+* How to write long syntax lines.
+* Line ends around email or web addresses in texts.
+ How to distinguish something is inline or not ?
+
+* Images and equations are discouraged.
+* Lists in admonitions are not intended.
+* Encoding declaration ``'\" t -*- coding: ISO-8859-1 -*-``
+ in first line.
+
+ BUT if UTF-8 is declared tables are no longer processed.
+
+* Input and output encoding are problematic at least.
+
+.. _Docutils: http://docutils.sourceforge.net/
--- /dev/null
+=======================
+Odt Writer for Docutils
+=======================
+
+:Author: Dave Kuhlman
+:Contact: docutils-develop@lists.sourceforge.net
+:Revision: $Revision: 8162 $
+:Date: $Date: 2017-08-10 19:51:01 +0200 (Do, 10. Aug 2017) $
+:Copyright: This document has been placed in the public domain.
+
+:abstract: This document describes the Docutils odtwriter
+ (rst2odt.py).
+
+.. sectnum::
+
+.. contents::
+
+
+
+Introduction
+============
+
+What it does -- ``rst2odt.py`` translates reST
+(reStructuredText) into a Open Document Format ``.odt`` file. You
+can learn more about the ODF format here:
+
+- `OASIS Open Document Format for Office Applications
+ (OpenDocument) TC`_
+
+- `Open Document at Wikipedia`_
+
+You should be able to open documents (.odt files) generated with
+``rst2odt.py`` in ``OpenOffice/oowriter``.
+
+You can learn more about Docutils and reST here: `Docutils`_
+
+
+Requirements
+============
+
+In addition to the Docutils standard requirements, ``odtwriter``
+requires:
+
+- Optional -- `Pygments`_ is required if you want syntax
+ highlighting of code in literal blocks. See section `Syntax
+ highlighting`_.
+
+- Optional -- `Python Imaging Library`_ (PIL) is required if on an
+ image or figure directive, you specify ``scale`` but not ``width``
+ and ``height``. See section `Images and figures`_.
+
+
+
+How to Use It
+=============
+
+Run it from the command line as follows::
+
+ $ rst2odt.py myinput.txt myoutput.odt
+
+To see usage information and to learn about command line options
+that you can use, run the following::
+
+ $ rst2odt.py --help
+
+Examples::
+
+ $ rst2odt.py -s -g python_comments.txt python_comments.odt
+
+ $ rst2odt.py --source-url=odtwriter.txt --generator --stylesheet=/myconfigs/styles.odt odtwriter.txt odtwriter.odt
+
+
+Configuration file
+------------------
+
+The options described below can also be set in a configuration file.
+Use section ``[odf_odt writer]`` to set options specific to the
+``odtwriter``. For example::
+
+ [odf_odt writer]
+ stylesheet: styles1.odt
+
+See the "Docutils Configuration" document for more information on
+Docutils configuration files, including locations which are
+searched.
+
+
+Command line options
+--------------------
+
+The following command line options are specific to ``odtwriter``:
+
+--stylesheet=<URL> Specify a stylesheet URL, used verbatim.
+ Default: writers/odf_odt/styles.odt in the
+ installation directory.
+--odf-config-file=<file>
+ Specify a configuration/mapping file relative to the
+ current working directory for additional ODF options.
+ In particular, this file may contain a section named
+ "Formats" that maps default style names to names to be
+ used in the resulting output file allowing for
+ adhering to external standards. For more info and the
+ format of the configuration/mapping file, see the
+ odtwriter doc.
+--cloak-email-addresses
+ Obfuscate email addresses to confuse harvesters while
+ still keeping email links usable with standards-
+ compliant browsers.
+--no-cloak-email-addresses
+ Do not obfuscate email addresses.
+--table-border-thickness=TABLE_BORDER_THICKNESS
+ Specify the thickness of table borders in thousands of
+ a cm. Default is 35.
+--add-syntax-highlighting
+ Add syntax highlighting in literal code blocks.
+--no-syntax-highlighting
+ Do not add syntax highlighting in literal code blocks.
+ (default)
+--create-sections Create sections for headers. (default)
+--no-sections Do not create sections for headers.
+--create-links Create links.
+--no-links Do not create links. (default)
+--endnotes-end-doc Generate endnotes at end of document, not footnotes at
+ bottom of page.
+--no-endnotes-end-doc Generate footnotes at bottom of page, not endnotes at
+ end of document. (default)
+--generate-list-toc Generate a bullet list table of contents, not an
+ ODF/``oowriter`` table of contents.
+--generate-oowriter-toc
+ Generate an ODF/``oowriter`` table of contents,
+ not a bullet list. (default) **Note:**
+ ``odtwriter`` is not able to determine page
+ numbers, so you will need to open the
+ generated document in ``oowriter``, then
+ right-click on the table of contents and
+ select "Update" to insert page numbers.
+--custom-odt-header=CUSTOM_HEADER
+ Specify the contents of an custom header line. See
+ odf_odt writer documentation for details about special
+ field character sequences. See section
+ `Custom header/footers: inserting page numbers, date, time, etc`_
+ for details
+--custom-odt-footer=CUSTOM_FOOTER
+ Specify the contents of an custom footer line. See
+ odf_odt writer documentation for details about special
+ field character sequences. See section
+ `Custom header/footers: inserting page numbers, date, time, etc`_
+ for details
+
+
+
+Styles and Classes
+==================
+
+``odtwriter`` uses a number of styles that are defined in
+``styles.xml`` in the default ``styles.odt``. This section
+describes those styles.
+
+Note that with the ``--stylesheet`` command line option, you can
+use either ``styles.odt`` or ``styles.xml``, as described below.
+Use of ``styles.odt`` is recommended over ``styles.xml``.
+
+You can modify the look of documents generated by ``odtwriter`` in
+several ways:
+
+- Open (a copy of) ``styles.odt`` in ``OpenOffice/oowriter`` and
+ modify the style you wish to change. Now, save this document,
+ then generate your documents using this modified copy of
+ ``styles.odt``.
+
+ In my version of ``oowriter``, to modify styles, either (1)
+ press F11 or (2) use menu item "Format/Styles and Formatting",
+ then right-click on the relevant style and select "Modify".
+ Modify the style, then save your document.
+
+- Open a document generated by ``odtwriter`` in `oowriter``. Now,
+ edit the style you are interested in modifying. Now, you
+ can extract the styles.xml file from your document and either
+ (1) use this as your default styles file or (2) copy and paste
+ the relevant style definition into your styles.xml.
+
+- Extract ``styles.xml`` from ``styles.odt`` using your favorite
+ ``zip/unzip`` tool. Then modify ``styles.xml`` with a text
+ editor. Now re-zip it back into your own ``styles.odt``, or use
+ it directly by specifying it with the ``--stylesheet`` command
+ line option. **Hint:** If you intend to extract ``styles.xml``
+ from an ``.odt`` file (and then "re-zip" it), you should turn off
+ XML optimization/compression in ``oowriter``. In order to this
+ in ``oowriter``, use Tools --> Options... --> Load-Save -->
+ General and turn off "Size optimization for XML format".
+
+- Open an empty (or new) document in ``oowriter``. Define all of
+ the styles described in this section. Then, use that document (a
+ .odt file) as your stylesheet. ``odtwriter`` will extract the
+ ``styles.xml`` file from that document and insert it into the
+ output document.
+
+- Some combination of the above.
+
+
+Styles used by odtwriter
+------------------------
+
+This section describes the styles used by ``odtwriter``.
+
+Note that we do not describe the "look" of these styles. That can
+be easily changed by using ``oowriter`` to edit the document
+``styles.odt`` (or a copy of it), and modifying any of the styles
+described here.
+
+To change the definition and appearance of these styles, open
+``styles.odt`` in ``oowriter`` and open the Styles and Formatting
+window by using the following menu item::
+
+ Format --> Styles and Formatting
+
+Then, click on the Paragraph Styles button or the Character Styles
+button at the top of the Styles and Formatting window. You may
+also need to select "All Styles" from the drop-down selection list
+at the bottom of the Styles and Formatting window in order to see
+the styles used by ``odtwriter``.
+
+Notice that you can make a copy of file ``styles.odt``, modify it
+using ``oowriter``, and then use your copy with the
+``--stylesheet=<file>`` command line option. Example::
+
+ $ rst2odt.py --stylesheet=mystyles.odt test2.txt test2.odt
+
+
+Paragraph styles
+~~~~~~~~~~~~~~~~
+
+rststyle-attribution
+ The style for attributions, for example, the attribution in a
+ ``.. epigraph::`` directive. Derived from
+ ``rststyle-blockquote``.
+
+rststyle-blockindent
+ An indented block.
+
+rststyle-blockquote
+ A block quote.
+
+rststyle-blockquote-bulletitem
+ The style for bullet list items inside block quote.
+
+rststyle-blockquote-enumitem
+ The style for enumerated list items inside block quote.
+
+rststyle-bodyindent
+ An indented block.
+
+rststyle-bulletitem
+ An item in an bullet list.
+
+rststyle-caption
+ The caption in a figure or image. Also see
+ ``rststyle-legend``.
+
+rststyle-codeblock
+ Literal code blocks -- A block of example code. Created with
+ double colon ("::") followed by an indented block or with the
+ ``.. parsed-literal::`` directive. Derived from the
+ ``Preformatted Text`` style in ``oowriter``.
+
+rststyle-enumitem
+ An item in an enumerated list.
+
+rststyle-epigraph
+ The style for epigraphs, for example, the body of an
+ ``.. epigraph::`` directive. Derived from
+ ``rststyle-blockquote``.
+
+rststyle-epigraph-bulletitem
+ The style for bullet list items inside epigraphs.
+
+rststyle-epigraph-enumitem
+ The style for enumerated list items inside epigraphs.
+
+rststyle-footer
+ The style for footers. The footer content originates from the
+ ``..footer::`` directive and in response to the command line
+ flags for generator (``--generator``), date/time generated
+ (``--date`` and ``--time``), and view source link
+ (``--source-link`` and ``--source-url=URL``).
+
+rststyle-header
+ The style for headers. The header content originates from the
+ ``..header::`` directive.
+
+rststyle-highlights
+ The style for highlightss, for example, the body of an
+ ``.. highlights::`` directive. Derived from
+ ``rststyle-blockquote``.
+
+rststyle-highlights-bulletitem
+ The style for bullet list items inside highlights.
+
+rststyle-highlights-enumitem
+ The style for enumerated list items inside highlights.
+
+rststyle-horizontalline
+ A horizontal line, e.g. used for transitions.
+
+rststyle-legend
+ The legend in a figure. See the Docutils figure directive. Also
+ see ``rststyle-caption``.
+
+rststyle-table-title
+ The style for titles of tables. See section `The table
+ directive`_.
+
+rststyle-textbody
+ Normal text. The style for paragraphs. Derived from the ``Text
+ body`` style in ``oowriter``.
+
+
+Character styles
+~~~~~~~~~~~~~~~~
+
+rststyle-emphasis
+ Emphasis. Normally rendered as italics.
+
+rststyle-inlineliteral
+ An inline literal.
+
+rststyle-strong
+ Strong emphasis. Normally rendered as boldface.
+
+rststyle-quotation
+ In-line quoted material.
+
+rststyle-codeblock-classname
+ Syntax highlighting in literal code blocks -- class names.
+
+rststyle-codeblock-comment
+ Syntax highlighting in literal code blocks -- comments.
+
+rststyle-codeblock-functionname
+ Syntax highlighting in literal code blocks -- function names.
+
+rststyle-codeblock-keyword
+ Syntax highlighting in literal code blocks -- Python language
+ keywords.
+
+rststyle-codeblock-name
+ Syntax highlighting in literal code blocks -- other names, for
+ example, variables.
+
+rststyle-codeblock-number
+ Syntax highlighting in literal code blocks -- literal numbers,
+ including integers, floats, hex numbers, and octal numbers.
+
+rststyle-codeblock-operator
+ Syntax highlighting in literal code blocks -- Python operators.
+
+rststyle-codeblock-string
+ Syntax highlighting in literal code blocks -- literal strings.
+
+
+List styles
+~~~~~~~~~~~
+
+rststyle-bulletlist
+ Bullet lists (but not in the table of contents)
+
+rststyle-blockquote-bulletlist
+ Bullet lists in block quotes.
+
+rststyle-blockquote-enumlist
+ Enumerated lists in block quotes.
+
+rststyle-enumlist-arabic
+ Enumerated lists, arabic (but not in the table of contents)
+
+rststyle-enumlist-loweralpha
+ Enumerated lists, lower alpha (but not in the table of contents)
+
+rststyle-enumlist-lowerroman
+ Enumerated lists, lower roman (but not in the table of contents)
+
+rststyle-enumlist-upperalpha
+ Enumerated lists, upper alpha (but not in the table of contents)
+
+rststyle-enumlist-upperroman
+ Enumerated lists, upper roman (but not in the table of contents)
+
+rststyle-epigraph-bulletlist
+ Bullet lists in epigraphs. See the ``.. epigraph::``
+ directive.
+
+rststyle-epigraph-enumlist
+ Enumerated lists in epigraphs. See the ``.. epigraph::``
+ directive.
+
+rststyle-highlights-bulletlist
+ Bullet lists in highlights blocks. See the ``.. highlights::``
+ directive.
+
+rststyle-highlights-enumlist
+ Enumerated lists in highlights blocks. See the ``.. highlights::``
+ directive.
+
+rststyle-tocbulletlist
+ Lists in the table of contents when section numbering is off.
+
+rststyle-tocenumlist
+ Lists in the table of contents when section numbering is on.
+
+
+Admonition styles
+~~~~~~~~~~~~~~~~~
+
+rststyle-admon-attention-hdr
+ The style for the attention admonition header/title.
+
+rststyle-admon-attention-body
+ The style for the attention admonition body/paragraph.
+
+rststyle-admon-caution-hdr
+ The style for the caution admonition header/title.
+
+rststyle-admon-caution-body
+ The style for the caution admonition body/paragraph.
+
+rststyle-admon-danger-hdr
+ The style for the admonition header/title.
+
+rststyle-admon-danger-body
+ The style for the danger admonition body/paragraph.
+
+rststyle-admon-error-hdr
+ The style for the error admonition header/title.
+
+rststyle-admon-error-body
+ The style for the error admonition body/paragraph.
+
+rststyle-admon-hint-hdr
+ The style for the hint admonition header/title.
+
+rststyle-admon-hint-body
+ The style for the hint admonition body/paragraph.
+
+rststyle-admon-hint-hdr
+ The style for the hint admonition header/title.
+
+rststyle-admon-hint-body
+ The style for the hint admonition body/paragraph.
+
+rststyle-admon-important-hdr
+ The style for the important admonition header/title.
+
+rststyle-admon-important-body
+ The style for the important admonition body/paragraph.
+
+rststyle-admon-note-hdr
+ The style for the note admonition header/title.
+
+rststyle-admon-note-hdr
+ The style for the note admonition header/title.
+
+rststyle-admon-tip-body
+ The style for the tip admonition body/paragraph.
+
+rststyle-admon-tip-hdr
+ The style for the tip admonition header/title.
+
+rststyle-admon-warning-body
+ The style for the warning admonition body/paragraph.
+
+rststyle-admon-warning-hdr
+ The style for the warning admonition header/title.
+
+rststyle-admon-generic-body
+ The style for the generic admonition body/paragraph.
+
+rststyle-admon-generic-hdr
+ The style for the generic admonition header/title.
+
+
+Rubric style
+~~~~~~~~~~~~
+
+rststyle-rubric
+ The style for the text in a rubric directive.
+
+The rubric directive recognizes a "class" option. If entered,
+odtwriter uses the value of that option instead of the
+``rststyle-rubric`` style. Here is an example which which attaches
+the ``rststyle-heading1`` style to the generated rubric::
+
+ .. rubric:: This is my first rubric
+ :class: rststyle-heading1
+
+
+Table styles
+~~~~~~~~~~~~
+
+A table style is generated by ``oowriter`` for each table that you
+create. Therefore, ``odtwriter`` attempts to do something similar.
+These styles are created in the ``content.xml`` document in the
+generated ``.odt`` file. These styles have names prefixed with
+"rststyle-table-".
+
+There are two ways in which you can control the styles of your
+tables: one simple, the other a bit more complex, but more
+powerful.
+
+First, you can change the thickness of the borders of all tables
+generated in a document using the "--table-border-thickness"
+command line option.
+
+Second, you can control additional table properties and you can
+apply different styles to different tables within the same document
+by customizing and using tables in your stylesheet: ``styles.odt``
+or whatever you name your copy of it using the --stylesheet command
+line option. Then, follow these rules to apply a table style to
+the tables in your document:
+
+- The default table style -- Optionally, alter and customize the
+ style applied by default to tables in your document by modifying
+ table "rststyle-table-0" in your stylesheet (``styles.odt`` or a
+ copy). Caution: Do not change the name of this table.
+
+- User-created table styles -- Add one or more new table styles to
+ be applied selectively to tables in your document by doing the
+ following:
+
+ 1. Using ``oowriter``, add a table to your stylesheet and give it
+ a name that starts with the prefix "rststyle-table-", for
+ example "rststyle-table-vegetabledata". Customize the table's
+ border thickness, border color, and table background color.
+
+ 2. In your reStructuredText document, apply your new table style
+ to a specific table by placing the ".. class::" directive
+ immediately before the table, for example::
+
+ .. class:: rststyle-table-vegetabledata
+
+The default table style will be applied to all tables for which you
+do not specify a style with the ".. class::" directive.
+
+Customize the table properties in ``oowriter`` using the table
+properties dialog for the table (style) that you wish to customize.
+
+Note that "--table-border-thickness" command line option overrides
+the border thickness specified in the stylesheet.
+
+The specific properties that you can control with this second
+method are the following:
+
+- Border thickness and border color.
+
+- Background color -- When you change the background color of a
+ table to be used as a style (in ``styles.odt`` or whatever you
+ name it), make sure you change the background color for the
+ *table* and *not* for a cell in the table. ``odtwriter`` picks
+ the background color from the table, not from a cell within the
+ table.
+
+
+Line block styles
+~~~~~~~~~~~~~~~~~~
+
+The line block styles wrap the various nested levels of line
+blocks. There is one line block style for each indent level.
+
+rststyle-lineblock1
+ Line block style for line block with no indent.
+
+rststyle-lineblock2
+ Line block style for line block indented 1 level.
+
+rststyle-lineblock3
+ Line block style for line block indented 2 levels.
+
+rststyle-lineblock4
+ Line block style for line block indented 3 levels.
+
+rststyle-lineblock5
+ Line block style for line block indented 4 levels.
+
+rststyle-lineblock6
+ Line block style for line block indented 5 levels.
+
+Notes:
+
+- ``odtwriter`` does not check for a maximum level of indents
+ within line blocks. Therefore, you can define additional line
+ block styles for additional levels if you need them. Define
+ these styles with the names ``rststyle-lineblock7``,
+ ``rststyle-lineblock8``, ...
+
+- Since the line block style is used to create indentation, a line
+ block that is inside a block quote will use
+ ``rststyle-lineblock2`` as its first level of indentation.
+
+
+Footnote and citation styles
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+rststyle-footnote
+ The style for footnotes. This style affects the footnote
+ content, *not* the footnote reference in the body of the document.
+
+rststyle-citation
+ The style for citations. This style affects the citation
+ content, *not* the citation reference in the body of the document.
+ You might need to adjust the indentation in this style
+ depending on the length of the label used in your citations.
+
+
+Heading and title styles
+~~~~~~~~~~~~~~~~~~~~~~~~~
+
+rststyle-heading{1|2|3|4|5}
+ The styles for headings (section titles and sub-titles). Five
+ levels of sub-headings are provided: rststyle-heading1 through
+ rststyle-heading5.
+
+rststyle-title
+ The style for the document title.
+
+rststyle-subtitle
+ The style for the document sub-title.
+
+
+Image and figure styles
+~~~~~~~~~~~~~~~~~~~~~~~~~
+
+rststyle-image
+ The style applied to an image, either an image by itself or an
+ image in a figure.
+
+rststyle-figureframe
+ The style applied to a figure (actually to the frame that
+ surrounds a figure).
+
+
+
+Defining and using a custom stylesheet
+---------------------------------------
+
+You can create your own custom stylesheet. Here is how:
+
+1. Make a copy of ``styles.odt``, which is in the distribution.
+
+2. Open your copy of ``styles.odt`` in ``oowriter``. Modify styles
+ in that document. Then, save it.
+
+3. When you run ``rst2odt.py``, use the ``--stylesheet`` command
+ line option to use your custom stylesheet. Run ``rst2odt.py
+ --help`` to learn more about these options.
+
+
+Why custom stylesheets
+~~~~~~~~~~~~~~~~~~~~~~~
+
+Here are a few reasons and ideas:
+
+- The page size is stored in the style sheet. The default page
+ size is ``Letter``. You can change the page size (for example,
+ to ``A4``) in your custom stylesheet by opening it in
+ ``oowriter``, then clicking on menu: ``Format/Page...``, then
+ clicking on the ``Page`` tab.
+
+
+
+Defining and using custom style names
+-------------------------------------
+
+[Credits: Stefan Merten designed and implemented the custom style names
+capability. Thank you, Stefan.]
+
+You can also instruct ``odtwriter`` to use style names of your own
+choice.
+
+
+Why custom style names
+~~~~~~~~~~~~~~~~~~~~~~
+
+Here are a few reasons and ideas:
+
+- Suppose that your organization has a standard set of styles in
+ OOo ``oowriter`` and suppose that the use of these styles is
+ required. You would like to generate ODF documents from
+ reST text files, and you want the generated documents to contain
+ these styles.
+
+- Suppose that your company or organization has a policy of using a
+ certain MS Word template for some set of documents. You would
+ like to generate ODF documents that use these custom style names,
+ so that you can export these documents from ODF ``oowriter`` to MS
+ Word documents that use these style names.
+
+- Suppose that your documents are written in a language other than
+ English. You would like the style names visible in the "Styles
+ and Formatting" window in OOo ``oowriter`` (menu item
+ ``Format/Styles and Formatting``) to be understandable in the
+ language of your users.
+
+- ``odtwriter`` maps single asterisks/stars (for example, \*stuff\*)
+ to emphasis and double stars to strong. You'd like to reverse
+ these. Or, you would like to generate headings level 3 and 4
+ where headings level 1 and 2 would normally be produced.
+
+
+How to use custom style names
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+In order to define custom style names and to generate documents that
+contain them, do the following:
+
+
+1. Create a configuration file containing a "Formats" section. The
+ configuration file obeys the file format supported by the Python
+ ConfigParser module:
+ `ConfigParser -- Configuration file parser --
+ http://docs.python.org/lib/module-ConfigParser.html
+ <http://docs.python.org/lib/module-ConfigParser.html>`_.
+
+2. In the "Formats" section of the configuration file, create one
+ option (a name-value pair) for each custom style name that you
+ wish to define. The option name is the standard ``odtwriter``
+ style name (without "rststyle-"), and the value is your custom
+ style name. Here is an example::
+
+ [Formats]
+ textbody: mytextbody
+ bulletitem: mybulletitem
+ heading1: myheading1
+ o
+ o
+ o
+
+3. Create a styles document that defines the styles generated by
+ ``odtwriter``. You can create and edit the styles in OOo
+ ``oowriter``. It may be helpful to begin by making a copy of the
+ styles document that is part of the ``odtwriter`` distribution
+ (``styles.odt``).
+
+4. When you run ``odtwriter``, specify the ``--odf-config-file``
+ option. You might also want to specify your styles document
+ using the ``--stylesheet`` option in order to include your
+ custom style definitions. For example::
+
+ rst2odt.py --odf-config-file=mymappingfile.ini --stylesheet=mystyles.odt mydoc.txt mydoc.odt
+
+
+Classes
+-------
+
+``odtwriter`` uses the following Docutils class to provide additional
+control of the generation of ODF content:
+
+- Class ``wrap`` -- Use this to cause the wrapping of text around
+ an image. The default is *not* to wrap text around images.
+ Here is an example::
+
+ .. class:: wrap
+ .. image:: images/flower01.png
+ :alt: A bright yellow flower
+ :height: 55
+ :width: 60
+
+
+Roles
+-------
+
+You can use a Docutils custom interpreted text role to attach a
+character style to an inline area of text. This capability also
+enables you to attach a new character style (with a new name) that
+you define yourself. Do this by defining your role in a stylesheet
+as a character style with "rststyle-" prefixed to your role name,
+then use the ``role`` directive and inline markup to apply your
+role.
+
+In order to use this capability, do the following:
+
+- Define the character style for your custom role in a stylesheet
+ (a copy of ``styles.odt``) with the prefix "rststyle-".
+ Remember: (1) If the name of your custom role is "pretty", then
+ define a character style named "rststyle-pretty". (2) Define the
+ style as a *character* style, and *not*, for example as a
+ paragraph style.
+
+- Declare your role in the source reStructuredText document in a
+ ``role`` directive. Example::
+
+ .. role:: pretty
+
+- Use inline markup to apply your role to text. Example::
+
+ We have :pretty:`very nice` apples.
+
+Here is another example::
+
+ .. role:: fancy
+
+ Here is some :fancy:`pretty text` that looks fancy.
+
+For more on roles see:
+`Custom Interpreted Text Roles --
+http://docutils.sourceforge.net/docs/ref/rst/directives.html#custom-interpreted-text-roles
+<http://docutils.sourceforge.net/docs/ref/rst/directives.html#custom-interpreted-text-roles>`_.
+
+**Note:** The ability to base a role on another existing role is
+*not* supported by ``odtwriter``.
+
+
+Hints and Suggestions and Features
+==================================
+
+Table of contents
+-----------------
+
+The ``..contents::`` directive causes ``odtwriter`` to generate
+either:
+
+1. A static, outline style table of contents, if the
+ ``--generate-list-toc`` command line option is specified, or
+
+2. An ODF/``oowriter`` style table of contents containing
+ dynamically updated page numbers and with the formatting control
+ that ``oowriter`` gives you. This is the default, or use the
+ command line option ``--generate-list-toc``. **Note:**
+ ``odtwriter`` is not able to determine page numbers, so you will
+ need to open the generated document in ``oowriter``, then
+ right-click on the table of contents and select "Update" to
+ insert correct page numbers.
+
+
+Syntax highlighting
+-------------------
+
+``odtwriter`` can add syntax highlighting to code in code
+blocks. In order to activate this, do all of the following:
+
+1. Install `Pygments`_ and ...
+
+2. Use the command line option ``--add-syntax-highlighting``.
+ Example::
+
+ $ rst2odt.py --add-syntax-highlight test.txt test.odt
+
+The following styles are defined in styles.odt and are used for
+literal code blocks and syntax highlighting:
+
+- Paragraph styles:
+
+ - rststyle-codeblock -- The style for the code block as a whole.
+
+- Character styles:
+
+ - rststyle-codeblock-classname -- class names.
+
+ - rststyle-codeblock-comment -- comments.
+
+ - rststyle-codeblock-functionname -- function names.
+
+ - rststyle-codeblock-keyword -- Python language keywords.
+
+ - rststyle-codeblock-name -- other names, for example,
+ variables.
+
+ - rststyle-codeblock-number -- literal numbers, including
+ integers, floats, hex numbers, and octal numbers.
+
+ - rststyle-codeblock-operator -- Python operators.
+
+ - rststyle-codeblock-string -- literal strings.
+
+Each of the above styles has a default appearance that is defined
+in ``styles.odt``. To change that definition and appearance, open
+``styles.odt`` in ``oowriter`` and use menu item::
+
+ Format --> Styles and Formatting
+
+Then, click on the Paragraph Styles button or the Character Styles
+button at the top of the Styles and Formatting window. You may
+also need to select "All Styles" from the drop-down selection list
+at the bottom of the Styles and Formatting window.
+
+
+
+The container directive
+-----------------------
+
+There is limited support for the ``container`` directive. The
+limitations and rules for the container directive are the following:
+
+- Only the first class in the list of classes (arguments) is used.
+
+- That class/style must be a paragraph style and not (for example) a
+ character style.
+
+- The style/class given to the container directive will have a
+ "rststyle-" prefix in the odt file.
+
+So, for example::
+
+ .. container:: style-1 style-2 style-3
+
+ a block of text
+
+- Only ``style-1`` is used; ``style-2`` and ``style-3`` are ignored.
+
+- ``rststyle-style-1`` must be defined. It should be an existing,
+ predefined style, or you should define it in your stylesheet
+ (``styles.odt`` or the argument to the ``--stylesheet`` command
+ line option).
+
+- ``rststyle-style-1`` must be a paragraph style.
+
+To define a paragraph style, use the following menu item in
+``oowriter``::
+
+ Format --> Styles and Formatting
+
+Then, click on the Paragraph Styles button.
+
+The following example attaches the ``rststyle-heading2`` style (a
+predefined style) to each paragraph/line in the container::
+
+ .. container:: heading2
+
+ Line 1 of container.
+
+ Line 2 of container.
+
+More information on how to define a new style (for example, in your
+``styles.odt``) can be found in section
+`Defining and using custom style names`_.
+
+
+
+The table directive
+-------------------
+
+The ``table`` directive can be used to add a title to a table.
+Example::
+
+ .. table:: A little test table
+
+ =========== =============
+ Name Value
+ =========== =============
+ Dave Cute
+ Mona Smart
+ =========== =============
+
+The above will insert the title "A little test table" at the top of the
+table. You can modify the appearance of the title by modifying the
+paragraph style ``rststyle-table-title``.
+
+
+Footnotes and citations
+-----------------------
+
+Footnotes and citations are supported.
+
+There are additional styles ``rststyle-footnote`` and
+``rststyle-citation`` for footnotes and citations. See
+`Footnote and citation styles`_.
+
+You may need to modify the citation style to fit the length of your
+citation references.
+
+Endnotes -- There are command line options that control whether
+``odtwriter`` creates endnotes instead of footnotes. Endnotes
+appear at the end of the document instead of at the bottom of the
+page. See flags ``--endnotes-end-doc`` and
+``--no-endnotes-end-doc`` in section `Command line options`_.
+
+
+Images and figures
+------------------
+
+If on the image or the figure directive you provide the scale option
+but do not provide the width and height options, then ``odtwriter``
+will attempt to determine the size of the image using the `Python
+Imaging Library`_ (PIL). If ``odtwriter`` cannot find and import
+Python Imaging Library, it will raise an exception. If this
+ocurrs, you can fix it by doing one of the following:
+
+- Install the Python Imaging Library or
+
+- Remove the ``scale`` option or
+
+- Add both the ``width`` and the ``height`` options.
+
+So, the rule is: if on any image or figure, you specify scale but
+not both width and height, you must install the `Python Imaging
+Library`_ library.
+
+For more information about PIL, see: `Python Imaging Library`_.
+
+
+The raw directive
+-----------------
+
+The ``raw`` directive is supported. Use output format type "odt".
+
+You will need to be careful about the formatting of the raw
+content. In particular, introduced whitespace might be a problem.
+
+In order to produce content for the raw directive for use by
+``odtwriter``, you might want to extract the file ``content.xml``
+from a ``.odt`` file (using some Zip tool), and then clip, paste,
+and modify a selected bit of it.
+
+Here is an example::
+
+ .. raw:: odt
+
+ <text:p text:style-name="rststyle-textbody">Determining <text:span text:style-name="rststyle-emphasis">which</text:span> namespace a name is in is static. It can be
+ determined by a lexical scan of the code. If a variable is assigned a
+ value <text:span text:style-name="rststyle-emphasis">anywhere</text:span> in a scope (specifically within a function or method
+ body), then that variable is local to that scope. If Python does not
+ find a variable in the local scope, then it looks next in the global
+ scope (also sometimes called the module scope) and then in the
+ built-ins scope. But, the <text:span text:style-name="rststyle-inlineliteral">global</text:span> statement can be used to force
+ Python to find and use a global variable (a variable defined at top
+ level in a module) rather than create a local one.</text:p>
+
+
+The meta directive
+------------------
+
+``odtwriter`` supports the ``meta`` directive. Two fields are
+recognized: "keywords" and "description". Here is an example::
+
+ .. meta::
+ :keywords: reStructuredText, docutils, formatting
+ :description lang=en: A reST document, contains formatted
+ text in a formatted style.
+
+To see the results of the ``meta`` directive in ``oowriter``,
+select menu item "File/Properties...", then click on the
+"Description" tab.
+
+
+Footnote references inside footnotes
+------------------------------------
+
+Not supported.
+
+Get a grip. Be serious. Try a dose of reality.
+
+``odtwriter`` ignores them.
+
+They cause ``oowriter`` to croak.
+
+
+Page size
+---------
+
+The default page size, in documents generated by ``odtwriter`` is
+``Letter``. You can change this (for example to ``A4``) by using a
+custom stylesheet. See `Defining and using a custom stylesheet`_
+for instructions on how to do this.
+
+On machines which support ``paperconf``, ``odtwriter`` can insert
+the default page size for your locale. In order for this to work,
+the following conditions must be met:
+
+1. The program ``paperconf`` must be available on your system.
+ ``odtwriter`` uses ``paperconf -s`` to obtain the paper size.
+ See ``man paperconf`` for more information.
+
+2. The default page height and width must be removed from the
+ ``styles.odt`` used to generate the document. A Python script
+ ``rst2odt_prepstyles.py`` is distributed with ``odtwriter`` and
+ is installed in the ``bin`` directory. You can remove the page
+ height and width with something like the following::
+
+ $ rst2odt_prepstyles.py styles.odt
+
+.. warning:: If you edit your stylesheet in ``oowriter`` and then
+ save it, ``oowriter`` automatically inserts a page height and
+ width in the styles for that (stylesheet) document. If that is
+ not the page size that you want and you want ``odtwriter`` to
+ insert a default page size using ``paperconf``, then you will
+ need to strip the page size from your stylesheet each time you
+ edit that stylesheet with ``oowriter``.
+
+
+
+Custom header/footers: inserting page numbers, date, time, etc
+----------------------------------------------------------------
+
+You can specify custom headers and footers for your document from
+the command line. These headers and footers can be used to insert
+fields such as the page number, page count, date, time, etc. See
+below for a complete list.
+
+To insert a custom header or footer, use the "--custom-odt-header"
+or "--custom-odt-footer" command line options. For example, the
+following inserts a footer containing the page number and page
+count::
+
+ $ rst2odt.py --custom-odt-footer="Page %p% of %P%" f1.txt f1.odt
+
+
+Field specifiers
+~~~~~~~~~~~~~~~~~~
+
+You can use the following field specifiers to insert ``oowriter``
+fields in your custom headers and footers:
+
+%p%
+ The current page number.
+
+%P%
+ The number of pages in the document.
+
+%d1%
+ The current date in format 12/31/99.
+
+%d2%
+ The current date in format 12/31/1999.
+
+%d3%
+ The current date in format Dec 31, 1999.
+
+%d4%
+ The current date in format December 31, 1999.
+
+%d5%
+ The current date in format 1999-12-31.
+
+%t1%
+ The current time in format 14:22.
+
+%t2%
+ The current time in format 14:22:33.
+
+%t3%
+ The current time in format 02:22 PM.
+
+%t4%
+ The current time in format 02:22:33 PM.
+
+%a%
+ The author of the document (actually the initial creator).
+
+%t%
+ The document title.
+
+%s%
+ The document subject.
+
+
+**Note:** The use of the above field specifiers in the body of your
+reStructuredText document is **not** supported, because these
+specifiers are not standard across Docutils writers.
+
+
+
+Credits
+=======
+
+Stefan Merten designed and implemented the custom style names
+capability. Thank you, Stefan.
+
+Michael Schutte supports the Debian GNU/Linux distribution of
+``odtwriter``. Thank you, Michael, for providing and supporting
+the Debian package.
+
+Michael Schutte implemented the fix that enables ``odtwriter`` to
+pick up the default paper size on platforms where the program
+``paperconf`` is available. Thank you.
+
+
+
+
+.. _`Pygments`:
+ http://pygments.pocoo.org/
+
+.. _`Docutils`:
+ http://docutils.sourceforge.net/
+
+.. _`Python Imaging Library`:
+ http://www.pythonware.com/products/pil/
+
+.. _`Open Document at Wikipedia`:
+ http://en.wikipedia.org/wiki/OpenDocument
+
+.. _`OASIS Open Document Format for Office Applications (OpenDocument) TC`:
+ http://www.oasis-open.org/committees/tc_home.php?wg_abbrev=office
+
+
+
--- /dev/null
+=====================================================
+ The reStructuredText_ Cheat Sheet: Syntax Reminders
+=====================================================
+:Info: See <http://docutils.sf.net/rst.html> for introductory docs.
+:Author: David Goodger <goodger@python.org>
+:Date: $Date: 2013-02-20 02:10:53 +0100 (Mi, 20. Feb 2013) $
+:Revision: $Revision: 7612 $
+:Description: This is a "docinfo block", or bibliographic field list
+
+.. NOTE:: If you are reading this as HTML, please read
+ `<cheatsheet.txt>`_ instead to see the input syntax examples!
+
+Section Structure
+=================
+Section titles are underlined or overlined & underlined.
+
+Body Elements
+=============
+Grid table:
+
++--------------------------------+-----------------------------------+
+| Paragraphs are flush-left, | Literal block, preceded by "::":: |
+| separated by blank lines. | |
+| | Indented |
+| Block quotes are indented. | |
++--------------------------------+ or:: |
+| >>> print 'Doctest block' | |
+| Doctest block | > Quoted |
++--------------------------------+-----------------------------------+
+| | Line blocks preserve line breaks & indents. [new in 0.3.6] |
+| | Useful for addresses, verse, and adornment-free lists; long |
+| lines can be wrapped with continuation lines. |
++--------------------------------------------------------------------+
+
+Simple tables:
+
+================ ============================================================
+List Type Examples (syntax in the `text source <cheatsheet.txt>`_)
+================ ============================================================
+Bullet list * items begin with "-", "+", or "*"
+Enumerated list 1. items use any variation of "1.", "A)", and "(i)"
+ #. also auto-enumerated
+Definition list Term is flush-left : optional classifier
+ Definition is indented, no blank line between
+Field list :field name: field body
+Option list -o at least 2 spaces between option & description
+================ ============================================================
+
+================ ============================================================
+Explicit Markup Examples (visible in the `text source`_)
+================ ============================================================
+Footnote .. [1] Manually numbered or [#] auto-numbered
+ (even [#labelled]) or [*] auto-symbol
+Citation .. [CIT2002] A citation.
+Hyperlink Target .. _reStructuredText: http://docutils.sf.net/rst.html
+ .. _indirect target: reStructuredText_
+ .. _internal target:
+Anonymous Target __ http://docutils.sf.net/docs/ref/rst/restructuredtext.html
+Directive ("::") .. image:: images/biohazard.png
+Substitution Def .. |substitution| replace:: like an inline directive
+Comment .. is anything else
+Empty Comment (".." on a line by itself, with blank lines before & after,
+ used to separate indentation contexts)
+================ ============================================================
+
+Inline Markup
+=============
+*emphasis*; **strong emphasis**; `interpreted text`; `interpreted text
+with role`:emphasis:; ``inline literal text``; standalone hyperlink,
+http://docutils.sourceforge.net; named reference, reStructuredText_;
+`anonymous reference`__; footnote reference, [1]_; citation reference,
+[CIT2002]_; |substitution|; _`inline internal target`.
+\f
+Directive Quick Reference
+=========================
+See <http://docutils.sf.net/docs/ref/rst/directives.html> for full info.
+
+================ ============================================================
+Directive Name Description (Docutils version added to, in [brackets])
+================ ============================================================
+attention Specific admonition; also "caution", "danger",
+ "error", "hint", "important", "note", "tip", "warning"
+admonition Generic titled admonition: ``.. admonition:: By The Way``
+image ``.. image:: picture.png``; many options possible
+figure Like "image", but with optional caption and legend
+topic ``.. topic:: Title``; like a mini section
+sidebar ``.. sidebar:: Title``; like a mini parallel document
+parsed-literal A literal block with parsed inline markup
+rubric ``.. rubric:: Informal Heading``
+epigraph Block quote with class="epigraph"
+highlights Block quote with class="highlights"
+pull-quote Block quote with class="pull-quote"
+compound Compound paragraphs [0.3.6]
+container Generic block-level container element [0.3.10]
+table Create a titled table [0.3.1]
+list-table Create a table from a uniform two-level bullet list [0.3.8]
+csv-table Create a table from CSV data [0.3.4]
+contents Generate a table of contents
+sectnum Automatically number sections, subsections, etc.
+header, footer Create document decorations [0.3.8]
+target-notes Create an explicit footnote for each external target
+math Mathematical notation (input in LaTeX format)
+meta HTML-specific metadata
+include Read an external reST file as if it were inline
+raw Non-reST data passed untouched to the Writer
+replace Replacement text for substitution definitions
+unicode Unicode character code conversion for substitution defs
+date Generates today's date; for substitution defs
+class Set a "class" attribute on the next element
+role Create a custom interpreted text role [0.3.2]
+default-role Set the default interpreted text role [0.3.10]
+title Set the metadata document title [0.3.10]
+================ ============================================================
+
+Interpreted Text Role Quick Reference
+=====================================
+See <http://docutils.sf.net/docs/ref/rst/roles.html> for full info.
+
+================ ============================================================
+Role Name Description
+================ ============================================================
+emphasis Equivalent to *emphasis*
+literal Equivalent to ``literal`` but processes backslash escapes
+math Mathematical notation (input in LaTeX format)
+PEP Reference to a numbered Python Enhancement Proposal
+RFC Reference to a numbered Internet Request For Comments
+raw For non-reST data; cannot be used directly (see docs) [0.3.6]
+strong Equivalent to **strong**
+sub Subscript
+sup Superscript
+title Title reference (book, etc.); standard default role
+================ ============================================================
--- /dev/null
+.. This is a comment. Note how any initial comments are moved by
+ transforms to after the document title, subtitle, and docinfo.
+
+================================
+ reStructuredText Demonstration
+================================
+
+.. Above is the document title, and below is the subtitle.
+ They are transformed from section titles after parsing.
+
+--------------------------------
+ Examples of Syntax Constructs
+--------------------------------
+
+.. bibliographic fields (which also require a transform):
+
+:Author: David Goodger
+:Address: 123 Example Street
+ Example, EX Canada
+ A1B 2C3
+:Contact: docutils-develop@lists.sourceforge.net
+:Authors: Me; Myself; I
+:organization: humankind
+:date: $Date: 2012-01-03 20:23:53 +0100 (Di, 03. Jän 2012) $
+:status: This is a "work in progress"
+:revision: $Revision: 7302 $
+:version: 1
+:copyright: This document has been placed in the public domain. You
+ may do with it as you wish. You may copy, modify,
+ redistribute, reattribute, sell, buy, rent, lease,
+ destroy, or improve it, quote it at length, excerpt,
+ incorporate, collate, fold, staple, or mutilate it, or do
+ anything else to it that your or anyone else's heart
+ desires.
+:field name: This is a generic bibliographic field.
+:field name 2:
+ Generic bibliographic fields may contain multiple body elements.
+
+ Like this.
+
+:Dedication:
+
+ For Docutils users & co-developers.
+
+:abstract:
+
+ This document is a demonstration of the reStructuredText markup
+ language, containing examples of all basic reStructuredText
+ constructs and many advanced constructs.
+
+.. meta::
+ :keywords: reStructuredText, demonstration, demo, parser
+ :description lang=en: A demonstration of the reStructuredText
+ markup language, containing examples of all basic
+ constructs and many advanced constructs.
+
+.. contents:: Table of Contents
+.. section-numbering::
+
+
+Structural Elements
+===================
+
+Section Title
+-------------
+
+That's it, the text just above this line.
+
+Transitions
+-----------
+
+Here's a transition:
+
+---------
+
+It divides the section.
+
+Body Elements
+=============
+
+Paragraphs
+----------
+
+A paragraph.
+
+Inline Markup
+`````````````
+
+Paragraphs contain text and may contain inline markup: *emphasis*,
+**strong emphasis**, ``inline literals``, standalone hyperlinks
+(http://www.python.org), external hyperlinks (Python_), internal
+cross-references (example_), external hyperlinks with embedded URIs
+(`Python web site <http://www.python.org>`__), footnote references
+(manually numbered [1]_, anonymous auto-numbered [#]_, labeled
+auto-numbered [#label]_, or symbolic [*]_), citation references
+([CIT2002]_), substitution references (|example|), and _`inline
+hyperlink targets` (see Targets_ below for a reference back to here).
+Character-level inline markup is also possible (although exceedingly
+ugly!) in *re*\ ``Structured``\ *Text*. Problems are indicated by
+|problematic| text (generated by processing errors; this one is
+intentional).
+
+The default role for interpreted text is `Title Reference`. Here are
+some explicit interpreted text roles: a PEP reference (:PEP:`287`); an
+RFC reference (:RFC:`2822`); a :sub:`subscript`; a :sup:`superscript`;
+and explicit roles for :emphasis:`standard` :strong:`inline`
+:literal:`markup`.
+
+.. DO NOT RE-WRAP THE FOLLOWING PARAGRAPH!
+
+Let's test wrapping and whitespace significance in inline literals:
+``This is an example of --inline-literal --text, --including some--
+strangely--hyphenated-words. Adjust-the-width-of-your-browser-window
+to see how the text is wrapped. -- ---- -------- Now note the
+spacing between the words of this sentence (words
+should be grouped in pairs).``
+
+If the ``--pep-references`` option was supplied, there should be a
+live link to PEP 258 here.
+
+Bullet Lists
+------------
+
+- A bullet list
+
+ + Nested bullet list.
+ + Nested item 2.
+
+- Item 2.
+
+ Paragraph 2 of item 2.
+
+ * Nested bullet list.
+ * Nested item 2.
+
+ - Third level.
+ - Item 2.
+
+ * Nested item 3.
+
+Enumerated Lists
+----------------
+
+1. Arabic numerals.
+
+ a) lower alpha)
+
+ (i) (lower roman)
+
+ A. upper alpha.
+
+ I) upper roman)
+
+2. Lists that don't start at 1:
+
+ 3. Three
+
+ 4. Four
+
+ C. C
+
+ D. D
+
+ iii. iii
+
+ iv. iv
+
+#. List items may also be auto-enumerated.
+
+Definition Lists
+----------------
+
+Term
+ Definition
+Term : classifier
+ Definition paragraph 1.
+
+ Definition paragraph 2.
+Term
+ Definition
+
+Field Lists
+-----------
+
+:what: Field lists map field names to field bodies, like database
+ records. They are often part of an extension syntax. They are
+ an unambiguous variant of RFC 2822 fields.
+
+:how arg1 arg2:
+
+ The field marker is a colon, the field name, and a colon.
+
+ The field body may contain one or more body elements, indented
+ relative to the field marker.
+
+Option Lists
+------------
+
+For listing command-line options:
+
+-a command-line option "a"
+-b file options can have arguments
+ and long descriptions
+--long options can be long also
+--input=file long options can also have
+ arguments
+
+--very-long-option
+ The description can also start on the next line.
+
+ The description may contain multiple body elements,
+ regardless of where it starts.
+
+-x, -y, -z Multiple options are an "option group".
+-v, --verbose Commonly-seen: short & long options.
+-1 file, --one=file, --two file
+ Multiple options with arguments.
+/V DOS/VMS-style options too
+
+There must be at least two spaces between the option and the
+description.
+
+Literal Blocks
+--------------
+
+Literal blocks are indicated with a double-colon ("::") at the end of
+the preceding paragraph (over there ``-->``). They can be indented::
+
+ if literal_block:
+ text = 'is left as-is'
+ spaces_and_linebreaks = 'are preserved'
+ markup_processing = None
+
+Or they can be quoted without indentation::
+
+>> Great idea!
+>
+> Why didn't I think of that?
+
+Line Blocks
+-----------
+
+| This is a line block. It ends with a blank line.
+| Each new line begins with a vertical bar ("|").
+| Line breaks and initial indents are preserved.
+| Continuation lines are wrapped portions of long lines;
+ they begin with a space in place of the vertical bar.
+| The left edge of a continuation line need not be aligned with
+ the left edge of the text above it.
+
+| This is a second line block.
+|
+| Blank lines are permitted internally, but they must begin with a "|".
+
+Take it away, Eric the Orchestra Leader!
+
+ | A one, two, a one two three four
+ |
+ | Half a bee, philosophically,
+ | must, *ipso facto*, half not be.
+ | But half the bee has got to be,
+ | *vis a vis* its entity. D'you see?
+ |
+ | But can a bee be said to be
+ | or not to be an entire bee,
+ | when half the bee is not a bee,
+ | due to some ancient injury?
+ |
+ | Singing...
+
+Block Quotes
+------------
+
+Block quotes consist of indented body elements:
+
+ My theory by A. Elk. Brackets Miss, brackets. This theory goes
+ as follows and begins now. All brontosauruses are thin at one
+ end, much much thicker in the middle and then thin again at the
+ far end. That is my theory, it is mine, and belongs to me and I
+ own it, and what it is too.
+
+ -- Anne Elk (Miss)
+
+Doctest Blocks
+--------------
+
+>>> print 'Python-specific usage examples; begun with ">>>"'
+Python-specific usage examples; begun with ">>>"
+>>> print '(cut and pasted from interactive Python sessions)'
+(cut and pasted from interactive Python sessions)
+
+Tables
+------
+
+Here's a grid table followed by a simple table:
+
++------------------------+------------+----------+----------+
+| Header row, column 1 | Header 2 | Header 3 | Header 4 |
+| (header rows optional) | | | |
++========================+============+==========+==========+
+| body row 1, column 1 | column 2 | column 3 | column 4 |
++------------------------+------------+----------+----------+
+| body row 2 | Cells may span columns. |
++------------------------+------------+---------------------+
+| body row 3 | Cells may | - Table cells |
++------------------------+ span rows. | - contain |
+| body row 4 | | - body elements. |
++------------------------+------------+----------+----------+
+| body row 5 | Cells may also be | |
+| | empty: ``-->`` | |
++------------------------+-----------------------+----------+
+
+===== ===== ======
+ Inputs Output
+------------ ------
+ A B A or B
+===== ===== ======
+False False False
+True False True
+False True True
+True True True
+===== ===== ======
+
+Footnotes
+---------
+
+.. [1] A footnote contains body elements, consistently indented by at
+ least 3 spaces.
+
+ This is the footnote's second paragraph.
+
+.. [#label] Footnotes may be numbered, either manually (as in [1]_) or
+ automatically using a "#"-prefixed label. This footnote has a
+ label so it can be referred to from multiple places, both as a
+ footnote reference ([#label]_) and as a hyperlink reference
+ (label_).
+
+.. [#] This footnote is numbered automatically and anonymously using a
+ label of "#" only.
+
+.. [*] Footnotes may also use symbols, specified with a "*" label.
+ Here's a reference to the next footnote: [*]_.
+
+.. [*] This footnote shows the next symbol in the sequence.
+
+.. [4] Here's an unreferenced footnote, with a reference to a
+ nonexistent footnote: [5]_.
+
+Citations
+---------
+
+.. [CIT2002] Citations are text-labeled footnotes. They may be
+ rendered separately and differently from footnotes.
+
+Here's a reference to the above, [CIT2002]_, and a [nonexistent]_
+citation.
+
+Targets
+-------
+
+.. _example:
+
+This paragraph is pointed to by the explicit "example" target. A
+reference can be found under `Inline Markup`_, above. `Inline
+hyperlink targets`_ are also possible.
+
+Section headers are implicit targets, referred to by name. See
+Targets_, which is a subsection of `Body Elements`_.
+
+Explicit external targets are interpolated into references such as
+"Python_".
+
+.. _Python: http://www.python.org/
+
+Targets may be indirect and anonymous. Thus `this phrase`__ may also
+refer to the Targets_ section.
+
+__ Targets_
+
+Here's a `hyperlink reference without a target`_, which generates an
+error.
+
+Duplicate Target Names
+``````````````````````
+
+Duplicate names in section headers or other implicit targets will
+generate "info" (level-1) system messages. Duplicate names in
+explicit targets will generate "warning" (level-2) system messages.
+
+Duplicate Target Names
+``````````````````````
+
+Since there are two "Duplicate Target Names" section headers, we
+cannot uniquely refer to either of them by name. If we try to (like
+this: `Duplicate Target Names`_), an error is generated.
+
+Directives
+----------
+
+.. contents:: :local:
+
+These are just a sample of the many reStructuredText Directives. For
+others, please see
+http://docutils.sourceforge.net/docs/ref/rst/directives.html.
+
+Document Parts
+``````````````
+
+An example of the "contents" directive can be seen above this section
+(a local, untitled table of contents_) and at the beginning of the
+document (a document-wide `table of contents`_).
+
+Images
+``````
+
+An image directive (also clickable -- a hyperlink reference):
+
+.. image:: images/title.png
+ :target: directives_
+
+A figure directive:
+
+.. figure:: images/title.png
+ :alt: reStructuredText, the markup syntax
+
+ A figure is an image with a caption and/or a legend:
+
+ +------------+-----------------------------------------------+
+ | re | Revised, revisited, based on 're' module. |
+ +------------+-----------------------------------------------+
+ | Structured | Structure-enhanced text, structuredtext. |
+ +------------+-----------------------------------------------+
+ | Text | Well it is, isn't it? |
+ +------------+-----------------------------------------------+
+
+ This paragraph is also part of the legend.
+
+Admonitions
+```````````
+
+.. Attention:: Directives at large.
+
+.. Caution::
+
+ Don't take any wooden nickels.
+
+.. DANGER:: Mad scientist at work!
+
+.. Error:: Does not compute.
+
+.. Hint:: It's bigger than a bread box.
+
+.. Important::
+ - Wash behind your ears.
+ - Clean up your room.
+ - Call your mother.
+ - Back up your data.
+
+.. Note:: This is a note.
+
+.. Tip:: 15% if the service is good.
+
+.. WARNING:: Strong prose may provoke extreme mental exertion.
+ Reader discretion is strongly advised.
+
+.. admonition:: And, by the way...
+
+ You can make up your own admonition too.
+
+Topics, Sidebars, and Rubrics
+`````````````````````````````
+
+.. sidebar:: Sidebar Title
+ :subtitle: Optional Subtitle
+
+ This is a sidebar. It is for text outside the flow of the main
+ text.
+
+ .. rubric:: This is a rubric inside a sidebar
+
+ Sidebars often appears beside the main text with a border and
+ background color.
+
+.. topic:: Topic Title
+
+ This is a topic.
+
+.. rubric:: This is a rubric
+
+Target Footnotes
+````````````````
+
+.. target-notes::
+
+Replacement Text
+````````````````
+
+I recommend you try |Python|_.
+
+.. |Python| replace:: Python, *the* best language around
+
+Compound Paragraph
+``````````````````
+
+.. compound::
+
+ This paragraph contains a literal block::
+
+ Connecting... OK
+ Transmitting data... OK
+ Disconnecting... OK
+
+ and thus consists of a simple paragraph, a literal block, and
+ another simple paragraph. Nonetheless it is semantically *one*
+ paragraph.
+
+This construct is called a *compound paragraph* and can be produced
+with the "compound" directive.
+
+Substitution Definitions
+------------------------
+
+An inline image (|example|) example:
+
+.. |EXAMPLE| image:: images/biohazard.png
+
+(Substitution definitions are not visible in the HTML source.)
+
+Comments
+--------
+
+Here's one:
+
+.. Comments begin with two dots and a space. Anything may
+ follow, except for the syntax of footnotes, hyperlink
+ targets, directives, or substitution definitions.
+
+ Double-dashes -- "--" -- must be escaped somehow in HTML output.
+
+(View the HTML source to see the comment.)
+
+Error Handling
+==============
+
+Any errors caught during processing will generate system messages.
+
+|*** Expect 6 errors (including this one). ***|
+
+There should be six messages in the following, auto-generated
+section, "Docutils System Messages":
+
+.. section should be added by Docutils automatically
--- /dev/null
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ version="1.1"
+ viewBox="0 0 16 16"
+ width="100%"
+ height="100%"
+ id="svg2">
+ <metadata
+ id="metadata8">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title></dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <defs
+ id="defs6" />
+ <image
+ xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABHNCSVQICAgIfAhkiAAAAIRJREFU
+OI2lUkEOwCAIa83+/+XusGCQIWOxF1GhUICSEEFSkvj1BgCjEwwAkkjylW0hyByyBP5+dR2zqrYE
+ux5kvq8e/AVtCh39HlbhqIIlcafdx+jxFezs2BY3fDkxO0lVezElnGA2MWrzmxftkiASxZIjjiWk
+BNlYd6NeJCyzLVbZ/92om331AFqcoAAAAABJRU5ErkJggg==
+"
+ x="4.9541664"
+ y="-5.2426963"
+ width="11.322034"
+ height="9.3559322"
+ transform="matrix(0.77695327,0.62955828,-0.62955828,0.77695327,0,0)"
+ id="image10" />
+ <text
+ x="0.40677962"
+ y="15.186441"
+ id="text2987"
+ xml:space="preserve"
+ style="font-size:4px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:DejaVu Sans;-inkscape-font-specification:DejaVu Sans"><tspan
+ x="0.40677962"
+ y="15.186441"
+ id="tspan2989">turned</tspan></text>
+</svg>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ version="1.1"
+ width="16"
+ height="16"
+ id="svg2">
+ <metadata
+ id="metadata8">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title></dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <defs
+ id="defs6" />
+ <image
+ xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABHNCSVQICAgIfAhkiAAAAIRJREFU
+OI2lUkEOwCAIa83+/+XusGCQIWOxF1GhUICSEEFSkvj1BgCjEwwAkkjylW0hyByyBP5+dR2zqrYE
+ux5kvq8e/AVtCh39HlbhqIIlcafdx+jxFezs2BY3fDkxO0lVezElnGA2MWrzmxftkiASxZIjjiWk
+BNlYd6NeJCyzLVbZ/92om331AFqcoAAAAABJRU5ErkJggg==
+"
+ x="4.9541664"
+ y="-5.2426963"
+ width="11.322034"
+ height="9.3559322"
+ transform="matrix(0.77695327,0.62955828,-0.62955828,0.77695327,0,0)"
+ id="image10" />
+ <text
+ x="0.40677962"
+ y="15.186441"
+ id="text2987"
+ xml:space="preserve"
+ style="font-size:4px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:DejaVu Sans;-inkscape-font-specification:DejaVu Sans"><tspan
+ x="0.40677962"
+ y="15.186441"
+ id="tspan2989">turned</tspan></text>
+</svg>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ sodipodi:docname="biohazard-scaling.svg"
+ inkscape:version="0.47 r22583"
+ sodipodi:version="0.32"
+ id="svg24159"
+ viewBox="0 0 48 48"
+ width="100%"
+ height="100%"
+ version="1.0">
+ <title
+ id="title2837">Biohazard</title>
+ <metadata
+ id="metadata7">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title>Biohazard</dc:title>
+ <cc:license
+ rdf:resource="http://creativecommons.org/licenses/publicdomain/" />
+ <dc:description>Standalone biohazard symbol, with no border, background or descriptive text.</dc:description>
+ <dc:creator>
+ <cc:Agent>
+ <dc:title>Silsor</dc:title>
+ </cc:Agent>
+ </dc:creator>
+ <dc:identifier></dc:identifier>
+ <dc:source></dc:source>
+ <dc:relation>http://de.wikipedia.org/wiki/Datei:Biohazard_symbol.svg</dc:relation>
+ <dc:publisher>
+ <cc:Agent>
+ <dc:title>Wikipedia</dc:title>
+ </cc:Agent>
+ </dc:publisher>
+ <dc:contributor>
+ <cc:Agent>
+ <dc:title>Bastique, Andux, MarianSigler, GM</dc:title>
+ </cc:Agent>
+ </dc:contributor>
+ </cc:Work>
+ <cc:License
+ rdf:about="http://creativecommons.org/licenses/publicdomain/">
+ <cc:permits
+ rdf:resource="http://creativecommons.org/ns#Reproduction" />
+ <cc:permits
+ rdf:resource="http://creativecommons.org/ns#Distribution" />
+ <cc:permits
+ rdf:resource="http://creativecommons.org/ns#DerivativeWorks" />
+ </cc:License>
+ </rdf:RDF>
+ </metadata>
+ <defs
+ id="defs5">
+ <inkscape:perspective
+ sodipodi:type="inkscape:persp3d"
+ inkscape:vp_x="0 : 178.13126 : 1"
+ inkscape:vp_y="0 : 1000 : 0"
+ inkscape:vp_z="376.4375 : 178.13126 : 1"
+ inkscape:persp3d-origin="188.21875 : 118.75417 : 1"
+ id="perspective2835" />
+ </defs>
+ <sodipodi:namedview
+ inkscape:current-layer="svg24159"
+ inkscape:window-y="33"
+ inkscape:window-x="0"
+ inkscape:cy="22.455418"
+ inkscape:cx="22.152639"
+ inkscape:zoom="8.9316693"
+ inkscape:window-height="771"
+ inkscape:window-width="993"
+ inkscape:pageshadow="2"
+ inkscape:pageopacity="0.0"
+ borderopacity="1.0"
+ bordercolor="#666666"
+ pagecolor="#ffffff"
+ id="base"
+ showgrid="false"
+ inkscape:window-maximized="0" />
+ <path
+ id="path7214"
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline"
+ d="m 23.585163,1.377771 c -7.3e-5,1.1e-4 6.2e-5,0.0039 0,0.0039 0.0013,-3.54e-4 0.0026,-0.0032 0.0039,-0.0039 -4.78e-4,0 -0.0034,-2.3e-5 -0.0039,0 z m -0.293287,0.01173 c -0.0027,3.39e-4 -0.0051,0.0032 -0.0078,0.0039 0.01047,-6.47e-4 0.0208,-0.0032 0.0313,-0.0039 -0.0026,3.1e-5 -0.0053,-1.18e-4 -0.0078,0 -0.0057,2.6e-4 -0.01016,-6.94e-4 -0.01564,0 z m 1.4234,0.0078 c 0.02085,0.0016 0.04176,0.0023 0.06257,0.0039 -0.02047,-0.0016 -0.04204,-0.0032 -0.06257,-0.0039 z m 0.06257,0.0039 c 5.265987,0.418547 9.412454,4.8332343 9.412454,10.206258 0,5.470767 -4.303553,9.932781 -9.705743,10.210182 l 0,2.096004 c 1.474852,0.23317 2.604371,1.513993 2.604371,3.054059 0,0.376932 -0.06786,0.737393 -0.191614,1.071465 l 1.916125,1.106653 c 2.96118,-4.473042 8.935485,-5.932586 13.643543,-3.214395 4.696858,2.711739 6.431117,8.594706 4.062951,13.389373 3.25012,-6.325927 0.990037,-14.166586 -5.236079,-17.761246 -1.557783,-0.899383 -3.21756,-1.447302 -4.895883,-1.673666 0.642426,-1.566299 0.997159,-3.281384 0.997159,-5.079678 0,-7.1369497 -5.576639,-12.979536 -12.607284,-13.405009 z m -1.716682,0.0078 c -6.995507,0.462047 -12.536897,6.2854693 -12.536897,13.397187 0,1.7471 0.33392,3.416827 0.942418,4.946709 C 9.8382992,19.991498 8.2240722,20.533989 6.7115792,21.40722 0.52714555,24.977806 -1.7383295,32.735989 1.4168439,39.039434 -0.86121285,34.26773 0.88578585,28.463663 5.5423552,25.775186 10.280179,23.039814 16.295416,24.535893 19.236731,29.07561 l 1.849653,-1.06755 c -0.116245,-0.324958 -0.175968,-0.675422 -0.175968,-1.040177 0,-1.474684 1.033904,-2.7081 2.416653,-3.014963 l 0,-2.138998 c -5.354361,-0.327959 -9.604053,-4.769878 -9.604053,-10.206284 0,-5.3484377 4.106511,-9.745581 9.338141,-10.198436 z m 0.5983,12.857539 c -2.702513,0.06215 -5.1939,0.982199 -7.238239,2.479239 0.163319,0.241678 0.3388,0.475581 0.523995,0.699968 0.185211,0.224379 0.381018,0.43966 0.586572,0.64522 0.205552,0.205552 0.420838,0.401368 0.645233,0.586565 0.164974,0.136169 0.34173,0.258763 0.516174,0.383226 1.509041,-0.990801 3.316157,-1.571993 5.263466,-1.571993 1.947286,-8e-6 3.750506,0.581192 5.259545,1.571993 0.174446,-0.124463 0.351193,-0.247057 0.516176,-0.383226 0.22439,-0.185197 0.439673,-0.381013 0.645219,-0.586565 0.205567,-0.20556 0.401375,-0.420841 0.586578,-0.64522 0.185195,-0.224387 0.360669,-0.45829 0.523998,-0.699968 -2.118228,-1.551143 -4.716051,-2.479239 -7.531516,-2.479239 -0.06599,0 -0.133689,-7.88e-4 -0.199445,0 -0.0321,5.04e-4 -0.06572,-7.33e-4 -0.09775,0 z m -12.31791,11.277867 c -0.284223,2.610003 0.211199,5.323971 1.618924,7.76224 1.407734,2.438252 3.510158,4.228056 5.912592,5.286916 0.127648,-0.262284 0.242394,-0.532967 0.344121,-0.805556 0.101731,-0.272573 0.190676,-0.548209 0.265902,-0.828999 0.07525,-0.280797 0.139504,-0.565564 0.187704,-0.852481 0.03545,-0.210964 0.05374,-0.42411 0.07431,-0.637415 -1.612588,-0.811463 -3.018925,-2.087157 -3.992574,-3.773578 -0.973652,-1.686412 -1.374436,-3.539399 -1.270899,-5.341664 -0.194995,-0.08884 -0.390062,-0.179391 -0.590482,-0.254187 -0.272577,-0.10171 -0.548216,-0.190664 -0.829012,-0.265909 -0.280794,-0.07523 -0.565552,-0.135585 -0.852473,-0.183786 -0.286919,-0.04821 -0.577155,-0.08499 -0.868119,-0.105582 z m 25.316234,0.152498 c -0.290976,0.02064 -0.581196,0.05743 -0.868118,0.105592 -0.286924,0.04821 -0.571694,0.108551 -0.852489,0.183796 -0.28078,0.07523 -0.560331,0.164188 -0.832917,0.265916 -0.200416,0.07475 -0.391568,0.169238 -0.586562,0.258079 0.103529,1.802257 -0.297254,3.655268 -1.270904,5.341672 -0.973644,1.686405 -2.379987,2.958198 -3.992556,3.769663 0.02056,0.213296 0.03885,0.42645 0.07429,0.637406 0.0482,0.286925 0.108544,0.571684 0.183787,0.85249 0.07524,0.280789 0.164195,0.560349 0.265917,0.832913 0.10171,0.272598 0.21648,0.539357 0.344115,0.80165 2.402441,-1.05887 4.504863,-2.844756 5.91259,-5.283018 1.407749,-2.438268 1.907058,-5.156151 1.622843,-7.766155 z m -14.984836,3.300424 -1.861376,1.079286 c 2.393175,4.80097 0.67248,10.702448 -4.035564,13.420654 -4.684876,2.704807 -10.6285418,1.281437 -13.6044538,-3.140087 3.861645,5.950286 11.7584698,7.900842 17.9724108,4.31321 1.505271,-0.869071 2.775062,-1.989431 3.793133,-3.273026 1.038062,1.349323 2.351864,2.521178 3.918266,3.425539 6.220932,3.591652 14.127263,1.63317 17.98415,-4.332768 -2.970401,4.440658 -8.922715,5.877231 -13.616174,3.167461 -4.737818,-2.735388 -6.449511,-8.693465 -3.988659,-13.51059 L 26.29902,29.028617 c -0.565692,0.629844 -1.386768,1.028448 -2.299348,1.028448 -0.927577,0 -1.760299,-0.411791 -2.32672,-1.059736 z" />
+</svg>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ sodipodi:docname="biohazard.svg"
+ inkscape:version="0.47 r22583"
+ sodipodi:version="0.32"
+ id="svg24159"
+ height="48"
+ width="48"
+ version="1.0">
+ <title
+ id="title2837">Biohazard</title>
+ <metadata
+ id="metadata7">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title>Biohazard</dc:title>
+ <cc:license
+ rdf:resource="http://creativecommons.org/licenses/publicdomain/" />
+ <dc:description>Standalone biohazard symbol, with no border, background or descriptive text.</dc:description>
+ <dc:creator>
+ <cc:Agent>
+ <dc:title>Silsor</dc:title>
+ </cc:Agent>
+ </dc:creator>
+ <dc:identifier></dc:identifier>
+ <dc:source></dc:source>
+ <dc:relation>http://de.wikipedia.org/wiki/Datei:Biohazard_symbol.svg</dc:relation>
+ <dc:publisher>
+ <cc:Agent>
+ <dc:title>Wikipedia</dc:title>
+ </cc:Agent>
+ </dc:publisher>
+ <dc:contributor>
+ <cc:Agent>
+ <dc:title>Bastique, Andux, MarianSigler, GM</dc:title>
+ </cc:Agent>
+ </dc:contributor>
+ </cc:Work>
+ <cc:License
+ rdf:about="http://creativecommons.org/licenses/publicdomain/">
+ <cc:permits
+ rdf:resource="http://creativecommons.org/ns#Reproduction" />
+ <cc:permits
+ rdf:resource="http://creativecommons.org/ns#Distribution" />
+ <cc:permits
+ rdf:resource="http://creativecommons.org/ns#DerivativeWorks" />
+ </cc:License>
+ </rdf:RDF>
+ </metadata>
+ <defs
+ id="defs5">
+ <inkscape:perspective
+ sodipodi:type="inkscape:persp3d"
+ inkscape:vp_x="0 : 178.13126 : 1"
+ inkscape:vp_y="0 : 1000 : 0"
+ inkscape:vp_z="376.4375 : 178.13126 : 1"
+ inkscape:persp3d-origin="188.21875 : 118.75417 : 1"
+ id="perspective2835" />
+ </defs>
+ <sodipodi:namedview
+ inkscape:current-layer="svg24159"
+ inkscape:window-y="33"
+ inkscape:window-x="0"
+ inkscape:cy="22.455418"
+ inkscape:cx="22.152639"
+ inkscape:zoom="8.9316693"
+ inkscape:window-height="771"
+ inkscape:window-width="993"
+ inkscape:pageshadow="2"
+ inkscape:pageopacity="0.0"
+ borderopacity="1.0"
+ bordercolor="#666666"
+ pagecolor="#ffffff"
+ id="base"
+ showgrid="false"
+ inkscape:window-maximized="0" />
+ <path
+ id="path7214"
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline"
+ d="m 23.585163,1.377771 c -7.3e-5,1.1e-4 6.2e-5,0.0039 0,0.0039 0.0013,-3.54e-4 0.0026,-0.0032 0.0039,-0.0039 -4.78e-4,0 -0.0034,-2.3e-5 -0.0039,0 z m -0.293287,0.01173 c -0.0027,3.39e-4 -0.0051,0.0032 -0.0078,0.0039 0.01047,-6.47e-4 0.0208,-0.0032 0.0313,-0.0039 -0.0026,3.1e-5 -0.0053,-1.18e-4 -0.0078,0 -0.0057,2.6e-4 -0.01016,-6.94e-4 -0.01564,0 z m 1.4234,0.0078 c 0.02085,0.0016 0.04176,0.0023 0.06257,0.0039 -0.02047,-0.0016 -0.04204,-0.0032 -0.06257,-0.0039 z m 0.06257,0.0039 c 5.265987,0.418547 9.412454,4.8332343 9.412454,10.206258 0,5.470767 -4.303553,9.932781 -9.705743,10.210182 l 0,2.096004 c 1.474852,0.23317 2.604371,1.513993 2.604371,3.054059 0,0.376932 -0.06786,0.737393 -0.191614,1.071465 l 1.916125,1.106653 c 2.96118,-4.473042 8.935485,-5.932586 13.643543,-3.214395 4.696858,2.711739 6.431117,8.594706 4.062951,13.389373 3.25012,-6.325927 0.990037,-14.166586 -5.236079,-17.761246 -1.557783,-0.899383 -3.21756,-1.447302 -4.895883,-1.673666 0.642426,-1.566299 0.997159,-3.281384 0.997159,-5.079678 0,-7.1369497 -5.576639,-12.979536 -12.607284,-13.405009 z m -1.716682,0.0078 c -6.995507,0.462047 -12.536897,6.2854693 -12.536897,13.397187 0,1.7471 0.33392,3.416827 0.942418,4.946709 C 9.8382992,19.991498 8.2240722,20.533989 6.7115792,21.40722 0.52714555,24.977806 -1.7383295,32.735989 1.4168439,39.039434 -0.86121285,34.26773 0.88578585,28.463663 5.5423552,25.775186 10.280179,23.039814 16.295416,24.535893 19.236731,29.07561 l 1.849653,-1.06755 c -0.116245,-0.324958 -0.175968,-0.675422 -0.175968,-1.040177 0,-1.474684 1.033904,-2.7081 2.416653,-3.014963 l 0,-2.138998 c -5.354361,-0.327959 -9.604053,-4.769878 -9.604053,-10.206284 0,-5.3484377 4.106511,-9.745581 9.338141,-10.198436 z m 0.5983,12.857539 c -2.702513,0.06215 -5.1939,0.982199 -7.238239,2.479239 0.163319,0.241678 0.3388,0.475581 0.523995,0.699968 0.185211,0.224379 0.381018,0.43966 0.586572,0.64522 0.205552,0.205552 0.420838,0.401368 0.645233,0.586565 0.164974,0.136169 0.34173,0.258763 0.516174,0.383226 1.509041,-0.990801 3.316157,-1.571993 5.263466,-1.571993 1.947286,-8e-6 3.750506,0.581192 5.259545,1.571993 0.174446,-0.124463 0.351193,-0.247057 0.516176,-0.383226 0.22439,-0.185197 0.439673,-0.381013 0.645219,-0.586565 0.205567,-0.20556 0.401375,-0.420841 0.586578,-0.64522 0.185195,-0.224387 0.360669,-0.45829 0.523998,-0.699968 -2.118228,-1.551143 -4.716051,-2.479239 -7.531516,-2.479239 -0.06599,0 -0.133689,-7.88e-4 -0.199445,0 -0.0321,5.04e-4 -0.06572,-7.33e-4 -0.09775,0 z m -12.31791,11.277867 c -0.284223,2.610003 0.211199,5.323971 1.618924,7.76224 1.407734,2.438252 3.510158,4.228056 5.912592,5.286916 0.127648,-0.262284 0.242394,-0.532967 0.344121,-0.805556 0.101731,-0.272573 0.190676,-0.548209 0.265902,-0.828999 0.07525,-0.280797 0.139504,-0.565564 0.187704,-0.852481 0.03545,-0.210964 0.05374,-0.42411 0.07431,-0.637415 -1.612588,-0.811463 -3.018925,-2.087157 -3.992574,-3.773578 -0.973652,-1.686412 -1.374436,-3.539399 -1.270899,-5.341664 -0.194995,-0.08884 -0.390062,-0.179391 -0.590482,-0.254187 -0.272577,-0.10171 -0.548216,-0.190664 -0.829012,-0.265909 -0.280794,-0.07523 -0.565552,-0.135585 -0.852473,-0.183786 -0.286919,-0.04821 -0.577155,-0.08499 -0.868119,-0.105582 z m 25.316234,0.152498 c -0.290976,0.02064 -0.581196,0.05743 -0.868118,0.105592 -0.286924,0.04821 -0.571694,0.108551 -0.852489,0.183796 -0.28078,0.07523 -0.560331,0.164188 -0.832917,0.265916 -0.200416,0.07475 -0.391568,0.169238 -0.586562,0.258079 0.103529,1.802257 -0.297254,3.655268 -1.270904,5.341672 -0.973644,1.686405 -2.379987,2.958198 -3.992556,3.769663 0.02056,0.213296 0.03885,0.42645 0.07429,0.637406 0.0482,0.286925 0.108544,0.571684 0.183787,0.85249 0.07524,0.280789 0.164195,0.560349 0.265917,0.832913 0.10171,0.272598 0.21648,0.539357 0.344115,0.80165 2.402441,-1.05887 4.504863,-2.844756 5.91259,-5.283018 1.407749,-2.438268 1.907058,-5.156151 1.622843,-7.766155 z m -14.984836,3.300424 -1.861376,1.079286 c 2.393175,4.80097 0.67248,10.702448 -4.035564,13.420654 -4.684876,2.704807 -10.6285418,1.281437 -13.6044538,-3.140087 3.861645,5.950286 11.7584698,7.900842 17.9724108,4.31321 1.505271,-0.869071 2.775062,-1.989431 3.793133,-3.273026 1.038062,1.349323 2.351864,2.521178 3.918266,3.425539 6.220932,3.591652 14.127263,1.63317 17.98415,-4.332768 -2.970401,4.440658 -8.922715,5.877231 -13.616174,3.167461 -4.737818,-2.735388 -6.449511,-8.693465 -3.988659,-13.51059 L 26.29902,29.028617 c -0.565692,0.629844 -1.386768,1.028448 -2.299348,1.028448 -0.927577,0 -1.760299,-0.411791 -2.32672,-1.059736 z" />
+</svg>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ version="1.1"
+ viewBox="0 0 280.82999 27.34"
+ width="100%"
+ height="100%"
+ id="svg2"
+ inkscape:version="0.48.5 r10040"
+ sodipodi:docname="title.svg">
+ <sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="1000"
+ inkscape:window-height="680"
+ id="namedview10"
+ showgrid="false"
+ inkscape:zoom="1.573906"
+ inkscape:cx="58.770981"
+ inkscape:cy="13.67"
+ inkscape:window-x="0"
+ inkscape:window-y="0"
+ inkscape:window-maximized="0"
+ inkscape:current-layer="svg2" />
+ <metadata
+ id="metadata8">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <defs
+ id="defs6" />
+ <text
+ x="1.1959002"
+ y="24.185671"
+ transform="scale(0.95603363,1.0459883)"
+ id="text2818"
+ xml:space="preserve"
+ style="font-size:34.41720963px;font-style:italic;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:TeXGyrePagella;-inkscape-font-specification:TeXGyrePagella Italic"
+ sodipodi:linespacing="100%"><tspan
+ x="1.1959002"
+ y="24.185671"
+ id="tspan2820"><tspan
+ id="tspan2985"
+ style="font-family:Times New Roman;-inkscape-font-specification:Times New Roman">re</tspan><tspan
+ id="tspan2822"
+ style="font-size:34.41720963px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;font-family:Courier New;-inkscape-font-specification:Courier New">Structured</tspan><tspan
+ id="tspan2989"
+ style="font-family:Times New Roman;-inkscape-font-specification:Times New Roman">Text</tspan></tspan></text>
+</svg>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ version="1.1"
+ width="280.82999"
+ height="27.34"
+ id="svg2"
+ inkscape:version="0.48.5 r10040"
+ sodipodi:docname="title.svg">
+ <sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="1000"
+ inkscape:window-height="680"
+ id="namedview10"
+ showgrid="false"
+ inkscape:zoom="1.573906"
+ inkscape:cx="58.770981"
+ inkscape:cy="13.67"
+ inkscape:window-x="0"
+ inkscape:window-y="0"
+ inkscape:window-maximized="0"
+ inkscape:current-layer="svg2" />
+ <metadata
+ id="metadata8">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <defs
+ id="defs6" />
+ <text
+ x="1.1959002"
+ y="24.185671"
+ transform="scale(0.95603363,1.0459883)"
+ id="text2818"
+ xml:space="preserve"
+ style="font-size:34.41720963px;font-style:italic;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:TeXGyrePagella;-inkscape-font-specification:TeXGyrePagella Italic"
+ sodipodi:linespacing="100%"><tspan
+ x="1.1959002"
+ y="24.185671"
+ id="tspan2820"><tspan
+ id="tspan2985"
+ style="font-family:Times New Roman;-inkscape-font-specification:Times New Roman">re</tspan><tspan
+ id="tspan2822"
+ style="font-size:34.41720963px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;font-family:Courier New;-inkscape-font-specification:Courier New">Structured</tspan><tspan
+ id="tspan2989"
+ style="font-family:Times New Roman;-inkscape-font-specification:Times New Roman">Text</tspan></tspan></text>
+</svg>
--- /dev/null
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
+ "http://www.w3.org/TR/html4/loose.dtd">
+
+<html>
+ <head>
+ <title>Quick reStructuredText</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+
+ <style type="text/css"><!--
+ a.backref { text-decoration: none ; color: black }
+ div.line-block { display: block }
+ div.line-block div.line-block { margin-left: 1.5em }
+ --></style>
+
+ </head>
+
+ <body>
+ <h1>Quick <i>re</i><font size="+4"><tt>Structured</tt></font><i>Text</i></h1>
+
+ <!-- Caveat: if you're reading the HTML for the examples, -->
+ <!-- beware that it was hand-generated, not by Docutils/ReST. -->
+
+ <p align="right"><em><a href="http://docutils.sourceforge.net/docs/user/rst/quickref.html"
+ >http://docutils.sourceforge.net/docs/user/rst/quickref.html</a></em>
+ <br><em>Being a cheat-sheet for reStructuredText</em>
+ <br><em>Updated $Date: 2019-09-30 13:36:39 +0200 (Mo, 30. Sep 2019) $</em>
+
+ <blockquote>
+ <p>Copyright: This document has been placed in the public domain.
+ </blockquote>
+
+
+ <p>The full details of the markup may be found on the
+ <a href="http://docutils.sourceforge.net/rst.html">reStructuredText</a>
+ page. This document is just intended as a reminder.
+
+ <p>Links that look like "(<a href="#details">details</a>)" point
+ into the HTML version of the full <a
+ href="../../ref/rst/restructuredtext.html">reStructuredText
+ specification</a> document. These are relative links; if they
+ don't work, please use the <a
+ href="http://docutils.sourceforge.net/docs/user/rst/quickref.html"
+ >master "Quick reStructuredText"</a> document.
+
+ <h2><a name="contents">Contents</a></h2>
+
+ <ul>
+ <li><a href="#inline-markup">Inline Markup</a></li>
+ <li><a href="#escaping">Escaping with Backslashes</a></li>
+ <li><a href="#section-structure">Section Structure</a></li>
+ <li><a href="#paragraphs">Paragraphs</a></li>
+ <li><a href="#bullet-lists">Bullet Lists</a></li>
+ <li><a href="#enumerated-lists">Enumerated Lists</a></li>
+ <li><a href="#definition-lists">Definition Lists</a></li>
+ <li><a href="#field-lists">Field Lists</a></li>
+ <li><a href="#option-lists">Option Lists</a></li>
+ <li><a href="#literal-blocks">Literal Blocks</a></li>
+ <li><a href="#line-blocks">Line Blocks</a></li>
+ <li><a href="#block-quotes">Block Quotes</a></li>
+ <li><a href="#doctest-blocks">Doctest Blocks</a></li>
+ <li><a href="#tables">Tables</a></li>
+ <li><a href="#transitions">Transitions</a></li>
+ <li><a href="#explicit-markup">Explicit Markup</a>
+ <ul>
+ <li><a href="#footnotes">Footnotes</a></li>
+ <li><a href="#citations">Citations</a></li>
+ <li><a href="#hyperlink-targets">Hyperlink Targets</a>
+ <ul>
+ <li><a href="#external-hyperlink-targets">External Hyperlink Targets</a></li>
+ <li><a href="#internal-hyperlink-targets">Internal Hyperlink Targets</a></li>
+ <li><a href="#indirect-hyperlink-targets">Indirect Hyperlink Targets</a></li>
+ <li><a href="#implicit-hyperlink-targets">Implicit Hyperlink Targets</a></li>
+ </ul></li>
+ <li><a href="#directives">Directives</a></li>
+ <li><a href="#substitution-references-and-definitions">Substitution References and Definitions</a></li>
+ <li><a href="#comments">Comments</a></li>
+ </ul></li>
+ <li><a href="#getting-help">Getting Help</a></li>
+ </ul>
+
+ <h2><a href="#contents" name="inline-markup" class="backref"
+ >Inline Markup</a></h2>
+
+ <p>(<a href="../../ref/rst/restructuredtext.html#inline-markup">details</a>)
+
+ <p>Inline markup allows words and phrases within text to have
+ character styles (like italics and boldface) and functionality
+ (like hyperlinks).
+
+ <p><table border="1" width="100%" bgcolor="#ffffcc" cellpadding="3">
+ <thead>
+ <tr align="left" bgcolor="#99CCFF">
+ <th>Plain text
+ <th>Typical result
+ <th>Notes
+ </thead>
+ <tbody>
+ <tr valign="top">
+ <td nowrap><samp>*emphasis*</samp>
+ <td><em>emphasis</em>
+ <td>Normally rendered as italics.
+
+ <tr valign="top">
+ <td nowrap><samp>**strong emphasis**</samp>
+ <td><strong>strong emphasis</strong>
+ <td>Normally rendered as boldface.
+
+ <tr valign="top">
+ <td nowrap><samp>`interpreted text`</samp>
+ <td>(see note at right)
+ <td>The rendering and <em>meaning</em> of interpreted text is
+ domain- or application-dependent. It can be used for things
+ like index entries or explicit descriptive markup (like program
+ identifiers).
+
+ <tr valign="top">
+ <td nowrap><samp>``inline literal``</samp>
+ <td><code>inline literal</code>
+ <td>Normally rendered as monospaced text. Spaces should be
+ preserved, but line breaks will not be.
+
+ <tr valign="top">
+ <td nowrap><samp>reference_</samp>
+ <td><a href="#hyperlink-targets">reference</a>
+ <td>A simple, one-word hyperlink reference. See <a
+ href="#hyperlink-targets">Hyperlink Targets</a>.
+
+ <tr valign="top">
+ <td nowrap><samp>`phrase reference`_</samp>
+ <td><a href="#hyperlink-targets">phrase reference</a>
+ <td>A hyperlink reference with spaces or punctuation needs to be
+ quoted with backquotes. See <a
+ href="#hyperlink-targets">Hyperlink Targets</a>.
+
+ <tr valign="top">
+ <td nowrap><samp>anonymous__</samp>
+ <td><a href="#hyperlink-targets">anonymous</a>
+ <td>With two underscores instead of one, both simple and phrase
+ references may be anonymous (the reference text is not repeated
+ at the target). See <a
+ href="#hyperlink-targets">Hyperlink Targets</a>.
+
+ <tr valign="top">
+ <td nowrap><samp>_`inline internal target`</samp>
+ <td><a name="inline-internal-target">inline internal target</a>
+ <td>A crossreference target within text.
+ See <a href="#hyperlink-targets">Hyperlink Targets</a>.
+
+ <tr valign="top">
+ <td nowrap><samp>|substitution reference|</samp>
+ <td>(see note at right)
+ <td>The result is substituted in from the <a
+ href="#substitution-references-and-definitions">substitution
+ definition</a>. It could be text, an image, a hyperlink, or a
+ combination of these and others.
+
+ <tr valign="top">
+ <td nowrap><samp>footnote reference [1]_</samp>
+ <td>footnote reference <sup><a href="#footnotes">1</a></sup>
+ <td>See <a href="#footnotes">Footnotes</a>.
+
+ <tr valign="top">
+ <td nowrap><samp>citation reference [CIT2002]_</samp>
+ <td>citation reference <a href="#citations">[CIT2002]</a>
+ <td>See <a href="#citations">Citations</a>.
+
+ <tr valign="top">
+ <td nowrap><samp>http://docutils.sf.net/</samp>
+ <td><a href="http://docutils.sf.net/">http://docutils.sf.net/</a>
+ <td>A standalone hyperlink.
+
+ </table>
+
+ <p>Asterisk, backquote, vertical bar, and underscore are inline
+ delimiter characters. Asterisk, backquote, and vertical bar act
+ like quote marks; matching characters surround the marked-up word
+ or phrase, whitespace or other quoting is required outside them,
+ and there can't be whitespace just inside them. If you want to use
+ inline delimiter characters literally, <a href="#escaping">escape
+ (with backslash)</a> or quote them (with double backquotes; i.e.
+ use inline literals).
+
+ <p>In detail, the reStructuredText specification says that in
+ inline markup, the following rules apply to start-strings and
+ end-strings (inline markup delimiters):
+
+ <ol>
+ <li>The start-string must start a text block or be
+ immediately preceded by whitespace or any of
+ <samp>' " ( [ {</samp> or <samp><</samp>.
+ <li>The start-string must be immediately followed by non-whitespace.
+ <li>The end-string must be immediately preceded by non-whitespace.
+ <li>The end-string must end a text block (end of document or
+ followed by a blank line) or be immediately followed by whitespace
+ or any of <samp>' " . , : ; ! ? - ) ] } / \</samp>
+ or <samp>></samp>.
+ <li>If a start-string is immediately preceded by one of
+ <samp>' " ( [ {</samp> or <samp><</samp>, it must not be
+ immediately followed by the corresponding character from
+ <samp>' " ) ] }</samp> or <samp>></samp>.
+ <li>An end-string must be separated by at least one
+ character from the start-string.
+ <li>An <a href="#escaping">unescaped</a> backslash preceding a
+ start-string or end-string will disable markup recognition, except
+ for the end-string of inline literals.
+ </ol>
+
+ <p>Also remember that inline markup may not be nested (well,
+ except that inline literals can contain any of the other inline
+ markup delimiter characters, but that doesn't count because
+ nothing is processed).
+
+ <h2><a href="#contents" name="escaping" class="backref"
+ >Escaping with Backslashes</a></h2>
+
+ <p>(<a
+ href="../../ref/rst/restructuredtext.html#escaping-mechanism">details</a>)
+
+ <p>reStructuredText uses backslashes ("\") to override the special
+ meaning given to markup characters and get the literal characters
+ themselves. To get a literal backslash, use an escaped backslash
+ ("\\"). For example:
+
+ <p><table border="1" width="100%" bgcolor="#ffffcc" cellpadding="3">
+ <thead>
+ <tr align="left" bgcolor="#99CCFF">
+ <th width="50%">Raw reStructuredText
+ <th width="50%">Typical result
+ </thead>
+ <tbody>
+ <tr valign="top"><td>
+ <samp>*escape* ``with`` "\"</samp>
+ <td><em>escape</em> <samp>with</samp> ""
+ <tr valign="top"><td>
+ <samp>\*escape* \``with`` "\\"</samp>
+ <td>*escape* ``with`` "\"
+ </table>
+
+ <p>In Python strings it will, of course, be necessary
+ to escape any backslash characters so that they actually
+ <em>reach</em> reStructuredText.
+ The simplest way to do this is to use raw strings:
+
+ <p><table border="1" width="100%" bgcolor="#ffffcc" cellpadding="3">
+ <thead>
+ <tr align="left" bgcolor="#99CCFF">
+ <th width="50%">Python string
+ <th width="50%">Typical result
+ </thead>
+ <tbody>
+ <tr valign="top"><td>
+ <samp>r"""\*escape* \`with` "\\""""</samp>
+ <td>*escape* `with` "\"
+ <tr valign="top"><td>
+ <samp> """\\*escape* \\`with` "\\\\""""</samp>
+ <td>*escape* `with` "\"
+ <tr valign="top"><td>
+ <samp> """\*escape* \`with` "\\""""</samp>
+ <td><em>escape</em> with ""
+ </table>
+
+ <h2><a href="#contents" name="section-structure" class="backref"
+ >Section Structure</a></h2>
+
+ <p>(<a href="../../ref/rst/restructuredtext.html#sections">details</a>)
+
+ <p><table border="1" width="100%" bgcolor="#ffffcc" cellpadding="3">
+ <thead>
+ <tr align="left" bgcolor="#99CCFF">
+ <th width="50%">Plain text
+ <th width="50%">Typical result
+ </thead>
+ <tbody>
+ <tr valign="top">
+ <td>
+<samp>=====</samp>
+<br><samp>Title</samp>
+<br><samp>=====</samp>
+<br><samp>Subtitle</samp>
+<br><samp>--------</samp>
+<br><samp>Titles are underlined (or over-</samp>
+<br><samp>and underlined) with a printing</samp>
+<br><samp>nonalphanumeric 7-bit ASCII</samp>
+<br><samp>character. Recommended choices</samp>
+<br><samp>are "``= - ` : ' " ~ ^ _ * + # < >``".</samp>
+<br><samp>The underline/overline must be at</samp>
+<br><samp>least as long as the title text.</samp>
+<br><samp></samp>
+<br><samp>A lone top-level (sub)section</samp>
+<br><samp>is lifted up to be the document's</samp>
+<br><samp>(sub)title.</samp>
+
+ <td>
+ <font size="+2"><strong>Title</strong></font>
+ <p><font size="+1"><strong>Subtitle</strong></font>
+ <p>Titles are underlined (or over-
+ and underlined) with a printing
+ nonalphanumeric 7-bit ASCII
+ character. Recommended choices
+ are "<samp>= - ` : ' " ~ ^ _ * + # < ></samp>".
+ The underline/overline must be at
+ least as long as the title text.
+ <p>A lone top-level (sub)section is
+ lifted up to be the document's
+ (sub)title.
+ </table>
+
+ <h2><a href="#contents" name="paragraphs" class="backref"
+ >Paragraphs</a></h2>
+
+ <p>(<a href="../../ref/rst/restructuredtext.html#paragraphs">details</a>)
+
+ <p><table border="1" width="100%" bgcolor="#ffffcc" cellpadding="3">
+ <thead>
+ <tr align="left" bgcolor="#99CCFF">
+ <th width="50%">Plain text
+ <th width="50%">Typical result
+ </thead>
+ <tbody>
+ <tr valign="top">
+ <td>
+<p><samp>This is a paragraph.</samp>
+
+<p><samp>Paragraphs line up at their left</samp>
+<br><samp>edges, and are normally separated</samp>
+<br><samp>by blank lines.</samp>
+
+ <td>
+ <p>This is a paragraph.
+
+ <p>Paragraphs line up at their left edges, and are normally
+ separated by blank lines.
+
+ </table>
+
+ <h2><a href="#contents" name="bullet-lists" class="backref"
+ >Bullet Lists</a></h2>
+
+ <p>(<a href="../../ref/rst/restructuredtext.html#bullet-lists">details</a>)
+
+ <p><table border="1" width="100%" bgcolor="#ffffcc" cellpadding="3">
+ <thead>
+ <tr align="left" bgcolor="#99CCFF">
+ <th width="50%">Plain text
+ <th width="50%">Typical result
+ </thead>
+ <tbody>
+ <tr valign="top">
+ <td>
+<samp>Bullet lists:</samp>
+
+<p><samp>- This is item 1</samp>
+<br><samp>- This is item 2</samp>
+
+<p><samp>- Bullets are "-", "*" or "+".</samp>
+<br><samp> Continuing text must be aligned</samp>
+<br><samp> after the bullet and whitespace.</samp>
+
+<p><samp>Note that a blank line is required</samp>
+<br><samp>before the first item and after the</samp>
+<br><samp>last, but is optional between items.</samp>
+ <td>Bullet lists:
+ <ul>
+ <li>This is item 1
+ <li>This is item 2
+ <li>Bullets are "-", "*" or "+".
+ Continuing text must be aligned
+ after the bullet and whitespace.
+ </ul>
+ <p>Note that a blank line is required before the first
+ item and after the last, but is optional between items.
+ </table>
+
+ <h2><a href="#contents" name="enumerated-lists" class="backref"
+ >Enumerated Lists</a></h2>
+
+ <p>(<a href="../../ref/rst/restructuredtext.html#enumerated-lists">details</a>)
+
+ <p><table border="1" width="100%" bgcolor="#ffffcc" cellpadding="3">
+ <thead>
+ <tr align="left" bgcolor="#99CCFF">
+ <th width="50%">Plain text
+ <th width="50%">Typical result
+ </thead>
+ <tbody>
+ <tr valign="top">
+ <td>
+<samp>Enumerated lists:</samp>
+
+<p><samp>3. This is the first item</samp>
+<br><samp>4. This is the second item</samp>
+<br><samp>5. Enumerators are arabic numbers,</samp>
+<br><samp> single letters, or roman numerals</samp>
+<br><samp>6. List items should be sequentially</samp>
+<br><samp> numbered, but need not start at 1</samp>
+<br><samp> (although not all formatters will</samp>
+<br><samp> honour the first index).</samp>
+<br><samp>#. This item is auto-enumerated</samp>
+ <td>Enumerated lists:
+ <ol type="1">
+ <li value="3">This is the first item
+ <li>This is the second item
+ <li>Enumerators are arabic numbers, single letters,
+ or roman numerals
+ <li>List items should be sequentially numbered,
+ but need not start at 1 (although not all
+ formatters will honour the first index).
+ <li>This item is auto-enumerated
+ </ol>
+ </table>
+
+ <h2><a href="#contents" name="definition-lists" class="backref"
+ >Definition Lists</a></h2>
+
+ <p>(<a href="../../ref/rst/restructuredtext.html#definition-lists">details</a>)
+
+ <p><table border="1" width="100%" bgcolor="#ffffcc" cellpadding="3">
+ <thead>
+ <tr align="left" bgcolor="#99CCFF">
+ <th width="50%">Plain text
+ <th width="50%">Typical result
+ </thead>
+ <tbody>
+ <tr valign="top">
+ <td>
+<samp>Definition lists:</samp>
+<br>
+<br><samp>what</samp>
+<br><samp> Definition lists associate a term with</samp>
+<br><samp> a definition.</samp>
+<br>
+<br><samp>how</samp>
+<br><samp> The term is a one-line phrase, and the</samp>
+<br><samp> definition is one or more paragraphs or</samp>
+<br><samp> body elements, indented relative to the</samp>
+<br><samp> term. Blank lines are not allowed</samp>
+<br><samp> between term and definition.</samp>
+ <td>Definition lists:
+ <dl>
+ <dt><strong>what</strong>
+ <dd>Definition lists associate a term with
+ a definition.
+
+ <dt><strong>how</strong>
+ <dd>The term is a one-line phrase, and the
+ definition is one or more paragraphs or
+ body elements, indented relative to the
+ term. Blank lines are not allowed
+ between term and definition.
+ </dl>
+ </table>
+
+ <h2><a href="#contents" name="field-lists" class="backref"
+ >Field Lists</a></h2>
+
+ <p>(<a href="../../ref/rst/restructuredtext.html#field-lists">details</a>)
+
+ <p><table border="1" width="100%" bgcolor="#ffffcc" cellpadding="3">
+ <thead>
+ <tr align="left" bgcolor="#99CCFF">
+ <th width="50%">Plain text
+ <th width="50%">Typical result
+ </thead>
+ <tbody>
+ <tr valign="top">
+ <td>
+<samp>:Authors:</samp>
+<br><samp> Tony J. (Tibs) Ibbs,</samp>
+<br><samp> David Goodger</samp>
+
+<p><samp> (and sundry other good-natured folks)</samp>
+
+<p><samp>:Version: 1.0 of 2001/08/08</samp>
+<br><samp>:Dedication: To my father.</samp>
+ <td>
+ <table>
+ <tr valign="top">
+ <td><strong>Authors:</strong>
+ <td>Tony J. (Tibs) Ibbs,
+ David Goodger
+ <tr><td><td>(and sundry other good-natured folks)
+ <tr><td><strong>Version:</strong><td>1.0 of 2001/08/08
+ <tr><td><strong>Dedication:</strong><td>To my father.
+ </table>
+ </table>
+
+ <p>Field lists are used as part of an extension syntax, such as
+ options for <a href="#directives">directives</a>, or database-like
+ records meant for further processing. Field lists may also be
+ used as generic two-column table constructs in documents.
+
+ <h2><a href="#contents" name="option-lists" class="backref"
+ >Option Lists</a></h2>
+
+ <p>(<a href="../../ref/rst/restructuredtext.html#option-lists">details</a>)
+
+ <p><table border="1" width="100%" bgcolor="#ffffcc" cellpadding="3">
+ <thead>
+ <tr align="left" bgcolor="#99CCFF">
+ <th width="50%">Plain text
+ <th width="50%">Typical result
+ </thead>
+ <tbody>
+ <tr valign="top">
+ <td>
+ <p><samp>
+-a command-line option "a"
+<br>-b file options can have arguments
+<br> and long descriptions
+<br>--long options can be long also
+<br>--input=file long options can also have
+<br> arguments
+<br>/V DOS/VMS-style options too
+</samp>
+
+ <td>
+ <table border="0" width="100%">
+ <tbody valign="top">
+ <tr>
+ <td width="30%"><samp>-a</samp>
+ <td>command-line option "a"
+ <tr>
+ <td><samp>-b <i>file</i></samp>
+ <td>options can have arguments and long descriptions
+ <tr>
+ <td><samp>--long</samp>
+ <td>options can be long also
+ <tr>
+ <td><samp>--input=<i>file</i></samp>
+ <td>long options can also have arguments
+ <tr>
+ <td><samp>/V</samp>
+ <td>DOS/VMS-style options too
+ </table>
+ </table>
+
+ <p>There must be at least two spaces between the option and the
+ description.
+
+ <h2><a href="#contents" name="literal-blocks" class="backref"
+ >Literal Blocks</a></h2>
+
+ <p>(<a href="../../ref/rst/restructuredtext.html#literal-blocks">details</a>)
+
+ <p><table border="1" width="100%" bgcolor="#ffffcc" cellpadding="3">
+ <thead>
+ <tr align="left" bgcolor="#99CCFF">
+ <th width="50%">Plain text
+ <th width="50%">Typical result
+ </thead>
+ <tbody>
+ <tr valign="top">
+ <td>
+<samp>A paragraph containing only two colons</samp>
+<br><samp>indicates that the following indented</samp>
+<br><samp>or quoted text is a literal block.</samp>
+<br>
+<br><samp>::</samp>
+<br>
+<br><samp> Whitespace, newlines, blank lines, and</samp>
+<br><samp> all kinds of markup (like *this* or</samp>
+<br><samp> \this) is preserved by literal blocks.</samp>
+<br>
+<br><samp> The paragraph containing only '::'</samp>
+<br><samp> will be omitted from the result.</samp>
+<br>
+<br><samp>The ``::`` may be tacked onto the very</samp>
+<br><samp>end of any paragraph. The ``::`` will be</samp>
+<br><samp>omitted if it is preceded by whitespace.</samp>
+<br><samp>The ``::`` will be converted to a single</samp>
+<br><samp>colon if preceded by text, like this::</samp>
+<br>
+<br><samp> It's very convenient to use this form.</samp>
+<br>
+<br><samp>Literal blocks end when text returns to</samp>
+<br><samp>the preceding paragraph's indentation.</samp>
+<br><samp>This means that something like this</samp>
+<br><samp>is possible::</samp>
+<br>
+<br><samp> We start here</samp>
+<br><samp> and continue here</samp>
+<br><samp> and end here.</samp>
+<br>
+<br><samp>Per-line quoting can also be used on</samp>
+<br><samp>unindented literal blocks::</samp>
+<br>
+<br><samp>> Useful for quotes from email and</samp>
+<br><samp>> for Haskell literate programming.</samp>
+
+ <td>
+ <p>A paragraph containing only two colons
+indicates that the following indented or quoted
+text is a literal block.
+
+ <pre>
+ Whitespace, newlines, blank lines, and
+ all kinds of markup (like *this* or
+ \this) is preserved by literal blocks.
+
+ The paragraph containing only '::'
+ will be omitted from the result.</pre>
+
+ <p>The <samp>::</samp> may be tacked onto the very
+end of any paragraph. The <samp>::</samp> will be
+omitted if it is preceded by whitespace.
+The <samp>::</samp> will be converted to a single
+colon if preceded by text, like this:
+
+ <pre>
+ It's very convenient to use this form.</pre>
+
+ <p>Literal blocks end when text returns to
+the preceding paragraph's indentation.
+This means that something like this is possible:
+
+ <pre>
+ We start here
+ and continue here
+ and end here.</pre>
+
+ <p>Per-line quoting can also be used on
+unindented literal blocks:
+
+ <pre>
+ > Useful for quotes from email and
+ > for Haskell literate programming.</pre>
+ </table>
+
+ <h2><a href="#contents" name="line-blocks" class="backref"
+ >Line Blocks</a></h2>
+
+ <p>(<a href="../../ref/rst/restructuredtext.html#line-blocks">details</a>)
+
+ <p><table border="1" width="100%" bgcolor="#ffffcc" cellpadding="3">
+ <thead>
+ <tr align="left" bgcolor="#99CCFF">
+ <th width="50%">Plain text
+ <th width="50%">Typical result
+ </thead>
+ <tbody>
+ <tr valign="top">
+ <td>
+<samp>| Line blocks are useful for addresses,</samp>
+<br><samp>| verse, and adornment-free lists.</samp>
+<br><samp>|</samp>
+<br><samp>| Each new line begins with a</samp>
+<br><samp>| vertical bar ("|").</samp>
+<br><samp>| Line breaks and initial indents</samp>
+<br><samp>| are preserved.</samp>
+<br><samp>| Continuation lines are wrapped</samp>
+<br><samp> portions of long lines; they begin</samp>
+<br><samp> with spaces in place of vertical bars.</samp>
+
+ <td>
+ <div class="line-block">
+ <div class="line">Line blocks are useful for addresses,</div>
+ <div class="line">verse, and adornment-free lists.</div>
+ <div class="line"><br /></div>
+ <div class="line">Each new line begins with a</div>
+ <div class="line">vertical bar ("|").</div>
+ <div class="line-block">
+ <div class="line">Line breaks and initial indents</div>
+ <div class="line">are preserved.</div>
+ </div>
+ <div class="line">Continuation lines are wrapped portions
+ of long lines; they begin
+ with spaces in place of vertical bars.</div>
+ </div>
+ </table>
+
+ <h2><a href="#contents" name="block-quotes" class="backref"
+ >Block Quotes</a></h2>
+
+ <p>(<a href="../../ref/rst/restructuredtext.html#block-quotes">details</a>)
+
+ <p><table border="1" width="100%" bgcolor="#ffffcc" cellpadding="3">
+ <thead>
+ <tr align="left" bgcolor="#99CCFF">
+ <th width="50%">Plain text
+ <th width="50%">Typical result
+ </thead>
+ <tbody>
+ <tr valign="top">
+ <td>
+<samp>Block quotes are just:</samp>
+
+<p><samp> Indented paragraphs,</samp>
+
+<p><samp> and they may nest.</samp>
+ <td>
+ Block quotes are just:
+ <blockquote>
+ <p>Indented paragraphs,
+ <blockquote>
+ <p>and they may nest.
+ </blockquote>
+ </blockquote>
+ </table>
+
+ <p>Use <a href="#comments">empty comments</a> to separate indentation
+ contexts, such as block quotes and directive contents.</p>
+
+ <h2><a href="#contents" name="doctest-blocks" class="backref"
+ >Doctest Blocks</a></h2>
+
+ <p>(<a href="../../ref/rst/restructuredtext.html#doctest-blocks">details</a>)
+
+ <p><table border="1" width="100%" bgcolor="#ffffcc" cellpadding="3">
+ <thead>
+ <tr align="left" bgcolor="#99CCFF">
+ <th width="50%">Plain text
+ <th width="50%">Typical result
+ </thead>
+ <tbody>
+ <tr valign="top">
+ <td>
+ <p><samp>Doctest blocks are interactive
+<br>Python sessions. They begin with
+<br>"``>>>``" and end with a blank line.</samp>
+
+ <p><samp>>>> print "This is a doctest block."
+<br>This is a doctest block.</samp>
+
+ <td>
+ <p>Doctest blocks are interactive
+ Python sessions. They begin with
+ "<samp>>>></samp>" and end with a blank line.
+
+ <p><samp>>>> print "This is a doctest block."
+<br>This is a doctest block.</samp>
+ </table>
+
+ <p>"The <a
+ href="http://www.python.org/doc/current/lib/module-doctest.html">doctest</a>
+ module searches a module's docstrings for text that looks like an
+ interactive Python session, then executes all such sessions to
+ verify they still work exactly as shown." (From the doctest docs.)
+
+ <h2><a href="#contents" name="tables" class="backref"
+ >Tables</a></h2>
+
+ <p>(<a href="../../ref/rst/restructuredtext.html#tables">details</a>)
+
+ <p>There are two syntaxes for tables in reStructuredText. Grid
+ tables are complete but cumbersome to create. Simple tables are
+ easy to create but limited (no row spans, etc.).</p>
+
+ <p><table border="1" width="100%" bgcolor="#ffffcc" cellpadding="3">
+ <thead>
+ <tr align="left" bgcolor="#99CCFF">
+ <th width="50%">Plain text
+ <th width="50%">Typical result
+ </thead>
+ <tbody>
+ <tr valign="top">
+ <td>
+<p><samp>Grid table:</samp></p>
+
+<p><samp>+------------+------------+-----------+</samp>
+<br><samp>| Header 1 | Header 2 | Header 3 |</samp>
+<br><samp>+============+============+===========+</samp>
+<br><samp>| body row 1 | column 2 | column 3 |</samp>
+<br><samp>+------------+------------+-----------+</samp>
+<br><samp>| body row 2 | Cells may span columns.|</samp>
+<br><samp>+------------+------------+-----------+</samp>
+<br><samp>| body row 3 | Cells may | - Cells |</samp>
+<br><samp>+------------+ span rows. | - contain |</samp>
+<br><samp>| body row 4 | | - blocks. |</samp>
+<br><samp>+------------+------------+-----------+</samp></p>
+ <td>
+ <p>Grid table:</p>
+ <table border="1">
+ <thead valign="bottom">
+ <tr>
+ <th>Header 1
+ <th>Header 2
+ <th>Header 3
+ </tr>
+ </thead>
+ <tbody valign="top">
+ <tr>
+ <td>body row 1
+ <td>column 2
+ <td>column 3
+ </tr>
+ <tr>
+ <td>body row 2
+ <td colspan="2">Cells may span columns.
+ </tr>
+ <tr>
+ <td>body row 3
+ <td rowspan="2">Cells may<br>span rows.
+ <td rowspan="2">
+ <ul>
+ <li>Cells
+ <li>contain
+ <li>blocks.
+ </ul>
+ </tr>
+ <tr>
+ <td>body row 4
+ </tr>
+ </table>
+ <tr valign="top">
+ <td>
+<p><samp>Simple table:</samp></p>
+
+<p><samp>===== ===== ======</samp>
+<br><samp> Inputs Output</samp>
+<br><samp>------------ ------</samp>
+<br><samp> A B A or B</samp>
+<br><samp>===== ===== ======</samp>
+<br><samp>False False False</samp>
+<br><samp>True False True</samp>
+<br><samp>False True True</samp>
+<br><samp>True True True</samp>
+<br><samp>===== ===== ======</samp></p>
+
+ <td>
+ <p>Simple table:</p>
+ <table border="1">
+ <colgroup>
+ <col width="31%">
+ <col width="31%">
+ <col width="38%">
+ </colgroup>
+ <thead valign="bottom">
+ <tr>
+ <th colspan="2">Inputs
+ <th>Output
+ <tr>
+ <th>A
+ <th>B
+ <th>A or B
+ <tbody valign="top">
+ <tr>
+ <td>False
+ <td>False
+ <td>False
+ <tr>
+ <td>True
+ <td>False
+ <td>True
+ <tr>
+ <td>False
+ <td>True
+ <td>True
+ <tr>
+ <td>True
+ <td>True
+ <td>True
+ </table>
+
+ </table>
+
+ <h2><a href="#contents" name="transitions" class="backref"
+ >Transitions</a></h2>
+
+ <p>(<a href="../../ref/rst/restructuredtext.html#transitions">details</a>)
+
+ <p><table border="1" width="100%" bgcolor="#ffffcc" cellpadding="3">
+ <thead>
+ <tr align="left" bgcolor="#99CCFF">
+ <th width="50%">Plain text
+ <th width="50%">Typical result
+ </thead>
+ <tbody>
+ <tr valign="top">
+ <td>
+ <p><samp>
+A transition marker is a horizontal line
+<br>of 4 or more repeated punctuation
+<br>characters.</samp>
+
+ <p><samp>------------</samp>
+
+ <p><samp>A transition should not begin or end a
+<br>section or document, nor should two
+<br>transitions be immediately adjacent.</samp>
+
+ <td>
+ <p>A transition marker is a horizontal line
+ of 4 or more repeated punctuation
+ characters.</p>
+
+ <hr>
+
+ <p>A transition should not begin or end a
+ section or document, nor should two
+ transitions be immediately adjacent.
+ </table>
+
+ <p>Transitions are commonly seen in novels and short fiction, as a
+ gap spanning one or more lines, marking text divisions or
+ signaling changes in subject, time, point of view, or emphasis.
+
+ <h2><a href="#contents" name="explicit-markup" class="backref"
+ >Explicit Markup</a></h2>
+
+ <p>Explicit markup blocks are used for constructs which float
+ (footnotes), have no direct paper-document representation
+ (hyperlink targets, comments), or require specialized processing
+ (directives). They all begin with two periods and whitespace, the
+ "explicit markup start".
+
+ <h3><a href="#contents" name="footnotes" class="backref"
+ >Footnotes</a></h3>
+
+ <p>(<a href="../../ref/rst/restructuredtext.html#footnotes">details</a>)
+
+ <p><table border="1" width="100%" bgcolor="#ffffcc" cellpadding="3">
+ <thead>
+ <tr align="left" bgcolor="#99CCFF">
+ <th width="50%">Plain text
+ <th width="50%">Typical result
+ </thead>
+ <tbody>
+
+ <tr valign="top">
+ <td>
+ <samp>Footnote references, like [5]_.</samp>
+ <br><samp>Note that footnotes may get</samp>
+ <br><samp>rearranged, e.g., to the bottom of</samp>
+ <br><samp>the "page".</samp>
+
+ <p><samp>.. [5] A numerical footnote. Note</samp>
+ <br><samp> there's no colon after the ``]``.</samp>
+
+ <td>
+ Footnote references, like <sup><a href="#5">5</a></sup>.
+ Note that footnotes may get rearranged, e.g., to the bottom of
+ the "page".
+
+ <p><table>
+ <tr><td colspan="2"><hr>
+ <!-- <tr><td colspan="2">Footnotes: -->
+ <tr><td><a name="5"><strong>[5]</strong></a><td> A numerical footnote.
+ Note there's no colon after the <samp>]</samp>.
+ </table>
+
+ <tr valign="top">
+ <td>
+ <samp>Autonumbered footnotes are</samp>
+ <br><samp>possible, like using [#]_ and [#]_.</samp>
+ <p><samp>.. [#] This is the first one.</samp>
+ <br><samp>.. [#] This is the second one.</samp>
+
+ <p><samp>They may be assigned 'autonumber</samp>
+ <br><samp>labels' - for instance,
+ <br>[#fourth]_ and [#third]_.</samp>
+
+ <p><samp>.. [#third] a.k.a. third_</samp>
+ <p><samp>.. [#fourth] a.k.a. fourth_</samp>
+ <td>
+ Autonumbered footnotes are possible, like using <sup><a
+ href="#auto1">1</a></sup> and <sup><a href="#auto2">2</a></sup>.
+
+ <p>They may be assigned 'autonumber labels' - for instance,
+ <sup><a href="#fourth">4</a></sup> and <sup><a
+ href="#third">3</a></sup>.
+
+ <p><table>
+ <tr><td colspan="2"><hr>
+ <!-- <tr><td colspan="2">Footnotes: -->
+ <tr><td><a name="auto1"><strong>[1]</strong></a><td> This is the first one.
+ <tr><td><a name="auto2"><strong>[2]</strong></a><td> This is the second one.
+ <tr><td><a name="third"><strong>[3]</strong></a><td> a.k.a. <a href="#third">third</a>
+ <tr><td><a name="fourth"><strong>[4]</strong></a><td> a.k.a. <a href="#fourth">fourth</a>
+ </table>
+
+ <tr valign="top">
+ <td>
+ <samp>Auto-symbol footnotes are also</samp>
+ <br><samp>possible, like this: [*]_ and [*]_.</samp>
+ <p><samp>.. [*] This is the first one.</samp>
+ <br><samp>.. [*] This is the second one.</samp>
+
+ <td>
+ Auto-symbol footnotes are also
+ possible, like this: <sup><a href="#symbol1">*</a></sup>
+ and <sup><a href="#symbol2">†</a></sup>.
+
+ <p><table>
+ <tr><td colspan="2"><hr>
+ <!-- <tr><td colspan="2">Footnotes: -->
+ <tr><td><a name="symbol1"><strong>[*]</strong></a><td> This is the first symbol footnote
+ <tr><td><a name="symbol2"><strong>[†]</strong></a><td> This is the second one.
+ </table>
+
+ </table>
+
+ <p>The numbering of auto-numbered footnotes is determined by the
+ order of the footnotes, not of the references. For auto-numbered
+ footnote references without autonumber labels
+ ("<samp>[#]_</samp>"), the references and footnotes must be in the
+ same relative order. Similarly for auto-symbol footnotes
+ ("<samp>[*]_</samp>").
+
+ <h3><a href="#contents" name="citations" class="backref"
+ >Citations</a></h3>
+
+ <p>(<a href="../../ref/rst/restructuredtext.html#citations">details</a>)
+
+ <p><table border="1" width="100%" bgcolor="#ffffcc" cellpadding="3">
+ <thead>
+ <tr align="left" bgcolor="#99CCFF">
+ <th width="50%">Plain text
+ <th width="50%">Typical result
+ </thead>
+ <tbody>
+
+ <tr valign="top">
+ <td>
+ <samp>Citation references, like [CIT2002]_.</samp>
+ <br><samp>Note that citations may get</samp>
+ <br><samp>rearranged, e.g., to the bottom of</samp>
+ <br><samp>the "page".</samp>
+
+ <p><samp>.. [CIT2002] A citation</samp>
+ <br><samp> (as often used in journals).</samp>
+
+ <p><samp>Citation labels contain alphanumerics,</samp>
+ <br><samp>underlines, hyphens and fullstops.</samp>
+ <br><samp>Case is not significant.</samp>
+
+ <p><samp>Given a citation like [this]_, one</samp>
+ <br><samp>can also refer to it like this_.</samp>
+
+ <p><samp>.. [this] here.</samp>
+
+ <td>
+ Citation references, like <a href="#cit2002">[CIT2002]</a>.
+ Note that citations may get rearranged, e.g., to the bottom of
+ the "page".
+
+ <p>Citation labels contain alphanumerics, underlines, hyphens
+ and fullstops. Case is not significant.
+
+ <p>Given a citation like <a href="#this">[this]</a>, one
+ can also refer to it like <a href="#this">this</a>.
+
+ <p><table>
+ <tr><td colspan="2"><hr>
+ <!-- <tr><td colspan="2">Citations: -->
+ <tr><td><a name="cit2002"><strong>[CIT2002]</strong></a><td> A citation
+ (as often used in journals).
+ <tr><td><a name="this"><strong>[this]</strong></a><td> here.
+ </table>
+
+ </table>
+
+ <h3><a href="#contents" name="hyperlink-targets" class="backref"
+ >Hyperlink Targets</a></h3>
+
+ <p>(<a href="../../ref/rst/restructuredtext.html#hyperlink-targets">details</a>)
+
+ <h4><a href="#contents" name="external-hyperlink-targets" class="backref"
+ >External Hyperlink Targets</a></h4>
+
+ <p><table border="1" width="100%" bgcolor="#ffffcc" cellpadding="3">
+ <thead>
+ <tr align="left" bgcolor="#99CCFF">
+ <th width="50%">Plain text
+ <th width="50%">Typical result
+ </thead>
+ <tbody>
+
+ <tr valign="top">
+ <td rowspan="2">
+ <samp>External hyperlinks, like Python_.</samp>
+
+ <p><samp>.. _Python: http://www.python.org/</samp>
+ <td>
+ <table width="100%">
+ <tr bgcolor="#99CCFF"><td><em>Fold-in form</em>
+ <tr><td>External hyperlinks, like
+ <a href="http://www.python.org/">Python</a>.
+ </table>
+ <tr valign="top">
+ <td>
+ <table width="100%">
+ <tr bgcolor="#99CCFF"><td><em>Call-out form</em>
+ <tr><td>External hyperlinks, like
+ <a href="#labPython"><i>Python</i></a>.
+
+ <p><table>
+ <tr><td colspan="2"><hr>
+ <tr><td><a name="labPython"><i>Python:</i></a>
+ <td> <a href="http://www.python.org/">http://www.python.org/</a>
+ </table>
+ </table>
+ </table>
+
+ <p>"<em>Fold-in</em>" is the representation typically used in HTML
+ documents (think of the indirect hyperlink being "folded in" like
+ ingredients into a cake), and "<em>call-out</em>" is more suitable for
+ printed documents, where the link needs to be presented explicitly, for
+ example as a footnote. You can force usage of the call-out form by
+ using the
+ "<a href="../../ref/rst/directives.html#target-notes">target-notes</a>"
+ directive.
+
+ <p>reStructuredText also provides for <b>embedded URIs</b> (<a
+ href="../../ref/rst/restructuredtext.html#embedded-uris-and-aliases">details</a>),
+ a convenience at the expense of readability. A hyperlink
+ reference may directly embed a target URI inline, within angle
+ brackets. The following is exactly equivalent to the example above:
+
+ <p><table border="1" width="100%" bgcolor="#ffffcc" cellpadding="3">
+ <thead>
+ <tr align="left" bgcolor="#99CCFF">
+ <th width="50%">Plain text
+ <th width="50%">Typical result
+ </thead>
+ <tbody>
+
+ <tr valign="top">
+ <td rowspan="2">
+ <samp>External hyperlinks, like `Python
+<br><http://www.python.org/>`_.</samp>
+ <td>External hyperlinks, like
+ <a href="http://www.python.org/">Python</a>.
+ </table>
+
+ <h4><a href="#contents" name="internal-hyperlink-targets" class="backref"
+ >Internal Hyperlink Targets</a></h4>
+
+ <p><table border="1" width="100%" bgcolor="#ffffcc" cellpadding="3">
+ <thead>
+ <tr align="left" bgcolor="#99CCFF">
+ <th width="50%">Plain text
+ <th width="50%">Typical result
+ </thead>
+ <tbody>
+
+ <tr valign="top">
+ <td rowspan="2"><samp>Internal crossreferences, like example_.</samp>
+
+ <p><samp>.. _example:</samp>
+
+ <p><samp>This is an example crossreference target.</samp>
+ <td>
+ <table width="100%">
+ <tr bgcolor="#99CCFF"><td><em>Fold-in form</em>
+ <!-- Note that some browsers may not like an "a" tag that -->
+ <!-- does not have any content, so we could arbitrarily -->
+ <!-- use the first word as content - *or* just trust to -->
+ <!-- luck! -->
+ <tr><td>Internal crossreferences, like <a href="#example-foldin">example</a>
+ <p><a name="example-foldin">This</a> is an example
+ crossreference target.
+ </table>
+ <tr valign="top">
+ <td>
+ <table width="100%">
+ <tr><td bgcolor="#99CCFF"><em>Call-out form</em>
+ <tr><td>Internal crossreferences, like <a href="#example-callout">example</a>
+
+ <p><a name="example-callout"><i>example:</i></a>
+ <br>This is an example crossreference target.
+ </table>
+
+ </table>
+
+ <h4><a href="#contents" name="indirect-hyperlink-targets" class="backref"
+ >Indirect Hyperlink Targets</a></h4>
+
+ <p>(<a href="../../ref/rst/restructuredtext.html#indirect-hyperlink-targets">details</a>)
+
+ <p><table border="1" width="100%" bgcolor="#ffffcc" cellpadding="3">
+ <thead>
+ <tr align="left" bgcolor="#99CCFF">
+ <th width="50%">Plain text
+ <th width="50%">Typical result
+ </thead>
+ <tbody>
+
+ <tr valign="top">
+ <td>
+ <samp>Python_ is `my favourite
+<br>programming language`__.</samp>
+
+ <p><samp>.. _Python: http://www.python.org/</samp>
+
+ <p><samp>__ Python_</samp>
+
+ <td>
+ <p><a href="http://www.python.org/">Python</a> is
+ <a href="http://www.python.org/">my favourite
+ programming language</a>.
+
+ </table>
+
+ <p>The second hyperlink target (the line beginning with
+ "<samp>__</samp>") is both an indirect hyperlink target
+ (<i>indirectly</i> pointing at the Python website via the
+ "<samp>Python_</samp>" reference) and an <b>anonymous hyperlink
+ target</b>. In the text, a double-underscore suffix is used to
+ indicate an <b>anonymous hyperlink reference</b>. In an anonymous
+ hyperlink target, the reference text is not repeated. This is
+ useful for references with long text or throw-away references, but
+ the target should be kept close to the reference to prevent them
+ going out of sync.
+
+ <h4><a href="#contents" name="implicit-hyperlink-targets" class="backref"
+ >Implicit Hyperlink Targets</a></h4>
+
+ <p>(<a href="../../ref/rst/restructuredtext.html#implicit-hyperlink-targets">details</a>)
+
+ <p>Section titles, footnotes, and citations automatically generate
+ hyperlink targets (the title text or footnote/citation label is
+ used as the hyperlink name).
+
+ <p><table border="1" width="100%" bgcolor="#ffffcc" cellpadding="3">
+ <thead><tr align="left" bgcolor="#99CCFF">
+ <th width="50%">Plain text
+ <th width="50%">Typical result
+ </thead>
+ <tbody>
+
+ <tr valign="top">
+ <td>
+ <samp>Titles are targets, too</samp>
+ <br><samp>=======================</samp>
+ <br><samp>Implict references, like `Titles are</samp>
+ <br><samp>targets, too`_.</samp>
+ <td>
+ <font size="+2"><strong><a name="title">Titles are targets, too</a></strong></font>
+ <p>Implict references, like <a href="#title">Titles are
+ targets, too</a>.
+ </table>
+
+ <h3><a href="#contents" name="directives" class="backref"
+ >Directives</a></h3>
+
+ <p>(<a href="../../ref/rst/restructuredtext.html#directives">details</a>)
+
+ <p>Directives are a general-purpose extension mechanism, a way of
+ adding support for new constructs without adding new syntax. For
+ a description of all standard directives, see <a
+ href="../../ref/rst/directives.html" >reStructuredText
+ Directives</a>.
+
+ <p><table border="1" width="100%" bgcolor="#ffffcc" cellpadding="3">
+ <thead>
+ <tr align="left" bgcolor="#99CCFF">
+ <th width="50%">Plain text
+ <th width="50%">Typical result
+ </thead>
+ <tbody>
+ <tr valign="top">
+ <td><samp>For instance:</samp>
+
+ <p><samp>.. image:: images/ball1.gif</samp>
+
+ <td>
+ For instance:
+ <p><img src="images/ball1.gif" alt="ball1">
+ </table>
+
+ <h3><a href="#contents" name="substitution-references-and-definitions"
+ class="backref" >Substitution References and Definitions</a></h3>
+
+ <p>(<a href="../../ref/rst/restructuredtext.html#substitution-definitions">details</a>)
+
+ <p>Substitutions are like inline directives, allowing graphics and
+ arbitrary constructs within text.
+
+ <p><table border="1" width="100%" bgcolor="#ffffcc" cellpadding="3">
+ <thead>
+ <tr align="left" bgcolor="#99CCFF">
+ <th width="50%">Plain text
+ <th width="50%">Typical result
+ </thead>
+ <tbody>
+ <tr valign="top">
+ <td><samp>
+The |biohazard| symbol must be
+used on containers used to
+dispose of medical waste.</samp>
+
+ <p><samp>
+.. |biohazard| image:: biohazard.png</samp>
+
+ <td>
+
+ <p>The <img src="images/biohazard.png" align="bottom" alt="biohazard"> symbol
+ must be used on containers used to dispose of medical waste.
+
+ </table>
+
+ <h3><a href="#contents" name="comments" class="backref"
+ >Comments</a></h3>
+
+ <p>(<a href="../../ref/rst/restructuredtext.html#comments">details</a>)
+
+ <p>Any text which begins with an explicit markup start but doesn't
+ use the syntax of any of the constructs above, is a comment.
+
+ <p><table border="1" width="100%" bgcolor="#ffffcc" cellpadding="3">
+ <thead>
+ <tr align="left" bgcolor="#99CCFF">
+ <th width="50%">Plain text
+ <th width="50%">Typical result
+ </thead>
+ <tbody>
+ <tr valign="top">
+ <td><samp>.. This text will not be shown</samp>
+ <br><samp> (but, for instance, in HTML might be</samp>
+ <br><samp> rendered as an HTML comment)</samp>
+
+ <td>
+ <!-- This text will not be shown -->
+ <!-- (but, for instance in HTML might be -->
+ <!-- rendered as an HTML comment) -->
+
+ <tr valign="top">
+ <td>
+ <samp>An "empty comment" does not</samp>
+ <br><samp>consume following blocks.</samp>
+ <br><samp>(An empty comment is ".." with</samp>
+ <br><samp>blank lines before and after.)</samp>
+ <p><samp>..</samp>
+ <p><samp> So this block is not "lost",</samp>
+ <br><samp> despite its indentation.</samp>
+ <td>
+ An "empty comment" does not
+ consume following blocks.
+ (An empty comment is ".." with
+ blank lines before and after.)
+ <blockquote>
+ So this block is not "lost",
+ despite its indentation.
+ </blockquote>
+ </table>
+
+ <h2><a href="#contents" name="getting-help" class="backref"
+ >Getting Help</a></h2>
+
+ <p>Users who have questions or need assistance with Docutils or
+ reStructuredText should <a
+ href="mailto:docutils-users@lists.sourceforge.net" >post a
+ message</a> to the <a
+ href="http://lists.sourceforge.net/lists/listinfo/docutils-users"
+ >Docutils-Users mailing list</a>. The <a
+ href="http://docutils.sourceforge.net/" >Docutils project web
+ site</a> has more information.
+
+ <p><hr>
+ <address>
+ <p>Authors:
+ <a href="http://www.tibsnjoan.co.uk/">Tibs</a>
+ (<a href="mailto:tibs@tibsnjoan.co.uk"><tt>tibs@tibsnjoan.co.uk</tt></a>)
+ and David Goodger
+ (<a href="mailto:goodger@python.org">goodger@python.org</a>)
+ </address>
+ <!-- Created: Fri Aug 03 09:11:57 GMT Daylight Time 2001 -->
+ </body>
+</html>
--- /dev/null
+A ReStructuredText Primer
+=========================
+
+:Author: Richard Jones
+:Version: $Revision: 5801 $
+:Copyright: This document has been placed in the public domain.
+
+.. contents::
+
+
+The text below contains links that look like "(quickref__)". These
+are relative links that point to the `Quick reStructuredText`_ user
+reference. If these links don't work, please refer to the `master
+quick reference`_ document.
+
+__
+.. _Quick reStructuredText: quickref.html
+.. _master quick reference:
+ http://docutils.sourceforge.net/docs/user/rst/quickref.html
+
+.. Note:: This document is an informal introduction to
+ reStructuredText. The `What Next?`_ section below has links to
+ further resources, including a formal reference.
+
+
+Structure
+---------
+
+From the outset, let me say that "Structured Text" is probably a bit
+of a misnomer. It's more like "Relaxed Text" that uses certain
+consistent patterns. These patterns are interpreted by a HTML
+converter to produce "Very Structured Text" that can be used by a web
+browser.
+
+The most basic pattern recognised is a **paragraph** (quickref__).
+That's a chunk of text that is separated by blank lines (one is
+enough). Paragraphs must have the same indentation -- that is, line
+up at their left edge. Paragraphs that start indented will result in
+indented quote paragraphs. For example::
+
+ This is a paragraph. It's quite
+ short.
+
+ This paragraph will result in an indented block of
+ text, typically used for quoting other text.
+
+ This is another one.
+
+Results in:
+
+ This is a paragraph. It's quite
+ short.
+
+ This paragraph will result in an indented block of
+ text, typically used for quoting other text.
+
+ This is another one.
+
+__ quickref.html#paragraphs
+
+
+Text styles
+-----------
+
+(quickref__)
+
+__ quickref.html#inline-markup
+
+Inside paragraphs and other bodies of text, you may additionally mark
+text for *italics* with "``*italics*``" or **bold** with
+"``**bold**``". This is called "inline markup".
+
+If you want something to appear as a fixed-space literal, use
+"````double back-quotes````". Note that no further fiddling is done
+inside the double back-quotes -- so asterisks "``*``" etc. are left
+alone.
+
+If you find that you want to use one of the "special" characters in
+text, it will generally be OK -- reStructuredText is pretty smart.
+For example, this lone asterisk * is handled just fine, as is the
+asterisk in this equation: 5*6=30. If you actually
+want text \*surrounded by asterisks* to **not** be italicised, then
+you need to indicate that the asterisk is not special. You do this by
+placing a backslash just before it, like so "``\*``" (quickref__), or
+by enclosing it in double back-quotes (inline literals), like this::
+
+ ``*``
+
+__ quickref.html#escaping
+
+.. Tip:: Think of inline markup as a form of (parentheses) and use it
+ the same way: immediately before and after the text being marked
+ up. Inline markup by itself (surrounded by whitespace) or in the
+ middle of a word won't be recognized. See the `markup spec`__ for
+ full details.
+
+__ ../../ref/rst/restructuredtext.html#inline-markup
+
+
+Lists
+-----
+
+Lists of items come in three main flavours: **enumerated**,
+**bulleted** and **definitions**. In all list cases, you may have as
+many paragraphs, sublists, etc. as you want, as long as the left-hand
+side of the paragraph or whatever aligns with the first line of text
+in the list item.
+
+Lists must always start a new paragraph -- that is, they must appear
+after a blank line.
+
+**enumerated** lists (numbers, letters or roman numerals; quickref__)
+ __ quickref.html#enumerated-lists
+
+ Start a line off with a number or letter followed by a period ".",
+ right bracket ")" or surrounded by brackets "( )" -- whatever you're
+ comfortable with. All of the following forms are recognised::
+
+ 1. numbers
+
+ A. upper-case letters
+ and it goes over many lines
+
+ with two paragraphs and all!
+
+ a. lower-case letters
+
+ 3. with a sub-list starting at a different number
+ 4. make sure the numbers are in the correct sequence though!
+
+ I. upper-case roman numerals
+
+ i. lower-case roman numerals
+
+ (1) numbers again
+
+ 1) and again
+
+ Results in (note: the different enumerated list styles are not
+ always supported by every web browser, so you may not get the full
+ effect here):
+
+ 1. numbers
+
+ A. upper-case letters
+ and it goes over many lines
+
+ with two paragraphs and all!
+
+ a. lower-case letters
+
+ 3. with a sub-list starting at a different number
+ 4. make sure the numbers are in the correct sequence though!
+
+ I. upper-case roman numerals
+
+ i. lower-case roman numerals
+
+ (1) numbers again
+
+ 1) and again
+
+**bulleted** lists (quickref__)
+ __ quickref.html#bullet-lists
+
+ Just like enumerated lists, start the line off with a bullet point
+ character - either "-", "+" or "*"::
+
+ * a bullet point using "*"
+
+ - a sub-list using "-"
+
+ + yet another sub-list
+
+ - another item
+
+ Results in:
+
+ * a bullet point using "*"
+
+ - a sub-list using "-"
+
+ + yet another sub-list
+
+ - another item
+
+**definition** lists (quickref__)
+ __ quickref.html#definition-lists
+
+ Unlike the other two, the definition lists consist of a term, and
+ the definition of that term. The format of a definition list is::
+
+ what
+ Definition lists associate a term with a definition.
+
+ *how*
+ The term is a one-line phrase, and the definition is one or more
+ paragraphs or body elements, indented relative to the term.
+ Blank lines are not allowed between term and definition.
+
+ Results in:
+
+ what
+ Definition lists associate a term with a definition.
+
+ *how*
+ The term is a one-line phrase, and the definition is one or more
+ paragraphs or body elements, indented relative to the term.
+ Blank lines are not allowed between term and definition.
+
+
+Preformatting (code samples)
+----------------------------
+(quickref__)
+
+__ quickref.html#literal-blocks
+
+To just include a chunk of preformatted, never-to-be-fiddled-with
+text, finish the prior paragraph with "``::``". The preformatted
+block is finished when the text falls back to the same indentation
+level as a paragraph prior to the preformatted block. For example::
+
+ An example::
+
+ Whitespace, newlines, blank lines, and all kinds of markup
+ (like *this* or \this) is preserved by literal blocks.
+ Lookie here, I've dropped an indentation level
+ (but not far enough)
+
+ no more example
+
+Results in:
+
+ An example::
+
+ Whitespace, newlines, blank lines, and all kinds of markup
+ (like *this* or \this) is preserved by literal blocks.
+ Lookie here, I've dropped an indentation level
+ (but not far enough)
+
+ no more example
+
+Note that if a paragraph consists only of "``::``", then it's removed
+from the output::
+
+ ::
+
+ This is preformatted text, and the
+ last "::" paragraph is removed
+
+Results in:
+
+::
+
+ This is preformatted text, and the
+ last "::" paragraph is removed
+
+
+Sections
+--------
+
+(quickref__)
+
+__ quickref.html#section-structure
+
+To break longer text up into sections, you use **section headers**.
+These are a single line of text (one or more words) with adornment: an
+underline alone, or an underline and an overline together, in dashes
+"``-----``", equals "``======``", tildes "``~~~~~~``" or any of the
+non-alphanumeric characters ``= - ` : ' " ~ ^ _ * + # < >`` that you
+feel comfortable with. An underline-only adornment is distinct from
+an overline-and-underline adornment using the same character. The
+underline/overline must be at least as long as the title text. Be
+consistent, since all sections marked with the same adornment style
+are deemed to be at the same level::
+
+ Chapter 1 Title
+ ===============
+
+ Section 1.1 Title
+ -----------------
+
+ Subsection 1.1.1 Title
+ ~~~~~~~~~~~~~~~~~~~~~~
+
+ Section 1.2 Title
+ -----------------
+
+ Chapter 2 Title
+ ===============
+
+This results in the following structure, illustrated by simplified
+pseudo-XML::
+
+ <section>
+ <title>
+ Chapter 1 Title
+ <section>
+ <title>
+ Section 1.1 Title
+ <section>
+ <title>
+ Subsection 1.1.1 Title
+ <section>
+ <title>
+ Section 1.2 Title
+ <section>
+ <title>
+ Chapter 2 Title
+
+(Pseudo-XML uses indentation for nesting and has no end-tags. It's
+not possible to show actual processed output, as in the other
+examples, because sections cannot exist inside block quotes. For a
+concrete example, compare the section structure of this document's
+source text and processed output.)
+
+Note that section headers are available as link targets, just using
+their name. To link to the Lists_ heading, I write "``Lists_``". If
+the heading has a space in it like `text styles`_, we need to quote
+the heading "```text styles`_``".
+
+
+Document Title / Subtitle
+`````````````````````````
+
+The title of the whole document is distinct from section titles and
+may be formatted somewhat differently (e.g. the HTML writer by default
+shows it as a centered heading).
+
+To indicate the document title in reStructuredText, use a unique adornment
+style at the beginning of the document. To indicate the document subtitle,
+use another unique adornment style immediately after the document title. For
+example::
+
+ ================
+ Document Title
+ ================
+ ----------
+ Subtitle
+ ----------
+
+ Section Title
+ =============
+
+ ...
+
+Note that "Document Title" and "Section Title" above both use equals
+signs, but are distict and unrelated styles. The text of
+overline-and-underlined titles (but not underlined-only) may be inset
+for aesthetics.
+
+
+Images
+------
+
+(quickref__)
+
+__ quickref.html#directives
+
+To include an image in your document, you use the the ``image`` directive__.
+For example::
+
+ .. image:: images/biohazard.png
+
+results in:
+
+.. image:: images/biohazard.png
+
+The ``images/biohazard.png`` part indicates the filename of the image
+you wish to appear in the document. There's no restriction placed on
+the image (format, size etc). If the image is to appear in HTML and
+you wish to supply additional information, you may::
+
+ .. image:: images/biohazard.png
+ :height: 100
+ :width: 200
+ :scale: 50
+ :alt: alternate text
+
+See the full `image directive documentation`__ for more info.
+
+__ ../../ref/rst/directives.html
+__ ../../ref/rst/directives.html#images
+
+
+What Next?
+----------
+
+This primer introduces the most common features of reStructuredText,
+but there are a lot more to explore. The `Quick reStructuredText`_
+user reference is a good place to go next. For complete details, the
+`reStructuredText Markup Specification`_ is the place to go [#]_.
+
+Users who have questions or need assistance with Docutils or
+reStructuredText should post a message to the Docutils-users_ mailing
+list.
+
+.. [#] If that relative link doesn't work, try the master document:
+ http://docutils.sourceforge.net/docs/ref/rst/restructuredtext.html.
+
+.. _reStructuredText Markup Specification:
+ ../../ref/rst/restructuredtext.html
+.. _Docutils-users: ../mailing-lists.html#docutils-users
+.. _Docutils project web site: http://docutils.sourceforge.net/
--- /dev/null
+.. include:: <s5defs.txt>
+
+=================================
+ Easy Slide Shows With reST & S5
+=================================
+
+:Authors: David Goodger & Chris Liechti
+:Date: $Date: 2006-03-30 16:29:59 +0200 (Do, 30. Mär 2006) $
+
+.. This document has been placed in the public domain.
+
+.. container:: handout
+
+ How to create quick, good-looking presentation slide shows with
+ Docutils_/reStructuredText_ and S5_.
+
+ This document serves both as a user manual and as a usage example
+ of the s5_html.py writer and the rst2s5.py front end.
+
+ To view this document as a slide show see
+ http://docutils.sf.net/docs/user/slide-shows.s5.html (or `your
+ local copy <slide-shows.s5.html>`__).
+
+.. contents::
+ :class: handout
+
+.. class:: tiny
+
+* S5 themes are designed for full-screen display areas with a 4:3
+ aspect ratio. If the slide text doesn't fit in your browser window,
+ try decreasing the text size.
+
+* Use the space bar to advance, Page Up/Down & arrow keys to navigate.
+
+* Best viewed in Firefox_, Safari, and Konqueror. Click the "|mode|"
+ button to switch between presentation & handout/outline modes. Hit
+ the "C" key to display the navigation controls, or mouse over the
+ lower right-hand corner.
+
+* Functionality is limited in Opera. Switch to full-screen mode (F11
+ key) to activate Opera Show.
+
+* S5 works in Internet Explorer, but it may look ugly.
+
+.. container:: handout
+
+ The first slide of a presentation consists of all visible text up
+ to the first section title. The document title is also added to
+ the footer of all slides.
+
+ The "footer" directive is used to specify part of the slide footer
+ text. It is currently limited to one short line (one paragraph).
+
+ There is no support for the "header" directive in the themes
+ included with Docutils.
+
+.. _Docutils: http://docutils.sourceforge.net/
+.. _reStructuredText: http://docutils.sourceforge.net/rst.html
+.. _S5: http://meyerweb.com/eric/tools/s5/
+.. _Firefox: http://www.mozilla.com/firefox/
+.. |bullet| unicode:: U+02022
+.. |mode| unicode:: U+00D8 .. capital o with stroke
+
+.. footer:: Location |bullet| Date
+
+
+Introduction
+============
+
+.. class:: handout
+
+ ``rst2s5.py`` is a Docutils_ front end that outputs HTML for use
+ with S5_, a "Simple Standards-based Slide Show System" by Eric
+ Meyer.
+
+.. topic:: Installation
+ :class: handout
+
+ Prerequisites: Python and the Docutils_ package have to be
+ installed. See the `Docutils README`__ file for installation
+ instructions.
+
+ __ http://docutils.sourceforge.net/README.html
+
+* reStructuredText
+
+ .. class:: handout
+
+ Uses normal reStructuredText as input.
+
+* One section per slide
+
+ .. class:: handout
+
+ Each first-level section is converted into a single slide.
+
+* XHTML output
+
+ .. container:: handout
+
+ Presentations can be viewed using most modern graphical web
+ browsers. The browser must support CSS, JavaScript, and XHTML.
+ S5 even works with IE!
+
+ S5 was designed to add the functionality of the `Opera Show`_
+ standard (without Opera Show's limitations) to non-Opera
+ browsers. Unfortunately, most of S5's CSS and JavaScript
+ extensions don't function in the Opera browser.
+
+ .. _Opera Show: http://www.opera.com/support/tutorials/operashow/
+
+* Themes
+
+ .. class:: handout
+
+ A variety of themes are available. See `Example Themes`_, below.
+
+* ``rst2s5.py``
+
+ .. class:: handout
+
+ The front-end tool to generate S5 slide shows.
+
+.. topic:: Keyboard Controls
+ :class: handout
+
+ The following apply in any supporting browser besides Opera, which
+ uses the default Opera Show controls instead.
+
+ .. list-table::
+ :header-rows: 1
+
+ * - Action
+ - Key(s)
+ * - Go to the next slide
+ - * [Space bar]
+ * [Return]
+ * [Enter]
+ * [Right arrow]
+ * [Down arrow]
+ * [Page down]
+ * Click the left mouse button outside of the control area,
+ Flash object, or movie
+ * - Go to the previous slide
+ - * [Left arrow]
+ * [Up arrow]
+ * [Page up]
+ * - Go to the title (first) slide
+ - [Home]
+ * - Go to the last slide
+ - [End]
+ * - Jump directly to a slide
+ - Type the slide number, then hit [Return] or [Enter]
+ * - Skip forward *n* slides
+ - Type the number of slides to skip, then hit any "go to next"
+ key (except [Return] or [Enter])
+ * - Skip backward *n* slides
+ - Type the number of slides to skip, then hit any "go to
+ previous" key
+ * - Switch between slideshow and outline view
+ - * [T]
+ * Click the |mode| button
+ * - Show/hide slide controls
+ - * [C]
+ * Move the mouse pointer over the control area
+
+ Further details of the S5 user interface can be found at `Eric
+ Meyer's S5 page`__.
+
+ __ S5_
+
+
+Features (1)
+============
+
+.. container:: handout
+
+ The S5/HTML Writer supports all the standard Docutils HTML
+ features. S5 has been released to the Public Domain.
+
+S5-specific features:
+
+.. class:: incremental
+
+* The document title is duplicated on each slide in the S5 footer.
+
+* The ``footer`` directive may be used to define additional text in
+ the S5 footer.
+
+ .. container:: handout
+
+ But it is limited to one line of text.
+
+ This is useful for information such as the date of the
+ presentation and/or the location. The field in the footer is
+ left blank if no ``footer`` directive is used.
+
+ Example::
+
+ .. footer:: Location - Date
+
+ There is also a progress indicator (slide counter) in the footer
+ that can be enabled. It's disabled by default.
+
+* Incremental display.
+
+ .. class:: handout
+
+ An "incremental" class can be assigned to lists and other elements
+ to get one-item-at-a-time behavior (like this list). Incremental
+ display does not work in the Opera browser.
+
+* Text auto-scaling.
+
+ .. class:: handout
+
+ The text size adjusts relative to the size of your browser window
+ automatically. You may need to reload the document after resizing
+ the window. The browser and platform affect the font used; be sure
+ to test the slide show on the presentation system.
+
+
+Features (2): Handouts
+======================
+
+.. container:: handout
+
+ The contents of any element with a "class" attribute value of
+ "handout" are hidden in the slide presentation, and are only
+ visible when the presentation is printed, or viewed in outline
+ mode. "Handout"-class elements can appear anywhere in the text, as
+ often as needed.
+
+ This means that the slides and extra handout material can be
+ combined in one document. The handout can be printed directly from
+ the browser, and it will contain more than just silly framed
+ slides. This can be used to provide more detailed information, or
+ for speaker's notes.
+
+.. class:: incremental
+
+* Use the "class" directive::
+
+ .. class:: handout
+
+ .. container:: handout
+
+ The ``.. class:: handout`` directive can be used to tag
+ individual paragraphs and other elements. The "class" directive
+ applies to the first element immediately following::
+
+ .. class:: handout
+
+ This paragraph will get a
+ ``class="handout"`` attribute.
+
+ This paragraph will not be affected.
+
+ It also applies to multiple elements in the directive content::
+
+ .. class:: handout
+
+ These paragraphs are the content
+ of the "class" directive. And as such...
+
+ Both paragraphs will *individually* receive
+ ``class="handout"`` attributes.
+
+* Use the "container" directive::
+
+ .. container:: handout
+
+ .. container:: handout
+
+ Arbitrary handout blocks can be created using the ``container``
+ directive. The content is treated as one.
+
+* Use the "class" option of directives that support it::
+
+ .. topic:: Extra Material For Handouts
+ :class: handout
+
+.. container:: handout
+
+ The following directives support "class" options:
+
+ * all admonition directives ("admonition", "note", "hint", etc.)
+ * "image" & "figure"
+ * "topic"
+ * "sidebar"
+ * "line-block"
+ * "parsed-literal"
+ * "rubric"
+ * "compound"
+ * "table", "csv-table", & "list-table"
+ * "target-notes" (more about that below)
+ * "role" (pre-defined; more below)
+
+ Handout contents are also visible on the screen if the S5 view mode
+ is toggled from "slide show" to "outline" mode.
+
+
+Caveats
+=======
+
+.. class:: incremental
+
+1. Some Docutils features are not supported by some themes.
+
+ .. container:: handout
+
+ For example, header rendering is not supported by the themes
+ supplied with Docutils.
+
+ The "header" directive is used to set header text. S5
+ automatically inserts section/slide titles into the "header"
+ area of a slide. If both Docutils headers and S5 headers (slide
+ titles) exist simultaneously, they interfere with each other.
+
+2. Care must be taken with the "contents" directive.
+
+ .. container:: handout
+
+ The ``--no-toc-backlinks`` option is the default for the S5/HTML
+ writer (``toc_backlinks=0`` setting). Other values for this
+ setting will change the CSS class of headings such that they
+ won't show up correctly in the slide show.
+
+ Use the ``:class: handout`` option on the "contents" directive
+ to limit the table of contents to the handout/outline mode
+ only::
+
+ .. contents::
+ :class: handout
+
+
+.. class:: incremental
+
+3. Subsections ...
+------------------
+
+... may be used, sparingly.
+
+.. container:: handout
+
+ Only first-level sections become slides. Not many levels of
+ subsections can fit on a slide.
+
+ Subsections (of any level) work normally in handouts though. Add
+ "``.. class:: handout``" before a subsection (or sub-subsection, or
+ ...), and the entire subsection will only appear in the handout.
+
+
+Generating a Slide Show (1)
+===========================
+
+.. class:: incremental
+
+1. Open a console (terminal, command shell) and go to the folder
+ containing your file, ``slides.txt``.
+
+2. Run the command::
+
+ rst2s5.py slides.txt slides.html
+
+3. Specify an S5 theme with the ``--theme`` option.
+
+ .. class:: handout
+
+ Docutils will copy the S5 theme files into a ``ui/<theme>`` folder
+ beside the output HTML file. A slide show can also link to an
+ existing theme using the ``--theme-url`` option.
+
+
+Generating a Slide Show (2)
+===========================
+
+.. class:: incremental
+
+4. Include a copy of any linked stylesheet.
+
+ .. class:: handout
+
+ The default Docutils stylesheet, ``html4css1.css``, will normally
+ be embedded in the output HTML. If you choose to link to a
+ stylesheet instead of embedding, you must include a copy (suggested
+ location: in the ``ui/`` directory).
+
+5. Open ``slides.html`` in a web browser.
+
+6. Expand the browser window to full-screen mode, and speak.
+
+ .. class:: handout
+
+ The `Web Developer`__ extension for Firefox is very useful. With
+ it, you can resize your browser window to the exact dimensions of
+ the projector you'll be using, so you can test beforehand. There
+ are many other useful features as well.
+
+ __ http://chrispederick.com/work/webdeveloper/
+
+7. Profit!
+
+
+Examples (1)
+============
+
+.. sidebar:: Hint
+
+ Admonitions, tables, sidebars, and other elements can be used in
+ on-screen presentations in handouts. Images too!
+
+ .. image:: images/happy_monkey.png
+ :alt: sample image
+
+===== ===== ======
+ A B A or B
+===== ===== ======
+False False False
+True False True
+False True True
+True True True
+===== ===== ======
+
+
+Examples (2): Incremental Text
+==============================
+
+.. class:: incremental
+
+ Paragraphs can be displayed one at a time...
+
+ .. container::
+
+ ... or a bunch at a time.
+
+ This second paragraph is displayed together with the previous
+ one by grouping them with the "container" directive.
+
+`We can also display` `one` `word` `at` `a` `time,`
+`or a phrase` `at a time,`
+`or even` `o`\ `n`\ `e` `l`\ `e`\ `t`\ `t`\ `e`\ `r` `at a time!`
+
+`(But the markup ain't pretty.)`
+
+
+Examples (3): Incr. Graphics
+============================
+
+Let's play... Rock, Scissors, Paper
+
+.. container:: animation
+
+ .. image:: images/rsp-empty.png
+ :class: hidden slide-display
+
+ .. class:: incremental hidden slide-display
+
+ .. image:: images/rsp-objects.png
+ .. image:: images/rsp-cuts.png
+ .. image:: images/rsp-covers.png
+ .. image:: images/rsp-breaks.png
+
+ .. image:: images/rsp-all.png
+ :class: incremental
+
+
+Themes
+======
+
+.. class:: incremental
+
+* Several themes are available, and they're easy to adapt.
+
+ .. container:: handout
+
+ Themes from the `S5 tutorial`__ can be used. These themes are in
+ the public domain and may be redistributed freely.
+
+ __ http://meyerweb.com/eric/tools/s5/s5blank.zip
+
+ Sites with other S5 themes:
+
+ * http://meyerweb.com/eric/tools/s5/themes/
+ * http://mozilla.wikicities.com/wiki/Firefox_S5:Designs
+ * http://lachy.id.au/dev/mozilla/firefox/s5/
+ * http://www.openlight.com/Python-S5-Theme.tar.gz
+
+ S5 is becoming more popular every day. Do a web search for "S5
+ theme" and you're bound to find plenty of choices.
+
+* "``--theme``" option.
+
+ .. container:: handout
+
+ The theme can be specified with the "``--theme``" command-line
+ option.
+
+ Example::
+
+ rst2s5 --theme big-black slides.txt slides.html
+
+ The default theme is "default".
+
+* "``theme``" setting.
+
+ .. class:: handout
+
+ You can set the theme with the "``theme``" configuration file
+ setting.
+
+* Copied to ``./ui/<theme>/``.
+
+ .. class:: handout
+
+ Themes are copied into a ``ui/<theme>`` folder inside the folder
+ containing the presentation.
+
+* Link with "``--theme-url``" option.
+
+ .. class:: handout
+
+ Link to a theme on the same or another web site, using the
+ "``--theme-url``" option or "``theme_url``" configuration file
+ setting.
+
+
+Example Themes
+==============
+
+.. class:: handout
+
+ The default theme, "default", is a simplified version of S5's
+ default theme. It accommodates up to 13 lines of text.
+
+.. class:: center
+
+ "default"
+
+ .. image:: images/default.png
+ :align: center
+
+
+Example Themes: Small Text
+==========================
+
+.. class:: handout
+
+ The "small-white" and "small-black" themes are simplifications of
+ the default theme (**small** black text on a **white** background,
+ and **small** black text on a **white** background, respectively).
+ They each accommodate up to 15 lines of text.
+
+.. list-table::
+ :class: borderless
+
+ * - "small-white"
+
+ .. image:: images/small-white.png
+
+ - "small-black"
+
+ .. image:: images/small-black.png
+
+
+Example Themes: Large Text
+==========================
+
+.. class:: handout
+
+ The "big-white" and "big-black" themes feature very large, bold
+ text, with no footers. Only five short lines fit in a slide.
+
+.. list-table::
+ :class: borderless
+
+ * - "big-white"
+
+ .. image:: images/big-white.png
+
+ - "big-black"
+
+ .. image:: images/big-black.png
+
+
+Example Themes: Medium Text
+===========================
+
+.. class:: handout
+
+ The "medium-white" and "medium-black" themes feature medium-sized
+ text. Up to 8 lines of text are accommodated.
+
+.. list-table::
+ :class: borderless
+
+ * - "medium-white"
+
+ .. image:: images/medium-white.png
+
+ - "medium-black"
+
+ .. image:: images/medium-black.png
+
+
+S5 Theme Files
+==============
+
+An S5 theme consists of a directory containing several files --
+stylesheets, JavaScript, and graphics:
+
+.. image:: images/s5-files.png
+ :align: center
+
+.. container:: handout
+
+ The generated HTML contains the entire slide show text. It also
+ contains links to the following files:
+
+ * slides.css simply contains import links to:
+
+ - s5-core.css: Default styles critical to the proper functioning
+ of the slide show; don't touch this!
+
+ - framing.css: Sets the basic layout of slide components (header,
+ footer, controls, etc. This file is the often edited.
+
+ - pretty.css: Presentation styles that give the slide show a
+ unique look and feel. This is the file that you're most likely
+ to edit for a custom theme. You can make a whole new theme
+ just by editing this file, and not touching the others.
+
+ * outline.css: Styles for outline mode.
+
+ * print.css: Styles for printing; hides most layout elements, and
+ may display others.
+
+ * opera.css: Styles necessary for the proper functioning of S5 in
+ Opera Show.
+
+ * slides.js: the JavaScript that drives the dynamic side of the
+ slide show (actions and navigation controls). It automatically
+ IDs the slides when the document loads, builds the navigation
+ menu, handles the hiding and showing of slides, and so on. The
+ code also manages the fallback to Opera Show if you're using
+ the Opera web browser.
+
+ Two files are included to support PNG transparency (alpha
+ channels) in Internet Explorer:
+
+ - iepngfix.htc
+ - blank.gif
+
+
+Making a Custom Theme
+=====================
+
+.. class:: incremental
+
+1. Run "``rst2s5.py --theme <base-theme> <doc>.txt <doc>.html``".
+
+ .. class:: handout
+
+ This initializes the ``ui`` directory with the base theme files.
+
+2. Copy ``ui/<base-theme>`` to ``ui/<new-theme>``.
+
+3. Edit the styles.
+
+ .. class:: handout
+
+ Start with ``pretty.css``; edit ``framing.css`` if you need to make
+ layout changes.
+
+4. Run "``rst2s5.py --theme-url ui/<new-theme> <doc>.txt <doc>.html``".
+
+ .. class:: handout
+
+ We use the ``--theme-url`` option to refer to the new theme. Open
+ your ``<doc>.html`` in a browser to test the new theme.
+
+5. Rinse & repeat.
+
+ .. class:: handout
+
+ Repeat from step 3 until you're satisfied.
+
+.. TODO: What to do next:
+
+ * add a ``__base__`` file
+ * create a personal reusable theme (plugin)
+ * submit the new theme to Docutils
+
+ ``docutils/writers/s5_html/themes/<theme>``
+
+.. container:: handout
+
+ Resources:
+
+ * W3C's `Learning CSS <http://www.w3.org/Style/CSS/learning>`__
+
+ * `Creating An S5 Theme <http://home.cogeco.ca/~ve3ll/s5themes.htm>`__
+
+ * A short tutorial on how to create themes (in German):
+ `Eigenes Theme erstellen <http://yatil.de/s5/dokumentation/9/>`__
+
+
+Classes: Incremental (1)
+========================
+
+.. class:: handout
+
+ Several "class" attribute values have built-in support in the
+ themes supplied with Docutils.
+
+.. class:: incremental
+
+ As described earlier,
+
+ * ``.. class:: incremental``
+
+ * ``.. container:: incremental``
+
+ * ::
+
+ .. sidebar:: title
+ :class: incremental
+
+
+Classes: Incremental (2)
+========================
+
+The "incremental" interpreted text role is also supported:
+
+.. class:: incremental
+
+ ::
+
+ :incremental:`This will appear first,` `and
+ this will appear second.`:incremental:
+
+ Requires "``.. include:: <s5defs.txt>``".
+
+.. container:: handout
+
+ As you can see, this markup is not very convenient.
+
+.. class:: incremental
+
+ | But ``s5defs.txt`` includes this useful definition:
+ | "``.. default-role:: incremental``". So:
+
+ ::
+
+ `This` `is` `all` `we` `need`
+
+`This` `is` `all` `we` `need` `to mark up incremental text.`
+
+
+Classes: Incremental (3)
+========================
+
+.. class:: small
+
+::
+
+ .. container:: animation
+
+ .. image:: images/empty.png
+ :class: hidden slide-display
+
+ .. class:: incremental hidden slide-display
+
+ .. image:: images/1.png
+ .. image:: images/2.png
+
+ .. image:: images/3.png
+ :class: incremental
+
+.. container:: handout
+
+ This is how the example works.
+
+ The animation effects are caused by placing successive images at
+ the same location, laying each image over the last. For best
+ results, all images should be the same size, and the positions of
+ image elements should be consistent. Use image transparency (alpha
+ channels) to get overlay effects.
+
+ Absolute positioning is used, which means that the images take up
+ no space in the flow. If you want text to follow the images, you
+ have to specify the total size of the container via a style.
+ Otherwise, the images and any following text will overlap.
+
+ These class values do the work:
+
+ animation
+ This wraps the container with styles that position the images
+ absolutely, overlaying them over each other. Only useful on a
+ container.
+
+ hidden
+ Unless overridden (by "slide-display", for example), these
+ elements will not be displayed. Only the last image will be
+ displayed in handout mode, when print, or when processed to
+ ordinary HTML, because it does *not* carry a "hidden" class.
+
+ slide-display
+ In conjunction with "hidden", these elements will only appear
+ on the slide, preventing clutter in the handout.
+
+ incremental
+ The second and subsequent images will appear one at a time.
+ The first image will already be present when the slide is
+ displayed, because it does *not* carry an "incremental" class.
+
+
+Classes: Text Size
+==================
+
+.. class:: incremental
+
+ * :tiny:`tiny` (class & role name: "tiny", e.g. "``:tiny:`text```")
+ * :small:`small` ("small")
+ * normal (unstyled)
+ * :big:`big` ("big")
+ * :huge:`huge` ("huge")
+
+ Requires "``.. include:: <s5defs.txt>``".
+
+
+Classes: Alignment
+==================
+
+.. class:: incremental
+
+ .. class:: left
+
+ Left (class name: "left")
+
+ .. class:: center
+
+ Center ("center" & "centre")
+
+ .. class:: right
+
+ Right ("right")
+
+.. class:: handout
+
+ These classes apply to block-level elements only. They cannot be
+ used for inline text (i.e., they're not interpreted text roles).
+
+.. class:: incremental
+
+ Example::
+
+ .. class:: center
+
+ Text to be centered.
+
+
+Classes: Text Colours
+=====================
+
+:black:`black` [black], :gray:`gray`, :silver:`silver`, :white:`white`
+[white], :maroon:`maroon`, :red:`red`, :magenta:`magenta`,
+:fuchsia:`fuchsia`, :pink:`pink`, :orange:`orange`, :yellow:`yellow`,
+:lime:`lime`, :green:`green`, :olive:`olive`, :teal:`teal`,
+:cyan:`cyan`, :aqua:`aqua`, :blue:`blue`, :navy:`navy`,
+:purple:`purple`
+
+The class names and role names are the same as the colour names. For
+example, "``:orange:`text```" produces ":orange:`text`".
+
+.. class:: incremental
+
+Requires "``.. include:: <s5defs.txt>``".
+
+
+Classes: Borderless Tables
+==========================
+
+.. class:: handout
+
+ Here's an ordinary, unstyled table:
+
+.. class:: incremental
+
+ ========= =======
+ Sometimes borders
+ --------- -------
+ are useful.
+ ========= =======
+
+ And after applying "``.. class:: borderless``":
+
+ .. class:: borderless
+
+ ======= ========== =======
+ But sometimes, borders
+ ------- ---------- -------
+ are **not** wanted.
+ ======= ========== =======
+
+
+Classes: Print-Only
+===================
+
+.. class:: handout
+
+ Elements with ``class="print"`` attributes display their contents
+ when printed, overriding ``class="hidden"``.
+
+.. class:: incremental
+
+ Example: the "target-notes" directive::
+
+ .. topic:: Links
+ :class: hidden print
+
+ .. target-notes::
+ :class: hidden print
+
+.. container:: handout
+
+ One good example, used in this document, is the "target-notes"
+ directive. For each external target (hyperlink) in the text, this
+ directive generates a footnote containing the visible URL as
+ content. Footnote references are placed after each hyperlink
+ reference.
+
+ The "topic" directive is given a "class" attribute with values
+ "hidden" and "print", so the entire topic will only be displayed
+ when printed. The "target-notes" directive also assigns a "class"
+ attributes with values "hidden" and "print" to each of the footnote
+ references it inserts throughout the text; they will only show up
+ when printed.
+
+.. class:: incremental
+
+ Other uses may require "``.. include:: <s5defs.txt>``".
+
+
+Useful Extensions For Firefox
+=============================
+
+* `Autohide`__
+
+ .. class:: handout
+
+ Automatically hides toolbars in full-screen mode.
+
+ __ http://www.krickelkrackel.de/autohide/autohide.htm
+
+* `Web Developer`__
+
+ .. class:: handout
+
+ Adds a context submenu and a toolbar with a lot of useful
+ functionality, including the viewing and live editing of
+ stylesheets, and sizing the browser window.
+
+ __ http://chrispederick.com/work/webdeveloper/
+
+
+To Do
+=====
+
+.. class:: incremental
+
+ * Multi-display support:
+
+ - speaker's notes on the laptop screen
+ - slides on the projector
+ - two views stay in sync
+ - presentation controlled from either display
+
+ * Add timeout to incremental style.
+
+ .. class:: handout
+
+ I.e., incremental-specific style should go away (revert to
+ normal) after a certain interval.
+
+ These will require some serious JavaScript-fu!
+
+
+That's All, Folks!
+==================
+
+.. class:: huge
+
+ Further information:
+ http://docutils.sf.net
+
+ Docutils users' mailing list:
+ docutils-users@lists.sf.net
+
+ `Any questions?`
+
+
+.. topic:: Links
+ :class: hidden print
+
+ .. target-notes:: :class: hidden print
--- /dev/null
+=========================
+Smart Quotes for Docutils
+=========================
+
+:Author: Günter Milde,
+ based on SmartyPants by John Gruber, Brad Choate, and Chad Miller
+:Contact: docutils-develop@lists.sourceforge.net
+:Revision: $Revision: 8405 $
+:Date: $Date: 2019-10-29 23:48:16 +0100 (Di, 29. Okt 2019) $
+:License: Released under the terms of the `2-Clause BSD license`_
+:Abstract: This document describes the Docutils `smartquotes` module.
+
+.. _2-Clause BSD license: http://www.spdx.org/licenses/BSD-2-Clause
+
+.. contents::
+
+Description
+===========
+
+The `"smart_quotes" configuration setting`_ triggers the SmartQuotes
+transformation on Text nodes that includes the following steps:
+
+- Straight quotes (``"`` and ``'``) into "curly" quote characters
+- dashes (``--`` and ``---``) into en- and em-dash entities
+- three consecutive dots (``...`` or ``. . .``) into an ellipsis entity.
+
+This means you can write, edit, and save your documents using plain old
+ASCII -- straight quotes, plain dashes, and plain dots -- while Docutils
+generates documents with typographical quotes, dashes, and ellipses.
+
+Advantages:
+
+* Typing speed (especially when blind-typing).
+* The possibility to change the quoting style of the
+ complete document with just one configuration option.
+* Typographical quotes with just 7-bit ASCII characters in the source.
+
+However, there are `algorithmic shortcomings`_ for 2 reasons:
+
+* Dual use of the "ASCII-apostrophe" (') as single quote and apostrophe.
+* Languages that do not use whitespace around words.
+
+So, please consider also
+`Why You Might Not Want to Use "Smart" Quotes in Your Documents`_.
+
+.. _"smart_quotes" configuration setting:
+.. _"smart_quotes" setting: config.html#smart-quotes
+
+
+Escaping
+========
+
+The `SmartQuotes` transform does not modify characters in literal text
+such as source code, maths, or literal blocks.
+
+If you need literal straight quotes (or plain hyphens and periods) in normal
+text, you can `backslash escape`_ the characters to preserve
+ASCII-punctuation.
+
+.. class:: booktabs
+
+========= ========= == ======== ==========
+Input Output Input Output
+========= ========= == ======== ==========
+``\\`` \\ ``\...`` \...
+``\"`` \" ``\--`` \--
+``\'`` \' ``\``` \`
+========= ========= == ======== ==========
+
+This is useful, for example, when you want to use straight quotes as
+foot and inch marks:
+
+ 6\'2\" tall; a 17\" monitor.
+
+.. _backslash escape: ../ref/rst/restructuredtext.html#escaping-mechanism
+
+
+Localization
+============
+
+Quotation marks have a `variety of forms`__ in different languages and
+media.
+
+__ https://en.wikipedia.org/wiki/Quotation_mark#Summary_table
+
+`SmartQuotes` inserts quotation marks depending on the language of the
+current block element and the value of the `"smart_quotes" setting`_.\
+[#x-altquot]_
+There is built-in support for the following languages:\ [#smartquotes-locales]_
+
+:af: .. class:: language-af
+
+ "'Afrikaans' quotes"
+
+:af-x-altquot: .. class:: language-af-x-altquot
+
+ "'Afrikaans' alternative quotes"
+
+:ca: .. class:: language-ca
+
+ "'Catalan' quotes"
+
+:ca-x-altquot: .. class:: language-ca-x-altquot
+
+ "'Catalan' alternative quotes"
+
+:cs: .. class:: language-cs
+
+ "'Czech' quotes"
+
+:cs-x-altquot: .. class:: language-cs-x-altquot
+
+ "'Czech' alternative quotes"
+
+:da: .. class:: language-da
+
+ "'Danish' quotes"
+
+:da-x-altquot: .. class:: language-da-x-altquot
+
+ "'Danish' alternative quotes"
+
+:de: .. class:: language-de
+
+ "'German' quotes"
+
+:de-x-altquot: .. class:: language-de-x-altquot
+
+ "'German' alternative quotes"
+
+:de-ch: .. class:: language-de-ch
+
+ "'Swiss-German' quotes"
+
+:el: .. class:: language-el
+
+ "'Greek' quotes"
+
+:en: .. class:: language-en
+
+ "'English' quotes"
+
+:en-uk-x-altquot: .. class:: language-en-uk-x-altquot
+
+ "'British' alternative quotes"
+ (swaps single and double quotes: ``"`` → ‘ and ``'`` → “)
+
+:eo: .. class:: language-eo
+
+ "'Esperanto' quotes"
+
+:es: .. class:: language-es
+
+ "'Spanish' quotes"
+
+:es-x-altquot: .. class:: language-es-x-altquot
+
+ "'Spanish' alternative quotes"
+
+:et: .. class:: language-et
+
+ "'Estonian' quotes" (no secondary quote listed in Wikipedia)
+
+:et-x-altquot: .. class:: language-et-x-altquot
+
+ "'Estonian' alternative quotes"
+
+:eu: .. class:: language-eu
+
+ "'Basque' quotes"
+
+:fi: .. class:: language-fi
+
+ "'Finnish' quotes"
+
+:fi-x-altquot: .. class:: language-fi-x-altquot
+
+ "'Finnish' alternative quotes"
+
+:fr: .. class:: language-fr
+
+ "'French' quotes"
+
+:fr-x-altquot: .. class:: language-fr-x-altquot
+
+ "'French' alternative quotes"
+
+:fr-ch: .. class:: language-fr-ch
+
+ "'Swiss-French' quotes"
+
+:fr-ch-x-altquot: .. class:: language-fr-ch-x-altquot
+
+ "'Swiss-French' alternative quotes" (narrow no-break space, see
+ http://typoguide.ch/)
+
+:gl: .. class:: language-gl
+
+ "'Galician' quotes"
+
+:he: .. class:: language-he
+
+ "'Hebrew' quotes"
+
+:he-x-altquot: .. class:: language-he-x-altquot
+
+ "'Hebrew' alternative quotes"
+
+:hr: .. class:: language-hr
+
+ "'Croatian' quotes"
+
+:hr-x-altquot: .. class:: language-hr-x-altquot
+
+ "'Croatian' alternative quotes"
+
+:hsb: .. class:: language-hsb
+
+ "'Upper Sorbian' quotes"
+
+:hsb-x-altquot: .. class:: language-hsb-x-altquot
+
+ "'Upper Sorbian' alternative quotes"
+
+:hu: .. class:: language-hu
+
+ "'Hungarian' quotes"
+
+:is: .. class:: language-is
+
+ "'Icelandic' quotes"
+
+:it: .. class:: language-it
+
+ "'Italian' quotes"
+
+:it-ch: .. class:: language-it-ch
+
+ "'Swiss-Italian' quotes"
+
+:it-x-altquot: .. class:: language-it-x-altquot
+
+ "'Italian' alternative quotes"
+
+:ja: .. class:: language-ja
+
+ "'Japanese' quotes"
+
+:lt: .. class:: language-lt
+
+ "'Lithuanian' quotes"
+
+:lv: .. class:: language-lv
+
+ "'Latvian' quotes"
+
+:nl: .. class:: language-nl
+
+ "'Dutch' quotes"
+
+:nl-x-altquot: .. class:: language-nl-x-altquot
+
+ "'Dutch' alternative quotes"
+
+.. # 'nl-x-altquot2': u'””’’',
+
+:pl: .. class:: language-pl
+
+ "'Polish' quotes"
+
+:pl-x-altquot: .. class:: language-pl-x-altquot
+
+ "'Polish' alternative quotes"
+
+:pt: .. class:: language-pt
+
+ "'Portuguese' quotes"
+
+:pt-br: .. class:: language-pt-br
+
+ "'Portuguese (Brazil)' quotes"
+
+:ro: .. class:: language-ro
+
+ "'Romanian' quotes"
+
+:ru: .. class:: language-ru
+
+ "'Russian' quotes"
+
+:sh: .. class:: language-sh
+
+ "'Serbo-Croatian' quotes"
+
+:sh-x-altquot: .. class:: language-sh-x-altquot
+
+ "'Serbo-Croatian' alternative quotes"
+
+:sk: .. class:: language-sk
+
+ "'Slovak' quotes"
+
+:sk-x-altquot: .. class:: language-sk-x-altquot
+
+ "'Slovak' alternative quotes"
+
+:sl: .. class:: language-sl
+
+ "'Slovenian' quotes"
+
+:sl-x-altquot: .. class:: language-sl-x-altquot
+
+ "'Slovenian' alternative quotes"
+
+:sr: .. class:: language-sr
+
+ "'Serbian' quotes"
+
+:sr-x-altquot: .. class:: language-sr-x-altquot
+
+ "'Serbian' alternative quotes"
+
+:sv: .. class:: language-sv
+
+ "'Swedish' quotes"
+
+:sv-x-altquot: .. class:: language-sv-x-altquot
+
+ "'Swedish' alternative quotes"
+
+:tr: .. class:: language-tr
+
+ "'Turkish' quotes"
+
+:tr-x-altquot: .. class:: language-tr-x-altquot
+
+ "'Turkish' alternative quotes"
+
+.. 'tr-x-altquot2': u'“„‘‚', # antiquated?
+
+:uk: .. class:: language-uk
+
+ "'Ukrainian' quotes"
+
+:uk-x-altquot: .. class:: language-uk-x-altquot
+
+ "'Ukrainian' alternative quotes"
+
+:zh-cn: .. class:: language-zh-cn
+
+ "'Chinese (China)' quotes"
+
+:zh-tw: .. class:: language-zh-tw
+
+ "'Chinese (Taiwan)' quotes"
+
+Quotes in text blocks in a non-configured language are kept as plain quotes:
+
+:undefined: .. class:: language-undefined-example
+
+ "'Undefined' quotes"
+
+.. [#x-altquot] Tags with the non-standard extension ``-x-altquot`` define
+ the quote set used with the `"smart_quotes" setting`_ value ``"alt"``.
+
+.. [#smartquotes-locales] The definitions for language-dependend
+ typographical quotes can be extended or overwritten using the
+ `"smartquotes_locales" setting`_.
+
+ The following example ensures a correct leading apostrophe in ``'s
+ Gravenhage`` (at the cost of incorrect leading single quotes) in Dutch
+ and sets French quotes to double and single guillemets with inner
+ spacing::
+
+ smartquote-locales: nl: „”’’
+ fr: « : »:‹ : ›
+
+.. _"smartquotes_locales" setting: config.html#smartquotes-locales
+
+
+Caveats
+=======
+
+Why You Might Not Want to Use "Smart" Quotes in Your Documents
+--------------------------------------------------------------
+
+For one thing, you might not care.
+
+Most normal, mentally stable individuals do not take notice of proper
+typographic punctuation. Many design and typography nerds, however, break
+out in a nasty rash when they encounter, say, a restaurant sign that uses
+a straight apostrophe to spell "Joe's".
+
+If you're the sort of person who just doesn't care, you might well want to
+continue not caring. Using straight quotes -- and sticking to the 7-bit
+ASCII character set in general -- is certainly a simpler way to live.
+
+Even if you *do* care about accurate typography, you still might want to
+think twice before "auto-educating" the quote characters in your documents.
+As there is always a chance that the algorithm gets it wrong, you may
+instead prefer to use the compose key or some other means to insert the
+correct Unicode characters into the source.
+
+
+Algorithmic Shortcomings
+------------------------
+
+The ASCII character (u0027 APOSTROPHE) is used for apostrophe and single
+quotes. If used inside a word, it is converted into an apostrophe:
+
+ .. class:: language-fr
+
+ Il dit : "C'est 'super' !"
+
+At the beginning or end of a word, it cannot be distinguished from a single
+quote by the algorithm.
+
+The `right single quotation mark`_ character -- used to close a secondary
+(inner) quote in English -- is also "the preferred character to use for
+apostrophe" (Unicode_). Therefore, "educating" works as expected for
+apostrophes at the end of a word, e.g.,
+
+ Mr. Hastings' pen; three days' leave; my two cents' worth.
+
+However, when apostrophes are used at the start of leading contractions,
+"educating" will turn the apostrophe into an *opening* secondary quote. In
+English, this is *not* the apostrophe character, e.g., ``'Twas brillig``
+is "miseducated" to
+
+ 'Twas brillig.
+
+In other locales (French, Italian, German, ...), secondary closing quotes
+differ from the apostrophe. A text like::
+
+ .. class:: language-de-CH
+
+ "Er sagt: 'Ich fass' es nicht.'"
+
+becomes
+
+ «Er sagt: ‹Ich fass› es nicht.›»
+
+with a single closing guillemet in place of the apostrophe.
+
+In such cases, it's best to use the recommended apostrophe character (’) in
+the source:
+
+ | ’Twas brillig, and the slithy toves
+ | Did gyre and gimble in the wabe;
+ | All mimsy were the borogoves,
+ | And the mome raths outgrabe.
+
+.. _right single quotation mark:
+ http://www.fileformat.info/info/unicode/char/2019/index.htm
+.. _Unicode: http://www.unicode.org/charts/PDF/U2000.pdf
+
+History
+=======
+
+The smartquotes module is an adaption of "SmartyPants_" to Docutils.
+
+`John Gruber`_ did all of the hard work of writing this software in Perl for
+`Movable Type`_ and almost all of this useful documentation. `Chad Miller`_
+ported it to Python to use with Pyblosxom_.
+
+Portions of the SmartyPants original work are based on Brad Choate's nifty
+MTRegex plug-in. `Brad Choate`_ also contributed a few bits of source code to
+this plug-in. Brad Choate is a fine hacker indeed.
+`Jeremy Hedley`_ and `Charles Wiltgen`_ deserve mention for exemplary beta
+testing of the original SmartyPants.
+
+Internationalization and adaption to Docutils by Günter Milde.
+
+.. _SmartyPants: http://daringfireball.net/projects/smartypants/
+.. _Pyblosxom: http://pyblosxom.bluesock.org/
+.. _Movable Type: http://www.movabletype.org/
+.. _John Gruber: http://daringfireball.net/
+.. _Chad Miller: http://web.chad.org/
+.. _Brad Choate: http://bradchoate.com/
+.. _Jeremy Hedley: http://antipixel.com/
+.. _Charles Wiltgen: http://playbacktime.com/
+.. _Rael Dornfest: http://raelity.org/
--- /dev/null
+==========================
+ Docutils Front-End Tools
+==========================
+
+:Author: David Goodger
+:Contact: docutils-develop@lists.sourceforge.net
+:Revision: $Revision: 8012 $
+:Date: $Date: 2017-01-04 00:08:19 +0100 (Mi, 04. Jän 2017) $
+:Copyright: This document has been placed in the public domain.
+
+.. contents::
+
+
+--------------
+ Introduction
+--------------
+
+Once the Docutils package is unpacked, you will discover a "``tools``"
+directory containing several front ends for common Docutils
+processing. Rather than a single all-purpose program, Docutils has
+many small front ends, each specialized for a specific "Reader" (which
+knows how to interpret a file in context), a "Parser" (which
+understands the syntax of the text), and a "Writer" (which knows how
+to generate a specific data format).
+
+Most front ends have common options and the same command-line usage
+pattern::
+
+ toolname [options] [<source> [<destination]]
+
+(The exceptions are buildhtml.py_ and rstpep2html.py_.) See
+rst2html.py_ for concrete examples. Each tool has a "``--help``"
+option which lists the `command-line options`_ and arguments it
+supports. Processing can also be customized with `configuration
+files`_.
+
+The two arguments, "source" and "destination", are optional. If only
+one argument (source) is specified, the standard output (stdout) is
+used for the destination. If no arguments are specified, the standard
+input (stdin) is used for the source.
+
+
+Getting Help
+============
+
+First, try the "``--help``" option each front-end tool has.
+
+Users who have questions or need assistance with Docutils or
+reStructuredText should post a message to the Docutils-users_ mailing
+list.
+
+.. _Docutils-users: mailing-lists.html#docutils-users
+
+
+-----------
+ The Tools
+-----------
+
+HTML-Generating Tools
+=====================
+
+buildhtml.py
+------------
+
+:Readers: Standalone, PEP
+:Parser: reStructuredText
+:Writers: html_, pep_html_
+
+Use ``buildhtml.py`` to generate ``*.html`` from all the ``*.txt`` files
+(including PEPs) in each <directory> given, and their subdirectories
+too. (Use the ``--local`` option to skip subdirectories.)
+
+Usage::
+
+ buildhtml.py [options] [<directory> ...]
+
+After unpacking the Docutils package, the following shell commands
+will generate HTML for all included documentation::
+
+ cd docutils/tools
+ buildhtml.py ..
+
+For official releases, the directory may be called "docutils-X.Y",
+where "X.Y" is the release version. Alternatively::
+
+ cd docutils
+ tools/buildhtml.py --config=tools/docutils.conf
+
+The current directory (and all subdirectories) is chosen by default if
+no directory is named. Some files may generate system messages
+(docs/user/rst/demo.txt contains intentional errors); use the
+``--quiet`` option to suppress all warnings. The ``--config`` option
+ensures that the correct settings are in place (a ``docutils.conf``
+`configuration file`_ in the current directory is picked up
+automatically). Command-line options may be used to override config
+file settings or replace them altogether.
+
+
+rst2html.py
+-----------
+
+:Reader: Standalone
+:Parser: reStructuredText
+:Writer: html_
+
+`rst2html.py` is the front-end for the default Docutils HTML writer.
+The default writer may change with the development of HTML, browsers,
+Docutils, and the web. Currently, it is html4css1_.
+
+* Use `rst2html.py`, if you want the output to be up-to-date automatically.
+
+* Use a specific front end, if you depend on stability of the
+ generated HTML code, e.g. because you use a custom style sheet or
+ post-processing that may break otherwise.
+
+
+rst2html4.py
+------------
+
+:Reader: Standalone
+:Parser: reStructuredText
+:Writer: html4css1_
+
+The ``rst2html4.py`` front end reads standalone reStructuredText source
+files and produces `XHTML 1.0 Transitional`_ output.
+A CSS stylesheet is required for proper rendering; a simple but
+complete stylesheet is installed and used by default (see Stylesheets_
+below).
+
+For example, to process a reStructuredText file "``test.txt``" into
+HTML::
+
+ rst2html.py test.txt test.html
+
+Now open the "``test.html``" file in your favorite browser to see the
+results. To get a footer with a link to the source file, date & time
+of processing, and links to the Docutils project, add some options::
+
+ rst2html.py -stg test.txt test.html
+
+
+Stylesheets
+```````````
+
+``rst2html.py`` inserts into the generated HTML a cascading stylesheet
+(or a link to a stylesheet, when passing the "``--link-stylesheet``"
+option). A stylesheet is required for proper rendering. The default
+stylesheet (``docutils/writers/html4css1/html4css1.css``, located in
+the installation directory) is provided for basic use. To use
+different stylesheet(s), specify the stylesheets' location(s)
+as comma-separated list with the "``--stylesheet``" (for a URL)
+or "``--stylesheet-path``" (for a local file) command-line option,
+or with `configuration file`_ settings (e.g. ``./docutils.conf``
+or ``~/.docutils``). To experiment with styles, please see the
+`guide to writing HTML (CSS) stylesheets for Docutils`__.
+
+__ ../howto/html-stylesheets.html
+.. _html4css1: html.html#html4css1
+.. _html: html.html#html
+
+
+rst2html5.py
+------------
+
+:Reader: Standalone
+:Parser: reStructuredText
+:Writer: html5 (html5_polyglot_)
+
+The ``rst2html5.py`` front end reads standalone reStructuredText source
+files and produces `HTML 5`_ output.
+Correct rendering of elements not directly supported by HTML depends on a
+CSS style sheet. The provided style sheets ``minimal.css`` and ``plain.css``
+define required and optional styling rules respectively.
+
+.. _html5_polyglot: html.html#html5-polyglot
+
+rstpep2html.py
+--------------
+
+:Reader: PEP
+:Parser: reStructuredText
+:Writer: pep_html_
+
+``rstpep2html.py`` reads a new-style PEP (marked up with reStructuredText)
+and produces `XHTML 1.0 Transitional`_. It requires a template file and a
+stylesheet. By default, it makes use of a "``pep-html-template``" file and
+the "``pep.css``" stylesheet (both in the ``docutils/writers/pep_html/``
+directory), but these can be overridden by command-line options or
+configuration files.
+
+For example, to process a PEP into HTML::
+
+ cd <path-to-docutils>/docs/peps
+ rstpep2html.py pep-0287.txt pep-0287.html
+
+.. _pep_html: html.html#pep-html
+
+rst2s5.py
+---------
+
+:Reader: Standalone
+:Parser: reStructuredText
+:Writer: s5_html_
+
+The ``rst2s5.py`` front end reads standalone reStructuredText source
+files and produces (X)HTML output compatible with S5_, the "Simple
+Standards-based Slide Show System" by Eric Meyer. A theme is required
+for proper rendering; several are distributed with Docutils and others
+are available; see Themes_ below.
+
+For example, to process a reStructuredText file "``slides.txt``" into
+S5/HTML::
+
+ rst2s5.py slides.txt slides.html
+
+Now open the "``slides.html``" file in your favorite browser, switch
+to full-screen mode, and enjoy the results.
+
+.. _S5: http://meyerweb.com/eric/tools/s5/
+.. _s5_html: html.html#s5-html
+
+Themes
+``````
+
+Each S5 theme consists of a directory containing several files:
+stylesheets, JavaScript, and graphics. These are copied into a
+``ui/<theme>`` directory beside the generated HTML. A theme is chosen
+using the "``--theme``" option (for themes that come with Docutils) or
+the "``--theme-url``" option (for themes anywhere). For example, the
+"medium-black" theme can be specified as follows::
+
+ rst2s5.py --theme medium-black slides.txt slides.html
+
+The theme will be copied to the ``ui/medium-black`` directory.
+
+Several themes are included with Docutils:
+
+``default``
+ This is a simplified version of S5's default theme.
+
+ :Main content: black serif text on a white background
+ :Text capacity: about 13 lines
+ :Headers: light blue, bold sans-serif text on a dark blue
+ background; titles are limited to one line
+ :Footers: small, gray, bold sans-serif text on a dark blue
+ background
+
+``small-white``
+ (Small text on a white background.)
+
+ :Main content: black serif text on a white background
+ :Text capacity: about 15 lines
+ :Headers: black, bold sans-serif text on a white background;
+ titles wrap
+ :Footers: small, dark gray, bold sans-serif text on a white
+ background
+
+``small-black``
+ :Main content: white serif text on a black background
+ :Text capacity: about 15 lines
+ :Headers: white, bold sans-serif text on a black background;
+ titles wrap
+ :Footers: small, light gray, bold sans-serif text on a black
+ background
+
+``medium-white``
+ :Main content: black serif text on a white background
+ :Text capacity: about 9 lines
+ :Headers: black, bold sans-serif text on a white background;
+ titles wrap
+ :Footers: small, dark gray, bold sans-serif text on a white
+ background
+
+``medium-black``
+ :Main content: white serif text on a black background
+ :Text capacity: about 9 lines
+ :Headers: white, bold sans-serif text on a black background;
+ titles wrap
+ :Footers: small, light gray, bold sans-serif text on a black
+ background
+
+``big-white``
+ :Main content: black, bold sans-serif text on a white background
+ :Text capacity: about 5 lines
+ :Headers: black, bold sans-serif text on a white background;
+ titles wrap
+ :Footers: not displayed
+
+``big-black``
+ :Main content: white, bold sans-serif text on a black background
+ :Text capacity: about 5 lines
+ :Headers: white, bold sans-serif text on a black background;
+ titles wrap
+ :Footers: not displayed
+
+If a theme directory contains a file named ``__base__``, the name of
+the theme's base theme will be read from it. Files are accumulated
+from the named theme, any base themes, and the "default" theme (which
+is the implicit base of all themes).
+
+For details, please see `Easy Slide Shows With reStructuredText &
+S5 <slide-shows.html>`_.
+
+
+.. _HTML 5: http://www.w3.org/TR/html5/
+.. _HTML 4.1: http://www.w3.org/TR/html401/
+.. _XHTML 1.0 Transitional: http://www.w3.org/TR/xhtml1/
+.. _XHTML 1.1: http://www.w3.org/TR/xhtml1/
+
+
+LaTeX-Generating Tools
+======================
+
+rst2latex.py
+------------
+
+:Reader: Standalone
+:Parser: reStructuredText
+:Writer: latex2e
+
+The ``rst2latex.py`` front end reads standalone reStructuredText
+source files and produces LaTeX_ output. For example, to process a
+reStructuredText file "``test.txt``" into LaTeX::
+
+ rst2latex.py test.txt test.tex
+
+The output file "``test.tex``" should then be processed with ``latex``
+or ``pdflatex`` to get a document in DVI, PostScript or PDF format for
+printing or on-screen viewing.
+
+For details see `Generating LaTeX with Docutils`_.
+
+rst2xetex.py
+------------
+
+:Reader: Standalone
+:Parser: reStructuredText
+:Writer: xetex
+
+The ``rst2xetex.py`` front end reads standalone reStructuredText source
+files and produces `LaTeX` output for processing with unicode-aware
+TeX engines (`LuaTeX`_ or `XeTeX`_). For example, to process a
+reStructuredText file "``test.txt``" into LaTeX::
+
+ rst2xetex.py test.txt test.tex
+
+The output file "``test.tex``" should then be processed with ``xelatex`` or
+``lualatex`` to get a document in PDF format for printing or on-screen
+viewing.
+
+For details see `Generating LaTeX with Docutils`_.
+
+.. _LaTeX: https://en.wikipedia.org/wiki/LaTeX
+.. _XeTeX: https://en.wikipedia.org/wiki/XeTeX
+.. _LuaTeX: https://en.wikipedia.org/wiki/LuaTeX
+
+
+XML-Generating Tools
+====================
+
+rst2xml.py
+----------
+
+:Reader: Standalone
+:Parser: reStructuredText
+:Writer: XML (Docutils native)
+
+The ``rst2xml.py`` front end produces Docutils-native XML output.
+This can be transformed with standard XML tools such as XSLT
+processors into arbitrary final forms. An example is the xml2rst_ processor
+in the Docutils sandbox.
+
+.. _xml2rst: ../../../sandbox/xml2rst
+
+
+ODF/OpenOffice-Generating Tools
+===============================
+
+rst2odt.py
+----------
+
+:Reader: Standalone
+:Parser: reStructuredText
+:Writer: ODF/.odt
+
+The ``rst2odt.py`` front end reads standalone reStructuredText
+source files and produces ODF/.odt files that can be read, edited,
+printed, etc with OpenOffice ``oowriter``
+(http://www.openoffice.org/). A stylesheet file is required. A
+stylesheet file is an OpenOffice .odt file containing definitions
+of the styles required for ``rst2odt.py``. You can learn more
+about how to use ``rst2odt.py``, the styles used ``rst2odt.py``,
+etc from `Odt Writer for Docutils <odt.html>`_.
+
+
+reStructuredText-Generating Tools
+=================================
+
+Currently, there is no reStructuredText writer in Docutils and therefore
+an ``rst2rst.py`` tool is still missing.
+
+To generate reStructuredText documents with Docutils, you can use
+the XML (Docutils native) writer and the xml2rst_ processor.
+
+
+Testing/Debugging Tools
+=======================
+
+rst2pseudoxml.py
+----------------
+
+:Reader: Standalone
+:Parser: reStructuredText
+:Writer: Pseudo-XML
+
+``rst2pseudoxml.py`` is used for debugging the Docutils "Reader to
+Transform to Writer" pipeline. It produces a compact pretty-printed
+"pseudo-XML", where nesting is indicated by indentation (no end-tags).
+External attributes for all elements are output, and internal
+attributes for any leftover "pending" elements are also given.
+
+
+quicktest.py
+------------
+
+:Reader: N/A
+:Parser: reStructuredText
+:Writer: N/A
+
+The ``quicktest.py`` tool is used for testing the reStructuredText
+parser. It does not use a Docutils Reader or Writer or the standard
+Docutils command-line options. Rather, it does its own I/O and calls
+the parser directly. No transforms are applied to the parsed
+document. Various forms output are possible:
+
+- Pretty-printed pseudo-XML (default)
+- Test data (Python list of input and pseudo-XML output strings;
+ useful for creating new test cases)
+- Pretty-printed native XML
+- Raw native XML (with or without a stylesheet reference)
+
+
+
+---------------
+ Customization
+---------------
+
+Command-Line Options
+====================
+
+Each front-end tool supports command-line options for one-off
+customization. For persistent customization, use `configuration
+files`_. Command-line options take priority over configuration file
+settings.
+
+Use the "--help" option on each of the front ends to list the
+command-line options it supports. Command-line options and their
+corresponding configuration file entry names are listed in the
+`Docutils Configuration Files`_ document.
+
+
+.. _configuration file:
+
+Configuration Files
+===================
+
+Configuration files are used for persistent customization; they can be
+set once and take effect every time you use a front-end tool.
+
+For details, see `Docutils Configuration Files`_.
+
+.. _Docutils Configuration Files: config.html
+.. _Generating LaTeX with Docutils: latex.html
+\f
+..
+ Local Variables:
+ mode: indented-text
+ indent-tabs-mode: nil
+ sentence-end-double-space: t
+ fill-column: 70
+ End:
--- /dev/null
+Metadata-Version: 1.2
+Name: docutils
+Version: 0.16
+Summary: Docutils -- Python Documentation Utilities
+Home-page: http://docutils.sourceforge.net/
+Author: David Goodger
+Author-email: goodger@python.org
+Maintainer: docutils-develop list
+Maintainer-email: docutils-develop@lists.sourceforge.net
+License: public domain, Python, 2-Clause BSD, GPL 3 (see COPYING.txt)
+Description: Docutils is a modular system for processing documentation
+ into useful formats, such as HTML, XML, and LaTeX. For
+ input Docutils supports reStructuredText, an easy-to-read,
+ what-you-see-is-what-you-get plaintext markup syntax.
+Platform: OS-independent
+Classifier: Development Status :: 4 - Beta
+Classifier: Environment :: Console
+Classifier: Intended Audience :: End Users/Desktop
+Classifier: Intended Audience :: Other Audience
+Classifier: Intended Audience :: Developers
+Classifier: Intended Audience :: System Administrators
+Classifier: License :: Public Domain
+Classifier: License :: OSI Approved :: Python Software Foundation License
+Classifier: License :: OSI Approved :: BSD License
+Classifier: License :: OSI Approved :: GNU General Public License (GPL)
+Classifier: Operating System :: OS Independent
+Classifier: Programming Language :: Python :: 2
+Classifier: Programming Language :: Python :: 2.7
+Classifier: Programming Language :: Python :: 3
+Classifier: Programming Language :: Python :: 3.5
+Classifier: Programming Language :: Python :: 3.6
+Classifier: Programming Language :: Python :: 3.7
+Classifier: Topic :: Documentation
+Classifier: Topic :: Software Development :: Documentation
+Classifier: Topic :: Text Processing
+Classifier: Natural Language :: English
+Classifier: Natural Language :: Afrikaans
+Classifier: Natural Language :: Catalan
+Classifier: Natural Language :: Chinese (Simplified)
+Classifier: Natural Language :: Chinese (Traditional)
+Classifier: Natural Language :: Czech
+Classifier: Natural Language :: Danish
+Classifier: Natural Language :: Dutch
+Classifier: Natural Language :: Esperanto
+Classifier: Natural Language :: Finnish
+Classifier: Natural Language :: French
+Classifier: Natural Language :: Galician
+Classifier: Natural Language :: German
+Classifier: Natural Language :: Hebrew
+Classifier: Natural Language :: Italian
+Classifier: Natural Language :: Japanese
+Classifier: Natural Language :: Korean
+Classifier: Natural Language :: Latvian
+Classifier: Natural Language :: Lithuanian
+Classifier: Natural Language :: Persian
+Classifier: Natural Language :: Polish
+Classifier: Natural Language :: Portuguese (Brazilian)
+Classifier: Natural Language :: Russian
+Classifier: Natural Language :: Slovak
+Classifier: Natural Language :: Spanish
+Classifier: Natural Language :: Swedish
+Requires-Python: >=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*
--- /dev/null
+BUGS.txt
+COPYING.txt
+FAQ.txt
+HISTORY.txt
+MANIFEST
+MANIFEST.in
+README.txt
+RELEASE-NOTES.txt
+THANKS.txt
+install.py
+setup.cfg
+setup.py
+docs/index.txt
+docs/api/cmdline-tool.txt
+docs/api/publisher.txt
+docs/api/runtime-settings.txt
+docs/dev/distributing.txt
+docs/dev/enthought-plan.txt
+docs/dev/enthought-rfp.txt
+docs/dev/hacking.txt
+docs/dev/policies.txt
+docs/dev/pysource.dtd
+docs/dev/pysource.txt
+docs/dev/release.txt
+docs/dev/repository.txt
+docs/dev/semantics.txt
+docs/dev/testing.txt
+docs/dev/todo.txt
+docs/dev/website.txt
+docs/dev/rst/alternatives.txt
+docs/dev/rst/problems.txt
+docs/howto/html-stylesheets.txt
+docs/howto/i18n.txt
+docs/howto/rst-directives.txt
+docs/howto/rst-roles.txt
+docs/howto/security.txt
+docs/peps/pep-0256.txt
+docs/peps/pep-0257.txt
+docs/peps/pep-0258.txt
+docs/peps/pep-0287.txt
+docs/ref/doctree.txt
+docs/ref/docutils.dtd
+docs/ref/soextblx.dtd
+docs/ref/transforms.txt
+docs/ref/rst/definitions.txt
+docs/ref/rst/directives.txt
+docs/ref/rst/introduction.txt
+docs/ref/rst/restructuredtext.txt
+docs/ref/rst/roles.txt
+docs/user/Makefile.docutils-update
+docs/user/config.txt
+docs/user/docutils-05-compat.sty.txt
+docs/user/emacs.txt
+docs/user/html.txt
+docs/user/latex.txt
+docs/user/links.txt
+docs/user/mailing-lists.txt
+docs/user/manpage.txt
+docs/user/odt.txt
+docs/user/slide-shows.txt
+docs/user/smartquotes.txt
+docs/user/tools.txt
+docs/user/images/big-black.png
+docs/user/images/big-white.png
+docs/user/images/default.png
+docs/user/images/happy_monkey.png
+docs/user/images/medium-black.png
+docs/user/images/medium-white.png
+docs/user/images/rsp-all.png
+docs/user/images/rsp-breaks.png
+docs/user/images/rsp-covers.png
+docs/user/images/rsp-cuts.png
+docs/user/images/rsp-empty.png
+docs/user/images/rsp-objects.png
+docs/user/images/rsp.svg
+docs/user/images/s5-files.png
+docs/user/images/s5-files.svg
+docs/user/images/small-black.png
+docs/user/images/small-white.png
+docs/user/rst/cheatsheet.txt
+docs/user/rst/demo.txt
+docs/user/rst/quickref.html
+docs/user/rst/quickstart.txt
+docs/user/rst/images/biohazard-bitmap-scaling.svg
+docs/user/rst/images/biohazard-bitmap.svg
+docs/user/rst/images/biohazard-scaling.svg
+docs/user/rst/images/biohazard.png
+docs/user/rst/images/biohazard.svg
+docs/user/rst/images/biohazard.swf
+docs/user/rst/images/title-scaling.svg
+docs/user/rst/images/title.png
+docs/user/rst/images/title.svg
+docutils/__init__.py
+docutils/core.py
+docutils/docutils.conf
+docutils/examples.py
+docutils/frontend.py
+docutils/io.py
+docutils/nodes.py
+docutils/statemachine.py
+docutils.egg-info/PKG-INFO
+docutils.egg-info/SOURCES.txt
+docutils.egg-info/dependency_links.txt
+docutils.egg-info/top_level.txt
+docutils/languages/__init__.py
+docutils/languages/af.py
+docutils/languages/ca.py
+docutils/languages/cs.py
+docutils/languages/da.py
+docutils/languages/de.py
+docutils/languages/en.py
+docutils/languages/eo.py
+docutils/languages/es.py
+docutils/languages/fa.py
+docutils/languages/fi.py
+docutils/languages/fr.py
+docutils/languages/gl.py
+docutils/languages/he.py
+docutils/languages/it.py
+docutils/languages/ja.py
+docutils/languages/ko.py
+docutils/languages/lt.py
+docutils/languages/lv.py
+docutils/languages/nl.py
+docutils/languages/pl.py
+docutils/languages/pt_br.py
+docutils/languages/ru.py
+docutils/languages/sk.py
+docutils/languages/sv.py
+docutils/languages/zh_cn.py
+docutils/languages/zh_tw.py
+docutils/parsers/__init__.py
+docutils/parsers/null.py
+docutils/parsers/rst/__init__.py
+docutils/parsers/rst/roles.py
+docutils/parsers/rst/states.py
+docutils/parsers/rst/tableparser.py
+docutils/parsers/rst/directives/__init__.py
+docutils/parsers/rst/directives/admonitions.py
+docutils/parsers/rst/directives/body.py
+docutils/parsers/rst/directives/html.py
+docutils/parsers/rst/directives/images.py
+docutils/parsers/rst/directives/misc.py
+docutils/parsers/rst/directives/parts.py
+docutils/parsers/rst/directives/references.py
+docutils/parsers/rst/directives/tables.py
+docutils/parsers/rst/include/README.txt
+docutils/parsers/rst/include/isoamsa.txt
+docutils/parsers/rst/include/isoamsb.txt
+docutils/parsers/rst/include/isoamsc.txt
+docutils/parsers/rst/include/isoamsn.txt
+docutils/parsers/rst/include/isoamso.txt
+docutils/parsers/rst/include/isoamsr.txt
+docutils/parsers/rst/include/isobox.txt
+docutils/parsers/rst/include/isocyr1.txt
+docutils/parsers/rst/include/isocyr2.txt
+docutils/parsers/rst/include/isodia.txt
+docutils/parsers/rst/include/isogrk1.txt
+docutils/parsers/rst/include/isogrk2.txt
+docutils/parsers/rst/include/isogrk3.txt
+docutils/parsers/rst/include/isogrk4-wide.txt
+docutils/parsers/rst/include/isogrk4.txt
+docutils/parsers/rst/include/isolat1.txt
+docutils/parsers/rst/include/isolat2.txt
+docutils/parsers/rst/include/isomfrk-wide.txt
+docutils/parsers/rst/include/isomfrk.txt
+docutils/parsers/rst/include/isomopf-wide.txt
+docutils/parsers/rst/include/isomopf.txt
+docutils/parsers/rst/include/isomscr-wide.txt
+docutils/parsers/rst/include/isomscr.txt
+docutils/parsers/rst/include/isonum.txt
+docutils/parsers/rst/include/isopub.txt
+docutils/parsers/rst/include/isotech.txt
+docutils/parsers/rst/include/mmlalias.txt
+docutils/parsers/rst/include/mmlextra-wide.txt
+docutils/parsers/rst/include/mmlextra.txt
+docutils/parsers/rst/include/s5defs.txt
+docutils/parsers/rst/include/xhtml1-lat1.txt
+docutils/parsers/rst/include/xhtml1-special.txt
+docutils/parsers/rst/include/xhtml1-symbol.txt
+docutils/parsers/rst/languages/__init__.py
+docutils/parsers/rst/languages/af.py
+docutils/parsers/rst/languages/ca.py
+docutils/parsers/rst/languages/cs.py
+docutils/parsers/rst/languages/da.py
+docutils/parsers/rst/languages/de.py
+docutils/parsers/rst/languages/en.py
+docutils/parsers/rst/languages/eo.py
+docutils/parsers/rst/languages/es.py
+docutils/parsers/rst/languages/fa.py
+docutils/parsers/rst/languages/fi.py
+docutils/parsers/rst/languages/fr.py
+docutils/parsers/rst/languages/gl.py
+docutils/parsers/rst/languages/he.py
+docutils/parsers/rst/languages/it.py
+docutils/parsers/rst/languages/ja.py
+docutils/parsers/rst/languages/ko.py
+docutils/parsers/rst/languages/lt.py
+docutils/parsers/rst/languages/lv.py
+docutils/parsers/rst/languages/nl.py
+docutils/parsers/rst/languages/pl.py
+docutils/parsers/rst/languages/pt_br.py
+docutils/parsers/rst/languages/ru.py
+docutils/parsers/rst/languages/sk.py
+docutils/parsers/rst/languages/sv.py
+docutils/parsers/rst/languages/zh_cn.py
+docutils/parsers/rst/languages/zh_tw.py
+docutils/readers/__init__.py
+docutils/readers/doctree.py
+docutils/readers/pep.py
+docutils/readers/standalone.py
+docutils/transforms/__init__.py
+docutils/transforms/components.py
+docutils/transforms/frontmatter.py
+docutils/transforms/misc.py
+docutils/transforms/parts.py
+docutils/transforms/peps.py
+docutils/transforms/references.py
+docutils/transforms/universal.py
+docutils/transforms/writer_aux.py
+docutils/utils/__init__.py
+docutils/utils/code_analyzer.py
+docutils/utils/error_reporting.py
+docutils/utils/punctuation_chars.py
+docutils/utils/roman.py
+docutils/utils/smartquotes.py
+docutils/utils/urischemes.py
+docutils/utils/math/__init__.py
+docutils/utils/math/latex2mathml.py
+docutils/utils/math/math2html.py
+docutils/utils/math/tex2mathml_extern.py
+docutils/utils/math/tex2unichar.py
+docutils/utils/math/unichar2tex.py
+docutils/writers/__init__.py
+docutils/writers/_html_base.py
+docutils/writers/docutils_xml.py
+docutils/writers/manpage.py
+docutils/writers/null.py
+docutils/writers/pseudoxml.py
+docutils/writers/html4css1/__init__.py
+docutils/writers/html4css1/html4css1.css
+docutils/writers/html4css1/template.txt
+docutils/writers/html5_polyglot/__init__.py
+docutils/writers/html5_polyglot/math.css
+docutils/writers/html5_polyglot/minimal.css
+docutils/writers/html5_polyglot/plain.css
+docutils/writers/html5_polyglot/template.txt
+docutils/writers/latex2e/__init__.py
+docutils/writers/latex2e/default.tex
+docutils/writers/latex2e/docutils-05-compat.sty
+docutils/writers/latex2e/titlepage.tex
+docutils/writers/latex2e/xelatex.tex
+docutils/writers/odf_odt/__init__.py
+docutils/writers/odf_odt/pygmentsformatter.py
+docutils/writers/odf_odt/styles.odt
+docutils/writers/pep_html/__init__.py
+docutils/writers/pep_html/pep.css
+docutils/writers/pep_html/template.txt
+docutils/writers/s5_html/__init__.py
+docutils/writers/s5_html/themes/README.txt
+docutils/writers/s5_html/themes/big-black/__base__
+docutils/writers/s5_html/themes/big-black/framing.css
+docutils/writers/s5_html/themes/big-black/pretty.css
+docutils/writers/s5_html/themes/big-white/framing.css
+docutils/writers/s5_html/themes/big-white/pretty.css
+docutils/writers/s5_html/themes/default/blank.gif
+docutils/writers/s5_html/themes/default/framing.css
+docutils/writers/s5_html/themes/default/iepngfix.htc
+docutils/writers/s5_html/themes/default/opera.css
+docutils/writers/s5_html/themes/default/outline.css
+docutils/writers/s5_html/themes/default/pretty.css
+docutils/writers/s5_html/themes/default/print.css
+docutils/writers/s5_html/themes/default/s5-core.css
+docutils/writers/s5_html/themes/default/slides.css
+docutils/writers/s5_html/themes/default/slides.js
+docutils/writers/s5_html/themes/medium-black/__base__
+docutils/writers/s5_html/themes/medium-black/pretty.css
+docutils/writers/s5_html/themes/medium-white/framing.css
+docutils/writers/s5_html/themes/medium-white/pretty.css
+docutils/writers/s5_html/themes/small-black/__base__
+docutils/writers/s5_html/themes/small-black/pretty.css
+docutils/writers/s5_html/themes/small-white/framing.css
+docutils/writers/s5_html/themes/small-white/pretty.css
+docutils/writers/xetex/__init__.py
+licenses/BSD-2-Clause.txt
+licenses/docutils.conf
+licenses/gpl-3-0.txt
+licenses/python-2-1-1.txt
+test/DocutilsTestSupport.py
+test/alltests.out
+test/alltests.py
+test/coverage.sh
+test/docutils.conf
+test/local-parser.py
+test/local-reader.py
+test/local-writer.py
+test/local_dummy_lang.py
+test/package_unittest.py
+test/record.txt
+test/test__init__.py
+test/test_command_line.py
+test/test_dependencies.py
+test/test_error_reporting.py
+test/test_functional.py
+test/test_io.py
+test/test_language.py
+test/test_nodes.py
+test/test_pickle.py
+test/test_publisher.py
+test/test_settings.py
+test/test_statemachine.py
+test/test_traversals.py
+test/test_utils.py
+test/test_viewlist.py
+test/data/config_1.txt
+test/data/config_2.txt
+test/data/config_error_handler.txt
+test/data/config_list.txt
+test/data/config_list_2.txt
+test/data/config_old.txt
+test/data/csv_data.txt
+test/data/csv_dep.txt
+test/data/dependencies.txt
+test/data/full-template.txt
+test/data/ham.css
+test/data/ham.tex
+test/data/include.txt
+test/data/latin1.txt
+test/data/raw.txt
+test/data/stylesheet.txt
+test/functional/README.txt
+test/functional/expected/compact_lists.html
+test/functional/expected/cyrillic.tex
+test/functional/expected/dangerous.html
+test/functional/expected/field_name_limit.html
+test/functional/expected/footnotes_html5.html
+test/functional/expected/latex_babel.tex
+test/functional/expected/latex_cornercases.tex
+test/functional/expected/latex_docinfo.tex
+test/functional/expected/latex_literal_block.tex
+test/functional/expected/latex_literal_block_fancyvrb.tex
+test/functional/expected/latex_literal_block_listings.tex
+test/functional/expected/latex_literal_block_verbatim.tex
+test/functional/expected/latex_literal_block_verbatimtab.tex
+test/functional/expected/math_output_html.html
+test/functional/expected/math_output_latex.html
+test/functional/expected/math_output_mathjax.html
+test/functional/expected/math_output_mathml.xhtml
+test/functional/expected/misc_rst_html4css1.html
+test/functional/expected/odt_basic.odt
+test/functional/expected/odt_classifier.odt
+test/functional/expected/odt_contents.odt
+test/functional/expected/odt_custom_headfoot.odt
+test/functional/expected/odt_footnotes.odt
+test/functional/expected/odt_header_footer.odt
+test/functional/expected/odt_literal_block.odt
+test/functional/expected/odt_nested_class.odt
+test/functional/expected/odt_no_class.odt
+test/functional/expected/odt_raw.odt
+test/functional/expected/odt_tables1.odt
+test/functional/expected/odt_unnested_class.odt
+test/functional/expected/pep_html.html
+test/functional/expected/standalone_rst_docutils_xml.xml
+test/functional/expected/standalone_rst_html4css1.html
+test/functional/expected/standalone_rst_html5.html
+test/functional/expected/standalone_rst_latex.tex
+test/functional/expected/standalone_rst_manpage.man
+test/functional/expected/standalone_rst_pseudoxml.txt
+test/functional/expected/standalone_rst_s5_html_1.html
+test/functional/expected/standalone_rst_s5_html_2.html
+test/functional/expected/standalone_rst_xetex.tex
+test/functional/expected/xetex-cyrillic.tex
+test/functional/expected/ui/default/blank.gif
+test/functional/expected/ui/default/framing.css
+test/functional/expected/ui/default/iepngfix.htc
+test/functional/expected/ui/default/opera.css
+test/functional/expected/ui/default/outline.css
+test/functional/expected/ui/default/pretty.css
+test/functional/expected/ui/default/print.css
+test/functional/expected/ui/default/s5-core.css
+test/functional/expected/ui/default/slides.css
+test/functional/expected/ui/default/slides.js
+test/functional/expected/ui/small-black/blank.gif
+test/functional/expected/ui/small-black/framing.css
+test/functional/expected/ui/small-black/iepngfix.htc
+test/functional/expected/ui/small-black/opera.css
+test/functional/expected/ui/small-black/outline.css
+test/functional/expected/ui/small-black/pretty.css
+test/functional/expected/ui/small-black/print.css
+test/functional/expected/ui/small-black/s5-core.css
+test/functional/expected/ui/small-black/slides.css
+test/functional/expected/ui/small-black/slides.js
+test/functional/input/compact_lists.txt
+test/functional/input/cyrillic.txt
+test/functional/input/dangerous.txt
+test/functional/input/field_list.txt
+test/functional/input/footnotes.txt
+test/functional/input/html5-text-level-tags.txt
+test/functional/input/latex_babel.txt
+test/functional/input/latex_cornercases.txt
+test/functional/input/latex_docinfo.txt
+test/functional/input/latex_literal_block.txt
+test/functional/input/link_in_substitution.txt
+test/functional/input/odt_basic.txt
+test/functional/input/odt_classifier.txt
+test/functional/input/odt_contents.txt
+test/functional/input/odt_custom_headfoot.txt
+test/functional/input/odt_footnotes.txt
+test/functional/input/odt_header_footer.txt
+test/functional/input/odt_literal_block.txt
+test/functional/input/odt_nested_class.txt
+test/functional/input/odt_no_class.txt
+test/functional/input/odt_raw.txt
+test/functional/input/odt_tables1.txt
+test/functional/input/odt_unnested_class.txt
+test/functional/input/pep_html.txt
+test/functional/input/simple.txt
+test/functional/input/standalone_rst_docutils_xml.txt
+test/functional/input/standalone_rst_html4css1.txt
+test/functional/input/standalone_rst_html5.txt
+test/functional/input/standalone_rst_latex.txt
+test/functional/input/standalone_rst_manpage.txt
+test/functional/input/standalone_rst_pseudoxml.txt
+test/functional/input/standalone_rst_s5_html.txt
+test/functional/input/standalone_rst_xetex.txt
+test/functional/input/data/classes_latex.txt
+test/functional/input/data/custom_roles.txt
+test/functional/input/data/custom_roles_latex.txt
+test/functional/input/data/errors.txt
+test/functional/input/data/header_footer.txt
+test/functional/input/data/html4css1.css
+test/functional/input/data/hyperlinking.txt
+test/functional/input/data/latex-problematic.txt
+test/functional/input/data/latex_encoding.txt
+test/functional/input/data/list_table.txt
+test/functional/input/data/math.css
+test/functional/input/data/math.txt
+test/functional/input/data/minimal.css
+test/functional/input/data/nonalphanumeric.txt
+test/functional/input/data/option_lists.txt
+test/functional/input/data/plain.css
+test/functional/input/data/section_titles.txt
+test/functional/input/data/standard.txt
+test/functional/input/data/svg_images.txt
+test/functional/input/data/swf_images.txt
+test/functional/input/data/table_colspan.txt
+test/functional/input/data/table_complex.txt
+test/functional/input/data/table_rowspan.txt
+test/functional/input/data/tables_latex.txt
+test/functional/input/data/unicode.txt
+test/functional/input/data/urls.txt
+test/functional/output/README.txt
+test/functional/output/compact_lists.html
+test/functional/output/cyrillic.tex
+test/functional/output/dangerous.html
+test/functional/output/field_name_limit.html
+test/functional/output/footnotes_html5.html
+test/functional/output/latex_babel.tex
+test/functional/output/latex_cornercases.tex
+test/functional/output/latex_docinfo.tex
+test/functional/output/latex_literal_block.tex
+test/functional/output/latex_literal_block_fancyvrb.tex
+test/functional/output/latex_literal_block_listings.tex
+test/functional/output/latex_literal_block_verbatim.tex
+test/functional/output/latex_literal_block_verbatimtab.tex
+test/functional/output/math_output_html.html
+test/functional/output/math_output_latex.html
+test/functional/output/math_output_mathjax.html
+test/functional/output/math_output_mathml.xhtml
+test/functional/output/misc_rst_html4css1.html
+test/functional/output/odt_basic.odt
+test/functional/output/odt_custom_headfoot.odt
+test/functional/output/odt_footnotes.odt
+test/functional/output/odt_header_footer.odt
+test/functional/output/odt_nested_class.odt
+test/functional/output/odt_no_class.odt
+test/functional/output/odt_raw.odt
+test/functional/output/odt_tables1.odt
+test/functional/output/odt_unnested_class.odt
+test/functional/output/pep_html.html
+test/functional/output/standalone_rst_docutils_xml.xml
+test/functional/output/standalone_rst_html4css1.html
+test/functional/output/standalone_rst_html5.html
+test/functional/output/standalone_rst_latex.tex
+test/functional/output/standalone_rst_manpage.man
+test/functional/output/standalone_rst_pseudoxml.txt
+test/functional/output/standalone_rst_s5_html_1.html
+test/functional/output/standalone_rst_s5_html_2.html
+test/functional/output/standalone_rst_xetex.tex
+test/functional/output/xetex-cyrillic.tex
+test/functional/output/ui/default/blank.gif
+test/functional/output/ui/default/framing.css
+test/functional/output/ui/default/iepngfix.htc
+test/functional/output/ui/default/opera.css
+test/functional/output/ui/default/outline.css
+test/functional/output/ui/default/pretty.css
+test/functional/output/ui/default/print.css
+test/functional/output/ui/default/s5-core.css
+test/functional/output/ui/default/slides.css
+test/functional/output/ui/default/slides.js
+test/functional/output/ui/small-black/blank.gif
+test/functional/output/ui/small-black/framing.css
+test/functional/output/ui/small-black/iepngfix.htc
+test/functional/output/ui/small-black/opera.css
+test/functional/output/ui/small-black/outline.css
+test/functional/output/ui/small-black/pretty.css
+test/functional/output/ui/small-black/print.css
+test/functional/output/ui/small-black/s5-core.css
+test/functional/output/ui/small-black/slides.css
+test/functional/output/ui/small-black/slides.js
+test/functional/tests/_default.py
+test/functional/tests/_standalone_rst_defaults.py
+test/functional/tests/compact_lists.py
+test/functional/tests/dangerous.py
+test/functional/tests/field_name_limit.py
+test/functional/tests/footnotes_html5.py
+test/functional/tests/latex_babel.py
+test/functional/tests/latex_cornercases.py
+test/functional/tests/latex_cyrillic.py
+test/functional/tests/latex_docinfo.py
+test/functional/tests/latex_literal_block.py
+test/functional/tests/latex_literal_block_fancyvrb.py
+test/functional/tests/latex_literal_block_listings.py
+test/functional/tests/latex_literal_block_verbatim.py
+test/functional/tests/latex_literal_block_verbatimtab.py
+test/functional/tests/math_output_html.py
+test/functional/tests/math_output_latex.py
+test/functional/tests/math_output_mathjax.py
+test/functional/tests/math_output_mathml.py
+test/functional/tests/misc_rst_html4css1.py
+test/functional/tests/pep_html.py
+test/functional/tests/standalone_rst_docutils_xml.py
+test/functional/tests/standalone_rst_html4css1.py
+test/functional/tests/standalone_rst_html5.py
+test/functional/tests/standalone_rst_latex.py
+test/functional/tests/standalone_rst_manpage.py
+test/functional/tests/standalone_rst_pseudoxml.py
+test/functional/tests/standalone_rst_s5_html_1.py
+test/functional/tests/standalone_rst_s5_html_2.py
+test/functional/tests/standalone_rst_xetex.py
+test/functional/tests/xetex_cyrillic.py
+test/test_parsers/__init__.py
+test/test_parsers/test_get_parser_class.py
+test/test_parsers/test_parser.py
+test/test_parsers/test_rst/__init__.py
+test/test_parsers/test_rst/test_SimpleTableParser.py
+test/test_parsers/test_rst/test_TableParser.py
+test/test_parsers/test_rst/test_block_quotes.py
+test/test_parsers/test_rst/test_bullet_lists.py
+test/test_parsers/test_rst/test_character_level_inline_markup.py
+test/test_parsers/test_rst/test_citations.py
+test/test_parsers/test_rst/test_comments.py
+test/test_parsers/test_rst/test_definition_lists.py
+test/test_parsers/test_rst/test_doctest_blocks.py
+test/test_parsers/test_rst/test_east_asian_text.py
+test/test_parsers/test_rst/test_enumerated_lists.py
+test/test_parsers/test_rst/test_field_lists.py
+test/test_parsers/test_rst/test_footnotes.py
+test/test_parsers/test_rst/test_inline_markup.py
+test/test_parsers/test_rst/test_interpreted.py
+test/test_parsers/test_rst/test_interpreted_fr.py
+test/test_parsers/test_rst/test_line_blocks.py
+test/test_parsers/test_rst/test_literal_blocks.py
+test/test_parsers/test_rst/test_option_lists.py
+test/test_parsers/test_rst/test_outdenting.py
+test/test_parsers/test_rst/test_paragraphs.py
+test/test_parsers/test_rst/test_section_headers.py
+test/test_parsers/test_rst/test_substitutions.py
+test/test_parsers/test_rst/test_tables.py
+test/test_parsers/test_rst/test_targets.py
+test/test_parsers/test_rst/test_transitions.py
+test/test_parsers/test_rst/includes/include9.txt
+test/test_parsers/test_rst/test_directives/__init__.py
+test/test_parsers/test_rst/test_directives/empty.txt
+test/test_parsers/test_rst/test_directives/include 11.txt
+test/test_parsers/test_rst/test_directives/include1.txt
+test/test_parsers/test_rst/test_directives/include10.txt
+test/test_parsers/test_rst/test_directives/include12.txt
+test/test_parsers/test_rst/test_directives/include13.txt
+test/test_parsers/test_rst/test_directives/include2.txt
+test/test_parsers/test_rst/test_directives/include3.txt
+test/test_parsers/test_rst/test_directives/include8.txt
+test/test_parsers/test_rst/test_directives/include_literal.txt
+test/test_parsers/test_rst/test_directives/raw1.txt
+test/test_parsers/test_rst/test_directives/test_admonitions.py
+test/test_parsers/test_rst/test_directives/test_admonitions_de.py
+test/test_parsers/test_rst/test_directives/test_admonitions_dummy_lang.py
+test/test_parsers/test_rst/test_directives/test_block_quotes.py
+test/test_parsers/test_rst/test_directives/test_class.py
+test/test_parsers/test_rst/test_directives/test_code.py
+test/test_parsers/test_rst/test_directives/test_code_long.py
+test/test_parsers/test_rst/test_directives/test_code_none.py
+test/test_parsers/test_rst/test_directives/test_compound.py
+test/test_parsers/test_rst/test_directives/test_container.py
+test/test_parsers/test_rst/test_directives/test_contents.py
+test/test_parsers/test_rst/test_directives/test_date.py
+test/test_parsers/test_rst/test_directives/test_decorations.py
+test/test_parsers/test_rst/test_directives/test_default_role.py
+test/test_parsers/test_rst/test_directives/test_figures.py
+test/test_parsers/test_rst/test_directives/test_images.py
+test/test_parsers/test_rst/test_directives/test_include.py
+test/test_parsers/test_rst/test_directives/test_line_blocks.py
+test/test_parsers/test_rst/test_directives/test_math.py
+test/test_parsers/test_rst/test_directives/test_meta.py
+test/test_parsers/test_rst/test_directives/test_parsed_literals.py
+test/test_parsers/test_rst/test_directives/test_raw.py
+test/test_parsers/test_rst/test_directives/test_replace.py
+test/test_parsers/test_rst/test_directives/test_replace_fr.py
+test/test_parsers/test_rst/test_directives/test_role.py
+test/test_parsers/test_rst/test_directives/test_rubrics.py
+test/test_parsers/test_rst/test_directives/test_sectnum.py
+test/test_parsers/test_rst/test_directives/test_sidebars.py
+test/test_parsers/test_rst/test_directives/test_tables.py
+test/test_parsers/test_rst/test_directives/test_target_notes.py
+test/test_parsers/test_rst/test_directives/test_test_directives.py
+test/test_parsers/test_rst/test_directives/test_title.py
+test/test_parsers/test_rst/test_directives/test_topics.py
+test/test_parsers/test_rst/test_directives/test_unicode.py
+test/test_parsers/test_rst/test_directives/test_unknown.py
+test/test_parsers/test_rst/test_directives/utf-16.csv
+test/test_parsers/test_rst/test_directives/includes/include14.txt
+test/test_parsers/test_rst/test_directives/includes/include4.txt
+test/test_parsers/test_rst/test_directives/includes/include5.txt
+test/test_parsers/test_rst/test_directives/includes/more/include6.txt
+test/test_parsers/test_rst/test_directives/includes/sibling/include7.txt
+test/test_readers/__init__.py
+test/test_readers/test_get_reader_class.py
+test/test_readers/test_pep/__init__.py
+test/test_readers/test_pep/test_inline_markup.py
+test/test_readers/test_pep/test_rfc2822.py
+test/test_transforms/__init__.py
+test/test_transforms/test___init__.py
+test/test_transforms/test_class.py
+test/test_transforms/test_contents.py
+test/test_transforms/test_docinfo.py
+test/test_transforms/test_doctitle.py
+test/test_transforms/test_expose_internals.py
+test/test_transforms/test_filter.py
+test/test_transforms/test_footnotes.py
+test/test_transforms/test_hyperlinks.py
+test/test_transforms/test_messages.py
+test/test_transforms/test_peps.py
+test/test_transforms/test_sectnum.py
+test/test_transforms/test_smartquotes.py
+test/test_transforms/test_strip_comments.py
+test/test_transforms/test_strip_elements_with_class.py
+test/test_transforms/test_substitutions.py
+test/test_transforms/test_target_notes.py
+test/test_transforms/test_transitions.py
+test/test_transforms/test_writer_aux.py
+test/test_writers/__init__.py
+test/test_writers/test_docutils_xml.py
+test/test_writers/test_get_writer_class.py
+test/test_writers/test_html4css1_misc.py
+test/test_writers/test_html4css1_parts.py
+test/test_writers/test_html4css1_template.py
+test/test_writers/test_html5_polyglot_misc.py
+test/test_writers/test_html5_polyglot_parts.py
+test/test_writers/test_latex2e.py
+test/test_writers/test_manpage.py
+test/test_writers/test_null.py
+test/test_writers/test_odt.py
+test/test_writers/test_pseudoxml.py
+test/test_writers/test_s5.py
+tools/buildhtml.py
+tools/docutils.conf
+tools/quicktest.py
+tools/rst2html.py
+tools/rst2html4.py
+tools/rst2html5.py
+tools/rst2latex.py
+tools/rst2man.py
+tools/rst2odt.py
+tools/rst2odt_prepstyles.py
+tools/rst2pseudoxml.py
+tools/rst2s5.py
+tools/rst2xetex.py
+tools/rst2xml.py
+tools/rstpep2html.py
+tools/dev/README.txt
+tools/dev/create_unimap.py
+tools/dev/generate_punctuation_chars.py
+tools/dev/profile_docutils.py
+tools/dev/unicode2rstsubs.py
+tools/editors/README.txt
+tools/editors/emacs/IDEAS.rst
+tools/editors/emacs/README.txt
+tools/editors/emacs/docutils.conf
+tools/editors/emacs/rst.el
+tools/editors/emacs/tests/Ado.el
+tools/editors/emacs/tests/Hdr.el
+tools/editors/emacs/tests/Makefile
+tools/editors/emacs/tests/README.txt
+tools/editors/emacs/tests/Stn.el
+tools/editors/emacs/tests/Ttl.el
+tools/editors/emacs/tests/adjust-section.el
+tools/editors/emacs/tests/adjust-uc.el
+tools/editors/emacs/tests/adjust-uc_doc.rst
+tools/editors/emacs/tests/adornment.el
+tools/editors/emacs/tests/apply-block.el
+tools/editors/emacs/tests/buffer.el
+tools/editors/emacs/tests/comment.el
+tools/editors/emacs/tests/ert-buffer.el
+tools/editors/emacs/tests/fill.el
+tools/editors/emacs/tests/font-lock.el
+tools/editors/emacs/tests/helpers.el
+tools/editors/emacs/tests/imenu.el
+tools/editors/emacs/tests/indent.el
+tools/editors/emacs/tests/init.el
+tools/editors/emacs/tests/items.el
+tools/editors/emacs/tests/movement.el
+tools/editors/emacs/tests/re.el
+tools/editors/emacs/tests/shift.el
+tools/editors/emacs/tests/toc.el
+tools/editors/emacs/tests/tree.el
+tools/test/test_buildhtml.py
\ No newline at end of file
--- /dev/null
+# $Id: __init__.py 8453 2020-01-12 13:28:32Z grubert $
+# Author: David Goodger <goodger@python.org>
+# Copyright: This module has been placed in the public domain.
+
+"""
+This is the Docutils (Python Documentation Utilities) package.
+
+Package Structure
+=================
+
+Modules:
+
+- __init__.py: Contains component base classes, exception classes, and
+ Docutils version information.
+
+- core.py: Contains the ``Publisher`` class and ``publish_*()`` convenience
+ functions.
+
+- frontend.py: Runtime settings (command-line interface, configuration files)
+ processing, for Docutils front-ends.
+
+- io.py: Provides a uniform API for low-level input and output.
+
+- nodes.py: Docutils document tree (doctree) node class library.
+
+- statemachine.py: A finite state machine specialized for
+ regular-expression-based text filters.
+
+Subpackages:
+
+- languages: Language-specific mappings of terms.
+
+- parsers: Syntax-specific input parser modules or packages.
+
+- readers: Context-specific input handlers which understand the data
+ source and manage a parser.
+
+- transforms: Modules used by readers and writers to modify DPS
+ doctrees.
+
+- utils: Contains the ``Reporter`` system warning class and miscellaneous
+ utilities used by readers, writers, and transforms.
+
+ utils/urischemes.py: Contains a complete mapping of known URI addressing
+ scheme names to descriptions.
+
+- utils/math: Contains functions for conversion of mathematical notation
+ between different formats (LaTeX, MathML, text, ...).
+
+- writers: Format-specific output translators.
+"""
+
+import sys
+from collections import namedtuple
+
+
+__docformat__ = 'reStructuredText'
+
+__version__ = '0.16'
+"""Docutils version identifier (complies with PEP 440)::
+
+ major.minor[.micro][releaselevel[serial]][.dev]
+
+For version comparison operations, use `__version_info__` (see, below)
+rather than parsing the text of `__version__`.
+
+See 'Version Numbering' in docs/dev/policies.txt.
+"""
+
+VersionInfo = namedtuple(
+ 'VersionInfo', 'major minor micro releaselevel serial release')
+
+__version_info__ = VersionInfo(
+ major=0,
+ minor=16,
+ micro=0,
+ releaselevel='final', # one of 'alpha', 'beta', 'candidate', 'final'
+ # pre-release serial number (0 for final releases and active development):
+ serial=0,
+ release=True # True for official releases and pre-releases
+ )
+"""Comprehensive version information tuple. See 'Version Numbering' in
+docs/dev/policies.txt."""
+
+__version_details__ = 'release'
+"""Optional extra version details (e.g. 'snapshot 2005-05-29, r3410').
+(For development and release status see `__version_info__`.)
+"""
+
+
+class ApplicationError(Exception): pass
+
+class DataError(ApplicationError): pass
+
+
+class SettingsSpec(object):
+
+ """
+ Runtime setting specification base class.
+
+ SettingsSpec subclass objects used by `docutils.frontend.OptionParser`.
+ """
+
+ settings_spec = ()
+ """Runtime settings specification. Override in subclasses.
+
+ Defines runtime settings and associated command-line options, as used by
+ `docutils.frontend.OptionParser`. This is a tuple of:
+
+ - Option group title (string or `None` which implies no group, just a list
+ of single options).
+
+ - Description (string or `None`).
+
+ - A sequence of option tuples. Each consists of:
+
+ - Help text (string)
+
+ - List of option strings (e.g. ``['-Q', '--quux']``).
+
+ - Dictionary of keyword arguments sent to the OptionParser/OptionGroup
+ ``add_option`` method.
+
+ Runtime setting names are derived implicitly from long option names
+ ('--a-setting' becomes ``settings.a_setting``) or explicitly from the
+ 'dest' keyword argument.
+
+ Most settings will also have a 'validator' keyword & function. The
+ validator function validates setting values (from configuration files
+ and command-line option arguments) and converts them to appropriate
+ types. For example, the ``docutils.frontend.validate_boolean``
+ function, **required by all boolean settings**, converts true values
+ ('1', 'on', 'yes', and 'true') to 1 and false values ('0', 'off',
+ 'no', 'false', and '') to 0. Validators need only be set once per
+ setting. See the `docutils.frontend.validate_*` functions.
+
+ See the optparse docs for more details.
+
+ - More triples of group title, description, options, as many times as
+ needed. Thus, `settings_spec` tuples can be simply concatenated.
+ """
+
+ settings_defaults = None
+ """A dictionary of defaults for settings not in `settings_spec` (internal
+ settings, intended to be inaccessible by command-line and config file).
+ Override in subclasses."""
+
+ settings_default_overrides = None
+ """A dictionary of auxiliary defaults, to override defaults for settings
+ defined in other components. Override in subclasses."""
+
+ relative_path_settings = ()
+ """Settings containing filesystem paths. Override in subclasses.
+ Settings listed here are to be interpreted relative to the current working
+ directory."""
+
+ config_section = None
+ """The name of the config file section specific to this component
+ (lowercase, no brackets). Override in subclasses."""
+
+ config_section_dependencies = None
+ """A list of names of config file sections that are to be applied before
+ `config_section`, in order (from general to specific). In other words,
+ the settings in `config_section` are to be overlaid on top of the settings
+ from these sections. The "general" section is assumed implicitly.
+ Override in subclasses."""
+
+
+class TransformSpec:
+
+ """
+ Runtime transform specification base class.
+
+ TransformSpec subclass objects used by `docutils.transforms.Transformer`.
+ """
+
+ def get_transforms(self):
+ """Transforms required by this class. Override in subclasses."""
+ if self.default_transforms != ():
+ import warnings
+ warnings.warn('default_transforms attribute deprecated.\n'
+ 'Use get_transforms() method instead.',
+ DeprecationWarning)
+ return list(self.default_transforms)
+ return []
+
+ # Deprecated; for compatibility.
+ default_transforms = ()
+
+ unknown_reference_resolvers = ()
+ """List of functions to try to resolve unknown references. Unknown
+ references have a 'refname' attribute which doesn't correspond to any
+ target in the document. Called when the transforms in
+ `docutils.tranforms.references` are unable to find a correct target. The
+ list should contain functions which will try to resolve unknown
+ references, with the following signature::
+
+ def reference_resolver(node):
+ '''Returns boolean: true if resolved, false if not.'''
+
+ If the function is able to resolve the reference, it should also remove
+ the 'refname' attribute and mark the node as resolved::
+
+ del node['refname']
+ node.resolved = 1
+
+ Each function must have a "priority" attribute which will affect the order
+ the unknown_reference_resolvers are run::
+
+ reference_resolver.priority = 100
+
+ Override in subclasses."""
+
+
+class Component(SettingsSpec, TransformSpec):
+
+ """Base class for Docutils components."""
+
+ component_type = None
+ """Name of the component type ('reader', 'parser', 'writer'). Override in
+ subclasses."""
+
+ supported = ()
+ """Names for this component. Override in subclasses."""
+
+ def supports(self, format):
+ """
+ Is `format` supported by this component?
+
+ To be used by transforms to ask the dependent component if it supports
+ a certain input context or output format.
+ """
+ return format in self.supported
--- /dev/null
+# $Id: core.py 8367 2019-08-27 12:09:56Z milde $
+# Author: David Goodger <goodger@python.org>
+# Copyright: This module has been placed in the public domain.
+
+"""
+Calling the ``publish_*`` convenience functions (or instantiating a
+`Publisher` object) with component names will result in default
+behavior. For custom behavior (setting component options), create
+custom component objects first, and pass *them* to
+``publish_*``/`Publisher`. See `The Docutils Publisher`_.
+
+.. _The Docutils Publisher: http://docutils.sf.net/docs/api/publisher.html
+"""
+from __future__ import print_function
+
+__docformat__ = 'reStructuredText'
+
+import sys
+import pprint
+from docutils import __version__, __version_details__, SettingsSpec
+from docutils import frontend, io, utils, readers, writers
+from docutils.frontend import OptionParser
+from docutils.transforms import Transformer
+from docutils.utils.error_reporting import ErrorOutput, ErrorString
+import docutils.readers.doctree
+
+class Publisher(object):
+
+ """
+ A facade encapsulating the high-level logic of a Docutils system.
+ """
+
+ def __init__(self, reader=None, parser=None, writer=None,
+ source=None, source_class=io.FileInput,
+ destination=None, destination_class=io.FileOutput,
+ settings=None):
+ """
+ Initial setup. If any of `reader`, `parser`, or `writer` are not
+ specified, the corresponding ``set_...`` method should be called with
+ a component name (`set_reader` sets the parser as well).
+ """
+
+ self.document = None
+ """The document tree (`docutils.nodes` objects)."""
+
+ self.reader = reader
+ """A `docutils.readers.Reader` instance."""
+
+ self.parser = parser
+ """A `docutils.parsers.Parser` instance."""
+
+ self.writer = writer
+ """A `docutils.writers.Writer` instance."""
+
+ for component in 'reader', 'parser', 'writer':
+ assert not isinstance(getattr(self, component), str), (
+ 'passed string "%s" as "%s" parameter; pass an instance, '
+ 'or use the "%s_name" parameter instead (in '
+ 'docutils.core.publish_* convenience functions).'
+ % (getattr(self, component), component, component))
+
+ self.source = source
+ """The source of input data, a `docutils.io.Input` instance."""
+
+ self.source_class = source_class
+ """The class for dynamically created source objects."""
+
+ self.destination = destination
+ """The destination for docutils output, a `docutils.io.Output`
+ instance."""
+
+ self.destination_class = destination_class
+ """The class for dynamically created destination objects."""
+
+ self.settings = settings
+ """An object containing Docutils settings as instance attributes.
+ Set by `self.process_command_line()` or `self.get_settings()`."""
+
+ self._stderr = ErrorOutput()
+
+ def set_reader(self, reader_name, parser, parser_name):
+ """Set `self.reader` by name."""
+ reader_class = readers.get_reader_class(reader_name)
+ self.reader = reader_class(parser, parser_name)
+ self.parser = self.reader.parser
+
+ def set_writer(self, writer_name):
+ """Set `self.writer` by name."""
+ writer_class = writers.get_writer_class(writer_name)
+ self.writer = writer_class()
+
+ def set_components(self, reader_name, parser_name, writer_name):
+ if self.reader is None:
+ self.set_reader(reader_name, self.parser, parser_name)
+ if self.parser is None:
+ if self.reader.parser is None:
+ self.reader.set_parser(parser_name)
+ self.parser = self.reader.parser
+ if self.writer is None:
+ self.set_writer(writer_name)
+
+ def setup_option_parser(self, usage=None, description=None,
+ settings_spec=None, config_section=None,
+ **defaults):
+ if config_section:
+ if not settings_spec:
+ settings_spec = SettingsSpec()
+ settings_spec.config_section = config_section
+ parts = config_section.split()
+ if len(parts) > 1 and parts[-1] == 'application':
+ settings_spec.config_section_dependencies = ['applications']
+ #@@@ Add self.source & self.destination to components in future?
+ option_parser = OptionParser(
+ components=(self.parser, self.reader, self.writer, settings_spec),
+ defaults=defaults, read_config_files=True,
+ usage=usage, description=description)
+ return option_parser
+
+ def get_settings(self, usage=None, description=None,
+ settings_spec=None, config_section=None, **defaults):
+ """
+ Set and return default settings (overrides in `defaults` dict).
+
+ Set components first (`self.set_reader` & `self.set_writer`).
+ Explicitly setting `self.settings` disables command line option
+ processing from `self.publish()`.
+ """
+ option_parser = self.setup_option_parser(
+ usage, description, settings_spec, config_section, **defaults)
+ self.settings = option_parser.get_default_values()
+ return self.settings
+
+ def process_programmatic_settings(self, settings_spec,
+ settings_overrides,
+ config_section):
+ if self.settings is None:
+ defaults = (settings_overrides or {}).copy()
+ # Propagate exceptions by default when used programmatically:
+ defaults.setdefault('traceback', True)
+ self.get_settings(settings_spec=settings_spec,
+ config_section=config_section,
+ **defaults)
+
+ def process_command_line(self, argv=None, usage=None, description=None,
+ settings_spec=None, config_section=None,
+ **defaults):
+ """
+ Pass an empty list to `argv` to avoid reading `sys.argv` (the
+ default).
+
+ Set components first (`self.set_reader` & `self.set_writer`).
+ """
+ option_parser = self.setup_option_parser(
+ usage, description, settings_spec, config_section, **defaults)
+ if argv is None:
+ argv = sys.argv[1:]
+ # converting to Unicode (Python 3 does this automatically):
+ if sys.version_info < (3, 0):
+ # TODO: make this failsafe and reversible?
+ argv_encoding = (frontend.locale_encoding or 'ascii')
+ argv = [a.decode(argv_encoding) for a in argv]
+ self.settings = option_parser.parse_args(argv)
+
+ def set_io(self, source_path=None, destination_path=None):
+ if self.source is None:
+ self.set_source(source_path=source_path)
+ if self.destination is None:
+ self.set_destination(destination_path=destination_path)
+
+ def set_source(self, source=None, source_path=None):
+ if source_path is None:
+ source_path = self.settings._source
+ else:
+ self.settings._source = source_path
+ # Raise IOError instead of system exit with `tracback == True`
+ # TODO: change io.FileInput's default behaviour and remove this hack
+ try:
+ self.source = self.source_class(
+ source=source, source_path=source_path,
+ encoding=self.settings.input_encoding)
+ except TypeError:
+ self.source = self.source_class(
+ source=source, source_path=source_path,
+ encoding=self.settings.input_encoding)
+
+ def set_destination(self, destination=None, destination_path=None):
+ if destination_path is None:
+ destination_path = self.settings._destination
+ else:
+ self.settings._destination = destination_path
+ self.destination = self.destination_class(
+ destination=destination, destination_path=destination_path,
+ encoding=self.settings.output_encoding,
+ error_handler=self.settings.output_encoding_error_handler)
+
+ def apply_transforms(self):
+ self.document.transformer.populate_from_components(
+ (self.source, self.reader, self.reader.parser, self.writer,
+ self.destination))
+ self.document.transformer.apply_transforms()
+
+ def publish(self, argv=None, usage=None, description=None,
+ settings_spec=None, settings_overrides=None,
+ config_section=None, enable_exit_status=False):
+ """
+ Process command line options and arguments (if `self.settings` not
+ already set), run `self.reader` and then `self.writer`. Return
+ `self.writer`'s output.
+ """
+ exit = None
+ try:
+ if self.settings is None:
+ self.process_command_line(
+ argv, usage, description, settings_spec, config_section,
+ **(settings_overrides or {}))
+ self.set_io()
+ self.document = self.reader.read(self.source, self.parser,
+ self.settings)
+ self.apply_transforms()
+ output = self.writer.write(self.document, self.destination)
+ self.writer.assemble_parts()
+ except SystemExit as error:
+ exit = 1
+ exit_status = error.code
+ except Exception as error:
+ if not self.settings: # exception too early to report nicely
+ raise
+ if self.settings.traceback: # Propagate exceptions?
+ self.debugging_dumps()
+ raise
+ self.report_Exception(error)
+ exit = True
+ exit_status = 1
+ self.debugging_dumps()
+ if (enable_exit_status and self.document
+ and (self.document.reporter.max_level
+ >= self.settings.exit_status_level)):
+ sys.exit(self.document.reporter.max_level + 10)
+ elif exit:
+ sys.exit(exit_status)
+ return output
+
+ def debugging_dumps(self):
+ if not self.document:
+ return
+ if self.settings.dump_settings:
+ print('\n::: Runtime settings:', file=self._stderr)
+ print(pprint.pformat(self.settings.__dict__), file=self._stderr)
+ if self.settings.dump_internals:
+ print('\n::: Document internals:', file=self._stderr)
+ print(pprint.pformat(self.document.__dict__), file=self._stderr)
+ if self.settings.dump_transforms:
+ print('\n::: Transforms applied:', file=self._stderr)
+ print(' (priority, transform class, pending node details, '
+ 'keyword args)', file=self._stderr)
+ print(pprint.pformat(
+ [(priority, '%s.%s' % (xclass.__module__, xclass.__name__),
+ pending and pending.details, kwargs)
+ for priority, xclass, pending, kwargs
+ in self.document.transformer.applied]), file=self._stderr)
+ if self.settings.dump_pseudo_xml:
+ print('\n::: Pseudo-XML:', file=self._stderr)
+ print(self.document.pformat().encode(
+ 'raw_unicode_escape'), file=self._stderr)
+
+ def report_Exception(self, error):
+ if isinstance(error, utils.SystemMessage):
+ self.report_SystemMessage(error)
+ elif isinstance(error, UnicodeEncodeError):
+ self.report_UnicodeError(error)
+ elif isinstance(error, io.InputError):
+ self._stderr.write(u'Unable to open source file for reading:\n'
+ u' %s\n' % ErrorString(error))
+ elif isinstance(error, io.OutputError):
+ self._stderr.write(
+ u'Unable to open destination file for writing:\n'
+ u' %s\n' % ErrorString(error))
+ else:
+ print(u'%s' % ErrorString(error), file=self._stderr)
+ print(("""\
+Exiting due to error. Use "--traceback" to diagnose.
+Please report errors to <docutils-users@lists.sf.net>.
+Include "--traceback" output, Docutils version (%s%s),
+Python version (%s), your OS type & version, and the
+command line used.""" % (__version__,
+ docutils.__version_details__ and
+ ' [%s]'%docutils.__version_details__ or '',
+ sys.version.split()[0])), file=self._stderr)
+
+ def report_SystemMessage(self, error):
+ print('Exiting due to level-%s (%s) system message.' % (
+ error.level, utils.Reporter.levels[error.level]),
+ file=self._stderr)
+
+ def report_UnicodeError(self, error):
+ data = error.object[error.start:error.end]
+ self._stderr.write(
+ '%s\n'
+ '\n'
+ 'The specified output encoding (%s) cannot\n'
+ 'handle all of the output.\n'
+ 'Try setting "--output-encoding-error-handler" to\n'
+ '\n'
+ '* "xmlcharrefreplace" (for HTML & XML output);\n'
+ ' the output will contain "%s" and should be usable.\n'
+ '* "backslashreplace" (for other output formats);\n'
+ ' look for "%s" in the output.\n'
+ '* "replace"; look for "?" in the output.\n'
+ '\n'
+ '"--output-encoding-error-handler" is currently set to "%s".\n'
+ '\n'
+ 'Exiting due to error. Use "--traceback" to diagnose.\n'
+ 'If the advice above doesn\'t eliminate the error,\n'
+ 'please report it to <docutils-users@lists.sf.net>.\n'
+ 'Include "--traceback" output, Docutils version (%s),\n'
+ 'Python version (%s), your OS type & version, and the\n'
+ 'command line used.\n'
+ % (ErrorString(error),
+ self.settings.output_encoding,
+ data.encode('ascii', 'xmlcharrefreplace'),
+ data.encode('ascii', 'backslashreplace'),
+ self.settings.output_encoding_error_handler,
+ __version__, sys.version.split()[0]))
+
+default_usage = '%prog [options] [<source> [<destination>]]'
+default_description = ('Reads from <source> (default is stdin) and writes to '
+ '<destination> (default is stdout). See '
+ '<http://docutils.sf.net/docs/user/config.html> for '
+ 'the full reference.')
+
+def publish_cmdline(reader=None, reader_name='standalone',
+ parser=None, parser_name='restructuredtext',
+ writer=None, writer_name='pseudoxml',
+ settings=None, settings_spec=None,
+ settings_overrides=None, config_section=None,
+ enable_exit_status=True, argv=None,
+ usage=default_usage, description=default_description):
+ """
+ Set up & run a `Publisher` for command-line-based file I/O (input and
+ output file paths taken automatically from the command line). Return the
+ encoded string output also.
+
+ Parameters: see `publish_programmatically` for the remainder.
+
+ - `argv`: Command-line argument list to use instead of ``sys.argv[1:]``.
+ - `usage`: Usage string, output if there's a problem parsing the command
+ line.
+ - `description`: Program description, output for the "--help" option
+ (along with command-line option descriptions).
+ """
+ pub = Publisher(reader, parser, writer, settings=settings)
+ pub.set_components(reader_name, parser_name, writer_name)
+ output = pub.publish(
+ argv, usage, description, settings_spec, settings_overrides,
+ config_section=config_section, enable_exit_status=enable_exit_status)
+ return output
+
+def publish_file(source=None, source_path=None,
+ destination=None, destination_path=None,
+ reader=None, reader_name='standalone',
+ parser=None, parser_name='restructuredtext',
+ writer=None, writer_name='pseudoxml',
+ settings=None, settings_spec=None, settings_overrides=None,
+ config_section=None, enable_exit_status=False):
+ """
+ Set up & run a `Publisher` for programmatic use with file-like I/O.
+ Return the encoded string output also.
+
+ Parameters: see `publish_programmatically`.
+ """
+ output, pub = publish_programmatically(
+ source_class=io.FileInput, source=source, source_path=source_path,
+ destination_class=io.FileOutput,
+ destination=destination, destination_path=destination_path,
+ reader=reader, reader_name=reader_name,
+ parser=parser, parser_name=parser_name,
+ writer=writer, writer_name=writer_name,
+ settings=settings, settings_spec=settings_spec,
+ settings_overrides=settings_overrides,
+ config_section=config_section,
+ enable_exit_status=enable_exit_status)
+ return output
+
+def publish_string(source, source_path=None, destination_path=None,
+ reader=None, reader_name='standalone',
+ parser=None, parser_name='restructuredtext',
+ writer=None, writer_name='pseudoxml',
+ settings=None, settings_spec=None,
+ settings_overrides=None, config_section=None,
+ enable_exit_status=False):
+ """
+ Set up & run a `Publisher` for programmatic use with string I/O. Return
+ the encoded string or Unicode string output.
+
+ For encoded string output, be sure to set the 'output_encoding' setting to
+ the desired encoding. Set it to 'unicode' for unencoded Unicode string
+ output. Here's one way::
+
+ publish_string(..., settings_overrides={'output_encoding': 'unicode'})
+
+ Similarly for Unicode string input (`source`)::
+
+ publish_string(..., settings_overrides={'input_encoding': 'unicode'})
+
+ Parameters: see `publish_programmatically`.
+ """
+ output, pub = publish_programmatically(
+ source_class=io.StringInput, source=source, source_path=source_path,
+ destination_class=io.StringOutput,
+ destination=None, destination_path=destination_path,
+ reader=reader, reader_name=reader_name,
+ parser=parser, parser_name=parser_name,
+ writer=writer, writer_name=writer_name,
+ settings=settings, settings_spec=settings_spec,
+ settings_overrides=settings_overrides,
+ config_section=config_section,
+ enable_exit_status=enable_exit_status)
+ return output
+
+def publish_parts(source, source_path=None, source_class=io.StringInput,
+ destination_path=None,
+ reader=None, reader_name='standalone',
+ parser=None, parser_name='restructuredtext',
+ writer=None, writer_name='pseudoxml',
+ settings=None, settings_spec=None,
+ settings_overrides=None, config_section=None,
+ enable_exit_status=False):
+ """
+ Set up & run a `Publisher`, and return a dictionary of document parts.
+ Dictionary keys are the names of parts, and values are Unicode strings;
+ encoding is up to the client. For programmatic use with string I/O.
+
+ For encoded string input, be sure to set the 'input_encoding' setting to
+ the desired encoding. Set it to 'unicode' for unencoded Unicode string
+ input. Here's how::
+
+ publish_parts(..., settings_overrides={'input_encoding': 'unicode'})
+
+ Parameters: see `publish_programmatically`.
+ """
+ output, pub = publish_programmatically(
+ source=source, source_path=source_path, source_class=source_class,
+ destination_class=io.StringOutput,
+ destination=None, destination_path=destination_path,
+ reader=reader, reader_name=reader_name,
+ parser=parser, parser_name=parser_name,
+ writer=writer, writer_name=writer_name,
+ settings=settings, settings_spec=settings_spec,
+ settings_overrides=settings_overrides,
+ config_section=config_section,
+ enable_exit_status=enable_exit_status)
+ return pub.writer.parts
+
+def publish_doctree(source, source_path=None,
+ source_class=io.StringInput,
+ reader=None, reader_name='standalone',
+ parser=None, parser_name='restructuredtext',
+ settings=None, settings_spec=None,
+ settings_overrides=None, config_section=None,
+ enable_exit_status=False):
+ """
+ Set up & run a `Publisher` for programmatic use with string I/O.
+ Return the document tree.
+
+ For encoded string input, be sure to set the 'input_encoding' setting to
+ the desired encoding. Set it to 'unicode' for unencoded Unicode string
+ input. Here's one way::
+
+ publish_doctree(..., settings_overrides={'input_encoding': 'unicode'})
+
+ Parameters: see `publish_programmatically`.
+ """
+ pub = Publisher(reader=reader, parser=parser, writer=None,
+ settings=settings,
+ source_class=source_class,
+ destination_class=io.NullOutput)
+ pub.set_components(reader_name, parser_name, 'null')
+ pub.process_programmatic_settings(
+ settings_spec, settings_overrides, config_section)
+ pub.set_source(source, source_path)
+ pub.set_destination(None, None)
+ output = pub.publish(enable_exit_status=enable_exit_status)
+ return pub.document
+
+def publish_from_doctree(document, destination_path=None,
+ writer=None, writer_name='pseudoxml',
+ settings=None, settings_spec=None,
+ settings_overrides=None, config_section=None,
+ enable_exit_status=False):
+ """
+ Set up & run a `Publisher` to render from an existing document
+ tree data structure, for programmatic use with string I/O. Return
+ the encoded string output.
+
+ Note that document.settings is overridden; if you want to use the settings
+ of the original `document`, pass settings=document.settings.
+
+ Also, new document.transformer and document.reporter objects are
+ generated.
+
+ For encoded string output, be sure to set the 'output_encoding' setting to
+ the desired encoding. Set it to 'unicode' for unencoded Unicode string
+ output. Here's one way::
+
+ publish_from_doctree(
+ ..., settings_overrides={'output_encoding': 'unicode'})
+
+ Parameters: `document` is a `docutils.nodes.document` object, an existing
+ document tree.
+
+ Other parameters: see `publish_programmatically`.
+ """
+ reader = docutils.readers.doctree.Reader(parser_name='null')
+ pub = Publisher(reader, None, writer,
+ source=io.DocTreeInput(document),
+ destination_class=io.StringOutput, settings=settings)
+ if not writer and writer_name:
+ pub.set_writer(writer_name)
+ pub.process_programmatic_settings(
+ settings_spec, settings_overrides, config_section)
+ pub.set_destination(None, destination_path)
+ return pub.publish(enable_exit_status=enable_exit_status)
+
+def publish_cmdline_to_binary(reader=None, reader_name='standalone',
+ parser=None, parser_name='restructuredtext',
+ writer=None, writer_name='pseudoxml',
+ settings=None, settings_spec=None,
+ settings_overrides=None, config_section=None,
+ enable_exit_status=True, argv=None,
+ usage=default_usage, description=default_description,
+ destination=None, destination_class=io.BinaryFileOutput
+ ):
+ """
+ Set up & run a `Publisher` for command-line-based file I/O (input and
+ output file paths taken automatically from the command line). Return the
+ encoded string output also.
+
+ This is just like publish_cmdline, except that it uses
+ io.BinaryFileOutput instead of io.FileOutput.
+
+ Parameters: see `publish_programmatically` for the remainder.
+
+ - `argv`: Command-line argument list to use instead of ``sys.argv[1:]``.
+ - `usage`: Usage string, output if there's a problem parsing the command
+ line.
+ - `description`: Program description, output for the "--help" option
+ (along with command-line option descriptions).
+ """
+ pub = Publisher(reader, parser, writer, settings=settings,
+ destination_class=destination_class)
+ pub.set_components(reader_name, parser_name, writer_name)
+ output = pub.publish(
+ argv, usage, description, settings_spec, settings_overrides,
+ config_section=config_section, enable_exit_status=enable_exit_status)
+ return output
+
+def publish_programmatically(source_class, source, source_path,
+ destination_class, destination, destination_path,
+ reader, reader_name,
+ parser, parser_name,
+ writer, writer_name,
+ settings, settings_spec,
+ settings_overrides, config_section,
+ enable_exit_status):
+ """
+ Set up & run a `Publisher` for custom programmatic use. Return the
+ encoded string output and the Publisher object.
+
+ Applications should not need to call this function directly. If it does
+ seem to be necessary to call this function directly, please write to the
+ Docutils-develop mailing list
+ <http://docutils.sf.net/docs/user/mailing-lists.html#docutils-develop>.
+
+ Parameters:
+
+ * `source_class` **required**: The class for dynamically created source
+ objects. Typically `io.FileInput` or `io.StringInput`.
+
+ * `source`: Type depends on `source_class`:
+
+ - If `source_class` is `io.FileInput`: Either a file-like object
+ (must have 'read' and 'close' methods), or ``None``
+ (`source_path` is opened). If neither `source` nor
+ `source_path` are supplied, `sys.stdin` is used.
+
+ - If `source_class` is `io.StringInput` **required**: The input
+ string, either an encoded 8-bit string (set the
+ 'input_encoding' setting to the correct encoding) or a Unicode
+ string (set the 'input_encoding' setting to 'unicode').
+
+ * `source_path`: Type depends on `source_class`:
+
+ - `io.FileInput`: Path to the input file, opened if no `source`
+ supplied.
+
+ - `io.StringInput`: Optional. Path to the file or object that produced
+ `source`. Only used for diagnostic output.
+
+ * `destination_class` **required**: The class for dynamically created
+ destination objects. Typically `io.FileOutput` or `io.StringOutput`.
+
+ * `destination`: Type depends on `destination_class`:
+
+ - `io.FileOutput`: Either a file-like object (must have 'write' and
+ 'close' methods), or ``None`` (`destination_path` is opened). If
+ neither `destination` nor `destination_path` are supplied,
+ `sys.stdout` is used.
+
+ - `io.StringOutput`: Not used; pass ``None``.
+
+ * `destination_path`: Type depends on `destination_class`:
+
+ - `io.FileOutput`: Path to the output file. Opened if no `destination`
+ supplied.
+
+ - `io.StringOutput`: Path to the file or object which will receive the
+ output; optional. Used for determining relative paths (stylesheets,
+ source links, etc.).
+
+ * `reader`: A `docutils.readers.Reader` object.
+
+ * `reader_name`: Name or alias of the Reader class to be instantiated if
+ no `reader` supplied.
+
+ * `parser`: A `docutils.parsers.Parser` object.
+
+ * `parser_name`: Name or alias of the Parser class to be instantiated if
+ no `parser` supplied.
+
+ * `writer`: A `docutils.writers.Writer` object.
+
+ * `writer_name`: Name or alias of the Writer class to be instantiated if
+ no `writer` supplied.
+
+ * `settings`: A runtime settings (`docutils.frontend.Values`) object, for
+ dotted-attribute access to runtime settings. It's the end result of the
+ `SettingsSpec`, config file, and option processing. If `settings` is
+ passed, it's assumed to be complete and no further setting/config/option
+ processing is done.
+
+ * `settings_spec`: A `docutils.SettingsSpec` subclass or object. Provides
+ extra application-specific settings definitions independently of
+ components. In other words, the application becomes a component, and
+ its settings data is processed along with that of the other components.
+ Used only if no `settings` specified.
+
+ * `settings_overrides`: A dictionary containing application-specific
+ settings defaults that override the defaults of other components.
+ Used only if no `settings` specified.
+
+ * `config_section`: A string, the name of the configuration file section
+ for this application. Overrides the ``config_section`` attribute
+ defined by `settings_spec`. Used only if no `settings` specified.
+
+ * `enable_exit_status`: Boolean; enable exit status at end of processing?
+ """
+ pub = Publisher(reader, parser, writer, settings=settings,
+ source_class=source_class,
+ destination_class=destination_class)
+ pub.set_components(reader_name, parser_name, writer_name)
+ pub.process_programmatic_settings(
+ settings_spec, settings_overrides, config_section)
+ pub.set_source(source, source_path)
+ pub.set_destination(destination, destination_path)
+ output = pub.publish(enable_exit_status=enable_exit_status)
+ return output, pub
--- /dev/null
+# This configuration file is to prevent tools/buildhtml.py from
+# processing text files in and below this directory.
+
+[buildhtml application]
+prune: .
--- /dev/null
+# $Id: examples.py 7320 2012-01-19 22:33:02Z milde $
+# Author: David Goodger <goodger@python.org>
+# Copyright: This module has been placed in the public domain.
+
+"""
+This module contains practical examples of Docutils client code.
+
+Importing this module from client code is not recommended; its contents are
+subject to change in future Docutils releases. Instead, it is recommended
+that you copy and paste the parts you need into your own code, modifying as
+necessary.
+"""
+
+from docutils import core, io
+
+
+def html_parts(input_string, source_path=None, destination_path=None,
+ input_encoding='unicode', doctitle=True,
+ initial_header_level=1):
+ """
+ Given an input string, returns a dictionary of HTML document parts.
+
+ Dictionary keys are the names of parts, and values are Unicode strings;
+ encoding is up to the client.
+
+ Parameters:
+
+ - `input_string`: A multi-line text string; required.
+ - `source_path`: Path to the source file or object. Optional, but useful
+ for diagnostic output (system messages).
+ - `destination_path`: Path to the file or object which will receive the
+ output; optional. Used for determining relative paths (stylesheets,
+ source links, etc.).
+ - `input_encoding`: The encoding of `input_string`. If it is an encoded
+ 8-bit string, provide the correct encoding. If it is a Unicode string,
+ use "unicode", the default.
+ - `doctitle`: Disable the promotion of a lone top-level section title to
+ document title (and subsequent section title to document subtitle
+ promotion); enabled by default.
+ - `initial_header_level`: The initial level for header elements (e.g. 1
+ for "<h1>").
+ """
+ overrides = {'input_encoding': input_encoding,
+ 'doctitle_xform': doctitle,
+ 'initial_header_level': initial_header_level}
+ parts = core.publish_parts(
+ source=input_string, source_path=source_path,
+ destination_path=destination_path,
+ writer_name='html', settings_overrides=overrides)
+ return parts
+
+def html_body(input_string, source_path=None, destination_path=None,
+ input_encoding='unicode', output_encoding='unicode',
+ doctitle=True, initial_header_level=1):
+ """
+ Given an input string, returns an HTML fragment as a string.
+
+ The return value is the contents of the <body> element.
+
+ Parameters (see `html_parts()` for the remainder):
+
+ - `output_encoding`: The desired encoding of the output. If a Unicode
+ string is desired, use the default value of "unicode" .
+ """
+ parts = html_parts(
+ input_string=input_string, source_path=source_path,
+ destination_path=destination_path,
+ input_encoding=input_encoding, doctitle=doctitle,
+ initial_header_level=initial_header_level)
+ fragment = parts['html_body']
+ if output_encoding != 'unicode':
+ fragment = fragment.encode(output_encoding)
+ return fragment
+
+def internals(input_string, source_path=None, destination_path=None,
+ input_encoding='unicode', settings_overrides=None):
+ """
+ Return the document tree and publisher, for exploring Docutils internals.
+
+ Parameters: see `html_parts()`.
+ """
+ if settings_overrides:
+ overrides = settings_overrides.copy()
+ else:
+ overrides = {}
+ overrides['input_encoding'] = input_encoding
+ output, pub = core.publish_programmatically(
+ source_class=io.StringInput, source=input_string,
+ source_path=source_path,
+ destination_class=io.NullOutput, destination=None,
+ destination_path=destination_path,
+ reader=None, reader_name='standalone',
+ parser=None, parser_name='restructuredtext',
+ writer=None, writer_name='null',
+ settings=None, settings_spec=None, settings_overrides=overrides,
+ config_section=None, enable_exit_status=None)
+ return pub.writer.document, pub
--- /dev/null
+# $Id: frontend.py 8439 2019-12-13 17:02:41Z milde $
+# Author: David Goodger <goodger@python.org>
+# Copyright: This module has been placed in the public domain.
+
+"""
+Command-line and common processing for Docutils front-end tools.
+
+Exports the following classes:
+
+* `OptionParser`: Standard Docutils command-line processing.
+* `Option`: Customized version of `optparse.Option`; validation support.
+* `Values`: Runtime settings; objects are simple structs
+ (``object.attribute``). Supports cumulative list settings (attributes).
+* `ConfigParser`: Standard Docutils config file processing.
+
+Also exports the following functions:
+
+* Option callbacks: `store_multiple`, `read_config_file`.
+* Setting validators: `validate_encoding`,
+ `validate_encoding_error_handler`,
+ `validate_encoding_and_error_handler`,
+ `validate_boolean`, `validate_ternary`, `validate_threshold`,
+ `validate_colon_separated_string_list`,
+ `validate_comma_separated_string_list`,
+ `validate_dependency_file`.
+* `make_paths_absolute`.
+* SettingSpec manipulation: `filter_settings_spec`.
+"""
+
+__docformat__ = 'reStructuredText'
+
+import os
+import os.path
+import sys
+import warnings
+import codecs
+import optparse
+from optparse import SUPPRESS_HELP
+if sys.version_info >= (3, 0):
+ from configparser import RawConfigParser
+ from os import getcwd
+else:
+ from ConfigParser import RawConfigParser
+ from os import getcwdu as getcwd
+
+import docutils
+import docutils.utils
+import docutils.nodes
+from docutils.utils.error_reporting import (locale_encoding, SafeString,
+ ErrorOutput, ErrorString)
+
+if sys.version_info >= (3, 0):
+ unicode = str # noqa
+
+
+def store_multiple(option, opt, value, parser, *args, **kwargs):
+ """
+ Store multiple values in `parser.values`. (Option callback.)
+
+ Store `None` for each attribute named in `args`, and store the value for
+ each key (attribute name) in `kwargs`.
+ """
+ for attribute in args:
+ setattr(parser.values, attribute, None)
+ for key, value in kwargs.items():
+ setattr(parser.values, key, value)
+
+def read_config_file(option, opt, value, parser):
+ """
+ Read a configuration file during option processing. (Option callback.)
+ """
+ try:
+ new_settings = parser.get_config_file_settings(value)
+ except ValueError as error:
+ parser.error(error)
+ parser.values.update(new_settings, parser)
+
+def validate_encoding(setting, value, option_parser,
+ config_parser=None, config_section=None):
+ try:
+ codecs.lookup(value)
+ except LookupError:
+ raise LookupError('setting "%s": unknown encoding: "%s"'
+ % (setting, value))
+ return value
+
+def validate_encoding_error_handler(setting, value, option_parser,
+ config_parser=None, config_section=None):
+ try:
+ codecs.lookup_error(value)
+ except LookupError:
+ raise LookupError(
+ 'unknown encoding error handler: "%s" (choices: '
+ '"strict", "ignore", "replace", "backslashreplace", '
+ '"xmlcharrefreplace", and possibly others; see documentation for '
+ 'the Python ``codecs`` module)' % value)
+ return value
+
+def validate_encoding_and_error_handler(
+ setting, value, option_parser, config_parser=None, config_section=None):
+ """
+ Side-effect: if an error handler is included in the value, it is inserted
+ into the appropriate place as if it was a separate setting/option.
+ """
+ if ':' in value:
+ encoding, handler = value.split(':')
+ validate_encoding_error_handler(
+ setting + '_error_handler', handler, option_parser,
+ config_parser, config_section)
+ if config_parser:
+ config_parser.set(config_section, setting + '_error_handler',
+ handler)
+ else:
+ setattr(option_parser.values, setting + '_error_handler', handler)
+ else:
+ encoding = value
+ validate_encoding(setting, encoding, option_parser,
+ config_parser, config_section)
+ return encoding
+
+def validate_boolean(setting, value, option_parser,
+ config_parser=None, config_section=None):
+ """Check/normalize boolean settings:
+ True: '1', 'on', 'yes', 'true'
+ False: '0', 'off', 'no','false', ''
+ """
+ if isinstance(value, bool):
+ return value
+ try:
+ return option_parser.booleans[value.strip().lower()]
+ except KeyError:
+ raise LookupError('unknown boolean value: "%s"' % value)
+
+def validate_ternary(setting, value, option_parser,
+ config_parser=None, config_section=None):
+ """Check/normalize three-value settings:
+ True: '1', 'on', 'yes', 'true'
+ False: '0', 'off', 'no','false', ''
+ any other value: returned as-is.
+ """
+ if isinstance(value, bool) or value is None:
+ return value
+ try:
+ return option_parser.booleans[value.strip().lower()]
+ except KeyError:
+ return value
+
+def validate_nonnegative_int(setting, value, option_parser,
+ config_parser=None, config_section=None):
+ value = int(value)
+ if value < 0:
+ raise ValueError('negative value; must be positive or zero')
+ return value
+
+def validate_threshold(setting, value, option_parser,
+ config_parser=None, config_section=None):
+ try:
+ return int(value)
+ except ValueError:
+ try:
+ return option_parser.thresholds[value.lower()]
+ except (KeyError, AttributeError):
+ raise LookupError('unknown threshold: %r.' % value)
+
+def validate_colon_separated_string_list(
+ setting, value, option_parser, config_parser=None, config_section=None):
+ if not isinstance(value, list):
+ value = value.split(':')
+ else:
+ last = value.pop()
+ value.extend(last.split(':'))
+ return value
+
+def validate_comma_separated_list(setting, value, option_parser,
+ config_parser=None, config_section=None):
+ """Check/normalize list arguments (split at "," and strip whitespace).
+ """
+ # `value` is already a ``list`` when given as command line option
+ # and "action" is "append" and ``unicode`` or ``str`` else.
+ if not isinstance(value, list):
+ value = [value]
+ # this function is called for every option added to `value`
+ # -> split the last item and append the result:
+ last = value.pop()
+ items = [i.strip(u' \t\n') for i in last.split(u',') if i.strip(u' \t\n')]
+ value.extend(items)
+ return value
+
+def validate_url_trailing_slash(
+ setting, value, option_parser, config_parser=None, config_section=None):
+ if not value:
+ return './'
+ elif value.endswith('/'):
+ return value
+ else:
+ return value + '/'
+
+def validate_dependency_file(setting, value, option_parser,
+ config_parser=None, config_section=None):
+ try:
+ return docutils.utils.DependencyList(value)
+ except IOError:
+ return docutils.utils.DependencyList(None)
+
+def validate_strip_class(setting, value, option_parser,
+ config_parser=None, config_section=None):
+ # value is a comma separated string list:
+ value = validate_comma_separated_list(setting, value, option_parser,
+ config_parser, config_section)
+ # validate list elements:
+ for cls in value:
+ normalized = docutils.nodes.make_id(cls)
+ if cls != normalized:
+ raise ValueError('Invalid class value %r (perhaps %r?)'
+ % (cls, normalized))
+ return value
+
+def validate_smartquotes_locales(setting, value, option_parser,
+ config_parser=None, config_section=None):
+ """Check/normalize a comma separated list of smart quote definitions.
+
+ Return a list of (language-tag, quotes) string tuples."""
+
+ # value is a comma separated string list:
+ value = validate_comma_separated_list(setting, value, option_parser,
+ config_parser, config_section)
+ # validate list elements
+ lc_quotes = []
+ for item in value:
+ try:
+ lang, quotes = item.split(':', 1)
+ except AttributeError:
+ # this function is called for every option added to `value`
+ # -> ignore if already a tuple:
+ lc_quotes.append(item)
+ continue
+ except ValueError:
+ raise ValueError(u'Invalid value "%s".'
+ ' Format is "<language>:<quotes>".'
+ % item.encode('ascii', 'backslashreplace'))
+ # parse colon separated string list:
+ quotes = quotes.strip()
+ multichar_quotes = quotes.split(':')
+ if len(multichar_quotes) == 4:
+ quotes = multichar_quotes
+ elif len(quotes) != 4:
+ raise ValueError('Invalid value "%s". Please specify 4 quotes\n'
+ ' (primary open/close; secondary open/close).'
+ % item.encode('ascii', 'backslashreplace'))
+ lc_quotes.append((lang, quotes))
+ return lc_quotes
+
+def make_paths_absolute(pathdict, keys, base_path=None):
+ """
+ Interpret filesystem path settings relative to the `base_path` given.
+
+ Paths are values in `pathdict` whose keys are in `keys`. Get `keys` from
+ `OptionParser.relative_path_settings`.
+ """
+ if base_path is None:
+ base_path = getcwd() # type(base_path) == unicode
+ # to allow combining non-ASCII cwd with unicode values in `pathdict`
+ for key in keys:
+ if key in pathdict:
+ value = pathdict[key]
+ if isinstance(value, list):
+ value = [make_one_path_absolute(base_path, path)
+ for path in value]
+ elif value:
+ value = make_one_path_absolute(base_path, value)
+ pathdict[key] = value
+
+def make_one_path_absolute(base_path, path):
+ return os.path.abspath(os.path.join(base_path, path))
+
+def filter_settings_spec(settings_spec, *exclude, **replace):
+ """Return a copy of `settings_spec` excluding/replacing some settings.
+
+ `settings_spec` is a tuple of configuration settings with a structure
+ described for docutils.SettingsSpec.settings_spec.
+
+ Optional positional arguments are names of to-be-excluded settings.
+ Keyword arguments are option specification replacements.
+ (See the html4strict writer for an example.)
+ """
+ settings = list(settings_spec)
+ # every third item is a sequence of option tuples
+ for i in range(2, len(settings), 3):
+ newopts = []
+ for opt_spec in settings[i]:
+ # opt_spec is ("<help>", [<option strings>], {<keyword args>})
+ opt_name = [opt_string[2:].replace('-', '_')
+ for opt_string in opt_spec[1]
+ if opt_string.startswith('--')
+ ][0]
+ if opt_name in exclude:
+ continue
+ if opt_name in replace.keys():
+ newopts.append(replace[opt_name])
+ else:
+ newopts.append(opt_spec)
+ settings[i] = tuple(newopts)
+ return tuple(settings)
+
+
+class Values(optparse.Values):
+
+ """
+ Updates list attributes by extension rather than by replacement.
+ Works in conjunction with the `OptionParser.lists` instance attribute.
+ """
+
+ def __init__(self, *args, **kwargs):
+ optparse.Values.__init__(self, *args, **kwargs)
+ if (not hasattr(self, 'record_dependencies')
+ or self.record_dependencies is None):
+ # Set up dependency list, in case it is needed.
+ self.record_dependencies = docutils.utils.DependencyList()
+
+ def update(self, other_dict, option_parser):
+ if isinstance(other_dict, Values):
+ other_dict = other_dict.__dict__
+ other_dict = other_dict.copy()
+ for setting in option_parser.lists.keys():
+ if (hasattr(self, setting) and setting in other_dict):
+ value = getattr(self, setting)
+ if value:
+ value += other_dict[setting]
+ del other_dict[setting]
+ self._update_loose(other_dict)
+
+ def copy(self):
+ """Return a shallow copy of `self`."""
+ return self.__class__(defaults=self.__dict__)
+
+
+class Option(optparse.Option):
+
+ ATTRS = optparse.Option.ATTRS + ['validator', 'overrides']
+
+ def process(self, opt, value, values, parser):
+ """
+ Call the validator function on applicable settings and
+ evaluate the 'overrides' option.
+ Extends `optparse.Option.process`.
+ """
+ result = optparse.Option.process(self, opt, value, values, parser)
+ setting = self.dest
+ if setting:
+ if self.validator:
+ value = getattr(values, setting)
+ try:
+ new_value = self.validator(setting, value, parser)
+ except Exception as error:
+ raise optparse.OptionValueError(
+ 'Error in option "%s":\n %s'
+ % (opt, ErrorString(error)))
+ setattr(values, setting, new_value)
+ if self.overrides:
+ setattr(values, self.overrides, None)
+ return result
+
+
+class OptionParser(optparse.OptionParser, docutils.SettingsSpec):
+
+ """
+ Parser for command-line and library use. The `settings_spec`
+ specification here and in other Docutils components are merged to build
+ the set of command-line options and runtime settings for this process.
+
+ Common settings (defined below) and component-specific settings must not
+ conflict. Short options are reserved for common settings, and components
+ are restrict to using long options.
+ """
+
+ standard_config_files = [
+ '/etc/docutils.conf', # system-wide
+ './docutils.conf', # project-specific
+ '~/.docutils'] # user-specific
+ """Docutils configuration files, using ConfigParser syntax. Filenames
+ will be tilde-expanded later. Later files override earlier ones."""
+
+ threshold_choices = 'info 1 warning 2 error 3 severe 4 none 5'.split()
+ """Possible inputs for for --report and --halt threshold values."""
+
+ thresholds = {'info': 1, 'warning': 2, 'error': 3, 'severe': 4, 'none': 5}
+ """Lookup table for --report and --halt threshold values."""
+
+ booleans={'1': True, 'on': True, 'yes': True, 'true': True,
+ '0': False, 'off': False, 'no': False, 'false': False, '': False}
+ """Lookup table for boolean configuration file settings."""
+
+ default_error_encoding = getattr(sys.stderr, 'encoding',
+ None) or locale_encoding or 'ascii'
+
+ default_error_encoding_error_handler = 'backslashreplace'
+
+ settings_spec = (
+ 'General Docutils Options',
+ None,
+ (('Specify the document title as metadata.',
+ ['--title'], {}),
+ ('Include a "Generated by Docutils" credit and link.',
+ ['--generator', '-g'], {'action': 'store_true',
+ 'validator': validate_boolean}),
+ ('Do not include a generator credit.',
+ ['--no-generator'], {'action': 'store_false', 'dest': 'generator'}),
+ ('Include the date at the end of the document (UTC).',
+ ['--date', '-d'], {'action': 'store_const', 'const': '%Y-%m-%d',
+ 'dest': 'datestamp'}),
+ ('Include the time & date (UTC).',
+ ['--time', '-t'], {'action': 'store_const',
+ 'const': '%Y-%m-%d %H:%M UTC',
+ 'dest': 'datestamp'}),
+ ('Do not include a datestamp of any kind.',
+ ['--no-datestamp'], {'action': 'store_const', 'const': None,
+ 'dest': 'datestamp'}),
+ ('Include a "View document source" link.',
+ ['--source-link', '-s'], {'action': 'store_true',
+ 'validator': validate_boolean}),
+ ('Use <URL> for a source link; implies --source-link.',
+ ['--source-url'], {'metavar': '<URL>'}),
+ ('Do not include a "View document source" link.',
+ ['--no-source-link'],
+ {'action': 'callback', 'callback': store_multiple,
+ 'callback_args': ('source_link', 'source_url')}),
+ ('Link from section headers to TOC entries. (default)',
+ ['--toc-entry-backlinks'],
+ {'dest': 'toc_backlinks', 'action': 'store_const', 'const': 'entry',
+ 'default': 'entry'}),
+ ('Link from section headers to the top of the TOC.',
+ ['--toc-top-backlinks'],
+ {'dest': 'toc_backlinks', 'action': 'store_const', 'const': 'top'}),
+ ('Disable backlinks to the table of contents.',
+ ['--no-toc-backlinks'],
+ {'dest': 'toc_backlinks', 'action': 'store_false'}),
+ ('Link from footnotes/citations to references. (default)',
+ ['--footnote-backlinks'],
+ {'action': 'store_true', 'default': 1,
+ 'validator': validate_boolean}),
+ ('Disable backlinks from footnotes and citations.',
+ ['--no-footnote-backlinks'],
+ {'dest': 'footnote_backlinks', 'action': 'store_false'}),
+ ('Enable section numbering by Docutils. (default)',
+ ['--section-numbering'],
+ {'action': 'store_true', 'dest': 'sectnum_xform',
+ 'default': 1, 'validator': validate_boolean}),
+ ('Disable section numbering by Docutils.',
+ ['--no-section-numbering'],
+ {'action': 'store_false', 'dest': 'sectnum_xform'}),
+ ('Remove comment elements from the document tree.',
+ ['--strip-comments'],
+ {'action': 'store_true', 'validator': validate_boolean}),
+ ('Leave comment elements in the document tree. (default)',
+ ['--leave-comments'],
+ {'action': 'store_false', 'dest': 'strip_comments'}),
+ ('Remove all elements with classes="<class>" from the document tree. '
+ 'Warning: potentially dangerous; use with caution. '
+ '(Multiple-use option.)',
+ ['--strip-elements-with-class'],
+ {'action': 'append', 'dest': 'strip_elements_with_classes',
+ 'metavar': '<class>', 'validator': validate_strip_class}),
+ ('Remove all classes="<class>" attributes from elements in the '
+ 'document tree. Warning: potentially dangerous; use with caution. '
+ '(Multiple-use option.)',
+ ['--strip-class'],
+ {'action': 'append', 'dest': 'strip_classes',
+ 'metavar': '<class>', 'validator': validate_strip_class}),
+ ('Report system messages at or higher than <level>: "info" or "1", '
+ '"warning"/"2" (default), "error"/"3", "severe"/"4", "none"/"5"',
+ ['--report', '-r'], {'choices': threshold_choices, 'default': 2,
+ 'dest': 'report_level', 'metavar': '<level>',
+ 'validator': validate_threshold}),
+ ('Report all system messages. (Same as "--report=1".)',
+ ['--verbose', '-v'], {'action': 'store_const', 'const': 1,
+ 'dest': 'report_level'}),
+ ('Report no system messages. (Same as "--report=5".)',
+ ['--quiet', '-q'], {'action': 'store_const', 'const': 5,
+ 'dest': 'report_level'}),
+ ('Halt execution at system messages at or above <level>. '
+ 'Levels as in --report. Default: 4 (severe).',
+ ['--halt'], {'choices': threshold_choices, 'dest': 'halt_level',
+ 'default': 4, 'metavar': '<level>',
+ 'validator': validate_threshold}),
+ ('Halt at the slightest problem. Same as "--halt=info".',
+ ['--strict'], {'action': 'store_const', 'const': 1,
+ 'dest': 'halt_level'}),
+ ('Enable a non-zero exit status for non-halting system messages at '
+ 'or above <level>. Default: 5 (disabled).',
+ ['--exit-status'], {'choices': threshold_choices,
+ 'dest': 'exit_status_level',
+ 'default': 5, 'metavar': '<level>',
+ 'validator': validate_threshold}),
+ ('Enable debug-level system messages and diagnostics.',
+ ['--debug'], {'action': 'store_true', 'validator': validate_boolean}),
+ ('Disable debug output. (default)',
+ ['--no-debug'], {'action': 'store_false', 'dest': 'debug'}),
+ ('Send the output of system messages to <file>.',
+ ['--warnings'], {'dest': 'warning_stream', 'metavar': '<file>'}),
+ ('Enable Python tracebacks when Docutils is halted.',
+ ['--traceback'], {'action': 'store_true', 'default': None,
+ 'validator': validate_boolean}),
+ ('Disable Python tracebacks. (default)',
+ ['--no-traceback'], {'dest': 'traceback', 'action': 'store_false'}),
+ ('Specify the encoding and optionally the '
+ 'error handler of input text. Default: <locale-dependent>:strict.',
+ ['--input-encoding', '-i'],
+ {'metavar': '<name[:handler]>',
+ 'validator': validate_encoding_and_error_handler}),
+ ('Specify the error handler for undecodable characters. '
+ 'Choices: "strict" (default), "ignore", and "replace".',
+ ['--input-encoding-error-handler'],
+ {'default': 'strict', 'validator': validate_encoding_error_handler}),
+ ('Specify the text encoding and optionally the error handler for '
+ 'output. Default: UTF-8:strict.',
+ ['--output-encoding', '-o'],
+ {'metavar': '<name[:handler]>', 'default': 'utf-8',
+ 'validator': validate_encoding_and_error_handler}),
+ ('Specify error handler for unencodable output characters; '
+ '"strict" (default), "ignore", "replace", '
+ '"xmlcharrefreplace", "backslashreplace".',
+ ['--output-encoding-error-handler'],
+ {'default': 'strict', 'validator': validate_encoding_error_handler}),
+ ('Specify text encoding and error handler for error output. '
+ 'Default: %s:%s.'
+ % (default_error_encoding, default_error_encoding_error_handler),
+ ['--error-encoding', '-e'],
+ {'metavar': '<name[:handler]>', 'default': default_error_encoding,
+ 'validator': validate_encoding_and_error_handler}),
+ ('Specify the error handler for unencodable characters in '
+ 'error output. Default: %s.'
+ % default_error_encoding_error_handler,
+ ['--error-encoding-error-handler'],
+ {'default': default_error_encoding_error_handler,
+ 'validator': validate_encoding_error_handler}),
+ ('Specify the language (as BCP 47 language tag). Default: en.',
+ ['--language', '-l'], {'dest': 'language_code', 'default': 'en',
+ 'metavar': '<name>'}),
+ ('Write output file dependencies to <file>.',
+ ['--record-dependencies'],
+ {'metavar': '<file>', 'validator': validate_dependency_file,
+ 'default': None}), # default set in Values class
+ ('Read configuration settings from <file>, if it exists.',
+ ['--config'], {'metavar': '<file>', 'type': 'string',
+ 'action': 'callback', 'callback': read_config_file}),
+ ("Show this program's version number and exit.",
+ ['--version', '-V'], {'action': 'version'}),
+ ('Show this help message and exit.',
+ ['--help', '-h'], {'action': 'help'}),
+ # Typically not useful for non-programmatical use:
+ (SUPPRESS_HELP, ['--id-prefix'], {'default': ''}),
+ (SUPPRESS_HELP, ['--auto-id-prefix'], {'default': 'id'}),
+ # Hidden options, for development use only:
+ (SUPPRESS_HELP, ['--dump-settings'], {'action': 'store_true'}),
+ (SUPPRESS_HELP, ['--dump-internals'], {'action': 'store_true'}),
+ (SUPPRESS_HELP, ['--dump-transforms'], {'action': 'store_true'}),
+ (SUPPRESS_HELP, ['--dump-pseudo-xml'], {'action': 'store_true'}),
+ (SUPPRESS_HELP, ['--expose-internal-attribute'],
+ {'action': 'append', 'dest': 'expose_internals',
+ 'validator': validate_colon_separated_string_list}),
+ (SUPPRESS_HELP, ['--strict-visitor'], {'action': 'store_true'}),
+ ))
+ """Runtime settings and command-line options common to all Docutils front
+ ends. Setting specs specific to individual Docutils components are also
+ used (see `populate_from_components()`)."""
+
+ settings_defaults = {'_disable_config': None,
+ '_source': None,
+ '_destination': None,
+ '_config_files': None}
+ """Defaults for settings that don't have command-line option equivalents."""
+
+ relative_path_settings = ('warning_stream',)
+
+ config_section = 'general'
+
+ version_template = ('%%prog (Docutils %s%s, Python %s, on %s)'
+ % (docutils.__version__,
+ docutils.__version_details__ and
+ ' [%s]'%docutils.__version_details__ or '',
+ sys.version.split()[0], sys.platform))
+ """Default version message."""
+
+ def __init__(self, components=(), defaults=None, read_config_files=None,
+ *args, **kwargs):
+ """
+ `components` is a list of Docutils components each containing a
+ ``.settings_spec`` attribute. `defaults` is a mapping of setting
+ default overrides.
+ """
+
+ self.lists = {}
+ """Set of list-type settings."""
+
+ self.config_files = []
+ """List of paths of applied configuration files."""
+
+ optparse.OptionParser.__init__(
+ self, option_class=Option, add_help_option=None,
+ formatter=optparse.TitledHelpFormatter(width=78),
+ *args, **kwargs)
+ if not self.version:
+ self.version = self.version_template
+ # Make an instance copy (it will be modified):
+ self.relative_path_settings = list(self.relative_path_settings)
+ self.components = (self,) + tuple(components)
+ self.populate_from_components(self.components)
+ self.set_defaults_from_dict(defaults or {})
+ if read_config_files and not self.defaults['_disable_config']:
+ try:
+ config_settings = self.get_standard_config_settings()
+ except ValueError as error:
+ self.error(SafeString(error))
+ self.set_defaults_from_dict(config_settings.__dict__)
+
+ def populate_from_components(self, components):
+ """
+ For each component, first populate from the `SettingsSpec.settings_spec`
+ structure, then from the `SettingsSpec.settings_defaults` dictionary.
+ After all components have been processed, check for and populate from
+ each component's `SettingsSpec.settings_default_overrides` dictionary.
+ """
+ for component in components:
+ if component is None:
+ continue
+ settings_spec = component.settings_spec
+ self.relative_path_settings.extend(
+ component.relative_path_settings)
+ for i in range(0, len(settings_spec), 3):
+ title, description, option_spec = settings_spec[i:i+3]
+ if title:
+ group = optparse.OptionGroup(self, title, description)
+ self.add_option_group(group)
+ else:
+ group = self # single options
+ for (help_text, option_strings, kwargs) in option_spec:
+ option = group.add_option(help=help_text, *option_strings,
+ **kwargs)
+ if kwargs.get('action') == 'append':
+ self.lists[option.dest] = 1
+ if component.settings_defaults:
+ self.defaults.update(component.settings_defaults)
+ for component in components:
+ if component and component.settings_default_overrides:
+ self.defaults.update(component.settings_default_overrides)
+
+ def get_standard_config_files(self):
+ """Return list of config files, from environment or standard."""
+ try:
+ config_files = os.environ['DOCUTILSCONFIG'].split(os.pathsep)
+ except KeyError:
+ config_files = self.standard_config_files
+
+ # If 'HOME' is not set, expandvars() requires the 'pwd' module which is
+ # not available under certain environments, for example, within
+ # mod_python. The publisher ends up in here, and we need to publish
+ # from within mod_python. Therefore we need to avoid expanding when we
+ # are in those environments.
+ expand = os.path.expanduser
+ if 'HOME' not in os.environ:
+ try:
+ import pwd
+ except ImportError:
+ expand = lambda x: x
+ return [expand(f) for f in config_files if f.strip()]
+
+ def get_standard_config_settings(self):
+ settings = Values()
+ for filename in self.get_standard_config_files():
+ settings.update(self.get_config_file_settings(filename), self)
+ return settings
+
+ def get_config_file_settings(self, config_file):
+ """Returns a dictionary containing appropriate config file settings."""
+ parser = ConfigParser()
+ parser.read(config_file, self)
+ self.config_files.extend(parser._files)
+ base_path = os.path.dirname(config_file)
+ applied = {}
+ settings = Values()
+ for component in self.components:
+ if not component:
+ continue
+ for section in (tuple(component.config_section_dependencies or ())
+ + (component.config_section,)):
+ if section in applied:
+ continue
+ applied[section] = 1
+ settings.update(parser.get_section(section), self)
+ make_paths_absolute(
+ settings.__dict__, self.relative_path_settings, base_path)
+ return settings.__dict__
+
+ def check_values(self, values, args):
+ """Store positional arguments as runtime settings."""
+ values._source, values._destination = self.check_args(args)
+ make_paths_absolute(values.__dict__, self.relative_path_settings)
+ values._config_files = self.config_files
+ return values
+
+ def check_args(self, args):
+ source = destination = None
+ if args:
+ source = args.pop(0)
+ if source == '-': # means stdin
+ source = None
+ if args:
+ destination = args.pop(0)
+ if destination == '-': # means stdout
+ destination = None
+ if args:
+ self.error('Maximum 2 arguments allowed.')
+ if source and source == destination:
+ self.error('Do not specify the same file for both source and '
+ 'destination. It will clobber the source file.')
+ return source, destination
+
+ def set_defaults_from_dict(self, defaults):
+ self.defaults.update(defaults)
+
+ def get_default_values(self):
+ """Needed to get custom `Values` instances."""
+ defaults = Values(self.defaults)
+ defaults._config_files = self.config_files
+ return defaults
+
+ def get_option_by_dest(self, dest):
+ """
+ Get an option by its dest.
+
+ If you're supplying a dest which is shared by several options,
+ it is undefined which option of those is returned.
+
+ A KeyError is raised if there is no option with the supplied
+ dest.
+ """
+ for group in self.option_groups + [self]:
+ for option in group.option_list:
+ if option.dest == dest:
+ return option
+ raise KeyError('No option with dest == %r.' % dest)
+
+
+class ConfigParser(RawConfigParser):
+
+ old_settings = {
+ 'pep_stylesheet': ('pep_html writer', 'stylesheet'),
+ 'pep_stylesheet_path': ('pep_html writer', 'stylesheet_path'),
+ 'pep_template': ('pep_html writer', 'template')}
+ """{old setting: (new section, new setting)} mapping, used by
+ `handle_old_config`, to convert settings from the old [options] section."""
+
+ old_warning = """
+The "[option]" section is deprecated. Support for old-format configuration
+files may be removed in a future Docutils release. Please revise your
+configuration files. See <http://docutils.sf.net/docs/user/config.html>,
+section "Old-Format Configuration Files".
+"""
+
+ not_utf8_error = """\
+Unable to read configuration file "%s": content not encoded as UTF-8.
+Skipping "%s" configuration file.
+"""
+
+ def __init__(self, *args, **kwargs):
+ RawConfigParser.__init__(self, *args, **kwargs)
+
+ self._files = []
+ """List of paths of configuration files read."""
+
+ self._stderr = ErrorOutput()
+ """Wrapper around sys.stderr catching en-/decoding errors"""
+
+ def read(self, filenames, option_parser):
+ if type(filenames) in (str, unicode):
+ filenames = [filenames]
+ for filename in filenames:
+ try:
+ # Config files must be UTF-8-encoded:
+ fp = codecs.open(filename, 'r', 'utf-8')
+ except IOError:
+ continue
+ try:
+ if sys.version_info < (3, 0):
+ RawConfigParser.readfp(self, fp, filename)
+ else:
+ RawConfigParser.read_file(self, fp, filename)
+ except UnicodeDecodeError:
+ self._stderr.write(self.not_utf8_error % (filename, filename))
+ fp.close()
+ continue
+ fp.close()
+ self._files.append(filename)
+ if self.has_section('options'):
+ self.handle_old_config(filename)
+ self.validate_settings(filename, option_parser)
+
+ def handle_old_config(self, filename):
+ warnings.warn_explicit(self.old_warning, ConfigDeprecationWarning,
+ filename, 0)
+ options = self.get_section('options')
+ if not self.has_section('general'):
+ self.add_section('general')
+ for key, value in options.items():
+ if key in self.old_settings:
+ section, setting = self.old_settings[key]
+ if not self.has_section(section):
+ self.add_section(section)
+ else:
+ section = 'general'
+ setting = key
+ if not self.has_option(section, setting):
+ self.set(section, setting, value)
+ self.remove_section('options')
+
+ def validate_settings(self, filename, option_parser):
+ """
+ Call the validator function and implement overrides on all applicable
+ settings.
+ """
+ for section in self.sections():
+ for setting in self.options(section):
+ try:
+ option = option_parser.get_option_by_dest(setting)
+ except KeyError:
+ continue
+ if option.validator:
+ value = self.get(section, setting)
+ try:
+ new_value = option.validator(
+ setting, value, option_parser,
+ config_parser=self, config_section=section)
+ except Exception as error:
+ raise ValueError(
+ 'Error in config file "%s", section "[%s]":\n'
+ ' %s\n'
+ ' %s = %s'
+ % (filename, section, ErrorString(error),
+ setting, value))
+ self.set(section, setting, new_value)
+ if option.overrides:
+ self.set(section, option.overrides, None)
+
+ def optionxform(self, optionstr):
+ """
+ Transform '-' to '_' so the cmdline form of option names can be used.
+ """
+ return optionstr.lower().replace('-', '_')
+
+ def get_section(self, section):
+ """
+ Return a given section as a dictionary (empty if the section
+ doesn't exist).
+ """
+ section_dict = {}
+ if self.has_section(section):
+ for option in self.options(section):
+ section_dict[option] = self.get(section, option)
+ return section_dict
+
+
+class ConfigDeprecationWarning(DeprecationWarning):
+ """Warning for deprecated configuration file features."""
--- /dev/null
+# $Id: io.py 8394 2019-09-18 10:13:17Z milde $
+# Author: David Goodger <goodger@python.org>
+# Copyright: This module has been placed in the public domain.
+
+"""
+I/O classes provide a uniform API for low-level input and output. Subclasses
+exist for a variety of input/output mechanisms.
+"""
+from __future__ import print_function
+
+__docformat__ = 'reStructuredText'
+
+import sys
+import os
+import re
+import codecs
+from docutils import TransformSpec
+from docutils.utils.error_reporting import locale_encoding, ErrorString, ErrorOutput
+
+if sys.version_info >= (3, 0):
+ unicode = str # noqa
+
+
+class InputError(IOError): pass
+class OutputError(IOError): pass
+
+def check_encoding(stream, encoding):
+ """Test, whether the encoding of `stream` matches `encoding`.
+
+ Returns
+
+ :None: if `encoding` or `stream.encoding` are not a valid encoding
+ argument (e.g. ``None``) or `stream.encoding is missing.
+ :True: if the encoding argument resolves to the same value as `encoding`,
+ :False: if the encodings differ.
+ """
+ try:
+ return codecs.lookup(stream.encoding) == codecs.lookup(encoding)
+ except (LookupError, AttributeError, TypeError):
+ return None
+
+
+class Input(TransformSpec):
+
+ """
+ Abstract base class for input wrappers.
+ """
+
+ component_type = 'input'
+
+ default_source_path = None
+
+ def __init__(self, source=None, source_path=None, encoding=None,
+ error_handler='strict'):
+ self.encoding = encoding
+ """Text encoding for the input source."""
+
+ self.error_handler = error_handler
+ """Text decoding error handler."""
+
+ self.source = source
+ """The source of input data."""
+
+ self.source_path = source_path
+ """A text reference to the source."""
+
+ if not source_path:
+ self.source_path = self.default_source_path
+
+ self.successful_encoding = None
+ """The encoding that successfully decoded the source data."""
+
+ def __repr__(self):
+ return '%s: source=%r, source_path=%r' % (self.__class__, self.source,
+ self.source_path)
+
+ def read(self):
+ raise NotImplementedError
+
+ def decode(self, data):
+ """
+ Decode a string, `data`, heuristically.
+ Raise UnicodeError if unsuccessful.
+
+ The client application should call ``locale.setlocale`` at the
+ beginning of processing::
+
+ locale.setlocale(locale.LC_ALL, '')
+ """
+ if self.encoding and self.encoding.lower() == 'unicode':
+ assert isinstance(data, unicode), (
+ 'input encoding is "unicode" '
+ 'but input is not a unicode object')
+ if isinstance(data, unicode):
+ # Accept unicode even if self.encoding != 'unicode'.
+ return data
+ if self.encoding:
+ # We believe the user/application when the encoding is
+ # explicitly given.
+ encodings = [self.encoding]
+ else:
+ data_encoding = self.determine_encoding_from_data(data)
+ if data_encoding:
+ # If the data declares its encoding (explicitly or via a BOM),
+ # we believe it.
+ encodings = [data_encoding]
+ else:
+ # Apply heuristics only if no encoding is explicitly given and
+ # no BOM found. Start with UTF-8, because that only matches
+ # data that *IS* UTF-8:
+ encodings = ['utf-8', 'latin-1']
+ if locale_encoding:
+ encodings.insert(1, locale_encoding)
+ for enc in encodings:
+ try:
+ decoded = unicode(data, enc, self.error_handler)
+ self.successful_encoding = enc
+ # Return decoded, removing BOMs.
+ return decoded.replace(u'\ufeff', u'')
+ except (UnicodeError, LookupError) as err:
+ error = err # in Python 3, the <exception instance> is
+ # local to the except clause
+ raise UnicodeError(
+ 'Unable to decode input data. Tried the following encodings: '
+ '%s.\n(%s)' % (', '.join([repr(enc) for enc in encodings]),
+ ErrorString(error)))
+
+ coding_slug = re.compile(br"coding[:=]\s*([-\w.]+)")
+ """Encoding declaration pattern."""
+
+ byte_order_marks = ((codecs.BOM_UTF8, 'utf-8'),
+ (codecs.BOM_UTF16_BE, 'utf-16-be'),
+ (codecs.BOM_UTF16_LE, 'utf-16-le'),)
+ """Sequence of (start_bytes, encoding) tuples for encoding detection.
+ The first bytes of input data are checked against the start_bytes strings.
+ A match indicates the given encoding."""
+
+ def determine_encoding_from_data(self, data):
+ """
+ Try to determine the encoding of `data` by looking *in* `data`.
+ Check for a byte order mark (BOM) or an encoding declaration.
+ """
+ # check for a byte order mark:
+ for start_bytes, encoding in self.byte_order_marks:
+ if data.startswith(start_bytes):
+ return encoding
+ # check for an encoding declaration pattern in first 2 lines of file:
+ for line in data.splitlines()[:2]:
+ match = self.coding_slug.search(line)
+ if match:
+ return match.group(1).decode('ascii')
+ return None
+
+
+class Output(TransformSpec):
+
+ """
+ Abstract base class for output wrappers.
+ """
+
+ component_type = 'output'
+
+ default_destination_path = None
+
+ def __init__(self, destination=None, destination_path=None,
+ encoding=None, error_handler='strict'):
+ self.encoding = encoding
+ """Text encoding for the output destination."""
+
+ self.error_handler = error_handler or 'strict'
+ """Text encoding error handler."""
+
+ self.destination = destination
+ """The destination for output data."""
+
+ self.destination_path = destination_path
+ """A text reference to the destination."""
+
+ if not destination_path:
+ self.destination_path = self.default_destination_path
+
+ def __repr__(self):
+ return ('%s: destination=%r, destination_path=%r'
+ % (self.__class__, self.destination, self.destination_path))
+
+ def write(self, data):
+ """`data` is a Unicode string, to be encoded by `self.encode`."""
+ raise NotImplementedError
+
+ def encode(self, data):
+ if self.encoding and self.encoding.lower() == 'unicode':
+ assert isinstance(data, unicode), (
+ 'the encoding given is "unicode" but the output is not '
+ 'a Unicode string')
+ return data
+ if not isinstance(data, unicode):
+ # Non-unicode (e.g. bytes) output.
+ return data
+ else:
+ return data.encode(self.encoding, self.error_handler)
+
+
+class FileInput(Input):
+
+ """
+ Input for single, simple file-like objects.
+ """
+ def __init__(self, source=None, source_path=None,
+ encoding=None, error_handler='strict',
+ autoclose=True,
+ mode='r' if sys.version_info >= (3, 0) else 'rU'):
+ """
+ :Parameters:
+ - `source`: either a file-like object (which is read directly), or
+ `None` (which implies `sys.stdin` if no `source_path` given).
+ - `source_path`: a path to a file, which is opened and then read.
+ - `encoding`: the expected text encoding of the input file.
+ - `error_handler`: the encoding error handler to use.
+ - `autoclose`: close automatically after read (except when
+ `sys.stdin` is the source).
+ - `mode`: how the file is to be opened (see standard function
+ `open`). The default 'rU' provides universal newline support
+ for text files with Python 2.x.
+ """
+ Input.__init__(self, source, source_path, encoding, error_handler)
+ self.autoclose = autoclose
+ self._stderr = ErrorOutput()
+
+ if source is None:
+ if source_path:
+ # Specify encoding in Python 3
+ if sys.version_info >= (3, 0):
+ kwargs = {'encoding': self.encoding,
+ 'errors': self.error_handler}
+ else:
+ kwargs = {}
+ try:
+ self.source = open(source_path, mode, **kwargs)
+ except IOError as error:
+ raise InputError(error.errno, error.strerror, source_path)
+ else:
+ self.source = sys.stdin
+ elif (sys.version_info >= (3, 0) and
+ check_encoding(self.source, self.encoding) is False):
+ # TODO: re-open, warn or raise error?
+ raise UnicodeError('Encoding clash: encoding given is "%s" '
+ 'but source is opened with encoding "%s".' %
+ (self.encoding, self.source.encoding))
+ if not source_path:
+ try:
+ self.source_path = self.source.name
+ except AttributeError:
+ pass
+
+ def read(self):
+ """
+ Read and decode a single file and return the data (Unicode string).
+ """
+ try:
+ if self.source is sys.stdin and sys.version_info >= (3, 0):
+ # read as binary data to circumvent auto-decoding
+ data = self.source.buffer.read()
+ # normalize newlines
+ data = b'\n'.join(data.splitlines()) + b'\n'
+ else:
+ data = self.source.read()
+ except (UnicodeError, LookupError) as err: # (in Py3k read() decodes)
+ if not self.encoding and self.source_path:
+ # re-read in binary mode and decode with heuristics
+ b_source = open(self.source_path, 'rb')
+ data = b_source.read()
+ b_source.close()
+ # normalize newlines
+ data = b'\n'.join(data.splitlines()) + b'\n'
+ else:
+ raise
+ finally:
+ if self.autoclose:
+ self.close()
+ return self.decode(data)
+
+ def readlines(self):
+ """
+ Return lines of a single file as list of Unicode strings.
+ """
+ return self.read().splitlines(True)
+
+ def close(self):
+ if self.source is not sys.stdin:
+ self.source.close()
+
+
+class FileOutput(Output):
+
+ """
+ Output for single, simple file-like objects.
+ """
+
+ mode = 'w'
+ """The mode argument for `open()`."""
+ # 'wb' for binary (e.g. OpenOffice) files (see also `BinaryFileOutput`).
+ # (Do not use binary mode ('wb') for text files, as this prevents the
+ # conversion of newlines to the system specific default.)
+
+ def __init__(self, destination=None, destination_path=None,
+ encoding=None, error_handler='strict', autoclose=True,
+ handle_io_errors=None, mode=None):
+ """
+ :Parameters:
+ - `destination`: either a file-like object (which is written
+ directly) or `None` (which implies `sys.stdout` if no
+ `destination_path` given).
+ - `destination_path`: a path to a file, which is opened and then
+ written.
+ - `encoding`: the text encoding of the output file.
+ - `error_handler`: the encoding error handler to use.
+ - `autoclose`: close automatically after write (except when
+ `sys.stdout` or `sys.stderr` is the destination).
+ - `handle_io_errors`: ignored, deprecated, will be removed.
+ - `mode`: how the file is to be opened (see standard function
+ `open`). The default is 'w', providing universal newline
+ support for text files.
+ """
+ Output.__init__(self, destination, destination_path,
+ encoding, error_handler)
+ self.opened = True
+ self.autoclose = autoclose
+ if mode is not None:
+ self.mode = mode
+ self._stderr = ErrorOutput()
+ if destination is None:
+ if destination_path:
+ self.opened = False
+ else:
+ self.destination = sys.stdout
+ elif (# destination is file-type object -> check mode:
+ mode and hasattr(self.destination, 'mode')
+ and mode != self.destination.mode):
+ print('Warning: Destination mode "%s" differs from specified '
+ 'mode "%s"' % (self.destination.mode, mode),
+ file=self._stderr)
+ if not destination_path:
+ try:
+ self.destination_path = self.destination.name
+ except AttributeError:
+ pass
+
+ def open(self):
+ # Specify encoding in Python 3.
+ if sys.version_info >= (3, 0) and 'b' not in self.mode:
+ kwargs = {'encoding': self.encoding,
+ 'errors': self.error_handler}
+ else:
+ kwargs = {}
+ try:
+ self.destination = open(self.destination_path, self.mode, **kwargs)
+ except IOError as error:
+ raise OutputError(error.errno, error.strerror,
+ self.destination_path)
+ self.opened = True
+
+ def write(self, data):
+ """Encode `data`, write it to a single file, and return it.
+
+ With Python 3 or binary output mode, `data` is returned unchanged,
+ except when specified encoding and output encoding differ.
+ """
+ if not self.opened:
+ self.open()
+ if ('b' not in self.mode and sys.version_info < (3, 0)
+ or check_encoding(self.destination, self.encoding) is False
+ ):
+ data = self.encode(data)
+ if sys.version_info >= (3, 0) and os.linesep != '\n':
+ data = data.replace(b'\n', bytes(os.linesep, 'ascii')) # fix endings
+
+ try:
+ self.destination.write(data)
+ except TypeError as e:
+ if sys.version_info >= (3, 0) and isinstance(data, bytes):
+ try:
+ self.destination.buffer.write(data)
+ except AttributeError:
+ if check_encoding(self.destination,
+ self.encoding) is False:
+ raise ValueError('Encoding of %s (%s) differs \n'
+ ' from specified encoding (%s)' %
+ (self.destination_path or 'destination',
+ self.destination.encoding, self.encoding))
+ else:
+ raise e
+ except (UnicodeError, LookupError) as err:
+ raise UnicodeError(
+ 'Unable to encode output data. output-encoding is: '
+ '%s.\n(%s)' % (self.encoding, ErrorString(err)))
+ finally:
+ if self.autoclose:
+ self.close()
+ return data
+
+ def close(self):
+ if self.destination not in (sys.stdout, sys.stderr):
+ self.destination.close()
+ self.opened = False
+
+
+class BinaryFileOutput(FileOutput):
+ """
+ A version of docutils.io.FileOutput which writes to a binary file.
+ """
+ # Used by core.publish_cmdline_to_binary() which in turn is used by
+ # rst2odt (OpenOffice writer)
+ mode = 'wb'
+
+
+class StringInput(Input):
+
+ """
+ Direct string input.
+ """
+
+ default_source_path = '<string>'
+
+ def read(self):
+ """Decode and return the source string."""
+ return self.decode(self.source)
+
+
+class StringOutput(Output):
+
+ """
+ Direct string output.
+ """
+
+ default_destination_path = '<string>'
+
+ def write(self, data):
+ """Encode `data`, store it in `self.destination`, and return it."""
+ self.destination = self.encode(data)
+ return self.destination
+
+
+class NullInput(Input):
+
+ """
+ Degenerate input: read nothing.
+ """
+
+ default_source_path = 'null input'
+
+ def read(self):
+ """Return a null string."""
+ return u''
+
+
+class NullOutput(Output):
+
+ """
+ Degenerate output: write nothing.
+ """
+
+ default_destination_path = 'null output'
+
+ def write(self, data):
+ """Do nothing ([don't even] send data to the bit bucket)."""
+ pass
+
+
+class DocTreeInput(Input):
+
+ """
+ Adapter for document tree input.
+
+ The document tree must be passed in the ``source`` parameter.
+ """
+
+ default_source_path = 'doctree input'
+
+ def read(self):
+ """Return the document tree."""
+ return self.source
--- /dev/null
+# $Id: __init__.py 8376 2019-08-27 19:49:29Z milde $
+# Author: David Goodger <goodger@python.org>
+# Copyright: This module has been placed in the public domain.
+
+# Internationalization details are documented in
+# <http://docutils.sf.net/docs/howto/i18n.html>.
+
+"""
+This package contains modules for language-dependent features of Docutils.
+"""
+
+__docformat__ = 'reStructuredText'
+
+import sys
+
+from docutils.utils import normalize_language_tag
+
+
+_languages = {}
+
+def get_language(language_code, reporter=None):
+ """Return module with language localizations.
+
+ `language_code` is a "BCP 47" language tag.
+ If there is no matching module, warn and fall back to English.
+ """
+ # TODO: use a dummy module returning emtpy strings?, configurable?
+ for tag in normalize_language_tag(language_code):
+ tag = tag.replace('-', '_') # '-' not valid in module names
+ if tag in _languages:
+ return _languages[tag]
+ try:
+ module = __import__(tag, globals(), locals(), level=1)
+ except ImportError:
+ try:
+ module = __import__(tag, globals(), locals(), level=0)
+ except ImportError:
+ continue
+ _languages[tag] = module
+ return module
+ if reporter is not None:
+ reporter.warning(
+ 'language "%s" not supported: ' % language_code +
+ 'Docutils-generated text will be in English.')
+ module = __import__('en', globals(), locals(), level=1)
+ _languages[tag] = module # warn only one time!
+ return module
--- /dev/null
+# $Id: af.py 4564 2006-05-21 20:44:42Z wiemann $
+# Author: Jannie Hofmeyr <jhsh@sun.ac.za>
+# Copyright: This module has been placed in the public domain.
+
+# New language mappings are welcome. Before doing a new translation, please
+# read <http://docutils.sf.net/docs/howto/i18n.html>. Two files must be
+# translated for each language: one in docutils/languages, the other in
+# docutils/parsers/rst/languages.
+
+"""
+Afrikaans-language mappings for language-dependent features of Docutils.
+"""
+
+__docformat__ = 'reStructuredText'
+
+labels = {
+ 'author': 'Auteur',
+ 'authors': 'Auteurs',
+ 'organization': 'Organisasie',
+ 'address': 'Adres',
+ 'contact': 'Kontak',
+ 'version': 'Weergawe',
+ 'revision': 'Revisie',
+ 'status': 'Status',
+ 'date': 'Datum',
+ 'copyright': 'Kopiereg',
+ 'dedication': 'Opdrag',
+ 'abstract': 'Opsomming',
+ 'attention': 'Aandag!',
+ 'caution': 'Wees versigtig!',
+ 'danger': '!GEVAAR!',
+ 'error': 'Fout',
+ 'hint': 'Wenk',
+ 'important': 'Belangrik',
+ 'note': 'Nota',
+ 'tip': 'Tip', # hint and tip both have the same translation: wenk
+ 'warning': 'Waarskuwing',
+ 'contents': 'Inhoud'}
+"""Mapping of node class name to label text."""
+
+bibliographic_fields = {
+ 'auteur': 'author',
+ 'auteurs': 'authors',
+ 'organisasie': 'organization',
+ 'adres': 'address',
+ 'kontak': 'contact',
+ 'weergawe': 'version',
+ 'revisie': 'revision',
+ 'status': 'status',
+ 'datum': 'date',
+ 'kopiereg': 'copyright',
+ 'opdrag': 'dedication',
+ 'opsomming': 'abstract'}
+"""Afrikaans (lowcased) to canonical name mapping for bibliographic fields."""
+
+author_separators = [';', ',']
+"""List of separator strings for the 'Authors' bibliographic field. Tried in
+order."""
--- /dev/null
+# $Id: ca.py 4564 2006-05-21 20:44:42Z wiemann $
+# Author: Ivan Vilata i Balaguer <ivan@selidor.net>
+# Copyright: This module has been placed in the public domain.
+
+# New language mappings are welcome. Before doing a new translation, please
+# read <http://docutils.sf.net/docs/howto/i18n.html>. Two files must be
+# translated for each language: one in docutils/languages, the other in
+# docutils/parsers/rst/languages.
+
+"""
+Catalan-language mappings for language-dependent features of Docutils.
+"""
+
+__docformat__ = 'reStructuredText'
+
+labels = {
+ # fixed: language-dependent
+ 'author': u'Autor',
+ 'authors': u'Autors',
+ 'organization': u'Organitzaci\u00F3',
+ 'address': u'Adre\u00E7a',
+ 'contact': u'Contacte',
+ 'version': u'Versi\u00F3',
+ 'revision': u'Revisi\u00F3',
+ 'status': u'Estat',
+ 'date': u'Data',
+ 'copyright': u'Copyright',
+ 'dedication': u'Dedicat\u00F2ria',
+ 'abstract': u'Resum',
+ 'attention': u'Atenci\u00F3!',
+ 'caution': u'Compte!',
+ 'danger': u'PERILL!',
+ 'error': u'Error',
+ 'hint': u'Suggeriment',
+ 'important': u'Important',
+ 'note': u'Nota',
+ 'tip': u'Consell',
+ 'warning': u'Av\u00EDs',
+ 'contents': u'Contingut'}
+"""Mapping of node class name to label text."""
+
+bibliographic_fields = {
+ # language-dependent: fixed
+ u'autor': 'author',
+ u'autors': 'authors',
+ u'organitzaci\u00F3': 'organization',
+ u'adre\u00E7a': 'address',
+ u'contacte': 'contact',
+ u'versi\u00F3': 'version',
+ u'revisi\u00F3': 'revision',
+ u'estat': 'status',
+ u'data': 'date',
+ u'copyright': 'copyright',
+ u'dedicat\u00F2ria': 'dedication',
+ u'resum': 'abstract'}
+"""Catalan (lowcased) to canonical name mapping for bibliographic fields."""
+
+author_separators = [';', ',']
+"""List of separator strings for the 'Authors' bibliographic field. Tried in
+order."""
--- /dev/null
+# $Id: cs.py 4564 2006-05-21 20:44:42Z wiemann $
+# Author: Marek Blaha <mb@dat.cz>
+# Copyright: This module has been placed in the public domain.
+
+# New language mappings are welcome. Before doing a new translation, please
+# read <http://docutils.sf.net/docs/howto/i18n.html>. Two files must be
+# translated for each language: one in docutils/languages, the other in
+# docutils/parsers/rst/languages.
+
+"""
+Czech-language mappings for language-dependent features of Docutils.
+"""
+
+__docformat__ = 'reStructuredText'
+
+labels = {
+ # fixed: language-dependent
+ 'author': u'Autor',
+ 'authors': u'Auto\u0159i',
+ 'organization': u'Organizace',
+ 'address': u'Adresa',
+ 'contact': u'Kontakt',
+ 'version': u'Verze',
+ 'revision': u'Revize',
+ 'status': u'Stav',
+ 'date': u'Datum',
+ 'copyright': u'Copyright',
+ 'dedication': u'V\u011Bnov\u00E1n\u00ED',
+ 'abstract': u'Abstrakt',
+ 'attention': u'Pozor!',
+ 'caution': u'Opatrn\u011B!',
+ 'danger': u'!NEBEZPE\u010C\u00CD!',
+ 'error': u'Chyba',
+ 'hint': u'Rada',
+ 'important': u'D\u016Fle\u017Eit\u00E9',
+ 'note': u'Pozn\u00E1mka',
+ 'tip': u'Tip',
+ 'warning': u'Varov\u00E1n\u00ED',
+ 'contents': u'Obsah'}
+"""Mapping of node class name to label text."""
+
+bibliographic_fields = {
+ # language-dependent: fixed
+ u'autor': 'author',
+ u'auto\u0159i': 'authors',
+ u'organizace': 'organization',
+ u'adresa': 'address',
+ u'kontakt': 'contact',
+ u'verze': 'version',
+ u'revize': 'revision',
+ u'stav': 'status',
+ u'datum': 'date',
+ u'copyright': 'copyright',
+ u'v\u011Bnov\u00E1n\u00ED': 'dedication',
+ u'abstrakt': 'abstract'}
+"""Czech (lowcased) to canonical name mapping for bibliographic fields."""
+
+author_separators = [';', ',']
+"""List of separator strings for the 'Authors' bibliographic field. Tried in
+order."""
--- /dev/null
+# -*- coding: utf-8 -*-
+# $Id: da.py 7678 2013-07-03 09:57:36Z milde $
+# Author: E D
+# Copyright: This module has been placed in the public domain.
+
+# New language mappings are welcome. Before doing a new translation, please
+# read <http://docutils.sf.net/docs/howto/i18n.html>. Two files must be
+# translated for each language: one in docutils/languages, the other in
+# docutils/parsers/rst/languages.
+
+"""
+Danish-language mappings for language-dependent features of Docutils.
+"""
+
+__docformat__ = 'reStructuredText'
+
+labels = {
+ # fixed: language-dependent
+ 'author': u'Forfatter',
+ 'authors': u'Forfattere',
+ 'organization': u'Organisation',
+ 'address': u'Adresse',
+ 'contact': u'Kontakt',
+ 'version': u'Version',
+ 'revision': u'Revision',
+ 'status': u'Status',
+ 'date': u'Dato',
+ 'copyright': u'Copyright',
+ 'dedication': u'Dedikation',
+ 'abstract': u'Resumé',
+ 'attention': u'Giv agt!',
+ 'caution': u'Pas på!',
+ 'danger': u'!FARE!',
+ 'error': u'Fejl',
+ 'hint': u'Vink',
+ 'important': u'Vigtigt',
+ 'note': u'Bemærk',
+ 'tip': u'Tips',
+ 'warning': u'Advarsel',
+ 'contents': u'Indhold'}
+"""Mapping of node class name to label text."""
+
+bibliographic_fields = {
+ # language-dependent: fixed
+ u'forfatter': 'author',
+ u'forfattere': 'authors',
+ u'organisation': 'organization',
+ u'adresse': 'address',
+ u'kontakt': 'contact',
+ u'version': 'version',
+ u'revision': 'revision',
+ u'status': 'status',
+ u'dato': 'date',
+ u'copyright': 'copyright',
+ u'dedikation': 'dedication',
+ u'resume': 'abstract',
+ u'resumé': 'abstract'}
+"""Danish (lowcased) to canonical name mapping for bibliographic fields."""
+
+author_separators = [';', ',']
+"""List of separator strings for the 'Authors' bibliographic field. Tried in
+order."""
--- /dev/null
+# $Id: de.py 4564 2006-05-21 20:44:42Z wiemann $
+# Author: Gunnar Schwant <g.schwant@gmx.de>
+# Copyright: This module has been placed in the public domain.
+
+# New language mappings are welcome. Before doing a new translation, please
+# read <http://docutils.sf.net/docs/howto/i18n.html>. Two files must be
+# translated for each language: one in docutils/languages, the other in
+# docutils/parsers/rst/languages.
+
+"""
+German language mappings for language-dependent features of Docutils.
+"""
+
+__docformat__ = 'reStructuredText'
+
+labels = {
+ 'author': 'Autor',
+ 'authors': 'Autoren',
+ 'organization': 'Organisation',
+ 'address': 'Adresse',
+ 'contact': 'Kontakt',
+ 'version': 'Version',
+ 'revision': 'Revision',
+ 'status': 'Status',
+ 'date': 'Datum',
+ 'dedication': 'Widmung',
+ 'copyright': 'Copyright',
+ 'abstract': 'Zusammenfassung',
+ 'attention': 'Achtung!',
+ 'caution': 'Vorsicht!',
+ 'danger': '!GEFAHR!',
+ 'error': 'Fehler',
+ 'hint': 'Hinweis',
+ 'important': 'Wichtig',
+ 'note': 'Bemerkung',
+ 'tip': 'Tipp',
+ 'warning': 'Warnung',
+ 'contents': 'Inhalt'}
+"""Mapping of node class name to label text."""
+
+bibliographic_fields = {
+ 'autor': 'author',
+ 'autoren': 'authors',
+ 'organisation': 'organization',
+ 'adresse': 'address',
+ 'kontakt': 'contact',
+ 'version': 'version',
+ 'revision': 'revision',
+ 'status': 'status',
+ 'datum': 'date',
+ 'copyright': 'copyright',
+ 'widmung': 'dedication',
+ 'zusammenfassung': 'abstract'}
+"""German (lowcased) to canonical name mapping for bibliographic fields."""
+
+author_separators = [';', ',']
+"""List of separator strings for the 'Authors' bibliographic field. Tried in
+order."""
--- /dev/null
+# $Id: en.py 4564 2006-05-21 20:44:42Z wiemann $
+# Author: David Goodger <goodger@python.org>
+# Copyright: This module has been placed in the public domain.
+
+# New language mappings are welcome. Before doing a new translation, please
+# read <http://docutils.sf.net/docs/howto/i18n.html>. Two files must be
+# translated for each language: one in docutils/languages, the other in
+# docutils/parsers/rst/languages.
+
+"""
+English-language mappings for language-dependent features of Docutils.
+"""
+
+__docformat__ = 'reStructuredText'
+
+labels = {
+ # fixed: language-dependent
+ 'author': 'Author',
+ 'authors': 'Authors',
+ 'organization': 'Organization',
+ 'address': 'Address',
+ 'contact': 'Contact',
+ 'version': 'Version',
+ 'revision': 'Revision',
+ 'status': 'Status',
+ 'date': 'Date',
+ 'copyright': 'Copyright',
+ 'dedication': 'Dedication',
+ 'abstract': 'Abstract',
+ 'attention': 'Attention!',
+ 'caution': 'Caution!',
+ 'danger': '!DANGER!',
+ 'error': 'Error',
+ 'hint': 'Hint',
+ 'important': 'Important',
+ 'note': 'Note',
+ 'tip': 'Tip',
+ 'warning': 'Warning',
+ 'contents': 'Contents'}
+"""Mapping of node class name to label text."""
+
+bibliographic_fields = {
+ # language-dependent: fixed
+ 'author': 'author',
+ 'authors': 'authors',
+ 'organization': 'organization',
+ 'address': 'address',
+ 'contact': 'contact',
+ 'version': 'version',
+ 'revision': 'revision',
+ 'status': 'status',
+ 'date': 'date',
+ 'copyright': 'copyright',
+ 'dedication': 'dedication',
+ 'abstract': 'abstract'}
+"""English (lowcased) to canonical name mapping for bibliographic fields."""
+
+author_separators = [';', ',']
+"""List of separator strings for the 'Authors' bibliographic field. Tried in
+order."""
--- /dev/null
+# $Id: eo.py 4564 2006-05-21 20:44:42Z wiemann $
+# Author: Marcelo Huerta San Martin <richieadler@users.sourceforge.net>
+# Copyright: This module has been placed in the public domain.
+
+# New language mappings are welcome. Before doing a new translation, please
+# read <http://docutils.sf.net/docs/howto/i18n.html>. Two files must be
+# translated for each language: one in docutils/languages, the other in
+# docutils/parsers/rst/languages.
+
+"""
+Esperanto-language mappings for language-dependent features of Docutils.
+"""
+
+__docformat__ = 'reStructuredText'
+
+labels = {
+ # fixed: language-dependent
+ 'author': u'A\u016dtoro',
+ 'authors': u'A\u016dtoroj',
+ 'organization': u'Organizo',
+ 'address': u'Adreso',
+ 'contact': u'Kontakto',
+ 'version': u'Versio',
+ 'revision': u'Revido',
+ 'status': u'Stato',
+ 'date': u'Dato',
+ # 'copyright': u'Kopirajto',
+ 'copyright': u'A\u016dtorrajto',
+ 'dedication': u'Dedi\u0109o',
+ 'abstract': u'Resumo',
+ 'attention': u'Atentu!',
+ 'caution': u'Zorgu!',
+ 'danger': u'DAN\u011cERO!',
+ 'error': u'Eraro',
+ 'hint': u'Spuro',
+ 'important': u'Grava',
+ 'note': u'Noto',
+ 'tip': u'Helpeto',
+ 'warning': u'Averto',
+ 'contents': u'Enhavo'}
+"""Mapping of node class name to label text."""
+
+bibliographic_fields = {
+ # language-dependent: fixed
+ 'a\u016dtoro': 'author',
+ 'a\u016dtoroj': 'authors',
+ 'organizo': 'organization',
+ 'adreso': 'address',
+ 'kontakto': 'contact',
+ 'versio': 'version',
+ 'revido': 'revision',
+ 'stato': 'status',
+ 'dato': 'date',
+ 'a\u016dtorrajto': 'copyright',
+ 'dedi\u0109o': 'dedication',
+ 'resumo': 'abstract'}
+"""Esperanto (lowcased) to canonical name mapping for bibliographic fields."""
+
+author_separators = [';', ',']
+"""List of separator strings for the 'Authors' bibliographic field. Tried in
+order."""
--- /dev/null
+# -*- coding: utf-8 -*-
+# $Id: es.py 4572 2006-05-25 20:48:37Z richieadler $
+# Author: Marcelo Huerta San Martín <richieadler@users.sourceforge.net>
+# Copyright: This module has been placed in the public domain.
+
+# New language mappings are welcome. Before doing a new translation, please
+# read <http://docutils.sf.net/docs/howto/i18n.html>. Two files must be
+# translated for each language: one in docutils/languages, the other in
+# docutils/parsers/rst/languages.
+
+"""
+Spanish-language mappings for language-dependent features of Docutils.
+"""
+
+__docformat__ = 'reStructuredText'
+
+labels = {
+ 'author': u'Autor',
+ 'authors': u'Autores',
+ 'organization': u'Organizaci\u00f3n',
+ 'address': u'Direcci\u00f3n',
+ 'contact': u'Contacto',
+ 'version': u'Versi\u00f3n',
+ 'revision': u'Revisi\u00f3n',
+ 'status': u'Estado',
+ 'date': u'Fecha',
+ 'copyright': u'Copyright',
+ 'dedication': u'Dedicatoria',
+ 'abstract': u'Resumen',
+ 'attention': u'\u00a1Atenci\u00f3n!',
+ 'caution': u'\u00a1Precauci\u00f3n!',
+ 'danger': u'\u00a1PELIGRO!',
+ 'error': u'Error',
+ 'hint': u'Sugerencia',
+ 'important': u'Importante',
+ 'note': u'Nota',
+ 'tip': u'Consejo',
+ 'warning': u'Advertencia',
+ 'contents': u'Contenido'}
+"""Mapping of node class name to label text."""
+
+bibliographic_fields = {
+ u'autor': 'author',
+ u'autores': 'authors',
+ u'organizaci\u00f3n': 'organization',
+ u'direcci\u00f3n': 'address',
+ u'contacto': 'contact',
+ u'versi\u00f3n': 'version',
+ u'revisi\u00f3n': 'revision',
+ u'estado': 'status',
+ u'fecha': 'date',
+ u'copyright': 'copyright',
+ u'dedicatoria': 'dedication',
+ u'resumen': 'abstract'}
+"""Spanish (lowcased) to canonical name mapping for bibliographic fields."""
+
+author_separators = [';', ',']
+"""List of separator strings for the 'Authors' bibliographic field. Tried in
+order."""
--- /dev/null
+# -*- coding: utf-8 -*-
+# $Id: fa.py 4564 2016-08-10 11:48:42Z
+# Author: Shahin <me@5hah.in>
+# Copyright: This module has been placed in the public domain.
+
+# New language mappings are welcome. Before doing a new translation, please
+# read <http://docutils.sf.net/docs/howto/i18n.html>. Two files must be
+# translated for each language: one in docutils/languages, the other in
+# docutils/parsers/rst/languages.
+
+"""
+Persian-language mappings for language-dependent features of Docutils.
+"""
+
+__docformat__ = 'reStructuredText'
+
+labels = {
+ # fixed: language-dependent
+ u'author': u'نویسنده',
+ u'authors': u'نویسندگان',
+ u'organization': u'سازمان',
+ u'address': u'آدرس',
+ u'contact': u'تماس',
+ u'version': u'نسخه',
+ u'revision': u'بازبینی',
+ u'status': u'وضعیت',
+ u'date': u'تاریخ',
+ u'copyright': u'کپیرایت',
+ u'dedication': u'تخصیص',
+ u'abstract': u'چکیده',
+ u'attention': u'توجه!',
+ u'caution': u'احتیاط!',
+ u'danger': u'خطر!',
+ u'error': u'خطا',
+ u'hint': u'راهنما',
+ u'important': u'مهم',
+ u'note': u'یادداشت',
+ u'tip': u'نکته',
+ u'warning': u'اخطار',
+ u'contents': u'محتوا'}
+"""Mapping of node class name to label text."""
+
+bibliographic_fields = {
+ # language-dependent: fixed
+ u'نویسنده': u'author',
+ u'نویسندگان': u'authors',
+ u'سازمان': u'organization',
+ u'آدرس': u'address',
+ u'تماس': u'contact',
+ u'نسخه': u'version',
+ u'بازبینی': u'revision',
+ u'وضعیت': u'status',
+ u'تاریخ': u'date',
+ u'کپیرایت': u'copyright',
+ u'تخصیص': u'dedication',
+ u'چکیده': u'abstract'}
+"""Persian (lowcased) to canonical name mapping for bibliographic fields."""
+
+author_separators = [u'؛', u'،']
+"""List of separator strings for the 'Authors' bibliographic field. Tried in
+order."""
--- /dev/null
+# $Id: fi.py 4564 2006-05-21 20:44:42Z wiemann $
+# Author: Asko Soukka <asko.soukka@iki.fi>
+# Copyright: This module has been placed in the public domain.
+
+# New language mappings are welcome. Before doing a new translation, please
+# read <http://docutils.sf.net/docs/howto/i18n.html>. Two files must be
+# translated for each language: one in docutils/languages, the other in
+# docutils/parsers/rst/languages.
+
+"""
+Finnish-language mappings for language-dependent features of Docutils.
+"""
+
+__docformat__ = 'reStructuredText'
+
+labels = {
+ # fixed: language-dependent
+ u'author': u'Tekij\u00e4',
+ u'authors': u'Tekij\u00e4t',
+ u'organization': u'Yhteis\u00f6',
+ u'address': u'Osoite',
+ u'contact': u'Yhteystiedot',
+ u'version': u'Versio',
+ u'revision': u'Vedos',
+ u'status': u'Tila',
+ u'date': u'P\u00e4iv\u00e4ys',
+ u'copyright': u'Tekij\u00e4noikeudet',
+ u'dedication': u'Omistuskirjoitus',
+ u'abstract': u'Tiivistelm\u00e4',
+ u'attention': u'Huomio!',
+ u'caution': u'Varo!',
+ u'danger': u'!VAARA!',
+ u'error': u'Virhe',
+ u'hint': u'Vihje',
+ u'important': u'T\u00e4rke\u00e4\u00e4',
+ u'note': u'Huomautus',
+ u'tip': u'Neuvo',
+ u'warning': u'Varoitus',
+ u'contents': u'Sis\u00e4llys'}
+"""Mapping of node class name to label text."""
+
+bibliographic_fields = {
+ # language-dependent: fixed
+ u'tekij\u00e4': u'author',
+ u'tekij\u00e4t': u'authors',
+ u'yhteis\u00f6': u'organization',
+ u'osoite': u'address',
+ u'yhteystiedot': u'contact',
+ u'versio': u'version',
+ u'vedos': u'revision',
+ u'tila': u'status',
+ u'p\u00e4iv\u00e4ys': u'date',
+ u'tekij\u00e4noikeudet': u'copyright',
+ u'omistuskirjoitus': u'dedication',
+ u'tiivistelm\u00e4': u'abstract'}
+"""Finnish (lowcased) to canonical name mapping for bibliographic fields."""
+
+author_separators = [';', ',']
+"""List of separator strings for the 'Authors' bibliographic field. Tried in
+order."""
--- /dev/null
+# $Id: fr.py 4564 2006-05-21 20:44:42Z wiemann $
+# Author: Stefane Fermigier <sf@fermigier.com>
+# Copyright: This module has been placed in the public domain.
+
+# New language mappings are welcome. Before doing a new translation, please
+# read <http://docutils.sf.net/docs/howto/i18n.html>. Two files must be
+# translated for each language: one in docutils/languages, the other in
+# docutils/parsers/rst/languages.
+
+"""
+French-language mappings for language-dependent features of Docutils.
+"""
+
+__docformat__ = 'reStructuredText'
+
+labels = {
+ u'author': u'Auteur',
+ u'authors': u'Auteurs',
+ u'organization': u'Organisation',
+ u'address': u'Adresse',
+ u'contact': u'Contact',
+ u'version': u'Version',
+ u'revision': u'R\u00e9vision',
+ u'status': u'Statut',
+ u'date': u'Date',
+ u'copyright': u'Copyright',
+ u'dedication': u'D\u00e9dicace',
+ u'abstract': u'R\u00e9sum\u00e9',
+ u'attention': u'Attention!',
+ u'caution': u'Avertissement!',
+ u'danger': u'!DANGER!',
+ u'error': u'Erreur',
+ u'hint': u'Indication',
+ u'important': u'Important',
+ u'note': u'Note',
+ u'tip': u'Astuce',
+ u'warning': u'Avis',
+ u'contents': u'Sommaire'}
+"""Mapping of node class name to label text."""
+
+bibliographic_fields = {
+ u'auteur': u'author',
+ u'auteurs': u'authors',
+ u'organisation': u'organization',
+ u'adresse': u'address',
+ u'contact': u'contact',
+ u'version': u'version',
+ u'r\u00e9vision': u'revision',
+ u'statut': u'status',
+ u'date': u'date',
+ u'copyright': u'copyright',
+ u'd\u00e9dicace': u'dedication',
+ u'r\u00e9sum\u00e9': u'abstract'}
+"""French (lowcased) to canonical name mapping for bibliographic fields."""
+
+author_separators = [';', ',']
+"""List of separator strings for the 'Authors' bibliographic field. Tried in
+order."""
--- /dev/null
+# -*- coding: utf-8 -*-
+# Author: David Goodger
+# Contact: goodger@users.sourceforge.net
+# Revision: $Revision: 2224 $
+# Date: $Date: 2004-06-05 21:40:46 +0200 (Sat, 05 Jun 2004) $
+# Copyright: This module has been placed in the public domain.
+
+# New language mappings are welcome. Before doing a new translation, please
+# read <http://docutils.sf.net/docs/howto/i18n.html>. Two files must be
+# translated for each language: one in docutils/languages, the other in
+# docutils/parsers/rst/languages.
+
+"""
+Galician-language mappings for language-dependent features of Docutils.
+"""
+
+__docformat__ = 'reStructuredText'
+
+labels = {
+ # fixed: language-dependent
+ 'author': u'Autor',
+ 'authors': u'Autores',
+ 'organization': u'Organizaci\u00f3n',
+ 'address': u'Enderezo',
+ 'contact': u'Contacto',
+ 'version': u'Versi\u00f3n',
+ 'revision': u'Revisi\u00f3n',
+ 'status': u'Estado',
+ 'date': u'Data',
+ 'copyright': u'Dereitos de copia',
+ 'dedication': u'Dedicatoria',
+ 'abstract': u'Abstract',
+ 'attention': u'Atenci\u00f3n!',
+ 'caution': u'Advertencia!',
+ 'danger': u'PERIGO!',
+ 'error': u'Erro',
+ 'hint': u'Consello',
+ 'important': u'Importante',
+ 'note': u'Nota',
+ 'tip': u'Suxesti\u00f3n',
+ 'warning': u'Aviso',
+ 'contents': u'Contido'}
+"""Mapping of node class name to label text."""
+
+bibliographic_fields = {
+ # language-dependent: fixed
+ u'autor': 'author',
+ u'autores': 'authors',
+ u'organizaci\u00f3n': 'organization',
+ u'enderezo': 'address',
+ u'contacto': 'contact',
+ u'versi\u00f3n': 'version',
+ u'revisi\u00f3n': 'revision',
+ u'estado': 'status',
+ u'data': 'date',
+ u'dereitos de copia': 'copyright',
+ u'dedicatoria': 'dedication',
+ u'abstract': 'abstract'}
+"""Galician (lowcased) to canonical name mapping for bibliographic fields."""
+
+author_separators = [';', ',']
+"""List of separator strings for the 'Authors' bibliographic field. Tried in
+order."""
--- /dev/null
+# Author: Meir Kriheli
+# Id: $Id: he.py 4837 2006-12-26 09:59:41Z sfcben $
+# Copyright: This module has been placed in the public domain.
+
+# New language mappings are welcome. Before doing a new translation, please
+# read <http://docutils.sf.net/docs/howto/i18n.html>. Two files must be
+# translated for each language: one in docutils/languages, the other in
+# docutils/parsers/rst/languages.
+
+"""
+Hebrew-language mappings for language-dependent features of Docutils.
+"""
+
+__docformat__ = 'reStructuredText'
+
+labels = {
+ # fixed: language-dependent
+ 'author': u'\u05de\u05d7\u05d1\u05e8',
+ 'authors': u'\u05de\u05d7\u05d1\u05e8\u05d9',
+ 'organization': u'\u05d0\u05e8\u05d2\u05d5\u05df',
+ 'address': u'\u05db\u05ea\u05d5\u05d1\u05ea',
+ 'contact': u'\u05d0\u05d9\u05e9 \u05e7\u05e9\u05e8',
+ 'version': u'\u05d2\u05e8\u05e1\u05d4',
+ 'revision': u'\u05de\u05d4\u05d3\u05d5\u05e8\u05d4',
+ 'status': u'\u05e1\u05d8\u05d8\u05d5\u05e1',
+ 'date': u'\u05ea\u05d0\u05e8\u05d9\u05da',
+ 'copyright': u'\u05d6\u05db\u05d5\u05d9\u05d5\u05ea \u05e9\u05de\u05d5\u05e8\u05d5\u05ea',
+ 'dedication': u'\u05d4\u05e7\u05d3\u05e9\u05d4',
+ 'abstract': u'\u05ea\u05e7\u05e6\u05d9\u05e8',
+ 'attention': u'\u05ea\u05e9\u05d5\u05de\u05ea \u05dc\u05d1',
+ 'caution': u'\u05d6\u05d4\u05d9\u05e8\u05d5\u05ea',
+ 'danger': u'\u05e1\u05db\u05e0\u05d4',
+ 'error': u'\u05e9\u05d2\u05d9\u05d0\u05d4' ,
+ 'hint': u'\u05e8\u05de\u05d6',
+ 'important': u'\u05d7\u05e9\u05d5\u05d1',
+ 'note': u'\u05d4\u05e2\u05e8\u05d4',
+ 'tip': u'\u05d8\u05d9\u05e4',
+ 'warning': u'\u05d0\u05d6\u05d4\u05e8\u05d4',
+ 'contents': u'\u05ea\u05d5\u05db\u05df'}
+"""Mapping of node class name to label text."""
+
+bibliographic_fields = {
+ # language-dependent: fixed
+ u'\u05de\u05d7\u05d1\u05e8': 'author',
+ u'\u05de\u05d7\u05d1\u05e8\u05d9': 'authors',
+ u'\u05d0\u05e8\u05d2\u05d5\u05df': 'organization',
+ u'\u05db\u05ea\u05d5\u05d1\u05ea': 'address',
+ u'\u05d0\u05d9\u05e9 \u05e7\u05e9\u05e8': 'contact',
+ u'\u05d2\u05e8\u05e1\u05d4': 'version',
+ u'\u05de\u05d4\u05d3\u05d5\u05e8\u05d4': 'revision',
+ u'\u05e1\u05d8\u05d8\u05d5\u05e1': 'status',
+ u'\u05ea\u05d0\u05e8\u05d9\u05da': 'date',
+ u'\u05d6\u05db\u05d5\u05d9\u05d5\u05ea \u05e9\u05de\u05d5\u05e8\u05d5\u05ea': 'copyright',
+ u'\u05d4\u05e7\u05d3\u05e9\u05d4': 'dedication',
+ u'\u05ea\u05e7\u05e6\u05d9\u05e8': 'abstract'}
+"""Hebrew to canonical name mapping for bibliographic fields."""
+
+author_separators = [';', ',']
+"""List of separator strings for the 'Authors' bibliographic field. Tried in
+order."""
--- /dev/null
+# $Id: it.py 4564 2006-05-21 20:44:42Z wiemann $
+# Author: Nicola Larosa <docutils@tekNico.net>
+# Copyright: This module has been placed in the public domain.
+
+# New language mappings are welcome. Before doing a new translation, please
+# read <http://docutils.sf.net/docs/howto/i18n.html>. Two files must be
+# translated for each language: one in docutils/languages, the other in
+# docutils/parsers/rst/languages.
+
+"""
+Italian-language mappings for language-dependent features of Docutils.
+"""
+
+__docformat__ = 'reStructuredText'
+
+labels = {
+ 'author': 'Autore',
+ 'authors': 'Autori',
+ 'organization': 'Organizzazione',
+ 'address': 'Indirizzo',
+ 'contact': 'Contatti',
+ 'version': 'Versione',
+ 'revision': 'Revisione',
+ 'status': 'Status',
+ 'date': 'Data',
+ 'copyright': 'Copyright',
+ 'dedication': 'Dedica',
+ 'abstract': 'Riassunto',
+ 'attention': 'Attenzione!',
+ 'caution': 'Cautela!',
+ 'danger': '!PERICOLO!',
+ 'error': 'Errore',
+ 'hint': 'Suggerimento',
+ 'important': 'Importante',
+ 'note': 'Nota',
+ 'tip': 'Consiglio',
+ 'warning': 'Avvertenza',
+ 'contents': 'Indice'}
+"""Mapping of node class name to label text."""
+
+bibliographic_fields = {
+ 'autore': 'author',
+ 'autori': 'authors',
+ 'organizzazione': 'organization',
+ 'indirizzo': 'address',
+ 'contatto': 'contact',
+ 'versione': 'version',
+ 'revisione': 'revision',
+ 'status': 'status',
+ 'data': 'date',
+ 'copyright': 'copyright',
+ 'dedica': 'dedication',
+ 'riassunto': 'abstract'}
+"""Italian (lowcased) to canonical name mapping for bibliographic fields."""
+
+author_separators = [';', ',']
+"""List of separator strings for the 'Authors' bibliographic field. Tried in
+order."""
--- /dev/null
+# -*- coding: utf-8 -*-
+# $Id: ja.py 4564 2006-05-21 20:44:42Z wiemann $
+# Author: Hisashi Morita <hisashim@kt.rim.or.jp>
+# Copyright: This module has been placed in the public domain.
+
+# New language mappings are welcome. Before doing a new translation, please
+# read <http://docutils.sf.net/docs/howto/i18n.html>. Two files must be
+# translated for each language: one in docutils/languages, the other in
+# docutils/parsers/rst/languages.
+
+"""
+Japanese-language mappings for language-dependent features of Docutils.
+"""
+
+__docformat__ = 'reStructuredText'
+
+labels = {
+ # fixed: language-dependent
+ 'author': u'著者',
+ 'authors': u'著者',
+ 'organization': u'組織',
+ 'address': u'住所',
+ 'contact': u'連絡先',
+ 'version': u'バージョン',
+ 'revision': u'リビジョン',
+ 'status': u'ステータス',
+ 'date': u'日付',
+ 'copyright': u'著作権',
+ 'dedication': u'献辞',
+ 'abstract': u'概要',
+ 'attention': u'注目!',
+ 'caution': u'注意!',
+ 'danger': u'!危険!',
+ 'error': u'エラー',
+ 'hint': u'ヒント',
+ 'important': u'重要',
+ 'note': u'備考',
+ 'tip': u'通報',
+ 'warning': u'警告',
+ 'contents': u'目次'}
+"""Mapping of node class name to label text."""
+
+bibliographic_fields = {
+ # language-dependent: fixed
+ u'著者': 'author',
+ u' n/a': 'authors',
+ u'組織': 'organization',
+ u'住所': 'address',
+ u'連絡先': 'contact',
+ u'バージョン': 'version',
+ u'リビジョン': 'revision',
+ u'ステータス': 'status',
+ u'日付': 'date',
+ u'著作権': 'copyright',
+ u'献辞': 'dedication',
+ u'概要': 'abstract'}
+"""Japanese (lowcased) to canonical name mapping for bibliographic fields."""
+
+author_separators = [';', ',']
+"""List of separator strings for the 'Authors' bibliographic field. Tried in
+order."""
--- /dev/null
+# -*- coding: utf-8 -*-
+# $Id: ko.py 8253 2019-04-15 10:01:10Z milde $
+# Author: Thomas SJ Kang <thomas.kangsj@ujuc.kr>
+# Copyright: This module has been placed in the public domain.
+
+# New language mappings are welcome. Before doing a new translation, please
+# read <http://docutils.sf.net/docs/howto/i18n.html>. Two files must be
+# translated for each language: one in docutils/languages, the other in
+# docutils/parsers/rst/languages.
+
+"""
+Korean-language mappings for language-dependent features of Docutils.
+"""
+
+__docformat__ = 'reStructuredText'
+
+labels = {
+ # fixed: language-dependent
+ 'author': u'저자',
+ 'authors': u'저자들',
+ 'organization': u'조직',
+ 'address': u'주소',
+ 'contact': u'연락처',
+ 'version': 'Version',
+ 'revision': 'Revision',
+ 'status': u'상태',
+ 'date': u'날짜',
+ 'copyright': u'저작권',
+ 'dedication': u'헌정',
+ 'abstract': u'요약',
+ 'attention': u'집중!',
+ 'caution': u'주의!',
+ 'danger': u'!위험!',
+ 'error': u'오류',
+ 'hint': u'실마리',
+ 'important': u'중요한',
+ 'note': u'비고',
+ 'tip': u'팁',
+ 'warning': u'경고',
+ 'contents': u'목차'}
+"""Mapping of node class name to label text."""
+
+bibliographic_fields = {
+ # language-dependent: fixed
+ u'저자': 'author',
+ u'저자들': 'authors',
+ u'조직': 'organization',
+ u'주소': 'address',
+ u'연락처': 'contact',
+ u'version': 'version',
+ u'revision': 'revision',
+ u'상태': 'status',
+ u'날짜': 'date',
+ u'저작권': 'copyright',
+ u'헌정': 'dedication',
+ u'요약': 'abstract'}
+"""Korean to canonical name mapping for bibliographic fields."""
+
+author_separators = [';', ',']
+"""List of separator strings for the 'Authors' bibliographic field. Tried in
+order."""
--- /dev/null
+# -*- coding: utf-8 -*-
+# $Id: lt.py 7911 2015-08-31 08:23:06Z milde $
+# Author: Dalius Dobravolskas <dalius.do...@gmail.com>
+# Copyright: This module has been placed in the public domain.
+
+# New language mappings are welcome. Before doing a new translation, please
+# read <http://docutils.sf.net/docs/howto/i18n.html>. Two files must be
+# translated for each language: one in docutils/languages, the other in
+# docutils/parsers/rst/languages.
+
+"""
+Lithuanian language mappings for language-dependent features of Docutils.
+"""
+
+__docformat__ = 'reStructuredText'
+
+labels = {
+ # fixed: language-dependent
+ 'author': 'Autorius',
+ 'authors': 'Autoriai',
+ 'organization': 'Organizacija',
+ 'address': 'Adresas',
+ 'contact': 'Kontaktas',
+ 'version': 'Versija',
+ 'revision': 'Revizija',
+ 'status': u'Būsena',
+ 'date': 'Data',
+ 'copyright': u'Autoriaus teisės',
+ 'dedication': 'Dedikacija',
+ 'abstract': 'Santrauka',
+ 'attention': u'Dėmesio!',
+ 'caution': 'Atsargiai!',
+ 'danger': '!PAVOJINGA!',
+ 'error': 'Klaida',
+ 'hint': u'Užuomina',
+ 'important': 'Svarbu',
+ 'note': 'Pastaba',
+ 'tip': 'Patarimas',
+ 'warning': u'Įspėjimas',
+ 'contents': 'Turinys'}
+"""Mapping of node class name to label text."""
+
+bibliographic_fields = {
+ # language-dependent: fixed
+ 'autorius': 'author',
+ 'autoriai': 'authors',
+ 'organizacija': 'organization',
+ 'adresas': 'address',
+ 'kontaktas': 'contact',
+ 'versija': 'version',
+ 'revizija': 'revision',
+ 'būsena': 'status',
+ 'data': 'date',
+ 'autoriaus teisės': 'copyright',
+ 'dedikacija': 'dedication',
+ 'santrauka': 'abstract'}
+"""Lithuanian (lowcased) to canonical name mapping for bibliographic fields."""
+
+author_separators = [';', ',']
+"""List of separator strings for the 'Authors' bibliographic field. Tried in
+order."""
--- /dev/null
+# -*- coding: utf-8 -*-
+# $Id: lv.py 7975 2016-10-20 20:00:19Z milde $
+# Copyright: This module has been placed in the public domain.
+
+# New language mappings are welcome. Before doing a new translation, please
+# read <http://docutils.sf.net/docs/howto/i18n.html>. Two files must be
+# translated for each language: one in docutils/languages, the other in
+# docutils/parsers/rst/languages.
+
+"""
+Latvian-language mappings for language-dependent features of Docutils.
+"""
+
+__docformat__ = 'reStructuredText'
+
+labels = {
+ # fixed: language-dependent
+ 'author': 'Autors',
+ 'authors': 'Autori',
+ 'organization': 'Organizācija',
+ 'address': 'Adrese',
+ 'contact': 'Kontakti',
+ 'version': 'Versija',
+ 'revision': 'Revīzija',
+ 'status': 'Statuss',
+ 'date': 'Datums',
+ 'copyright': 'Copyright',
+ 'dedication': 'Veltījums',
+ 'abstract': 'Atreferējums',
+ 'attention': 'Uzmanību!',
+ 'caution': 'Piesardzību!',
+ 'danger': '!BĪSTAMI!',
+ 'error': 'Kļūda',
+ 'hint': 'Ieteikums',
+ 'important': 'Svarīgi',
+ 'note': 'Piezīme',
+ 'tip': 'Padoms',
+ 'warning': 'Brīdinājums',
+ 'contents': 'Saturs'}
+"""Mapping of node class name to label text."""
+
+bibliographic_fields = {
+ # language-dependent: fixed
+ 'autors': 'author',
+ 'autori': 'authors',
+ 'organizācija': 'organization',
+ 'adrese': 'address',
+ 'kontakti': 'contact',
+ 'versija': 'version',
+ 'revīzija': 'revision',
+ 'statuss': 'status',
+ 'datums': 'date',
+ 'copyright': 'copyright',
+ 'veltījums': 'dedication',
+ 'atreferējums': 'abstract'}
+"""English (lowcased) to canonical name mapping for bibliographic fields."""
+
+author_separators = [';', ',']
+"""List of separator strings for the 'Authors' bibliographic field. Tried in
+order."""
--- /dev/null
+# $Id: nl.py 4564 2006-05-21 20:44:42Z wiemann $
+# Author: Martijn Pieters <mjpieters@users.sourceforge.net>
+# Copyright: This module has been placed in the public domain.
+
+# New language mappings are welcome. Before doing a new translation, please
+# read <http://docutils.sf.net/docs/howto/i18n.html>. Two files must be
+# translated for each language: one in docutils/languages, the other in
+# docutils/parsers/rst/languages.
+
+"""
+Dutch-language mappings for language-dependent features of Docutils.
+"""
+
+__docformat__ = 'reStructuredText'
+
+labels = {
+ # fixed: language-dependent
+ 'author': 'Auteur',
+ 'authors': 'Auteurs',
+ 'organization': 'Organisatie',
+ 'address': 'Adres',
+ 'contact': 'Contact',
+ 'version': 'Versie',
+ 'revision': 'Revisie',
+ 'status': 'Status',
+ 'date': 'Datum',
+ 'copyright': 'Copyright',
+ 'dedication': 'Toewijding',
+ 'abstract': 'Samenvatting',
+ 'attention': 'Attentie!',
+ 'caution': 'Let op!',
+ 'danger': '!GEVAAR!',
+ 'error': 'Fout',
+ 'hint': 'Hint',
+ 'important': 'Belangrijk',
+ 'note': 'Opmerking',
+ 'tip': 'Tip',
+ 'warning': 'Waarschuwing',
+ 'contents': 'Inhoud'}
+"""Mapping of node class name to label text."""
+
+bibliographic_fields = {
+ # language-dependent: fixed
+ 'auteur': 'author',
+ 'auteurs': 'authors',
+ 'organisatie': 'organization',
+ 'adres': 'address',
+ 'contact': 'contact',
+ 'versie': 'version',
+ 'revisie': 'revision',
+ 'status': 'status',
+ 'datum': 'date',
+ 'copyright': 'copyright',
+ 'toewijding': 'dedication',
+ 'samenvatting': 'abstract'}
+"""Dutch (lowcased) to canonical name mapping for bibliographic fields."""
+
+author_separators = [';', ',']
+"""List of separator strings for the 'Authors' bibliographic field. Tried in
+order."""
--- /dev/null
+# $Id$
+# Author: Robert Wojciechowicz <rw@smsnet.pl>
+# Copyright: This module has been placed in the public domain.
+
+# New language mappings are welcome. Before doing a new translation, please
+# read <http://docutils.sf.net/docs/howto/i18n.html>. Two files must be
+# translated for each language: one in docutils/languages, the other in
+# docutils/parsers/rst/languages.
+
+"""
+Polish-language mappings for language-dependent features of Docutils.
+"""
+
+__docformat__ = 'reStructuredText'
+
+labels = {
+ # fixed: language-dependent
+ 'author': u'Autor',
+ 'authors': u'Autorzy',
+ 'organization': u'Organizacja',
+ 'address': u'Adres',
+ 'contact': u'Kontakt',
+ 'version': u'Wersja',
+ 'revision': u'Korekta',
+ 'status': u'Status',
+ 'date': u'Data',
+ 'copyright': u'Copyright',
+ 'dedication': u'Dedykacja',
+ 'abstract': u'Streszczenie',
+ 'attention': u'Uwaga!',
+ 'caution': u'Ostro\u017cnie!',
+ 'danger': u'!Niebezpiecze\u0144stwo!',
+ 'error': u'B\u0142\u0105d',
+ 'hint': u'Wskaz\u00f3wka',
+ 'important': u'Wa\u017cne',
+ 'note': u'Przypis',
+ 'tip': u'Rada',
+ 'warning': u'Ostrze\u017cenie',
+ 'contents': u'Tre\u015b\u0107'}
+"""Mapping of node class name to label text."""
+
+bibliographic_fields = {
+ # language-dependent: fixed
+ u'autor': 'author',
+ u'autorzy': 'authors',
+ u'organizacja': 'organization',
+ u'adres': 'address',
+ u'kontakt': 'contact',
+ u'wersja': 'version',
+ u'korekta': 'revision',
+ u'status': 'status',
+ u'data': 'date',
+ u'copyright': 'copyright',
+ u'dedykacja': 'dedication',
+ u'streszczenie': 'abstract'}
+"""Polish (lowcased) to canonical name mapping for bibliographic fields."""
+
+author_separators = [';', ',']
+"""List of separator strings for the 'Authors' bibliographic field. Tried in
+order."""
+
+
--- /dev/null
+# $Id: pt_br.py 5567 2008-06-03 01:11:03Z goodger $
+# Author: David Goodger <goodger@python.org>
+# Copyright: This module has been placed in the public domain.
+
+# New language mappings are welcome. Before doing a new translation, please
+# read <http://docutils.sf.net/docs/howto/i18n.html>. Two files must be
+# translated for each language: one in docutils/languages, the other in
+# docutils/parsers/rst/languages.
+
+"""
+Brazilian Portuguese-language mappings for language-dependent features of Docutils.
+"""
+
+__docformat__ = 'reStructuredText'
+
+labels = {
+ # fixed: language-dependent
+ 'author': u'Autor',
+ 'authors': u'Autores',
+ 'organization': u'Organiza\u00E7\u00E3o',
+ 'address': u'Endere\u00E7o',
+ 'contact': u'Contato',
+ 'version': u'Vers\u00E3o',
+ 'revision': u'Revis\u00E3o',
+ 'status': u'Estado',
+ 'date': u'Data',
+ 'copyright': u'Copyright',
+ 'dedication': u'Dedicat\u00F3ria',
+ 'abstract': u'Resumo',
+ 'attention': u'Aten\u00E7\u00E3o!',
+ 'caution': u'Cuidado!',
+ 'danger': u'PERIGO!',
+ 'error': u'Erro',
+ 'hint': u'Sugest\u00E3o',
+ 'important': u'Importante',
+ 'note': u'Nota',
+ 'tip': u'Dica',
+ 'warning': u'Aviso',
+ 'contents': u'Sum\u00E1rio'}
+"""Mapping of node class name to label text."""
+
+bibliographic_fields = {
+ # language-dependent: fixed
+ u'autor': 'author',
+ u'autores': 'authors',
+ u'organiza\u00E7\u00E3o': 'organization',
+ u'endere\u00E7o': 'address',
+ u'contato': 'contact',
+ u'vers\u00E3o': 'version',
+ u'revis\u00E3o': 'revision',
+ u'estado': 'status',
+ u'data': 'date',
+ u'copyright': 'copyright',
+ u'dedicat\u00F3ria': 'dedication',
+ u'resumo': 'abstract'}
+"""Brazilian Portuguese (lowcased) to canonical name mapping for bibliographic fields."""
+
+author_separators = [';', ',']
+"""List of separator strings for the 'Authors' bibliographic field. Tried in
+order."""
--- /dev/null
+# -*- coding: utf-8 -*-
+# $Id: ru.py 7125 2011-09-16 18:36:18Z milde $
+# Author: Roman Suzi <rnd@onego.ru>
+# Copyright: This module has been placed in the public domain.
+
+# New language mappings are welcome. Before doing a new translation, please
+# read <http://docutils.sf.net/docs/howto/i18n.html>. Two files must be
+# translated for each language: one in docutils/languages, the other in
+# docutils/parsers/rst/languages.
+
+"""
+Russian-language mappings for language-dependent features of Docutils.
+"""
+
+__docformat__ = 'reStructuredText'
+
+labels = {
+ u'abstract': u'Аннотация',
+ u'address': u'Адрес',
+ u'attention': u'Внимание!',
+ u'author': u'Автор',
+ u'authors': u'Авторы',
+ u'caution': u'Осторожно!',
+ u'contact': u'Контакт',
+ u'contents': u'Содержание',
+ u'copyright': u'Права копирования',
+ u'danger': u'ОПАСНО!',
+ u'date': u'Дата',
+ u'dedication': u'Посвящение',
+ u'error': u'Ошибка',
+ u'hint': u'Совет',
+ u'important': u'Важно',
+ u'note': u'Примечание',
+ u'organization': u'Организация',
+ u'revision': u'Редакция',
+ u'status': u'Статус',
+ u'tip': u'Подсказка',
+ u'version': u'Версия',
+ u'warning': u'Предупреждение'}
+"""Mapping of node class name to label text."""
+
+bibliographic_fields = {
+ u'аннотация': u'abstract',
+ u'адрес': u'address',
+ u'автор': u'author',
+ u'авторы': u'authors',
+ u'контакт': u'contact',
+ u'права копирования': u'copyright',
+ u'дата': u'date',
+ u'посвящение': u'dedication',
+ u'организация': u'organization',
+ u'редакция': u'revision',
+ u'статус': u'status',
+ u'версия': u'version'}
+"""Russian (lowcased) to canonical name mapping for bibliographic fields."""
+
+author_separators = [';', ',']
+"""List of separator strings for the 'Authors' bibliographic field. Tried in
+order."""
--- /dev/null
+# $Id: sk.py 4564 2006-05-21 20:44:42Z wiemann $
+# Author: Miroslav Vasko <zemiak@zoznam.sk>
+# Copyright: This module has been placed in the public domain.
+
+# New language mappings are welcome. Before doing a new translation, please
+# read <http://docutils.sf.net/docs/howto/i18n.html>. Two files must be
+# translated for each language: one in docutils/languages, the other in
+# docutils/parsers/rst/languages.
+
+"""
+Slovak-language mappings for language-dependent features of Docutils.
+"""
+
+__docformat__ = 'reStructuredText'
+
+labels = {
+ 'author': u'Autor',
+ 'authors': u'Autori',
+ 'organization': u'Organiz\u00E1cia',
+ 'address': u'Adresa',
+ 'contact': u'Kontakt',
+ 'version': u'Verzia',
+ 'revision': u'Rev\u00EDzia',
+ 'status': u'Stav',
+ 'date': u'D\u00E1tum',
+ 'copyright': u'Copyright',
+ 'dedication': u'Venovanie',
+ 'abstract': u'Abstraktne',
+ 'attention': u'Pozor!',
+ 'caution': u'Opatrne!',
+ 'danger': u'!NEBEZPE\u010cENSTVO!',
+ 'error': u'Chyba',
+ 'hint': u'Rada',
+ 'important': u'D\u00F4le\u017Eit\u00E9',
+ 'note': u'Pozn\u00E1mka',
+ 'tip': u'Tip',
+ 'warning': u'Varovanie',
+ 'contents': u'Obsah'}
+"""Mapping of node class name to label text."""
+
+bibliographic_fields = {
+ u'autor': 'author',
+ u'autori': 'authors',
+ u'organiz\u00E1cia': 'organization',
+ u'adresa': 'address',
+ u'kontakt': 'contact',
+ u'verzia': 'version',
+ u'rev\u00EDzia': 'revision',
+ u'stav': 'status',
+ u'd\u00E1tum': 'date',
+ u'copyright': 'copyright',
+ u'venovanie': 'dedication',
+ u'abstraktne': 'abstract'}
+"""Slovak (lowcased) to canonical name mapping for bibliographic fields."""
+
+author_separators = [';', ',']
+"""List of separator strings for the 'Authors' bibliographic field. Tried in
+order."""
--- /dev/null
+# -*- coding: utf-8 -*-
+# $Id: sv.py 8006 2016-12-22 23:02:44Z milde $
+# Author: Adam Chodorowski <chodorowski@users.sourceforge.net>
+# Copyright: This module has been placed in the public domain.
+
+# New language mappings are welcome. Before doing a new translation, please
+# read <http://docutils.sf.net/docs/howto/i18n.html>. Two files must be
+# translated for each language: one in docutils/languages, the other in
+# docutils/parsers/rst/languages.
+
+"""
+Swedish language mappings for language-dependent features of Docutils.
+"""
+
+__docformat__ = 'reStructuredText'
+
+labels = {
+ 'author': u'Författare',
+ 'authors': u'Författare',
+ 'organization': u'Organisation',
+ 'address': u'Adress',
+ 'contact': u'Kontakt',
+ 'version': u'Version',
+ 'revision': u'Revision',
+ 'status': u'Status',
+ 'date': u'Datum',
+ 'copyright': u'Copyright',
+ 'dedication': u'Dedikation',
+ 'abstract': u'Sammanfattning',
+ 'attention': u'Observera!',
+ 'caution': u'Akta!', # 'Varning' already used for 'warning'
+ 'danger': u'FARA!',
+ 'error': u'Fel',
+ 'hint': u'Vink',
+ 'important': u'Viktigt',
+ 'note': u'Notera',
+ 'tip': u'Tips',
+ 'warning': u'Varning',
+ 'contents': u'Innehåll' }
+"""Mapping of node class name to label text."""
+
+bibliographic_fields = {
+ # 'Author' and 'Authors' identical in Swedish; assume the plural:
+ u'författare': 'authors',
+ u' n/a': 'author',
+ u'organisation': 'organization',
+ u'adress': 'address',
+ u'kontakt': 'contact',
+ u'version': 'version',
+ u'revision': 'revision',
+ u'status': 'status',
+ u'datum': 'date',
+ u'copyright': 'copyright',
+ u'dedikation': 'dedication',
+ u'sammanfattning': 'abstract' }
+"""Swedish (lowcased) to canonical name mapping for bibliographic fields."""
+
+author_separators = [';', ',']
+"""List of separator strings for the 'Authors' bibliographic field. Tried in
+order."""
--- /dev/null
+# -*- coding: utf-8 -*-
+# $Id: zh_cn.py 4564 2006-05-21 20:44:42Z wiemann $
+# Author: Pan Junyong <panjy@zopechina.com>
+# Copyright: This module has been placed in the public domain.
+
+# New language mappings are welcome. Before doing a new translation, please
+# read <http://docutils.sf.net/docs/howto/i18n.html>. Two files must be
+# translated for each language: one in docutils/languages, the other in
+# docutils/parsers/rst/languages.
+
+"""
+Simplified Chinese language mappings for language-dependent features
+of Docutils.
+"""
+
+__docformat__ = 'reStructuredText'
+
+labels = {
+ # fixed: language-dependent
+ 'author': u'作者',
+ 'authors': u'作者群',
+ 'organization': u'组织',
+ 'address': u'地址',
+ 'contact': u'联系',
+ 'version': u'版本',
+ 'revision': u'修订',
+ 'status': u'状态',
+ 'date': u'日期',
+ 'copyright': u'版权',
+ 'dedication': u'献辞',
+ 'abstract': u'摘要',
+ 'attention': u'注意',
+ 'caution': u'小心',
+ 'danger': u'危险',
+ 'error': u'错误',
+ 'hint': u'提示',
+ 'important': u'重要',
+ 'note': u'注解',
+ 'tip': u'技巧',
+ 'warning': u'警告',
+ 'contents': u'目录',
+}
+"""Mapping of node class name to label text."""
+
+bibliographic_fields = {
+ # language-dependent: fixed
+ u'作者': 'author',
+ u'作者群': 'authors',
+ u'组织': 'organization',
+ u'地址': 'address',
+ u'联系': 'contact',
+ u'版本': 'version',
+ u'修订': 'revision',
+ u'状态': 'status',
+ u'时间': 'date',
+ u'版权': 'copyright',
+ u'献辞': 'dedication',
+ u'摘要': 'abstract'}
+"""Simplified Chinese to canonical name mapping for bibliographic fields."""
+
+author_separators = [';', ',',
+ u'\uff1b', # ';'
+ u'\uff0c', # ','
+ u'\u3001', # '、'
+ ]
+"""List of separator strings for the 'Authors' bibliographic field. Tried in
+order."""
--- /dev/null
+# -*- coding: utf-8 -*-
+# $Id: zh_tw.py 4564 2006-05-21 20:44:42Z wiemann $
+# Author: Joe YS Jaw <joeysj@users.sourceforge.net>
+# Copyright: This module has been placed in the public domain.
+
+# New language mappings are welcome. Before doing a new translation, please
+# read <http://docutils.sf.net/docs/howto/i18n.html>. Two files must be
+# translated for each language: one in docutils/languages, the other in
+# docutils/parsers/rst/languages.
+
+"""
+Traditional Chinese language mappings for language-dependent features of Docutils.
+"""
+
+__docformat__ = 'reStructuredText'
+
+labels = {
+ # fixed: language-dependent
+ 'author': u'\u4f5c\u8005', # '作者' <-- Chinese word
+ 'authors': u'\u4f5c\u8005\u7fa4', # '作者群',
+ 'organization': u'\u7d44\u7e54', # '組織',
+ 'address': u'\u5730\u5740', # '地址',
+ 'contact': u'\u9023\u7d61', # '連絡',
+ 'version': u'\u7248\u672c', # '版本',
+ 'revision': u'\u4fee\u8a02', # '修訂',
+ 'status': u'\u72c0\u614b', # '狀態',
+ 'date': u'\u65e5\u671f', # '日期',
+ 'copyright': u'\u7248\u6b0a', # '版權',
+ 'dedication': u'\u984c\u737b', # '題獻',
+ 'abstract': u'\u6458\u8981', # '摘要',
+ 'attention': u'\u6ce8\u610f\uff01', # '注意!',
+ 'caution': u'\u5c0f\u5fc3\uff01', # '小心!',
+ 'danger': u'\uff01\u5371\u96aa\uff01', # '!危險!',
+ 'error': u'\u932f\u8aa4', # '錯誤',
+ 'hint': u'\u63d0\u793a', # '提示',
+ 'important': u'\u91cd\u8981', # '注意!',
+ 'note': u'\u8a3b\u91cb', # '註釋',
+ 'tip': u'\u79d8\u8a23', # '秘訣',
+ 'warning': u'\u8b66\u544a', # '警告',
+ 'contents': u'\u76ee\u9304' # '目錄'
+}
+"""Mapping of node class name to label text."""
+
+bibliographic_fields = {
+ # language-dependent: fixed
+ 'author (translation required)': 'author',
+ 'authors (translation required)': 'authors',
+ 'organization (translation required)': 'organization',
+ 'address (translation required)': 'address',
+ 'contact (translation required)': 'contact',
+ 'version (translation required)': 'version',
+ 'revision (translation required)': 'revision',
+ 'status (translation required)': 'status',
+ 'date (translation required)': 'date',
+ 'copyright (translation required)': 'copyright',
+ 'dedication (translation required)': 'dedication',
+ 'abstract (translation required)': 'abstract'}
+"""Traditional Chinese to canonical name mapping for bibliographic fields."""
+
+author_separators = [';', ',',
+ u'\uff1b', # ';'
+ u'\uff0c', # ','
+ u'\u3001', # '、'
+ ]
+"""List of separator strings for the 'Authors' bibliographic field. Tried in
+order."""
--- /dev/null
+# $Id: nodes.py 8446 2019-12-23 21:43:20Z milde $
+# Author: David Goodger <goodger@python.org>
+# Maintainer: docutils-develop@lists.sourceforge.net
+# Copyright: This module has been placed in the public domain.
+
+"""
+Docutils document tree element class library.
+
+Classes in CamelCase are abstract base classes or auxiliary classes. The one
+exception is `Text`, for a text (PCDATA) node; uppercase is used to
+differentiate from element classes. Classes in lower_case_with_underscores
+are element classes, matching the XML element generic identifiers in the DTD_.
+
+The position of each node (the level at which it can occur) is significant and
+is represented by abstract base classes (`Root`, `Structural`, `Body`,
+`Inline`, etc.). Certain transformations will be easier because we can use
+``isinstance(node, base_class)`` to determine the position of the node in the
+hierarchy.
+
+.. _DTD: http://docutils.sourceforge.net/docs/ref/docutils.dtd
+"""
+from __future__ import print_function
+from collections import Counter
+
+__docformat__ = 'reStructuredText'
+
+import sys
+import os
+import re
+import warnings
+import unicodedata
+
+if sys.version_info >= (3, 0):
+ unicode = str # noqa
+ basestring = str # noqa
+
+class _traversal_list(list):
+ # auxiliary class to report a FutureWarning
+ done = False
+ def _warning_decorator(fun):
+ msg = ("\n The iterable returned by Node.traverse()"
+ "\n will become an iterator instead of a list in "
+ "Docutils > 0.16.")
+ def wrapper(self, *args, **kwargs):
+ if not self.done:
+ warnings.warn(msg, FutureWarning, stacklevel=2)
+ self.done = True
+ return fun(self, *args, **kwargs)
+ return wrapper
+
+ __add__ = _warning_decorator(list.__add__)
+ __contains__ = _warning_decorator(list.__contains__)
+ __getitem__ = _warning_decorator(list.__getitem__)
+ __reversed__ = _warning_decorator(list.__reversed__)
+ __setitem__ = _warning_decorator(list.__setitem__)
+ append = _warning_decorator(list.append)
+ count = _warning_decorator(list.count)
+ extend = _warning_decorator(list.extend)
+ index = _warning_decorator(list.index)
+ insert = _warning_decorator(list.insert)
+ pop = _warning_decorator(list.pop)
+ reverse = _warning_decorator(list.reverse)
+
+
+# ==============================
+# Functional Node Base Classes
+# ==============================
+
+class Node(object):
+
+ """Abstract base class of nodes in a document tree."""
+
+ parent = None
+ """Back-reference to the Node immediately containing this Node."""
+
+ document = None
+ """The `document` node at the root of the tree containing this Node."""
+
+ source = None
+ """Path or description of the input source which generated this Node."""
+
+ line = None
+ """The line number (1-based) of the beginning of this Node in `source`."""
+
+ def __bool__(self):
+ """
+ Node instances are always true, even if they're empty. A node is more
+ than a simple container. Its boolean "truth" does not depend on
+ having one or more subnodes in the doctree.
+
+ Use `len()` to check node length. Use `None` to represent a boolean
+ false value.
+ """
+ return True
+
+ if sys.version_info < (3, 0):
+ __nonzero__ = __bool__
+
+ if sys.version_info < (3, 0):
+ # on 2.x, str(node) will be a byte string with Unicode
+ # characters > 255 escaped; on 3.x this is no longer necessary
+ def __str__(self):
+ return unicode(self).encode('raw_unicode_escape')
+
+ def asdom(self, dom=None):
+ """Return a DOM **fragment** representation of this Node."""
+ if dom is None:
+ import xml.dom.minidom as dom
+ domroot = dom.Document()
+ return self._dom_node(domroot)
+
+ def pformat(self, indent=' ', level=0):
+ """
+ Return an indented pseudo-XML representation, for test purposes.
+
+ Override in subclasses.
+ """
+ raise NotImplementedError
+
+ def copy(self):
+ """Return a copy of self."""
+ raise NotImplementedError
+
+ def deepcopy(self):
+ """Return a deep copy of self (also copying children)."""
+ raise NotImplementedError
+
+ def astext(self):
+ """Return a string representation of this Node."""
+ raise NotImplementedError
+
+ def setup_child(self, child):
+ child.parent = self
+ if self.document:
+ child.document = self.document
+ if child.source is None:
+ child.source = self.document.current_source
+ if child.line is None:
+ child.line = self.document.current_line
+
+ def walk(self, visitor):
+ """
+ Traverse a tree of `Node` objects, calling the
+ `dispatch_visit()` method of `visitor` when entering each
+ node. (The `walkabout()` method is similar, except it also
+ calls the `dispatch_departure()` method before exiting each
+ node.)
+
+ This tree traversal supports limited in-place tree
+ modifications. Replacing one node with one or more nodes is
+ OK, as is removing an element. However, if the node removed
+ or replaced occurs after the current node, the old node will
+ still be traversed, and any new nodes will not.
+
+ Within ``visit`` methods (and ``depart`` methods for
+ `walkabout()`), `TreePruningException` subclasses may be raised
+ (`SkipChildren`, `SkipSiblings`, `SkipNode`, `SkipDeparture`).
+
+ Parameter `visitor`: A `NodeVisitor` object, containing a
+ ``visit`` implementation for each `Node` subclass encountered.
+
+ Return true if we should stop the traversal.
+ """
+ stop = False
+ visitor.document.reporter.debug(
+ 'docutils.nodes.Node.walk calling dispatch_visit for %s'
+ % self.__class__.__name__)
+ try:
+ try:
+ visitor.dispatch_visit(self)
+ except (SkipChildren, SkipNode):
+ return stop
+ except SkipDeparture: # not applicable; ignore
+ pass
+ children = self.children
+ try:
+ for child in children[:]:
+ if child.walk(visitor):
+ stop = True
+ break
+ except SkipSiblings:
+ pass
+ except StopTraversal:
+ stop = True
+ return stop
+
+ def walkabout(self, visitor):
+ """
+ Perform a tree traversal similarly to `Node.walk()` (which
+ see), except also call the `dispatch_departure()` method
+ before exiting each node.
+
+ Parameter `visitor`: A `NodeVisitor` object, containing a
+ ``visit`` and ``depart`` implementation for each `Node`
+ subclass encountered.
+
+ Return true if we should stop the traversal.
+ """
+ call_depart = True
+ stop = False
+ visitor.document.reporter.debug(
+ 'docutils.nodes.Node.walkabout calling dispatch_visit for %s'
+ % self.__class__.__name__)
+ try:
+ try:
+ visitor.dispatch_visit(self)
+ except SkipNode:
+ return stop
+ except SkipDeparture:
+ call_depart = False
+ children = self.children
+ try:
+ for child in children[:]:
+ if child.walkabout(visitor):
+ stop = True
+ break
+ except SkipSiblings:
+ pass
+ except SkipChildren:
+ pass
+ except StopTraversal:
+ stop = True
+ if call_depart:
+ visitor.document.reporter.debug(
+ 'docutils.nodes.Node.walkabout calling dispatch_departure '
+ 'for %s' % self.__class__.__name__)
+ visitor.dispatch_departure(self)
+ return stop
+
+ def _fast_traverse(self, cls):
+ """Return iterator that only supports instance checks."""
+ if isinstance(self, cls):
+ yield self
+ for child in self.children:
+ for subnode in child._fast_traverse(cls):
+ yield subnode
+
+ def _all_traverse(self):
+ """Return iterator that doesn't check for a condition."""
+ yield self
+ for child in self.children:
+ for subnode in child._all_traverse():
+ yield subnode
+
+ def traverse(self, condition=None, include_self=True, descend=True,
+ siblings=False, ascend=False):
+ """
+ Return an iterable containing
+
+ * self (if include_self is true)
+ * all descendants in tree traversal order (if descend is true)
+ * all siblings (if siblings is true) and their descendants (if
+ also descend is true)
+ * the siblings of the parent (if ascend is true) and their
+ descendants (if also descend is true), and so on
+
+ If `condition` is not None, the iterable contains only nodes
+ for which ``condition(node)`` is true. If `condition` is a
+ node class ``cls``, it is equivalent to a function consisting
+ of ``return isinstance(node, cls)``.
+
+ If ascend is true, assume siblings to be true as well.
+
+ For example, given the following tree::
+
+ <paragraph>
+ <emphasis> <--- emphasis.traverse() and
+ <strong> <--- strong.traverse() are called.
+ Foo
+ Bar
+ <reference name="Baz" refid="baz">
+ Baz
+
+ Then list(emphasis.traverse()) equals ::
+
+ [<emphasis>, <strong>, <#text: Foo>, <#text: Bar>]
+
+ and list(strong.traverse(ascend=True)) equals ::
+
+ [<strong>, <#text: Foo>, <#text: Bar>, <reference>, <#text: Baz>]
+ """
+ # Although the documented API only promises an "iterable" as return
+ # value, the implementation returned a list up to v. 0.15. Some 3rd
+ # party code still relies on this (e.g. Sphinx as of 2019-09-07).
+ # Therefore, let's return a list until this is sorted out:
+ return _traversal_list(self._traverse(condition, include_self,
+ descend, siblings, ascend))
+
+ def _traverse(self, condition=None, include_self=True, descend=True,
+ siblings=False, ascend=False):
+ """Return iterator over nodes following `self`. See `traverse()`."""
+ if ascend:
+ siblings=True
+ # Check for special argument combinations that allow using an
+ # optimized version of traverse()
+ if include_self and descend and not siblings:
+ if condition is None:
+ for subnode in self._all_traverse():
+ yield subnode
+ return
+ elif isinstance(condition, type):
+ for subnode in self._fast_traverse(condition):
+ yield subnode
+ return
+ # Check if `condition` is a class (check for TypeType for Python
+ # implementations that use only new-style classes, like PyPy).
+ if isinstance(condition, type):
+ node_class = condition
+ def condition(node, node_class=node_class):
+ return isinstance(node, node_class)
+
+
+ if include_self and (condition is None or condition(self)):
+ yield self
+ if descend and len(self.children):
+ for child in self:
+ for subnode in child._traverse(condition=condition,
+ include_self=True, descend=True,
+ siblings=False, ascend=False):
+ yield subnode
+ if siblings or ascend:
+ node = self
+ while node.parent:
+ index = node.parent.index(node)
+ for sibling in node.parent[index+1:]:
+ for subnode in sibling._traverse(condition=condition,
+ include_self=True, descend=descend,
+ siblings=False, ascend=False):
+ yield subnode
+ if not ascend:
+ break
+ else:
+ node = node.parent
+
+ def next_node(self, condition=None, include_self=False, descend=True,
+ siblings=False, ascend=False):
+ """
+ Return the first node in the iterable returned by traverse(),
+ or None if the iterable is empty.
+
+ Parameter list is the same as of traverse. Note that
+ include_self defaults to False, though.
+ """
+ node_iterator = self._traverse(condition, include_self,
+ descend, siblings, ascend)
+ try:
+ return next(node_iterator)
+ except StopIteration:
+ return None
+
+if sys.version_info < (3, 0):
+ class reprunicode(unicode):
+ """
+ A unicode sub-class that removes the initial u from unicode's repr.
+ """
+
+ def __repr__(self):
+ return unicode.__repr__(self)[1:]
+else:
+ reprunicode = unicode
+
+
+def ensure_str(s):
+ """
+ Failsave conversion of `unicode` to `str`.
+ """
+ if sys.version_info < (3, 0) and isinstance(s, unicode):
+ return s.encode('ascii', 'backslashreplace')
+ return s
+
+# definition moved here from `utils` to avoid circular import dependency
+def unescape(text, restore_backslashes=False, respect_whitespace=False):
+ """
+ Return a string with nulls removed or restored to backslashes.
+ Backslash-escaped spaces are also removed.
+ """
+ # `respect_whitespace` is ignored (since introduction 2016-12-16)
+ if restore_backslashes:
+ return text.replace('\x00', '\\')
+ else:
+ for sep in ['\x00 ', '\x00\n', '\x00']:
+ text = ''.join(text.split(sep))
+ return text
+
+
+class Text(Node, reprunicode):
+
+ """
+ Instances are terminal nodes (leaves) containing text only; no child
+ nodes or attributes. Initialize by passing a string to the constructor.
+ Access the text itself with the `astext` method.
+ """
+
+ tagname = '#text'
+
+ children = ()
+ """Text nodes have no children, and cannot have children."""
+
+ if sys.version_info > (3, 0):
+ def __new__(cls, data, rawsource=None):
+ """Prevent the rawsource argument from propagating to str."""
+ if isinstance(data, bytes):
+ raise TypeError('expecting str data, not bytes')
+ return reprunicode.__new__(cls, data)
+ else:
+ def __new__(cls, data, rawsource=None):
+ """Prevent the rawsource argument from propagating to str."""
+ return reprunicode.__new__(cls, data)
+
+ def __init__(self, data, rawsource=''):
+ self.rawsource = rawsource
+ """The raw text from which this element was constructed."""
+
+ def shortrepr(self, maxlen=18):
+ data = self
+ if len(data) > maxlen:
+ data = data[:maxlen-4] + ' ...'
+ return '<%s: %r>' % (self.tagname, reprunicode(data))
+
+ def __repr__(self):
+ return self.shortrepr(maxlen=68)
+
+ def _dom_node(self, domroot):
+ return domroot.createTextNode(unicode(self))
+
+ def astext(self):
+ return reprunicode(unescape(self))
+
+ # Note about __unicode__: The implementation of __unicode__ here,
+ # and the one raising NotImplemented in the superclass Node had
+ # to be removed when changing Text to a subclass of unicode instead
+ # of UserString, since there is no way to delegate the __unicode__
+ # call to the superclass unicode:
+ # unicode itself does not have __unicode__ method to delegate to
+ # and calling unicode(self) or unicode.__new__ directly creates
+ # an infinite loop
+
+ def copy(self):
+ return self.__class__(reprunicode(self), rawsource=self.rawsource)
+
+ def deepcopy(self):
+ return self.copy()
+
+ def pformat(self, indent=' ', level=0):
+ indent = indent * level
+ lines = [indent+line for line in self.astext().splitlines()]
+ if not lines:
+ return ''
+ return '\n'.join(lines) + '\n'
+
+ # rstrip and lstrip are used by substitution definitions where
+ # they are expected to return a Text instance, this was formerly
+ # taken care of by UserString.
+
+ def rstrip(self, chars=None):
+ return self.__class__(reprunicode.rstrip(self, chars), self.rawsource)
+
+ def lstrip(self, chars=None):
+ return self.__class__(reprunicode.lstrip(self, chars), self.rawsource)
+
+class Element(Node):
+
+ """
+ `Element` is the superclass to all specific elements.
+
+ Elements contain attributes and child nodes. Elements emulate
+ dictionaries for attributes, indexing by attribute name (a string). To
+ set the attribute 'att' to 'value', do::
+
+ element['att'] = 'value'
+
+ There are two special attributes: 'ids' and 'names'. Both are
+ lists of unique identifiers, and names serve as human interfaces
+ to IDs. Names are case- and whitespace-normalized (see the
+ fully_normalize_name() function), and IDs conform to the regular
+ expression ``[a-z](-?[a-z0-9]+)*`` (see the make_id() function).
+
+ Elements also emulate lists for child nodes (element nodes and/or text
+ nodes), indexing by integer. To get the first child node, use::
+
+ element[0]
+
+ Elements may be constructed using the ``+=`` operator. To add one new
+ child node to element, do::
+
+ element += node
+
+ This is equivalent to ``element.append(node)``.
+
+ To add a list of multiple child nodes at once, use the same ``+=``
+ operator::
+
+ element += [node1, node2]
+
+ This is equivalent to ``element.extend([node1, node2])``.
+ """
+
+ basic_attributes = ('ids', 'classes', 'names', 'dupnames')
+ """List attributes which are defined for every Element-derived class
+ instance and can be safely transferred to a different node."""
+
+ local_attributes = ('backrefs',)
+ """A list of class-specific attributes that should not be copied with the
+ standard attributes when replacing a node.
+
+ NOTE: Derived classes should override this value to prevent any of its
+ attributes being copied by adding to the value in its parent class."""
+
+ list_attributes = basic_attributes + local_attributes
+ """List attributes, automatically initialized to empty lists for
+ all nodes."""
+
+ known_attributes = list_attributes + ('source', 'rawsource')
+ """List attributes that are known to the Element base class."""
+
+ tagname = None
+ """The element generic identifier. If None, it is set as an instance
+ attribute to the name of the class."""
+
+ child_text_separator = '\n\n'
+ """Separator for child nodes, used by `astext()` method."""
+
+ def __init__(self, rawsource='', *children, **attributes):
+ self.rawsource = rawsource
+ """The raw text from which this element was constructed.
+
+ NOTE: some elements do not set this value (default '').
+ """
+
+ self.children = []
+ """List of child nodes (elements and/or `Text`)."""
+
+ self.extend(children) # maintain parent info
+
+ self.attributes = {}
+ """Dictionary of attribute {name: value}."""
+
+ # Initialize list attributes.
+ for att in self.list_attributes:
+ self.attributes[att] = []
+
+ for att, value in attributes.items():
+ att = att.lower()
+ if att in self.list_attributes:
+ # mutable list; make a copy for this node
+ self.attributes[att] = value[:]
+ else:
+ self.attributes[att] = value
+
+ if self.tagname is None:
+ self.tagname = self.__class__.__name__
+
+ def _dom_node(self, domroot):
+ element = domroot.createElement(self.tagname)
+ for attribute, value in self.attlist():
+ if isinstance(value, list):
+ value = ' '.join([serial_escape('%s' % (v,)) for v in value])
+ element.setAttribute(attribute, '%s' % value)
+ for child in self.children:
+ element.appendChild(child._dom_node(domroot))
+ return element
+
+ def __repr__(self):
+ data = ''
+ for c in self.children:
+ data += c.shortrepr()
+ if len(data) > 60:
+ data = data[:56] + ' ...'
+ break
+ if self['names']:
+ return '<%s "%s": %s>' % (self.__class__.__name__,
+ '; '.join([ensure_str(n) for n in self['names']]), data)
+ else:
+ return '<%s: %s>' % (self.__class__.__name__, data)
+
+ def shortrepr(self):
+ if self['names']:
+ return '<%s "%s"...>' % (self.__class__.__name__,
+ '; '.join([ensure_str(n) for n in self['names']]))
+ else:
+ return '<%s...>' % self.tagname
+
+ def __unicode__(self):
+ if self.children:
+ return u'%s%s%s' % (self.starttag(),
+ ''.join([unicode(c) for c in self.children]),
+ self.endtag())
+ else:
+ return self.emptytag()
+
+ if sys.version_info >= (3, 0):
+ __str__ = __unicode__
+
+ def starttag(self, quoteattr=None):
+ # the optional arg is used by the docutils_xml writer
+ if quoteattr is None:
+ quoteattr = pseudo_quoteattr
+ parts = [self.tagname]
+ for name, value in self.attlist():
+ if value is None: # boolean attribute
+ parts.append('%s="True"' % name)
+ continue
+ if isinstance(value, list):
+ values = [serial_escape('%s' % (v,)) for v in value]
+ value = ' '.join(values)
+ else:
+ value = unicode(value)
+ value = quoteattr(value)
+ parts.append(u'%s=%s' % (name, value))
+ return u'<%s>' % u' '.join(parts)
+
+ def endtag(self):
+ return '</%s>' % self.tagname
+
+ def emptytag(self):
+ return u'<%s/>' % u' '.join([self.tagname] +
+ ['%s="%s"' % (n, v)
+ for n, v in self.attlist()])
+
+ def __len__(self):
+ return len(self.children)
+
+ def __getitem__(self, key):
+ if isinstance(key, basestring):
+ return self.attributes[key]
+ elif isinstance(key, int):
+ return self.children[key]
+ elif isinstance(key, slice):
+ assert key.step in (None, 1), 'cannot handle slice with stride'
+ return self.children[key.start:key.stop]
+ else:
+ raise TypeError('element index must be an integer, a slice, or '
+ 'an attribute name string')
+
+ def __setitem__(self, key, item):
+ if isinstance(key, basestring):
+ self.attributes[str(key)] = item
+ elif isinstance(key, int):
+ self.setup_child(item)
+ self.children[key] = item
+ elif isinstance(key, slice):
+ assert key.step in (None, 1), 'cannot handle slice with stride'
+ for node in item:
+ self.setup_child(node)
+ self.children[key.start:key.stop] = item
+ else:
+ raise TypeError('element index must be an integer, a slice, or '
+ 'an attribute name string')
+
+ def __delitem__(self, key):
+ if isinstance(key, basestring):
+ del self.attributes[key]
+ elif isinstance(key, int):
+ del self.children[key]
+ elif isinstance(key, slice):
+ assert key.step in (None, 1), 'cannot handle slice with stride'
+ del self.children[key.start:key.stop]
+ else:
+ raise TypeError('element index must be an integer, a simple '
+ 'slice, or an attribute name string')
+
+ def __add__(self, other):
+ return self.children + other
+
+ def __radd__(self, other):
+ return other + self.children
+
+ def __iadd__(self, other):
+ """Append a node or a list of nodes to `self.children`."""
+ if isinstance(other, Node):
+ self.append(other)
+ elif other is not None:
+ self.extend(other)
+ return self
+
+ def astext(self):
+ return self.child_text_separator.join(
+ [child.astext() for child in self.children])
+
+ def non_default_attributes(self):
+ atts = {}
+ for key, value in self.attributes.items():
+ if self.is_not_default(key):
+ atts[key] = value
+ return atts
+
+ def attlist(self):
+ attlist = sorted(self.non_default_attributes().items())
+ return attlist
+
+ def get(self, key, failobj=None):
+ return self.attributes.get(key, failobj)
+
+ def hasattr(self, attr):
+ return attr in self.attributes
+
+ def delattr(self, attr):
+ if attr in self.attributes:
+ del self.attributes[attr]
+
+ def setdefault(self, key, failobj=None):
+ return self.attributes.setdefault(key, failobj)
+
+ has_key = hasattr
+
+ # support operator ``in``
+ def __contains__(self, key):
+ # support both membership test for children and attributes
+ # (has_key is translated to "in" by 2to3)
+ if isinstance(key, basestring):
+ return key in self.attributes
+ return key in self.children
+
+ def get_language_code(self, fallback=''):
+ """Return node's language tag.
+
+ Look iteratively in self and parents for a class argument
+ starting with ``language-`` and return the remainder of it
+ (which should be a `BCP49` language tag) or the `fallback`.
+ """
+ for cls in self.get('classes', []):
+ if cls.startswith('language-'):
+ return cls[9:]
+ try:
+ return self.parent.get_language(fallback)
+ except AttributeError:
+ return fallback
+
+ def append(self, item):
+ self.setup_child(item)
+ self.children.append(item)
+
+ def extend(self, item):
+ for node in item:
+ self.append(node)
+
+ def insert(self, index, item):
+ if isinstance(item, Node):
+ self.setup_child(item)
+ self.children.insert(index, item)
+ elif item is not None:
+ self[index:index] = item
+
+ def pop(self, i=-1):
+ return self.children.pop(i)
+
+ def remove(self, item):
+ self.children.remove(item)
+
+ def index(self, item):
+ return self.children.index(item)
+
+ def is_not_default(self, key):
+ if self[key] == [] and key in self.list_attributes:
+ return 0
+ else:
+ return 1
+
+ def update_basic_atts(self, dict_):
+ """
+ Update basic attributes ('ids', 'names', 'classes',
+ 'dupnames', but not 'source') from node or dictionary `dict_`.
+ """
+ if isinstance(dict_, Node):
+ dict_ = dict_.attributes
+ for att in self.basic_attributes:
+ self.append_attr_list(att, dict_.get(att, []))
+
+ def append_attr_list(self, attr, values):
+ """
+ For each element in values, if it does not exist in self[attr], append
+ it.
+
+ NOTE: Requires self[attr] and values to be sequence type and the
+ former should specifically be a list.
+ """
+ # List Concatenation
+ for value in values:
+ if not value in self[attr]:
+ self[attr].append(value)
+
+ def coerce_append_attr_list(self, attr, value):
+ """
+ First, convert both self[attr] and value to a non-string sequence
+ type; if either is not already a sequence, convert it to a list of one
+ element. Then call append_attr_list.
+
+ NOTE: self[attr] and value both must not be None.
+ """
+ # List Concatenation
+ if not isinstance(self.get(attr), list):
+ self[attr] = [self[attr]]
+ if not isinstance(value, list):
+ value = [value]
+ self.append_attr_list(attr, value)
+
+ def replace_attr(self, attr, value, force = True):
+ """
+ If self[attr] does not exist or force is True or omitted, set
+ self[attr] to value, otherwise do nothing.
+ """
+ # One or the other
+ if force or self.get(attr) is None:
+ self[attr] = value
+
+ def copy_attr_convert(self, attr, value, replace = True):
+ """
+ If attr is an attribute of self, set self[attr] to
+ [self[attr], value], otherwise set self[attr] to value.
+
+ NOTE: replace is not used by this function and is kept only for
+ compatibility with the other copy functions.
+ """
+ if self.get(attr) is not value:
+ self.coerce_append_attr_list(attr, value)
+
+ def copy_attr_coerce(self, attr, value, replace):
+ """
+ If attr is an attribute of self and either self[attr] or value is a
+ list, convert all non-sequence values to a sequence of 1 element and
+ then concatenate the two sequence, setting the result to self[attr].
+ If both self[attr] and value are non-sequences and replace is True or
+ self[attr] is None, replace self[attr] with value. Otherwise, do
+ nothing.
+ """
+ if self.get(attr) is not value:
+ if isinstance(self.get(attr), list) or \
+ isinstance(value, list):
+ self.coerce_append_attr_list(attr, value)
+ else:
+ self.replace_attr(attr, value, replace)
+
+ def copy_attr_concatenate(self, attr, value, replace):
+ """
+ If attr is an attribute of self and both self[attr] and value are
+ lists, concatenate the two sequences, setting the result to
+ self[attr]. If either self[attr] or value are non-sequences and
+ replace is True or self[attr] is None, replace self[attr] with value.
+ Otherwise, do nothing.
+ """
+ if self.get(attr) is not value:
+ if isinstance(self.get(attr), list) and \
+ isinstance(value, list):
+ self.append_attr_list(attr, value)
+ else:
+ self.replace_attr(attr, value, replace)
+
+ def copy_attr_consistent(self, attr, value, replace):
+ """
+ If replace is True or self[attr] is None, replace self[attr] with
+ value. Otherwise, do nothing.
+ """
+ if self.get(attr) is not value:
+ self.replace_attr(attr, value, replace)
+
+ def update_all_atts(self, dict_, update_fun = copy_attr_consistent,
+ replace = True, and_source = False):
+ """
+ Updates all attributes from node or dictionary `dict_`.
+
+ Appends the basic attributes ('ids', 'names', 'classes',
+ 'dupnames', but not 'source') and then, for all other attributes in
+ dict_, updates the same attribute in self. When attributes with the
+ same identifier appear in both self and dict_, the two values are
+ merged based on the value of update_fun. Generally, when replace is
+ True, the values in self are replaced or merged with the values in
+ dict_; otherwise, the values in self may be preserved or merged. When
+ and_source is True, the 'source' attribute is included in the copy.
+
+ NOTE: When replace is False, and self contains a 'source' attribute,
+ 'source' is not replaced even when dict_ has a 'source'
+ attribute, though it may still be merged into a list depending
+ on the value of update_fun.
+ NOTE: It is easier to call the update-specific methods then to pass
+ the update_fun method to this function.
+ """
+ if isinstance(dict_, Node):
+ dict_ = dict_.attributes
+
+ # Include the source attribute when copying?
+ if and_source:
+ filter_fun = self.is_not_list_attribute
+ else:
+ filter_fun = self.is_not_known_attribute
+
+ # Copy the basic attributes
+ self.update_basic_atts(dict_)
+
+ # Grab other attributes in dict_ not in self except the
+ # (All basic attributes should be copied already)
+ for att in filter(filter_fun, dict_):
+ update_fun(self, att, dict_[att], replace)
+
+ def update_all_atts_consistantly(self, dict_, replace = True,
+ and_source = False):
+ """
+ Updates all attributes from node or dictionary `dict_`.
+
+ Appends the basic attributes ('ids', 'names', 'classes',
+ 'dupnames', but not 'source') and then, for all other attributes in
+ dict_, updates the same attribute in self. When attributes with the
+ same identifier appear in both self and dict_ and replace is True, the
+ values in self are replaced with the values in dict_; otherwise, the
+ values in self are preserved. When and_source is True, the 'source'
+ attribute is included in the copy.
+
+ NOTE: When replace is False, and self contains a 'source' attribute,
+ 'source' is not replaced even when dict_ has a 'source'
+ attribute, though it may still be merged into a list depending
+ on the value of update_fun.
+ """
+ self.update_all_atts(dict_, Element.copy_attr_consistent, replace,
+ and_source)
+
+ def update_all_atts_concatenating(self, dict_, replace = True,
+ and_source = False):
+ """
+ Updates all attributes from node or dictionary `dict_`.
+
+ Appends the basic attributes ('ids', 'names', 'classes',
+ 'dupnames', but not 'source') and then, for all other attributes in
+ dict_, updates the same attribute in self. When attributes with the
+ same identifier appear in both self and dict_ whose values aren't each
+ lists and replace is True, the values in self are replaced with the
+ values in dict_; if the values from self and dict_ for the given
+ identifier are both of list type, then the two lists are concatenated
+ and the result stored in self; otherwise, the values in self are
+ preserved. When and_source is True, the 'source' attribute is
+ included in the copy.
+
+ NOTE: When replace is False, and self contains a 'source' attribute,
+ 'source' is not replaced even when dict_ has a 'source'
+ attribute, though it may still be merged into a list depending
+ on the value of update_fun.
+ """
+ self.update_all_atts(dict_, Element.copy_attr_concatenate, replace,
+ and_source)
+
+ def update_all_atts_coercion(self, dict_, replace = True,
+ and_source = False):
+ """
+ Updates all attributes from node or dictionary `dict_`.
+
+ Appends the basic attributes ('ids', 'names', 'classes',
+ 'dupnames', but not 'source') and then, for all other attributes in
+ dict_, updates the same attribute in self. When attributes with the
+ same identifier appear in both self and dict_ whose values are both
+ not lists and replace is True, the values in self are replaced with
+ the values in dict_; if either of the values from self and dict_ for
+ the given identifier are of list type, then first any non-lists are
+ converted to 1-element lists and then the two lists are concatenated
+ and the result stored in self; otherwise, the values in self are
+ preserved. When and_source is True, the 'source' attribute is
+ included in the copy.
+
+ NOTE: When replace is False, and self contains a 'source' attribute,
+ 'source' is not replaced even when dict_ has a 'source'
+ attribute, though it may still be merged into a list depending
+ on the value of update_fun.
+ """
+ self.update_all_atts(dict_, Element.copy_attr_coerce, replace,
+ and_source)
+
+ def update_all_atts_convert(self, dict_, and_source = False):
+ """
+ Updates all attributes from node or dictionary `dict_`.
+
+ Appends the basic attributes ('ids', 'names', 'classes',
+ 'dupnames', but not 'source') and then, for all other attributes in
+ dict_, updates the same attribute in self. When attributes with the
+ same identifier appear in both self and dict_ then first any non-lists
+ are converted to 1-element lists and then the two lists are
+ concatenated and the result stored in self; otherwise, the values in
+ self are preserved. When and_source is True, the 'source' attribute
+ is included in the copy.
+
+ NOTE: When replace is False, and self contains a 'source' attribute,
+ 'source' is not replaced even when dict_ has a 'source'
+ attribute, though it may still be merged into a list depending
+ on the value of update_fun.
+ """
+ self.update_all_atts(dict_, Element.copy_attr_convert,
+ and_source = and_source)
+
+ def clear(self):
+ self.children = []
+
+ def replace(self, old, new):
+ """Replace one child `Node` with another child or children."""
+ index = self.index(old)
+ if isinstance(new, Node):
+ self.setup_child(new)
+ self[index] = new
+ elif new is not None:
+ self[index:index+1] = new
+
+ def replace_self(self, new):
+ """
+ Replace `self` node with `new`, where `new` is a node or a
+ list of nodes.
+ """
+ update = new
+ if not isinstance(new, Node):
+ # `new` is a list; update first child.
+ try:
+ update = new[0]
+ except IndexError:
+ update = None
+ if isinstance(update, Element):
+ update.update_basic_atts(self)
+ else:
+ # `update` is a Text node or `new` is an empty list.
+ # Assert that we aren't losing any attributes.
+ for att in self.basic_attributes:
+ assert not self[att], \
+ 'Losing "%s" attribute: %s' % (att, self[att])
+ self.parent.replace(self, new)
+
+ def first_child_matching_class(self, childclass, start=0, end=sys.maxsize):
+ """
+ Return the index of the first child whose class exactly matches.
+
+ Parameters:
+
+ - `childclass`: A `Node` subclass to search for, or a tuple of `Node`
+ classes. If a tuple, any of the classes may match.
+ - `start`: Initial index to check.
+ - `end`: Initial index to *not* check.
+ """
+ if not isinstance(childclass, tuple):
+ childclass = (childclass,)
+ for index in range(start, min(len(self), end)):
+ for c in childclass:
+ if isinstance(self[index], c):
+ return index
+ return None
+
+ def first_child_not_matching_class(self, childclass, start=0,
+ end=sys.maxsize):
+ """
+ Return the index of the first child whose class does *not* match.
+
+ Parameters:
+
+ - `childclass`: A `Node` subclass to skip, or a tuple of `Node`
+ classes. If a tuple, none of the classes may match.
+ - `start`: Initial index to check.
+ - `end`: Initial index to *not* check.
+ """
+ if not isinstance(childclass, tuple):
+ childclass = (childclass,)
+ for index in range(start, min(len(self), end)):
+ for c in childclass:
+ if isinstance(self.children[index], c):
+ break
+ else:
+ return index
+ return None
+
+ def pformat(self, indent=' ', level=0):
+ return ''.join(['%s%s\n' % (indent * level, self.starttag())] +
+ [child.pformat(indent, level+1)
+ for child in self.children])
+
+ def copy(self):
+ obj = self.__class__(rawsource=self.rawsource, **self.attributes)
+ obj.document = self.document
+ obj.source = self.source
+ obj.line = self.line
+ return obj
+
+ def deepcopy(self):
+ copy = self.copy()
+ copy.extend([child.deepcopy() for child in self.children])
+ return copy
+
+ def set_class(self, name):
+ """Add a new class to the "classes" attribute."""
+ warnings.warn('docutils.nodes.Element.set_class deprecated; '
+ "append to Element['classes'] list attribute directly",
+ DeprecationWarning, stacklevel=2)
+ assert ' ' not in name
+ self['classes'].append(name.lower())
+
+ def note_referenced_by(self, name=None, id=None):
+ """Note that this Element has been referenced by its name
+ `name` or id `id`."""
+ self.referenced = 1
+ # Element.expect_referenced_by_* dictionaries map names or ids
+ # to nodes whose ``referenced`` attribute is set to true as
+ # soon as this node is referenced by the given name or id.
+ # Needed for target propagation.
+ by_name = getattr(self, 'expect_referenced_by_name', {}).get(name)
+ by_id = getattr(self, 'expect_referenced_by_id', {}).get(id)
+ if by_name:
+ assert name is not None
+ by_name.referenced = 1
+ if by_id:
+ assert id is not None
+ by_id.referenced = 1
+
+ @classmethod
+ def is_not_list_attribute(cls, attr):
+ """
+ Returns True if and only if the given attribute is NOT one of the
+ basic list attributes defined for all Elements.
+ """
+ return attr not in cls.list_attributes
+
+ @classmethod
+ def is_not_known_attribute(cls, attr):
+ """
+ Returns True if and only if the given attribute is NOT recognized by
+ this class.
+ """
+ return attr not in cls.known_attributes
+
+
+class TextElement(Element):
+
+ """
+ An element which directly contains text.
+
+ Its children are all `Text` or `Inline` subclass nodes. You can
+ check whether an element's context is inline simply by checking whether
+ its immediate parent is a `TextElement` instance (including subclasses).
+ This is handy for nodes like `image` that can appear both inline and as
+ standalone body elements.
+
+ If passing children to `__init__()`, make sure to set `text` to
+ ``''`` or some other suitable value.
+ """
+
+ child_text_separator = ''
+ """Separator for child nodes, used by `astext()` method."""
+
+ def __init__(self, rawsource='', text='', *children, **attributes):
+ if text != '':
+ textnode = Text(text)
+ Element.__init__(self, rawsource, textnode, *children,
+ **attributes)
+ else:
+ Element.__init__(self, rawsource, *children, **attributes)
+
+
+class FixedTextElement(TextElement):
+
+ """An element which directly contains preformatted text."""
+
+ def __init__(self, rawsource='', text='', *children, **attributes):
+ TextElement.__init__(self, rawsource, text, *children, **attributes)
+ self.attributes['xml:space'] = 'preserve'
+
+
+# ========
+# Mixins
+# ========
+
+class Resolvable(object):
+
+ resolved = 0
+
+
+class BackLinkable(object):
+
+ def add_backref(self, refid):
+ self['backrefs'].append(refid)
+
+
+# ====================
+# Element Categories
+# ====================
+
+class Root(object):
+ pass
+
+
+class Titular(object):
+ pass
+
+
+class PreBibliographic(object):
+ """Category of Node which may occur before Bibliographic Nodes."""
+
+
+class Bibliographic(object):
+ pass
+
+
+class Decorative(PreBibliographic):
+ pass
+
+
+class Structural(object):
+ pass
+
+
+class Body(object):
+ pass
+
+
+class General(Body):
+ pass
+
+
+class Sequential(Body):
+ """List-like elements."""
+
+
+class Admonition(Body): pass
+
+
+class Special(Body):
+ """Special internal body elements."""
+
+
+class Invisible(PreBibliographic):
+ """Internal elements that don't appear in output."""
+
+
+class Part(object):
+ pass
+
+
+class Inline(object):
+ pass
+
+
+class Referential(Resolvable):
+ pass
+
+
+class Targetable(Resolvable):
+
+ referenced = 0
+
+ indirect_reference_name = None
+ """Holds the whitespace_normalized_name (contains mixed case) of a target.
+ Required for MoinMoin/reST compatibility."""
+
+
+class Labeled(object):
+ """Contains a `label` as its first element."""
+
+
+# ==============
+# Root Element
+# ==============
+
+class document(Root, Structural, Element):
+
+ """
+ The document root element.
+
+ Do not instantiate this class directly; use
+ `docutils.utils.new_document()` instead.
+ """
+
+ def __init__(self, settings, reporter, *args, **kwargs):
+ Element.__init__(self, *args, **kwargs)
+
+ self.current_source = None
+ """Path to or description of the input source being processed."""
+
+ self.current_line = None
+ """Line number (1-based) of `current_source`."""
+
+ self.settings = settings
+ """Runtime settings data record."""
+
+ self.reporter = reporter
+ """System message generator."""
+
+ self.indirect_targets = []
+ """List of indirect target nodes."""
+
+ self.substitution_defs = {}
+ """Mapping of substitution names to substitution_definition nodes."""
+
+ self.substitution_names = {}
+ """Mapping of case-normalized substitution names to case-sensitive
+ names."""
+
+ self.refnames = {}
+ """Mapping of names to lists of referencing nodes."""
+
+ self.refids = {}
+ """Mapping of ids to lists of referencing nodes."""
+
+ self.nameids = {}
+ """Mapping of names to unique id's."""
+
+ self.nametypes = {}
+ """Mapping of names to hyperlink type (boolean: True => explicit,
+ False => implicit."""
+
+ self.ids = {}
+ """Mapping of ids to nodes."""
+
+ self.footnote_refs = {}
+ """Mapping of footnote labels to lists of footnote_reference nodes."""
+
+ self.citation_refs = {}
+ """Mapping of citation labels to lists of citation_reference nodes."""
+
+ self.autofootnotes = []
+ """List of auto-numbered footnote nodes."""
+
+ self.autofootnote_refs = []
+ """List of auto-numbered footnote_reference nodes."""
+
+ self.symbol_footnotes = []
+ """List of symbol footnote nodes."""
+
+ self.symbol_footnote_refs = []
+ """List of symbol footnote_reference nodes."""
+
+ self.footnotes = []
+ """List of manually-numbered footnote nodes."""
+
+ self.citations = []
+ """List of citation nodes."""
+
+ self.autofootnote_start = 1
+ """Initial auto-numbered footnote number."""
+
+ self.symbol_footnote_start = 0
+ """Initial symbol footnote symbol index."""
+
+ self.id_counter = Counter()
+ """Numbers added to otherwise identical IDs."""
+
+ self.parse_messages = []
+ """System messages generated while parsing."""
+
+ self.transform_messages = []
+ """System messages generated while applying transforms."""
+
+ import docutils.transforms
+ self.transformer = docutils.transforms.Transformer(self)
+ """Storage for transforms to be applied to this document."""
+
+ self.decoration = None
+ """Document's `decoration` node."""
+
+ self.document = self
+
+ def __getstate__(self):
+ """
+ Return dict with unpicklable references removed.
+ """
+ state = self.__dict__.copy()
+ state['reporter'] = None
+ state['transformer'] = None
+ return state
+
+ def asdom(self, dom=None):
+ """Return a DOM representation of this document."""
+ if dom is None:
+ import xml.dom.minidom as dom
+ domroot = dom.Document()
+ domroot.appendChild(self._dom_node(domroot))
+ return domroot
+
+ def set_id(self, node, msgnode=None, suggested_prefix=''):
+ for id in node['ids']:
+ if id in self.ids and self.ids[id] is not node:
+ msg = self.reporter.severe('Duplicate ID: "%s".' % id)
+ if msgnode != None:
+ msgnode += msg
+ if not node['ids']:
+ id_prefix = self.settings.id_prefix
+ auto_id_prefix = self.settings.auto_id_prefix
+ base_id = ''
+ id = ''
+ for name in node['names']:
+ base_id = make_id(name)
+ id = id_prefix + base_id
+ # TODO: allow names starting with numbers if `id_prefix`
+ # is non-empty: id = make_id(id_prefix + name)
+ if base_id and id not in self.ids:
+ break
+ else:
+ if base_id and auto_id_prefix.endswith('%'):
+ # disambiguate name-derived ID
+ # TODO: remove second condition after announcing change
+ prefix = id + '-'
+ else:
+ prefix = id_prefix + auto_id_prefix
+ if prefix.endswith('%'):
+ prefix = '%s%s-' % (prefix[:-1], suggested_prefix
+ or make_id(node.tagname))
+ while True:
+ self.id_counter[prefix] += 1
+ id = '%s%d' % (prefix, self.id_counter[prefix])
+ if id not in self.ids:
+ break
+ node['ids'].append(id)
+ self.ids[id] = node
+ return id
+
+ def set_name_id_map(self, node, id, msgnode=None, explicit=None):
+ """
+ `self.nameids` maps names to IDs, while `self.nametypes` maps names to
+ booleans representing hyperlink type (True==explicit,
+ False==implicit). This method updates the mappings.
+
+ The following state transition table shows how `self.nameids` ("ids")
+ and `self.nametypes` ("types") change with new input (a call to this
+ method), and what actions are performed ("implicit"-type system
+ messages are INFO/1, and "explicit"-type system messages are ERROR/3):
+
+ ==== ===== ======== ======== ======= ==== ===== =====
+ Old State Input Action New State Notes
+ ----------- -------- ----------------- ----------- -----
+ ids types new type sys.msg. dupname ids types
+ ==== ===== ======== ======== ======= ==== ===== =====
+ - - explicit - - new True
+ - - implicit - - new False
+ None False explicit - - new True
+ old False explicit implicit old new True
+ None True explicit explicit new None True
+ old True explicit explicit new,old None True [#]_
+ None False implicit implicit new None False
+ old False implicit implicit new,old None False
+ None True implicit implicit new None True
+ old True implicit implicit new old True
+ ==== ===== ======== ======== ======= ==== ===== =====
+
+ .. [#] Do not clear the name-to-id map or invalidate the old target if
+ both old and new targets are external and refer to identical URIs.
+ The new target is invalidated regardless.
+ """
+ for name in node['names']:
+ if name in self.nameids:
+ self.set_duplicate_name_id(node, id, name, msgnode, explicit)
+ else:
+ self.nameids[name] = id
+ self.nametypes[name] = explicit
+
+ def set_duplicate_name_id(self, node, id, name, msgnode, explicit):
+ old_id = self.nameids[name]
+ old_explicit = self.nametypes[name]
+ self.nametypes[name] = old_explicit or explicit
+ if explicit:
+ if old_explicit:
+ level = 2
+ if old_id is not None:
+ old_node = self.ids[old_id]
+ if 'refuri' in node:
+ refuri = node['refuri']
+ if old_node['names'] \
+ and 'refuri' in old_node \
+ and old_node['refuri'] == refuri:
+ level = 1 # just inform if refuri's identical
+ if level > 1:
+ dupname(old_node, name)
+ self.nameids[name] = None
+ msg = self.reporter.system_message(
+ level, 'Duplicate explicit target name: "%s".' % name,
+ backrefs=[id], base_node=node)
+ if msgnode != None:
+ msgnode += msg
+ dupname(node, name)
+ else:
+ self.nameids[name] = id
+ if old_id is not None:
+ old_node = self.ids[old_id]
+ dupname(old_node, name)
+ else:
+ if old_id is not None and not old_explicit:
+ self.nameids[name] = None
+ old_node = self.ids[old_id]
+ dupname(old_node, name)
+ dupname(node, name)
+ if not explicit or (not old_explicit and old_id is not None):
+ msg = self.reporter.info(
+ 'Duplicate implicit target name: "%s".' % name,
+ backrefs=[id], base_node=node)
+ if msgnode != None:
+ msgnode += msg
+
+ def has_name(self, name):
+ return name in self.nameids
+
+ # "note" here is an imperative verb: "take note of".
+ def note_implicit_target(self, target, msgnode=None):
+ id = self.set_id(target, msgnode)
+ self.set_name_id_map(target, id, msgnode, explicit=None)
+
+ def note_explicit_target(self, target, msgnode=None):
+ id = self.set_id(target, msgnode)
+ self.set_name_id_map(target, id, msgnode, explicit=True)
+
+ def note_refname(self, node):
+ self.refnames.setdefault(node['refname'], []).append(node)
+
+ def note_refid(self, node):
+ self.refids.setdefault(node['refid'], []).append(node)
+
+ def note_indirect_target(self, target):
+ self.indirect_targets.append(target)
+ if target['names']:
+ self.note_refname(target)
+
+ def note_anonymous_target(self, target):
+ self.set_id(target)
+
+ def note_autofootnote(self, footnote):
+ self.set_id(footnote)
+ self.autofootnotes.append(footnote)
+
+ def note_autofootnote_ref(self, ref):
+ self.set_id(ref)
+ self.autofootnote_refs.append(ref)
+
+ def note_symbol_footnote(self, footnote):
+ self.set_id(footnote)
+ self.symbol_footnotes.append(footnote)
+
+ def note_symbol_footnote_ref(self, ref):
+ self.set_id(ref)
+ self.symbol_footnote_refs.append(ref)
+
+ def note_footnote(self, footnote):
+ self.set_id(footnote)
+ self.footnotes.append(footnote)
+
+ def note_footnote_ref(self, ref):
+ self.set_id(ref)
+ self.footnote_refs.setdefault(ref['refname'], []).append(ref)
+ self.note_refname(ref)
+
+ def note_citation(self, citation):
+ self.citations.append(citation)
+
+ def note_citation_ref(self, ref):
+ self.set_id(ref)
+ self.citation_refs.setdefault(ref['refname'], []).append(ref)
+ self.note_refname(ref)
+
+ def note_substitution_def(self, subdef, def_name, msgnode=None):
+ name = whitespace_normalize_name(def_name)
+ if name in self.substitution_defs:
+ msg = self.reporter.error(
+ 'Duplicate substitution definition name: "%s".' % name,
+ base_node=subdef)
+ if msgnode != None:
+ msgnode += msg
+ oldnode = self.substitution_defs[name]
+ dupname(oldnode, name)
+ # keep only the last definition:
+ self.substitution_defs[name] = subdef
+ # case-insensitive mapping:
+ self.substitution_names[fully_normalize_name(name)] = name
+
+ def note_substitution_ref(self, subref, refname):
+ subref['refname'] = whitespace_normalize_name(refname)
+
+ def note_pending(self, pending, priority=None):
+ self.transformer.add_pending(pending, priority)
+
+ def note_parse_message(self, message):
+ self.parse_messages.append(message)
+
+ def note_transform_message(self, message):
+ self.transform_messages.append(message)
+
+ def note_source(self, source, offset):
+ self.current_source = source
+ if offset is None:
+ self.current_line = offset
+ else:
+ self.current_line = offset + 1
+
+ def copy(self):
+ obj = self.__class__(self.settings, self.reporter,
+ **self.attributes)
+ obj.source = self.source
+ obj.line = self.line
+ return obj
+
+ def get_decoration(self):
+ if not self.decoration:
+ self.decoration = decoration()
+ index = self.first_child_not_matching_class(Titular)
+ if index is None:
+ self.append(self.decoration)
+ else:
+ self.insert(index, self.decoration)
+ return self.decoration
+
+
+# ================
+# Title Elements
+# ================
+
+class title(Titular, PreBibliographic, TextElement): pass
+class subtitle(Titular, PreBibliographic, TextElement): pass
+class rubric(Titular, TextElement): pass
+
+
+# ========================
+# Bibliographic Elements
+# ========================
+
+class docinfo(Bibliographic, Element): pass
+class author(Bibliographic, TextElement): pass
+class authors(Bibliographic, Element): pass
+class organization(Bibliographic, TextElement): pass
+class address(Bibliographic, FixedTextElement): pass
+class contact(Bibliographic, TextElement): pass
+class version(Bibliographic, TextElement): pass
+class revision(Bibliographic, TextElement): pass
+class status(Bibliographic, TextElement): pass
+class date(Bibliographic, TextElement): pass
+class copyright(Bibliographic, TextElement): pass
+
+
+# =====================
+# Decorative Elements
+# =====================
+
+class decoration(Decorative, Element):
+
+ def get_header(self):
+ if not len(self.children) or not isinstance(self.children[0], header):
+ self.insert(0, header())
+ return self.children[0]
+
+ def get_footer(self):
+ if not len(self.children) or not isinstance(self.children[-1], footer):
+ self.append(footer())
+ return self.children[-1]
+
+
+class header(Decorative, Element): pass
+class footer(Decorative, Element): pass
+
+
+# =====================
+# Structural Elements
+# =====================
+
+class section(Structural, Element): pass
+
+
+class topic(Structural, Element):
+
+ """
+ Topics are terminal, "leaf" mini-sections, like block quotes with titles,
+ or textual figures. A topic is just like a section, except that it has no
+ subsections, and it doesn't have to conform to section placement rules.
+
+ Topics are allowed wherever body elements (list, table, etc.) are allowed,
+ but only at the top level of a section or document. Topics cannot nest
+ inside topics, sidebars, or body elements; you can't have a topic inside a
+ table, list, block quote, etc.
+ """
+
+
+class sidebar(Structural, Element):
+
+ """
+ Sidebars are like miniature, parallel documents that occur inside other
+ documents, providing related or reference material. A sidebar is
+ typically offset by a border and "floats" to the side of the page; the
+ document's main text may flow around it. Sidebars can also be likened to
+ super-footnotes; their content is outside of the flow of the document's
+ main text.
+
+ Sidebars are allowed wherever body elements (list, table, etc.) are
+ allowed, but only at the top level of a section or document. Sidebars
+ cannot nest inside sidebars, topics, or body elements; you can't have a
+ sidebar inside a table, list, block quote, etc.
+ """
+
+
+class transition(Structural, Element): pass
+
+
+# ===============
+# Body Elements
+# ===============
+
+class paragraph(General, TextElement): pass
+class compound(General, Element): pass
+class container(General, Element): pass
+class bullet_list(Sequential, Element): pass
+class enumerated_list(Sequential, Element): pass
+class list_item(Part, Element): pass
+class definition_list(Sequential, Element): pass
+class definition_list_item(Part, Element): pass
+class term(Part, TextElement): pass
+class classifier(Part, TextElement): pass
+class definition(Part, Element): pass
+class field_list(Sequential, Element): pass
+class field(Part, Element): pass
+class field_name(Part, TextElement): pass
+class field_body(Part, Element): pass
+
+
+class option(Part, Element):
+
+ child_text_separator = ''
+
+
+class option_argument(Part, TextElement):
+
+ def astext(self):
+ return self.get('delimiter', ' ') + TextElement.astext(self)
+
+
+class option_group(Part, Element):
+
+ child_text_separator = ', '
+
+
+class option_list(Sequential, Element): pass
+
+
+class option_list_item(Part, Element):
+
+ child_text_separator = ' '
+
+
+class option_string(Part, TextElement): pass
+class description(Part, Element): pass
+class literal_block(General, FixedTextElement): pass
+class doctest_block(General, FixedTextElement): pass
+class math_block(General, FixedTextElement): pass
+class line_block(General, Element): pass
+
+
+class line(Part, TextElement):
+
+ indent = None
+
+
+class block_quote(General, Element): pass
+class attribution(Part, TextElement): pass
+class attention(Admonition, Element): pass
+class caution(Admonition, Element): pass
+class danger(Admonition, Element): pass
+class error(Admonition, Element): pass
+class important(Admonition, Element): pass
+class note(Admonition, Element): pass
+class tip(Admonition, Element): pass
+class hint(Admonition, Element): pass
+class warning(Admonition, Element): pass
+class admonition(Admonition, Element): pass
+class comment(Special, Invisible, FixedTextElement): pass
+class substitution_definition(Special, Invisible, TextElement): pass
+class target(Special, Invisible, Inline, TextElement, Targetable): pass
+class footnote(General, BackLinkable, Element, Labeled, Targetable): pass
+class citation(General, BackLinkable, Element, Labeled, Targetable): pass
+class label(Part, TextElement): pass
+class figure(General, Element): pass
+class caption(Part, TextElement): pass
+class legend(Part, Element): pass
+class table(General, Element): pass
+class tgroup(Part, Element): pass
+class colspec(Part, Element): pass
+class thead(Part, Element): pass
+class tbody(Part, Element): pass
+class row(Part, Element): pass
+class entry(Part, Element): pass
+
+
+class system_message(Special, BackLinkable, PreBibliographic, Element):
+
+ """
+ System message element.
+
+ Do not instantiate this class directly; use
+ ``document.reporter.info/warning/error/severe()`` instead.
+ """
+
+ def __init__(self, message=None, *children, **attributes):
+ rawsource = attributes.get('rawsource', '')
+ if message:
+ p = paragraph('', message)
+ children = (p,) + children
+ try:
+ Element.__init__(self, rawsource, *children, **attributes)
+ except:
+ print('system_message: children=%r' % (children,))
+ raise
+
+ def astext(self):
+ line = self.get('line', '')
+ return u'%s:%s: (%s/%s) %s' % (self['source'], line, self['type'],
+ self['level'], Element.astext(self))
+
+
+class pending(Special, Invisible, Element):
+
+ """
+ The "pending" element is used to encapsulate a pending operation: the
+ operation (transform), the point at which to apply it, and any data it
+ requires. Only the pending operation's location within the document is
+ stored in the public document tree (by the "pending" object itself); the
+ operation and its data are stored in the "pending" object's internal
+ instance attributes.
+
+ For example, say you want a table of contents in your reStructuredText
+ document. The easiest way to specify where to put it is from within the
+ document, with a directive::
+
+ .. contents::
+
+ But the "contents" directive can't do its work until the entire document
+ has been parsed and possibly transformed to some extent. So the directive
+ code leaves a placeholder behind that will trigger the second phase of its
+ processing, something like this::
+
+ <pending ...public attributes...> + internal attributes
+
+ Use `document.note_pending()` so that the
+ `docutils.transforms.Transformer` stage of processing can run all pending
+ transforms.
+ """
+
+ def __init__(self, transform, details=None,
+ rawsource='', *children, **attributes):
+ Element.__init__(self, rawsource, *children, **attributes)
+
+ self.transform = transform
+ """The `docutils.transforms.Transform` class implementing the pending
+ operation."""
+
+ self.details = details or {}
+ """Detail data (dictionary) required by the pending operation."""
+
+ def pformat(self, indent=' ', level=0):
+ internals = [
+ '.. internal attributes:',
+ ' .transform: %s.%s' % (self.transform.__module__,
+ self.transform.__name__),
+ ' .details:']
+ details = sorted(self.details.items())
+ for key, value in details:
+ if isinstance(value, Node):
+ internals.append('%7s%s:' % ('', key))
+ internals.extend(['%9s%s' % ('', line)
+ for line in value.pformat().splitlines()])
+ elif value and isinstance(value, list) \
+ and isinstance(value[0], Node):
+ internals.append('%7s%s:' % ('', key))
+ for v in value:
+ internals.extend(['%9s%s' % ('', line)
+ for line in v.pformat().splitlines()])
+ else:
+ internals.append('%7s%s: %r' % ('', key, value))
+ return (Element.pformat(self, indent, level)
+ + ''.join([(' %s%s\n' % (indent * level, line))
+ for line in internals]))
+
+ def copy(self):
+ obj = self.__class__(self.transform, self.details, self.rawsource,
+ **self.attributes)
+ obj.document = self.document
+ obj.source = self.source
+ obj.line = self.line
+ return obj
+
+
+class raw(Special, Inline, PreBibliographic, FixedTextElement):
+
+ """
+ Raw data that is to be passed untouched to the Writer.
+ """
+
+ pass
+
+
+# =================
+# Inline Elements
+# =================
+
+class emphasis(Inline, TextElement): pass
+class strong(Inline, TextElement): pass
+class literal(Inline, TextElement): pass
+class reference(General, Inline, Referential, TextElement): pass
+class footnote_reference(Inline, Referential, TextElement): pass
+class citation_reference(Inline, Referential, TextElement): pass
+class substitution_reference(Inline, TextElement): pass
+class title_reference(Inline, TextElement): pass
+class abbreviation(Inline, TextElement): pass
+class acronym(Inline, TextElement): pass
+class superscript(Inline, TextElement): pass
+class subscript(Inline, TextElement): pass
+class math(Inline, TextElement): pass
+
+
+class image(General, Inline, Element):
+
+ def astext(self):
+ return self.get('alt', '')
+
+
+class inline(Inline, TextElement): pass
+class problematic(Inline, TextElement): pass
+class generated(Inline, TextElement): pass
+
+
+# ========================================
+# Auxiliary Classes, Functions, and Data
+# ========================================
+
+node_class_names = """
+ Text
+ abbreviation acronym address admonition attention attribution author
+ authors
+ block_quote bullet_list
+ caption caution citation citation_reference classifier colspec comment
+ compound contact container copyright
+ danger date decoration definition definition_list definition_list_item
+ description docinfo doctest_block document
+ emphasis entry enumerated_list error
+ field field_body field_list field_name figure footer
+ footnote footnote_reference
+ generated
+ header hint
+ image important inline
+ label legend line line_block list_item literal literal_block
+ math math_block
+ note
+ option option_argument option_group option_list option_list_item
+ option_string organization
+ paragraph pending problematic
+ raw reference revision row rubric
+ section sidebar status strong subscript substitution_definition
+ substitution_reference subtitle superscript system_message
+ table target tbody term tgroup thead tip title title_reference topic
+ transition
+ version
+ warning""".split()
+"""A list of names of all concrete Node subclasses."""
+
+
+class NodeVisitor(object):
+
+ """
+ "Visitor" pattern [GoF95]_ abstract superclass implementation for
+ document tree traversals.
+
+ Each node class has corresponding methods, doing nothing by
+ default; override individual methods for specific and useful
+ behaviour. The `dispatch_visit()` method is called by
+ `Node.walk()` upon entering a node. `Node.walkabout()` also calls
+ the `dispatch_departure()` method before exiting a node.
+
+ The dispatch methods call "``visit_`` + node class name" or
+ "``depart_`` + node class name", resp.
+
+ This is a base class for visitors whose ``visit_...`` & ``depart_...``
+ methods should be implemented for *all* node types encountered (such as
+ for `docutils.writers.Writer` subclasses). Unimplemented methods will
+ raise exceptions.
+
+ For sparse traversals, where only certain node types are of interest,
+ subclass `SparseNodeVisitor` instead. When (mostly or entirely) uniform
+ processing is desired, subclass `GenericNodeVisitor`.
+
+ .. [GoF95] Gamma, Helm, Johnson, Vlissides. *Design Patterns: Elements of
+ Reusable Object-Oriented Software*. Addison-Wesley, Reading, MA, USA,
+ 1995.
+ """
+
+ optional = ()
+ """
+ Tuple containing node class names (as strings).
+
+ No exception will be raised if writers do not implement visit
+ or departure functions for these node classes.
+
+ Used to ensure transitional compatibility with existing 3rd-party writers.
+ """
+
+ def __init__(self, document):
+ self.document = document
+
+ def dispatch_visit(self, node):
+ """
+ Call self."``visit_`` + node class name" with `node` as
+ parameter. If the ``visit_...`` method does not exist, call
+ self.unknown_visit.
+ """
+ node_name = node.__class__.__name__
+ method = getattr(self, 'visit_' + node_name, self.unknown_visit)
+ self.document.reporter.debug(
+ 'docutils.nodes.NodeVisitor.dispatch_visit calling %s for %s'
+ % (method.__name__, node_name))
+ return method(node)
+
+ def dispatch_departure(self, node):
+ """
+ Call self."``depart_`` + node class name" with `node` as
+ parameter. If the ``depart_...`` method does not exist, call
+ self.unknown_departure.
+ """
+ node_name = node.__class__.__name__
+ method = getattr(self, 'depart_' + node_name, self.unknown_departure)
+ self.document.reporter.debug(
+ 'docutils.nodes.NodeVisitor.dispatch_departure calling %s for %s'
+ % (method.__name__, node_name))
+ return method(node)
+
+ def unknown_visit(self, node):
+ """
+ Called when entering unknown `Node` types.
+
+ Raise an exception unless overridden.
+ """
+ if (self.document.settings.strict_visitor
+ or node.__class__.__name__ not in self.optional):
+ raise NotImplementedError(
+ '%s visiting unknown node type: %s'
+ % (self.__class__, node.__class__.__name__))
+
+ def unknown_departure(self, node):
+ """
+ Called before exiting unknown `Node` types.
+
+ Raise exception unless overridden.
+ """
+ if (self.document.settings.strict_visitor
+ or node.__class__.__name__ not in self.optional):
+ raise NotImplementedError(
+ '%s departing unknown node type: %s'
+ % (self.__class__, node.__class__.__name__))
+
+
+class SparseNodeVisitor(NodeVisitor):
+
+ """
+ Base class for sparse traversals, where only certain node types are of
+ interest. When ``visit_...`` & ``depart_...`` methods should be
+ implemented for *all* node types (such as for `docutils.writers.Writer`
+ subclasses), subclass `NodeVisitor` instead.
+ """
+
+
+class GenericNodeVisitor(NodeVisitor):
+
+ """
+ Generic "Visitor" abstract superclass, for simple traversals.
+
+ Unless overridden, each ``visit_...`` method calls `default_visit()`, and
+ each ``depart_...`` method (when using `Node.walkabout()`) calls
+ `default_departure()`. `default_visit()` (and `default_departure()`) must
+ be overridden in subclasses.
+
+ Define fully generic visitors by overriding `default_visit()` (and
+ `default_departure()`) only. Define semi-generic visitors by overriding
+ individual ``visit_...()`` (and ``depart_...()``) methods also.
+
+ `NodeVisitor.unknown_visit()` (`NodeVisitor.unknown_departure()`) should
+ be overridden for default behavior.
+ """
+
+ def default_visit(self, node):
+ """Override for generic, uniform traversals."""
+ raise NotImplementedError
+
+ def default_departure(self, node):
+ """Override for generic, uniform traversals."""
+ raise NotImplementedError
+
+def _call_default_visit(self, node):
+ self.default_visit(node)
+
+def _call_default_departure(self, node):
+ self.default_departure(node)
+
+def _nop(self, node):
+ pass
+
+def _add_node_class_names(names):
+ """Save typing with dynamic assignments:"""
+ for _name in names:
+ setattr(GenericNodeVisitor, "visit_" + _name, _call_default_visit)
+ setattr(GenericNodeVisitor, "depart_" + _name, _call_default_departure)
+ setattr(SparseNodeVisitor, 'visit_' + _name, _nop)
+ setattr(SparseNodeVisitor, 'depart_' + _name, _nop)
+
+_add_node_class_names(node_class_names)
+
+
+class TreeCopyVisitor(GenericNodeVisitor):
+
+ """
+ Make a complete copy of a tree or branch, including element attributes.
+ """
+
+ def __init__(self, document):
+ GenericNodeVisitor.__init__(self, document)
+ self.parent_stack = []
+ self.parent = []
+
+ def get_tree_copy(self):
+ return self.parent[0]
+
+ def default_visit(self, node):
+ """Copy the current node, and make it the new acting parent."""
+ newnode = node.copy()
+ self.parent.append(newnode)
+ self.parent_stack.append(self.parent)
+ self.parent = newnode
+
+ def default_departure(self, node):
+ """Restore the previous acting parent."""
+ self.parent = self.parent_stack.pop()
+
+
+class TreePruningException(Exception):
+
+ """
+ Base class for `NodeVisitor`-related tree pruning exceptions.
+
+ Raise subclasses from within ``visit_...`` or ``depart_...`` methods
+ called from `Node.walk()` and `Node.walkabout()` tree traversals to prune
+ the tree traversed.
+ """
+
+ pass
+
+
+class SkipChildren(TreePruningException):
+
+ """
+ Do not visit any children of the current node. The current node's
+ siblings and ``depart_...`` method are not affected.
+ """
+
+ pass
+
+
+class SkipSiblings(TreePruningException):
+
+ """
+ Do not visit any more siblings (to the right) of the current node. The
+ current node's children and its ``depart_...`` method are not affected.
+ """
+
+ pass
+
+
+class SkipNode(TreePruningException):
+
+ """
+ Do not visit the current node's children, and do not call the current
+ node's ``depart_...`` method.
+ """
+
+ pass
+
+
+class SkipDeparture(TreePruningException):
+
+ """
+ Do not call the current node's ``depart_...`` method. The current node's
+ children and siblings are not affected.
+ """
+
+ pass
+
+
+class NodeFound(TreePruningException):
+
+ """
+ Raise to indicate that the target of a search has been found. This
+ exception must be caught by the client; it is not caught by the traversal
+ code.
+ """
+
+ pass
+
+
+class StopTraversal(TreePruningException):
+
+ """
+ Stop the traversal alltogether. The current node's ``depart_...`` method
+ is not affected. The parent nodes ``depart_...`` methods are also called
+ as usual. No other nodes are visited. This is an alternative to
+ NodeFound that does not cause exception handling to trickle up to the
+ caller.
+ """
+
+ pass
+
+
+def make_id(string):
+ """
+ Convert `string` into an identifier and return it.
+
+ Docutils identifiers will conform to the regular expression
+ ``[a-z](-?[a-z0-9]+)*``. For CSS compatibility, identifiers (the "class"
+ and "id" attributes) should have no underscores, colons, or periods.
+ Hyphens may be used.
+
+ - The `HTML 4.01 spec`_ defines identifiers based on SGML tokens:
+
+ ID and NAME tokens must begin with a letter ([A-Za-z]) and may be
+ followed by any number of letters, digits ([0-9]), hyphens ("-"),
+ underscores ("_"), colons (":"), and periods (".").
+
+ - However the `CSS1 spec`_ defines identifiers based on the "name" token,
+ a tighter interpretation ("flex" tokenizer notation; "latin1" and
+ "escape" 8-bit characters have been replaced with entities)::
+
+ unicode \\[0-9a-f]{1,4}
+ latin1 [¡-ÿ]
+ escape {unicode}|\\[ -~¡-ÿ]
+ nmchar [-a-z0-9]|{latin1}|{escape}
+ name {nmchar}+
+
+ The CSS1 "nmchar" rule does not include underscores ("_"), colons (":"),
+ or periods ("."), therefore "class" and "id" attributes should not contain
+ these characters. They should be replaced with hyphens ("-"). Combined
+ with HTML's requirements (the first character must be a letter; no
+ "unicode", "latin1", or "escape" characters), this results in the
+ ``[a-z](-?[a-z0-9]+)*`` pattern.
+
+ .. _HTML 4.01 spec: http://www.w3.org/TR/html401
+ .. _CSS1 spec: http://www.w3.org/TR/REC-CSS1
+ """
+ id = string.lower()
+ if not isinstance(id, unicode):
+ id = id.decode()
+ id = id.translate(_non_id_translate_digraphs)
+ id = id.translate(_non_id_translate)
+ # get rid of non-ascii characters.
+ # 'ascii' lowercase to prevent problems with turkish locale.
+ id = unicodedata.normalize('NFKD', id).\
+ encode('ascii', 'ignore').decode('ascii')
+ # shrink runs of whitespace and replace by hyphen
+ id = _non_id_chars.sub('-', ' '.join(id.split()))
+ id = _non_id_at_ends.sub('', id)
+ return str(id)
+
+_non_id_chars = re.compile('[^a-z0-9]+')
+_non_id_at_ends = re.compile('^[-0-9]+|-+$')
+_non_id_translate = {
+ 0x00f8: u'o', # o with stroke
+ 0x0111: u'd', # d with stroke
+ 0x0127: u'h', # h with stroke
+ 0x0131: u'i', # dotless i
+ 0x0142: u'l', # l with stroke
+ 0x0167: u't', # t with stroke
+ 0x0180: u'b', # b with stroke
+ 0x0183: u'b', # b with topbar
+ 0x0188: u'c', # c with hook
+ 0x018c: u'd', # d with topbar
+ 0x0192: u'f', # f with hook
+ 0x0199: u'k', # k with hook
+ 0x019a: u'l', # l with bar
+ 0x019e: u'n', # n with long right leg
+ 0x01a5: u'p', # p with hook
+ 0x01ab: u't', # t with palatal hook
+ 0x01ad: u't', # t with hook
+ 0x01b4: u'y', # y with hook
+ 0x01b6: u'z', # z with stroke
+ 0x01e5: u'g', # g with stroke
+ 0x0225: u'z', # z with hook
+ 0x0234: u'l', # l with curl
+ 0x0235: u'n', # n with curl
+ 0x0236: u't', # t with curl
+ 0x0237: u'j', # dotless j
+ 0x023c: u'c', # c with stroke
+ 0x023f: u's', # s with swash tail
+ 0x0240: u'z', # z with swash tail
+ 0x0247: u'e', # e with stroke
+ 0x0249: u'j', # j with stroke
+ 0x024b: u'q', # q with hook tail
+ 0x024d: u'r', # r with stroke
+ 0x024f: u'y', # y with stroke
+}
+_non_id_translate_digraphs = {
+ 0x00df: u'sz', # ligature sz
+ 0x00e6: u'ae', # ae
+ 0x0153: u'oe', # ligature oe
+ 0x0238: u'db', # db digraph
+ 0x0239: u'qp', # qp digraph
+}
+
+def dupname(node, name):
+ node['dupnames'].append(name)
+ node['names'].remove(name)
+ # Assume that this method is referenced, even though it isn't; we
+ # don't want to throw unnecessary system_messages.
+ node.referenced = 1
+
+def fully_normalize_name(name):
+ """Return a case- and whitespace-normalized name."""
+ return ' '.join(name.lower().split())
+
+def whitespace_normalize_name(name):
+ """Return a whitespace-normalized name."""
+ return ' '.join(name.split())
+
+def serial_escape(value):
+ """Escape string values that are elements of a list, for serialization."""
+ return value.replace('\\', r'\\').replace(' ', r'\ ')
+
+def pseudo_quoteattr(value):
+ """Quote attributes for pseudo-xml"""
+ return '"%s"' % value
+
+# \f
+#
+# Local Variables:
+# indent-tabs-mode: nil
+# sentence-end-double-space: t
+# fill-column: 78
+# End:
--- /dev/null
+# $Id: __init__.py 8239 2018-11-21 21:46:00Z milde $
+# Author: David Goodger <goodger@python.org>
+# Copyright: This module has been placed in the public domain.
+
+"""
+This package contains Docutils parser modules.
+"""
+
+__docformat__ = 'reStructuredText'
+
+import sys
+from docutils import Component
+
+
+class Parser(Component):
+
+ component_type = 'parser'
+ config_section = 'parsers'
+
+ def parse(self, inputstring, document):
+ """Override to parse `inputstring` into document tree `document`."""
+ raise NotImplementedError('subclass must override this method')
+
+ def setup_parse(self, inputstring, document):
+ """Initial parse setup. Call at start of `self.parse()`."""
+ self.inputstring = inputstring
+ self.document = document
+ document.reporter.attach_observer(document.note_parse_message)
+
+ def finish_parse(self):
+ """Finalize parse details. Call at end of `self.parse()`."""
+ self.document.reporter.detach_observer(
+ self.document.note_parse_message)
+
+
+_parser_aliases = {
+ 'restructuredtext': 'rst',
+ 'rest': 'rst',
+ 'restx': 'rst',
+ 'rtxt': 'rst',}
+
+def get_parser_class(parser_name):
+ """Return the Parser class from the `parser_name` module."""
+ parser_name = parser_name.lower()
+ if parser_name in _parser_aliases:
+ parser_name = _parser_aliases[parser_name]
+ try:
+ module = __import__(parser_name, globals(), locals(), level=1)
+ except ImportError:
+ module = __import__(parser_name, globals(), locals(), level=0)
+ return module.Parser
--- /dev/null
+# $Id: null.py 4564 2006-05-21 20:44:42Z wiemann $
+# Author: Martin Blais <blais@furius.ca>
+# Copyright: This module has been placed in the public domain.
+
+"""A do-nothing parser."""
+
+from docutils import parsers
+
+
+class Parser(parsers.Parser):
+
+ """A do-nothing parser."""
+
+ supported = ('null',)
+
+ config_section = 'null parser'
+ config_section_dependencies = ('parsers',)
+
+ def parse(self, inputstring, document):
+ pass
--- /dev/null
+# $Id: __init__.py 8344 2019-08-26 12:10:43Z milde $
+# Author: David Goodger <goodger@python.org>
+# Copyright: This module has been placed in the public domain.
+
+"""
+This is ``docutils.parsers.rst`` package. It exports a single class, `Parser`,
+the reStructuredText parser.
+
+
+Usage
+=====
+
+1. Create a parser::
+
+ parser = docutils.parsers.rst.Parser()
+
+ Several optional arguments may be passed to modify the parser's behavior.
+ Please see `Customizing the Parser`_ below for details.
+
+2. Gather input (a multi-line string), by reading a file or the standard
+ input::
+
+ input = sys.stdin.read()
+
+3. Create a new empty `docutils.nodes.document` tree::
+
+ document = docutils.utils.new_document(source, settings)
+
+ See `docutils.utils.new_document()` for parameter details.
+
+4. Run the parser, populating the document tree::
+
+ parser.parse(input, document)
+
+
+Parser Overview
+===============
+
+The reStructuredText parser is implemented as a state machine, examining its
+input one line at a time. To understand how the parser works, please first
+become familiar with the `docutils.statemachine` module, then see the
+`states` module.
+
+
+Customizing the Parser
+----------------------
+
+Anything that isn't already customizable is that way simply because that type
+of customizability hasn't been implemented yet. Patches welcome!
+
+When instantiating an object of the `Parser` class, two parameters may be
+passed: ``rfc2822`` and ``inliner``. Pass ``rfc2822=True`` to enable an
+initial RFC-2822 style header block, parsed as a "field_list" element (with
+"class" attribute set to "rfc2822"). Currently this is the only body-level
+element which is customizable without subclassing. (Tip: subclass `Parser`
+and change its "state_classes" and "initial_state" attributes to refer to new
+classes. Contact the author if you need more details.)
+
+The ``inliner`` parameter takes an instance of `states.Inliner` or a subclass.
+It handles inline markup recognition. A common extension is the addition of
+further implicit hyperlinks, like "RFC 2822". This can be done by subclassing
+`states.Inliner`, adding a new method for the implicit markup, and adding a
+``(pattern, method)`` pair to the "implicit_dispatch" attribute of the
+subclass. See `states.Inliner.implicit_inline()` for details. Explicit
+inline markup can be customized in a `states.Inliner` subclass via the
+``patterns.initial`` and ``dispatch`` attributes (and new methods as
+appropriate).
+"""
+
+__docformat__ = 'reStructuredText'
+
+
+import docutils.parsers
+import docutils.statemachine
+from docutils.parsers.rst import roles, states
+from docutils import frontend, nodes, Component
+from docutils.transforms import universal
+
+
+class Parser(docutils.parsers.Parser):
+
+ """The reStructuredText parser."""
+
+ supported = ('restructuredtext', 'rst', 'rest', 'restx', 'rtxt', 'rstx')
+ """Aliases this parser supports."""
+
+ settings_spec = (
+ 'reStructuredText Parser Options',
+ None,
+ (('Recognize and link to standalone PEP references (like "PEP 258").',
+ ['--pep-references'],
+ {'action': 'store_true', 'validator': frontend.validate_boolean}),
+ ('Base URL for PEP references '
+ '(default "http://www.python.org/dev/peps/").',
+ ['--pep-base-url'],
+ {'metavar': '<URL>', 'default': 'http://www.python.org/dev/peps/',
+ 'validator': frontend.validate_url_trailing_slash}),
+ ('Template for PEP file part of URL. (default "pep-%04d")',
+ ['--pep-file-url-template'],
+ {'metavar': '<URL>', 'default': 'pep-%04d'}),
+ ('Recognize and link to standalone RFC references (like "RFC 822").',
+ ['--rfc-references'],
+ {'action': 'store_true', 'validator': frontend.validate_boolean}),
+ ('Base URL for RFC references (default "http://tools.ietf.org/html/").',
+ ['--rfc-base-url'],
+ {'metavar': '<URL>', 'default': 'http://tools.ietf.org/html/',
+ 'validator': frontend.validate_url_trailing_slash}),
+ ('Set number of spaces for tab expansion (default 8).',
+ ['--tab-width'],
+ {'metavar': '<width>', 'type': 'int', 'default': 8,
+ 'validator': frontend.validate_nonnegative_int}),
+ ('Remove spaces before footnote references.',
+ ['--trim-footnote-reference-space'],
+ {'action': 'store_true', 'validator': frontend.validate_boolean}),
+ ('Leave spaces before footnote references.',
+ ['--leave-footnote-reference-space'],
+ {'action': 'store_false', 'dest': 'trim_footnote_reference_space'}),
+ ('Disable directives that insert the contents of external file '
+ '("include" & "raw"); replaced with a "warning" system message.',
+ ['--no-file-insertion'],
+ {'action': 'store_false', 'default': 1,
+ 'dest': 'file_insertion_enabled',
+ 'validator': frontend.validate_boolean}),
+ ('Enable directives that insert the contents of external file '
+ '("include" & "raw"). Enabled by default.',
+ ['--file-insertion-enabled'],
+ {'action': 'store_true'}),
+ ('Disable the "raw" directives; replaced with a "warning" '
+ 'system message.',
+ ['--no-raw'],
+ {'action': 'store_false', 'default': 1, 'dest': 'raw_enabled',
+ 'validator': frontend.validate_boolean}),
+ ('Enable the "raw" directive. Enabled by default.',
+ ['--raw-enabled'],
+ {'action': 'store_true'}),
+ ('Token name set for parsing code with Pygments: one of '
+ '"long", "short", or "none (no parsing)". Default is "long".',
+ ['--syntax-highlight'],
+ {'choices': ['long', 'short', 'none'],
+ 'default': 'long', 'metavar': '<format>'}),
+ ('Change straight quotation marks to typographic form: '
+ 'one of "yes", "no", "alt[ernative]" (default "no").',
+ ['--smart-quotes'],
+ {'default': False, 'metavar': '<yes/no/alt>',
+ 'validator': frontend.validate_ternary}),
+ ('Characters to use as "smart quotes" for <language>. ',
+ ['--smartquotes-locales'],
+ {'metavar': '<language:quotes[,language:quotes,...]>',
+ 'action': 'append',
+ 'validator': frontend.validate_smartquotes_locales}),
+ ('Inline markup recognized at word boundaries only '
+ '(adjacent to punctuation or whitespace). '
+ 'Force character-level inline markup recognition with '
+ '"\\ " (backslash + space). Default.',
+ ['--word-level-inline-markup'],
+ {'action': 'store_false', 'dest': 'character_level_inline_markup'}),
+ ('Inline markup recognized anywhere, regardless of surrounding '
+ 'characters. Backslash-escapes must be used to avoid unwanted '
+ 'markup recognition. Useful for East Asian languages. '
+ 'Experimental.',
+ ['--character-level-inline-markup'],
+ {'action': 'store_true', 'default': False,
+ 'dest': 'character_level_inline_markup'}),
+ ))
+
+ config_section = 'restructuredtext parser'
+ config_section_dependencies = ('parsers',)
+
+ def __init__(self, rfc2822=False, inliner=None):
+ if rfc2822:
+ self.initial_state = 'RFC2822Body'
+ else:
+ self.initial_state = 'Body'
+ self.state_classes = states.state_classes
+ self.inliner = inliner
+
+ def get_transforms(self):
+ return Component.get_transforms(self) + [
+ universal.SmartQuotes]
+
+ def parse(self, inputstring, document):
+ """Parse `inputstring` and populate `document`, a document tree."""
+ self.setup_parse(inputstring, document)
+ self.statemachine = states.RSTStateMachine(
+ state_classes=self.state_classes,
+ initial_state=self.initial_state,
+ debug=document.reporter.debug_flag)
+ inputlines = docutils.statemachine.string2lines(
+ inputstring, tab_width=document.settings.tab_width,
+ convert_whitespace=True)
+ self.statemachine.run(inputlines, document, inliner=self.inliner)
+ # restore the "default" default role after parsing a document
+ if '' in roles._roles:
+ del roles._roles['']
+ self.finish_parse()
+
+
+class DirectiveError(Exception):
+
+ """
+ Store a message and a system message level.
+
+ To be thrown from inside directive code.
+
+ Do not instantiate directly -- use `Directive.directive_error()`
+ instead!
+ """
+
+ def __init__(self, level, message):
+ """Set error `message` and `level`"""
+ Exception.__init__(self)
+ self.level = level
+ self.msg = message
+
+
+class Directive(object):
+
+ """
+ Base class for reStructuredText directives.
+
+ The following attributes may be set by subclasses. They are
+ interpreted by the directive parser (which runs the directive
+ class):
+
+ - `required_arguments`: The number of required arguments (default:
+ 0).
+
+ - `optional_arguments`: The number of optional arguments (default:
+ 0).
+
+ - `final_argument_whitespace`: A boolean, indicating if the final
+ argument may contain whitespace (default: False).
+
+ - `option_spec`: A dictionary, mapping known option names to
+ conversion functions such as `int` or `float` (default: {}, no
+ options). Several conversion functions are defined in the
+ directives/__init__.py module.
+
+ Option conversion functions take a single parameter, the option
+ argument (a string or ``None``), validate it and/or convert it
+ to the appropriate form. Conversion functions may raise
+ `ValueError` and `TypeError` exceptions.
+
+ - `has_content`: A boolean; True if content is allowed. Client
+ code must handle the case where content is required but not
+ supplied (an empty content list will be supplied).
+
+ Arguments are normally single whitespace-separated words. The
+ final argument may contain whitespace and/or newlines if
+ `final_argument_whitespace` is True.
+
+ If the form of the arguments is more complex, specify only one
+ argument (either required or optional) and set
+ `final_argument_whitespace` to True; the client code must do any
+ context-sensitive parsing.
+
+ When a directive implementation is being run, the directive class
+ is instantiated, and the `run()` method is executed. During
+ instantiation, the following instance variables are set:
+
+ - ``name`` is the directive type or name (string).
+
+ - ``arguments`` is the list of positional arguments (strings).
+
+ - ``options`` is a dictionary mapping option names (strings) to
+ values (type depends on option conversion functions; see
+ `option_spec` above).
+
+ - ``content`` is a list of strings, the directive content line by line.
+
+ - ``lineno`` is the absolute line number of the first line
+ of the directive.
+
+ - ``content_offset`` is the line offset of the first line of the content from
+ the beginning of the current input. Used when initiating a nested parse.
+
+ - ``block_text`` is a string containing the entire directive.
+
+ - ``state`` is the state which called the directive function.
+
+ - ``state_machine`` is the state machine which controls the state which called
+ the directive function.
+
+ Directive functions return a list of nodes which will be inserted
+ into the document tree at the point where the directive was
+ encountered. This can be an empty list if there is nothing to
+ insert.
+
+ For ordinary directives, the list must contain body elements or
+ structural elements. Some directives are intended specifically
+ for substitution definitions, and must return a list of `Text`
+ nodes and/or inline elements (suitable for inline insertion, in
+ place of the substitution reference). Such directives must verify
+ substitution definition context, typically using code like this::
+
+ if not isinstance(state, states.SubstitutionDef):
+ error = state_machine.reporter.error(
+ 'Invalid context: the "%s" directive can only be used '
+ 'within a substitution definition.' % (name),
+ nodes.literal_block(block_text, block_text), line=lineno)
+ return [error]
+ """
+
+ # There is a "Creating reStructuredText Directives" how-to at
+ # <http://docutils.sf.net/docs/howto/rst-directives.html>. If you
+ # update this docstring, please update the how-to as well.
+
+ required_arguments = 0
+ """Number of required directive arguments."""
+
+ optional_arguments = 0
+ """Number of optional arguments after the required arguments."""
+
+ final_argument_whitespace = False
+ """May the final argument contain whitespace?"""
+
+ option_spec = None
+ """Mapping of option names to validator functions."""
+
+ has_content = False
+ """May the directive have content?"""
+
+ def __init__(self, name, arguments, options, content, lineno,
+ content_offset, block_text, state, state_machine):
+ self.name = name
+ self.arguments = arguments
+ self.options = options
+ self.content = content
+ self.lineno = lineno
+ self.content_offset = content_offset
+ self.block_text = block_text
+ self.state = state
+ self.state_machine = state_machine
+
+ def run(self):
+ raise NotImplementedError('Must override run() is subclass.')
+
+ # Directive errors:
+
+ def directive_error(self, level, message):
+ """
+ Return a DirectiveError suitable for being thrown as an exception.
+
+ Call "raise self.directive_error(level, message)" from within
+ a directive implementation to return one single system message
+ at level `level`, which automatically gets the directive block
+ and the line number added.
+
+ Preferably use the `debug`, `info`, `warning`, `error`, or `severe`
+ wrapper methods, e.g. ``self.error(message)`` to generate an
+ ERROR-level directive error.
+ """
+ return DirectiveError(level, message)
+
+ def debug(self, message):
+ return self.directive_error(0, message)
+
+ def info(self, message):
+ return self.directive_error(1, message)
+
+ def warning(self, message):
+ return self.directive_error(2, message)
+
+ def error(self, message):
+ return self.directive_error(3, message)
+
+ def severe(self, message):
+ return self.directive_error(4, message)
+
+ # Convenience methods:
+
+ def assert_has_content(self):
+ """
+ Throw an ERROR-level DirectiveError if the directive doesn't
+ have contents.
+ """
+ if not self.content:
+ raise self.error('Content block expected for the "%s" directive; '
+ 'none found.' % self.name)
+
+ def add_name(self, node):
+ """Append self.options['name'] to node['names'] if it exists.
+
+ Also normalize the name string and register it as explicit target.
+ """
+ if 'name' in self.options:
+ name = nodes.fully_normalize_name(self.options.pop('name'))
+ if 'name' in node:
+ del(node['name'])
+ node['names'].append(name)
+ self.state.document.note_explicit_target(node, node)
+
+
+def convert_directive_function(directive_fn):
+ """
+ Define & return a directive class generated from `directive_fn`.
+
+ `directive_fn` uses the old-style, functional interface.
+ """
+
+ class FunctionalDirective(Directive):
+
+ option_spec = getattr(directive_fn, 'options', None)
+ has_content = getattr(directive_fn, 'content', False)
+ _argument_spec = getattr(directive_fn, 'arguments', (0, 0, False))
+ required_arguments, optional_arguments, final_argument_whitespace \
+ = _argument_spec
+
+ def run(self):
+ return directive_fn(
+ self.name, self.arguments, self.options, self.content,
+ self.lineno, self.content_offset, self.block_text,
+ self.state, self.state_machine)
+
+ # Return new-style directive.
+ return FunctionalDirective
--- /dev/null
+# $Id: __init__.py 8367 2019-08-27 12:09:56Z milde $
+# Author: David Goodger <goodger@python.org>
+# Copyright: This module has been placed in the public domain.
+
+"""
+This package contains directive implementation modules.
+"""
+
+__docformat__ = 'reStructuredText'
+
+import re
+import codecs
+import sys
+
+from docutils import nodes
+from docutils.utils import split_escaped_whitespace, escape2null, unescape
+from docutils.parsers.rst.languages import en as _fallback_language_module
+
+if sys.version_info >= (3, 0):
+ unichr = chr # noqa
+
+
+_directive_registry = {
+ 'attention': ('admonitions', 'Attention'),
+ 'caution': ('admonitions', 'Caution'),
+ 'code': ('body', 'CodeBlock'),
+ 'danger': ('admonitions', 'Danger'),
+ 'error': ('admonitions', 'Error'),
+ 'important': ('admonitions', 'Important'),
+ 'note': ('admonitions', 'Note'),
+ 'tip': ('admonitions', 'Tip'),
+ 'hint': ('admonitions', 'Hint'),
+ 'warning': ('admonitions', 'Warning'),
+ 'admonition': ('admonitions', 'Admonition'),
+ 'sidebar': ('body', 'Sidebar'),
+ 'topic': ('body', 'Topic'),
+ 'line-block': ('body', 'LineBlock'),
+ 'parsed-literal': ('body', 'ParsedLiteral'),
+ 'math': ('body', 'MathBlock'),
+ 'rubric': ('body', 'Rubric'),
+ 'epigraph': ('body', 'Epigraph'),
+ 'highlights': ('body', 'Highlights'),
+ 'pull-quote': ('body', 'PullQuote'),
+ 'compound': ('body', 'Compound'),
+ 'container': ('body', 'Container'),
+ #'questions': ('body', 'question_list'),
+ 'table': ('tables', 'RSTTable'),
+ 'csv-table': ('tables', 'CSVTable'),
+ 'list-table': ('tables', 'ListTable'),
+ 'image': ('images', 'Image'),
+ 'figure': ('images', 'Figure'),
+ 'contents': ('parts', 'Contents'),
+ 'sectnum': ('parts', 'Sectnum'),
+ 'header': ('parts', 'Header'),
+ 'footer': ('parts', 'Footer'),
+ #'footnotes': ('parts', 'footnotes'),
+ #'citations': ('parts', 'citations'),
+ 'target-notes': ('references', 'TargetNotes'),
+ 'meta': ('html', 'Meta'),
+ #'imagemap': ('html', 'imagemap'),
+ 'raw': ('misc', 'Raw'),
+ 'include': ('misc', 'Include'),
+ 'replace': ('misc', 'Replace'),
+ 'unicode': ('misc', 'Unicode'),
+ 'class': ('misc', 'Class'),
+ 'role': ('misc', 'Role'),
+ 'default-role': ('misc', 'DefaultRole'),
+ 'title': ('misc', 'Title'),
+ 'date': ('misc', 'Date'),
+ 'restructuredtext-test-directive': ('misc', 'TestDirective'),}
+"""Mapping of directive name to (module name, class name). The
+directive name is canonical & must be lowercase. Language-dependent
+names are defined in the ``language`` subpackage."""
+
+_directives = {}
+"""Cache of imported directives."""
+
+def directive(directive_name, language_module, document):
+ """
+ Locate and return a directive function from its language-dependent name.
+ If not found in the current language, check English. Return None if the
+ named directive cannot be found.
+ """
+ normname = directive_name.lower()
+ messages = []
+ msg_text = []
+ if normname in _directives:
+ return _directives[normname], messages
+ canonicalname = None
+ try:
+ canonicalname = language_module.directives[normname]
+ except AttributeError as error:
+ msg_text.append('Problem retrieving directive entry from language '
+ 'module %r: %s.' % (language_module, error))
+ except KeyError:
+ msg_text.append('No directive entry for "%s" in module "%s".'
+ % (directive_name, language_module.__name__))
+ if not canonicalname:
+ try:
+ canonicalname = _fallback_language_module.directives[normname]
+ msg_text.append('Using English fallback for directive "%s".'
+ % directive_name)
+ except KeyError:
+ msg_text.append('Trying "%s" as canonical directive name.'
+ % directive_name)
+ # The canonical name should be an English name, but just in case:
+ canonicalname = normname
+ if msg_text:
+ message = document.reporter.info(
+ '\n'.join(msg_text), line=document.current_line)
+ messages.append(message)
+ try:
+ modulename, classname = _directive_registry[canonicalname]
+ except KeyError:
+ # Error handling done by caller.
+ return None, messages
+ try:
+ module = __import__(modulename, globals(), locals(), level=1)
+ except ImportError as detail:
+ messages.append(document.reporter.error(
+ 'Error importing directive module "%s" (directive "%s"):\n%s'
+ % (modulename, directive_name, detail),
+ line=document.current_line))
+ return None, messages
+ try:
+ directive = getattr(module, classname)
+ _directives[normname] = directive
+ except AttributeError:
+ messages.append(document.reporter.error(
+ 'No directive class "%s" in module "%s" (directive "%s").'
+ % (classname, modulename, directive_name),
+ line=document.current_line))
+ return None, messages
+ return directive, messages
+
+def register_directive(name, directive):
+ """
+ Register a nonstandard application-defined directive function.
+ Language lookups are not needed for such functions.
+ """
+ _directives[name] = directive
+
+def flag(argument):
+ """
+ Check for a valid flag option (no argument) and return ``None``.
+ (Directive option conversion function.)
+
+ Raise ``ValueError`` if an argument is found.
+ """
+ if argument and argument.strip():
+ raise ValueError('no argument is allowed; "%s" supplied' % argument)
+ else:
+ return None
+
+def unchanged_required(argument):
+ """
+ Return the argument text, unchanged.
+ (Directive option conversion function.)
+
+ Raise ``ValueError`` if no argument is found.
+ """
+ if argument is None:
+ raise ValueError('argument required but none supplied')
+ else:
+ return argument # unchanged!
+
+def unchanged(argument):
+ """
+ Return the argument text, unchanged.
+ (Directive option conversion function.)
+
+ No argument implies empty string ("").
+ """
+ if argument is None:
+ return u''
+ else:
+ return argument # unchanged!
+
+def path(argument):
+ """
+ Return the path argument unwrapped (with newlines removed).
+ (Directive option conversion function.)
+
+ Raise ``ValueError`` if no argument is found.
+ """
+ if argument is None:
+ raise ValueError('argument required but none supplied')
+ else:
+ path = ''.join([s.strip() for s in argument.splitlines()])
+ return path
+
+def uri(argument):
+ """
+ Return the URI argument with unescaped whitespace removed.
+ (Directive option conversion function.)
+
+ Raise ``ValueError`` if no argument is found.
+ """
+ if argument is None:
+ raise ValueError('argument required but none supplied')
+ else:
+ parts = split_escaped_whitespace(escape2null(argument))
+ uri = ' '.join(''.join(unescape(part).split()) for part in parts)
+ return uri
+
+def nonnegative_int(argument):
+ """
+ Check for a nonnegative integer argument; raise ``ValueError`` if not.
+ (Directive option conversion function.)
+ """
+ value = int(argument)
+ if value < 0:
+ raise ValueError('negative value; must be positive or zero')
+ return value
+
+def percentage(argument):
+ """
+ Check for an integer percentage value with optional percent sign.
+ """
+ try:
+ argument = argument.rstrip(' %')
+ except AttributeError:
+ pass
+ return nonnegative_int(argument)
+
+length_units = ['em', 'ex', 'px', 'in', 'cm', 'mm', 'pt', 'pc']
+
+def get_measure(argument, units):
+ """
+ Check for a positive argument of one of the units and return a
+ normalized string of the form "<value><unit>" (without space in
+ between).
+
+ To be called from directive option conversion functions.
+ """
+ match = re.match(r'^([0-9.]+) *(%s)$' % '|'.join(units), argument)
+ try:
+ float(match.group(1))
+ except (AttributeError, ValueError):
+ raise ValueError(
+ 'not a positive measure of one of the following units:\n%s'
+ % ' '.join(['"%s"' % i for i in units]))
+ return match.group(1) + match.group(2)
+
+def length_or_unitless(argument):
+ return get_measure(argument, length_units + [''])
+
+def length_or_percentage_or_unitless(argument, default=''):
+ """
+ Return normalized string of a length or percentage unit.
+
+ Add <default> if there is no unit. Raise ValueError if the argument is not
+ a positive measure of one of the valid CSS units (or without unit).
+
+ >>> length_or_percentage_or_unitless('3 pt')
+ '3pt'
+ >>> length_or_percentage_or_unitless('3%', 'em')
+ '3%'
+ >>> length_or_percentage_or_unitless('3')
+ '3'
+ >>> length_or_percentage_or_unitless('3', 'px')
+ '3px'
+ """
+ try:
+ return get_measure(argument, length_units + ['%'])
+ except ValueError:
+ try:
+ return get_measure(argument, ['']) + default
+ except ValueError:
+ # raise ValueError with list of valid units:
+ return get_measure(argument, length_units + ['%'])
+
+def class_option(argument):
+ """
+ Convert the argument into a list of ID-compatible strings and return it.
+ (Directive option conversion function.)
+
+ Raise ``ValueError`` if no argument is found.
+ """
+ if argument is None:
+ raise ValueError('argument required but none supplied')
+ names = argument.split()
+ class_names = []
+ for name in names:
+ class_name = nodes.make_id(name)
+ if not class_name:
+ raise ValueError('cannot make "%s" into a class name' % name)
+ class_names.append(class_name)
+ return class_names
+
+unicode_pattern = re.compile(
+ r'(?:0x|x|\\x|U\+?|\\u)([0-9a-f]+)$|&#x([0-9a-f]+);$', re.IGNORECASE)
+
+def unicode_code(code):
+ r"""
+ Convert a Unicode character code to a Unicode character.
+ (Directive option conversion function.)
+
+ Codes may be decimal numbers, hexadecimal numbers (prefixed by ``0x``,
+ ``x``, ``\x``, ``U+``, ``u``, or ``\u``; e.g. ``U+262E``), or XML-style
+ numeric character entities (e.g. ``☮``). Other text remains as-is.
+
+ Raise ValueError for illegal Unicode code values.
+ """
+ try:
+ if code.isdigit(): # decimal number
+ return unichr(int(code))
+ else:
+ match = unicode_pattern.match(code)
+ if match: # hex number
+ value = match.group(1) or match.group(2)
+ return unichr(int(value, 16))
+ else: # other text
+ return code
+ except OverflowError as detail:
+ raise ValueError('code too large (%s)' % detail)
+
+def single_char_or_unicode(argument):
+ """
+ A single character is returned as-is. Unicode characters codes are
+ converted as in `unicode_code`. (Directive option conversion function.)
+ """
+ char = unicode_code(argument)
+ if len(char) > 1:
+ raise ValueError('%r invalid; must be a single character or '
+ 'a Unicode code' % char)
+ return char
+
+def single_char_or_whitespace_or_unicode(argument):
+ """
+ As with `single_char_or_unicode`, but "tab" and "space" are also supported.
+ (Directive option conversion function.)
+ """
+ if argument == 'tab':
+ char = '\t'
+ elif argument == 'space':
+ char = ' '
+ else:
+ char = single_char_or_unicode(argument)
+ return char
+
+def positive_int(argument):
+ """
+ Converts the argument into an integer. Raises ValueError for negative,
+ zero, or non-integer values. (Directive option conversion function.)
+ """
+ value = int(argument)
+ if value < 1:
+ raise ValueError('negative or zero value; must be positive')
+ return value
+
+def positive_int_list(argument):
+ """
+ Converts a space- or comma-separated list of values into a Python list
+ of integers.
+ (Directive option conversion function.)
+
+ Raises ValueError for non-positive-integer values.
+ """
+ if ',' in argument:
+ entries = argument.split(',')
+ else:
+ entries = argument.split()
+ return [positive_int(entry) for entry in entries]
+
+def encoding(argument):
+ """
+ Verfies the encoding argument by lookup.
+ (Directive option conversion function.)
+
+ Raises ValueError for unknown encodings.
+ """
+ try:
+ codecs.lookup(argument)
+ except LookupError:
+ raise ValueError('unknown encoding: "%s"' % argument)
+ return argument
+
+def choice(argument, values):
+ """
+ Directive option utility function, supplied to enable options whose
+ argument must be a member of a finite set of possible values (must be
+ lower case). A custom conversion function must be written to use it. For
+ example::
+
+ from docutils.parsers.rst import directives
+
+ def yesno(argument):
+ return directives.choice(argument, ('yes', 'no'))
+
+ Raise ``ValueError`` if no argument is found or if the argument's value is
+ not valid (not an entry in the supplied list).
+ """
+ try:
+ value = argument.lower().strip()
+ except AttributeError:
+ raise ValueError('must supply an argument; choose from %s'
+ % format_values(values))
+ if value in values:
+ return value
+ else:
+ raise ValueError('"%s" unknown; choose from %s'
+ % (argument, format_values(values)))
+
+def format_values(values):
+ return '%s, or "%s"' % (', '.join(['"%s"' % s for s in values[:-1]]),
+ values[-1])
+
+def value_or(values, other):
+ """
+ The argument can be any of `values` or `argument_type`.
+ """
+ def auto_or_other(argument):
+ if argument in values:
+ return argument
+ else:
+ return other(argument)
+ return auto_or_other
+
--- /dev/null
+# $Id: admonitions.py 7681 2013-07-12 07:52:27Z milde $
+# Author: David Goodger <goodger@python.org>
+# Copyright: This module has been placed in the public domain.
+
+"""
+Admonition directives.
+"""
+
+__docformat__ = 'reStructuredText'
+
+
+from docutils.parsers.rst import Directive
+from docutils.parsers.rst import states, directives
+from docutils.parsers.rst.roles import set_classes
+from docutils import nodes
+
+
+class BaseAdmonition(Directive):
+
+ final_argument_whitespace = True
+ option_spec = {'class': directives.class_option,
+ 'name': directives.unchanged}
+ has_content = True
+
+ node_class = None
+ """Subclasses must set this to the appropriate admonition node class."""
+
+ def run(self):
+ set_classes(self.options)
+ self.assert_has_content()
+ text = '\n'.join(self.content)
+ admonition_node = self.node_class(text, **self.options)
+ self.add_name(admonition_node)
+ if self.node_class is nodes.admonition:
+ title_text = self.arguments[0]
+ textnodes, messages = self.state.inline_text(title_text,
+ self.lineno)
+ title = nodes.title(title_text, '', *textnodes)
+ title.source, title.line = (
+ self.state_machine.get_source_and_line(self.lineno))
+ admonition_node += title
+ admonition_node += messages
+ if not 'classes' in self.options:
+ admonition_node['classes'] += ['admonition-' +
+ nodes.make_id(title_text)]
+ self.state.nested_parse(self.content, self.content_offset,
+ admonition_node)
+ return [admonition_node]
+
+
+class Admonition(BaseAdmonition):
+
+ required_arguments = 1
+ node_class = nodes.admonition
+
+
+class Attention(BaseAdmonition):
+
+ node_class = nodes.attention
+
+
+class Caution(BaseAdmonition):
+
+ node_class = nodes.caution
+
+
+class Danger(BaseAdmonition):
+
+ node_class = nodes.danger
+
+
+class Error(BaseAdmonition):
+
+ node_class = nodes.error
+
+
+class Hint(BaseAdmonition):
+
+ node_class = nodes.hint
+
+
+class Important(BaseAdmonition):
+
+ node_class = nodes.important
+
+
+class Note(BaseAdmonition):
+
+ node_class = nodes.note
+
+
+class Tip(BaseAdmonition):
+
+ node_class = nodes.tip
+
+
+class Warning(BaseAdmonition):
+
+ node_class = nodes.warning
--- /dev/null
+# $Id: body.py 8347 2019-08-26 12:12:02Z milde $
+# Author: David Goodger <goodger@python.org>
+# Copyright: This module has been placed in the public domain.
+
+"""
+Directives for additional body elements.
+
+See `docutils.parsers.rst.directives` for API details.
+"""
+
+__docformat__ = 'reStructuredText'
+
+
+from docutils import nodes
+from docutils.parsers.rst import Directive
+from docutils.parsers.rst import directives
+from docutils.parsers.rst.roles import set_classes
+from docutils.utils.code_analyzer import Lexer, LexerError, NumberLines
+
+
+class BasePseudoSection(Directive):
+
+ required_arguments = 1
+ optional_arguments = 0
+ final_argument_whitespace = True
+ option_spec = {'class': directives.class_option,
+ 'name': directives.unchanged}
+ has_content = True
+
+ node_class = None
+ """Node class to be used (must be set in subclasses)."""
+
+ def run(self):
+ if not (self.state_machine.match_titles
+ or isinstance(self.state_machine.node, nodes.sidebar)):
+ raise self.error('The "%s" directive may not be used within '
+ 'topics or body elements.' % self.name)
+ self.assert_has_content()
+ title_text = self.arguments[0]
+ textnodes, messages = self.state.inline_text(title_text, self.lineno)
+ titles = [nodes.title(title_text, '', *textnodes)]
+ # Sidebar uses this code.
+ if 'subtitle' in self.options:
+ textnodes, more_messages = self.state.inline_text(
+ self.options['subtitle'], self.lineno)
+ titles.append(nodes.subtitle(self.options['subtitle'], '',
+ *textnodes))
+ messages.extend(more_messages)
+ text = '\n'.join(self.content)
+ node = self.node_class(text, *(titles + messages))
+ node['classes'] += self.options.get('class', [])
+ self.add_name(node)
+ if text:
+ self.state.nested_parse(self.content, self.content_offset, node)
+ return [node]
+
+
+class Topic(BasePseudoSection):
+
+ node_class = nodes.topic
+
+
+class Sidebar(BasePseudoSection):
+
+ node_class = nodes.sidebar
+
+ option_spec = BasePseudoSection.option_spec.copy()
+ option_spec['subtitle'] = directives.unchanged_required
+
+ def run(self):
+ if isinstance(self.state_machine.node, nodes.sidebar):
+ raise self.error('The "%s" directive may not be used within a '
+ 'sidebar element.' % self.name)
+ return BasePseudoSection.run(self)
+
+
+class LineBlock(Directive):
+
+ option_spec = {'class': directives.class_option,
+ 'name': directives.unchanged}
+ has_content = True
+
+ def run(self):
+ self.assert_has_content()
+ block = nodes.line_block(classes=self.options.get('class', []))
+ self.add_name(block)
+ node_list = [block]
+ for line_text in self.content:
+ text_nodes, messages = self.state.inline_text(
+ line_text.strip(), self.lineno + self.content_offset)
+ line = nodes.line(line_text, '', *text_nodes)
+ if line_text.strip():
+ line.indent = len(line_text) - len(line_text.lstrip())
+ block += line
+ node_list.extend(messages)
+ self.content_offset += 1
+ self.state.nest_line_block_lines(block)
+ return node_list
+
+
+class ParsedLiteral(Directive):
+
+ option_spec = {'class': directives.class_option,
+ 'name': directives.unchanged}
+ has_content = True
+
+ def run(self):
+ set_classes(self.options)
+ self.assert_has_content()
+ text = '\n'.join(self.content)
+ text_nodes, messages = self.state.inline_text(text, self.lineno)
+ node = nodes.literal_block(text, '', *text_nodes, **self.options)
+ node.line = self.content_offset + 1
+ self.add_name(node)
+ return [node] + messages
+
+
+class CodeBlock(Directive):
+ """Parse and mark up content of a code block.
+
+ Configuration setting: syntax_highlight
+ Highlight Code content with Pygments?
+ Possible values: ('long', 'short', 'none')
+
+ """
+ optional_arguments = 1
+ option_spec = {'class': directives.class_option,
+ 'name': directives.unchanged,
+ 'number-lines': directives.unchanged # integer or None
+ }
+ has_content = True
+
+ def run(self):
+ self.assert_has_content()
+ if self.arguments:
+ language = self.arguments[0]
+ else:
+ language = ''
+ set_classes(self.options)
+ classes = ['code']
+ if language:
+ classes.append(language)
+ if 'classes' in self.options:
+ classes.extend(self.options['classes'])
+
+ # set up lexical analyzer
+ try:
+ tokens = Lexer(u'\n'.join(self.content), language,
+ self.state.document.settings.syntax_highlight)
+ except LexerError as error:
+ raise self.warning(error)
+
+ if 'number-lines' in self.options:
+ # optional argument `startline`, defaults to 1
+ try:
+ startline = int(self.options['number-lines'] or 1)
+ except ValueError:
+ raise self.error(':number-lines: with non-integer start value')
+ endline = startline + len(self.content)
+ # add linenumber filter:
+ tokens = NumberLines(tokens, startline, endline)
+
+ node = nodes.literal_block('\n'.join(self.content), classes=classes)
+ self.add_name(node)
+ # if called from "include", set the source
+ if 'source' in self.options:
+ node.attributes['source'] = self.options['source']
+ # analyze content and add nodes for every token
+ for classes, value in tokens:
+ if classes:
+ node += nodes.inline(value, value, classes=classes)
+ else:
+ # insert as Text to decrease the verbosity of the output
+ node += nodes.Text(value)
+
+ return [node]
+
+
+class MathBlock(Directive):
+
+ option_spec = {'class': directives.class_option,
+ 'name': directives.unchanged}
+ ## TODO: Add Sphinx' ``mathbase.py`` option 'nowrap'?
+ # 'nowrap': directives.flag,
+ has_content = True
+
+ def run(self):
+ set_classes(self.options)
+ self.assert_has_content()
+ # join lines, separate blocks
+ content = '\n'.join(self.content).split('\n\n')
+ _nodes = []
+ for block in content:
+ if not block:
+ continue
+ node = nodes.math_block(self.block_text, block, **self.options)
+ node.line = self.content_offset + 1
+ self.add_name(node)
+ _nodes.append(node)
+ return _nodes
+
+
+class Rubric(Directive):
+
+ required_arguments = 1
+ optional_arguments = 0
+ final_argument_whitespace = True
+ option_spec = {'class': directives.class_option,
+ 'name': directives.unchanged}
+
+ def run(self):
+ set_classes(self.options)
+ rubric_text = self.arguments[0]
+ textnodes, messages = self.state.inline_text(rubric_text, self.lineno)
+ rubric = nodes.rubric(rubric_text, '', *textnodes, **self.options)
+ self.add_name(rubric)
+ return [rubric] + messages
+
+
+class BlockQuote(Directive):
+
+ has_content = True
+ classes = []
+
+ def run(self):
+ self.assert_has_content()
+ elements = self.state.block_quote(self.content, self.content_offset)
+ for element in elements:
+ if isinstance(element, nodes.block_quote):
+ element['classes'] += self.classes
+ return elements
+
+
+class Epigraph(BlockQuote):
+
+ classes = ['epigraph']
+
+
+class Highlights(BlockQuote):
+
+ classes = ['highlights']
+
+
+class PullQuote(BlockQuote):
+
+ classes = ['pull-quote']
+
+
+class Compound(Directive):
+
+ option_spec = {'class': directives.class_option,
+ 'name': directives.unchanged}
+ has_content = True
+
+ def run(self):
+ self.assert_has_content()
+ text = '\n'.join(self.content)
+ node = nodes.compound(text)
+ node['classes'] += self.options.get('class', [])
+ self.add_name(node)
+ self.state.nested_parse(self.content, self.content_offset, node)
+ return [node]
+
+
+class Container(Directive):
+
+ optional_arguments = 1
+ final_argument_whitespace = True
+ option_spec = {'name': directives.unchanged}
+ has_content = True
+
+ def run(self):
+ self.assert_has_content()
+ text = '\n'.join(self.content)
+ try:
+ if self.arguments:
+ classes = directives.class_option(self.arguments[0])
+ else:
+ classes = []
+ except ValueError:
+ raise self.error(
+ 'Invalid class attribute value for "%s" directive: "%s".'
+ % (self.name, self.arguments[0]))
+ node = nodes.container(text)
+ node['classes'].extend(classes)
+ self.add_name(node)
+ self.state.nested_parse(self.content, self.content_offset, node)
+ return [node]
--- /dev/null
+# $Id: html.py 8347 2019-08-26 12:12:02Z milde $
+# Author: David Goodger <goodger@python.org>
+# Copyright: This module has been placed in the public domain.
+
+"""
+Directives for typically HTML-specific constructs.
+"""
+
+__docformat__ = 'reStructuredText'
+
+import sys
+from docutils import nodes, utils
+from docutils.parsers.rst import Directive
+from docutils.parsers.rst import states
+from docutils.transforms import components
+
+
+class MetaBody(states.SpecializedBody):
+
+ class meta(nodes.Special, nodes.PreBibliographic, nodes.Element):
+ """HTML-specific "meta" element."""
+ pass
+
+ def field_marker(self, match, context, next_state):
+ """Meta element."""
+ node, blank_finish = self.parsemeta(match)
+ self.parent += node
+ return [], next_state, []
+
+ def parsemeta(self, match):
+ name = self.parse_field_marker(match)
+ name = utils.unescape(utils.escape2null(name))
+ indented, indent, line_offset, blank_finish = \
+ self.state_machine.get_first_known_indented(match.end())
+ node = self.meta()
+ pending = nodes.pending(components.Filter,
+ {'component': 'writer',
+ 'format': 'html',
+ 'nodes': [node]})
+ node['content'] = utils.unescape(utils.escape2null(
+ ' '.join(indented)))
+ if not indented:
+ line = self.state_machine.line
+ msg = self.reporter.info(
+ 'No content for meta tag "%s".' % name,
+ nodes.literal_block(line, line))
+ return msg, blank_finish
+ tokens = name.split()
+ try:
+ attname, val = utils.extract_name_value(tokens[0])[0]
+ node[attname.lower()] = val
+ except utils.NameValueError:
+ node['name'] = tokens[0]
+ for token in tokens[1:]:
+ try:
+ attname, val = utils.extract_name_value(token)[0]
+ node[attname.lower()] = val
+ except utils.NameValueError as detail:
+ line = self.state_machine.line
+ msg = self.reporter.error(
+ 'Error parsing meta tag attribute "%s": %s.'
+ % (token, detail), nodes.literal_block(line, line))
+ return msg, blank_finish
+ self.document.note_pending(pending)
+ return pending, blank_finish
+
+
+class Meta(Directive):
+
+ has_content = True
+
+ SMkwargs = {'state_classes': (MetaBody,)}
+
+ def run(self):
+ self.assert_has_content()
+ node = nodes.Element()
+ new_line_offset, blank_finish = self.state.nested_list_parse(
+ self.content, self.content_offset, node,
+ initial_state='MetaBody', blank_finish=True,
+ state_machine_kwargs=self.SMkwargs)
+ if (new_line_offset - self.content_offset) != len(self.content):
+ # incomplete parse of block?
+ error = self.state_machine.reporter.error(
+ 'Invalid meta directive.',
+ nodes.literal_block(self.block_text, self.block_text),
+ line=self.lineno)
+ node += error
+ return node.children
--- /dev/null
+# $Id: images.py 8370 2019-08-27 12:10:39Z milde $
+# Author: David Goodger <goodger@python.org>
+# Copyright: This module has been placed in the public domain.
+
+"""
+Directives for figures and simple images.
+"""
+
+__docformat__ = 'reStructuredText'
+
+
+import sys
+
+from docutils import nodes, utils
+from docutils.parsers.rst import Directive
+from docutils.parsers.rst import directives, states
+from docutils.nodes import fully_normalize_name, whitespace_normalize_name
+from docutils.parsers.rst.roles import set_classes
+
+try: # check for the Python Imaging Library
+ import PIL.Image
+except ImportError:
+ try: # sometimes PIL modules are put in PYTHONPATH's root
+ import Image
+ class PIL(object): pass # dummy wrapper
+ PIL.Image = Image
+ except ImportError:
+ PIL = None
+
+if sys.version_info >= (3, 0):
+ from urllib.request import url2pathname
+else:
+ from urllib import url2pathname
+
+
+class Image(Directive):
+
+ align_h_values = ('left', 'center', 'right')
+ align_v_values = ('top', 'middle', 'bottom')
+ align_values = align_v_values + align_h_values
+
+ def align(argument):
+ # This is not callable as self.align. We cannot make it a
+ # staticmethod because we're saving an unbound method in
+ # option_spec below.
+ return directives.choice(argument, Image.align_values)
+
+ required_arguments = 1
+ optional_arguments = 0
+ final_argument_whitespace = True
+ option_spec = {'alt': directives.unchanged,
+ 'height': directives.length_or_unitless,
+ 'width': directives.length_or_percentage_or_unitless,
+ 'scale': directives.percentage,
+ 'align': align,
+ 'name': directives.unchanged,
+ 'target': directives.unchanged_required,
+ 'class': directives.class_option}
+
+ def run(self):
+ if 'align' in self.options:
+ if isinstance(self.state, states.SubstitutionDef):
+ # Check for align_v_values.
+ if self.options['align'] not in self.align_v_values:
+ raise self.error(
+ 'Error in "%s" directive: "%s" is not a valid value '
+ 'for the "align" option within a substitution '
+ 'definition. Valid values for "align" are: "%s".'
+ % (self.name, self.options['align'],
+ '", "'.join(self.align_v_values)))
+ elif self.options['align'] not in self.align_h_values:
+ raise self.error(
+ 'Error in "%s" directive: "%s" is not a valid value for '
+ 'the "align" option. Valid values for "align" are: "%s".'
+ % (self.name, self.options['align'],
+ '", "'.join(self.align_h_values)))
+ messages = []
+ reference = directives.uri(self.arguments[0])
+ self.options['uri'] = reference
+ reference_node = None
+ if 'target' in self.options:
+ block = states.escape2null(
+ self.options['target']).splitlines()
+ block = [line for line in block]
+ target_type, data = self.state.parse_target(
+ block, self.block_text, self.lineno)
+ if target_type == 'refuri':
+ reference_node = nodes.reference(refuri=data)
+ elif target_type == 'refname':
+ reference_node = nodes.reference(
+ refname=fully_normalize_name(data),
+ name=whitespace_normalize_name(data))
+ reference_node.indirect_reference_name = data
+ self.state.document.note_refname(reference_node)
+ else: # malformed target
+ messages.append(data) # data is a system message
+ del self.options['target']
+ set_classes(self.options)
+ image_node = nodes.image(self.block_text, **self.options)
+ self.add_name(image_node)
+ if reference_node:
+ reference_node += image_node
+ return messages + [reference_node]
+ else:
+ return messages + [image_node]
+
+
+class Figure(Image):
+
+ def align(argument):
+ return directives.choice(argument, Figure.align_h_values)
+
+ def figwidth_value(argument):
+ if argument.lower() == 'image':
+ return 'image'
+ else:
+ return directives.length_or_percentage_or_unitless(argument, 'px')
+
+ option_spec = Image.option_spec.copy()
+ option_spec['figwidth'] = figwidth_value
+ option_spec['figclass'] = directives.class_option
+ option_spec['align'] = align
+ has_content = True
+
+ def run(self):
+ figwidth = self.options.pop('figwidth', None)
+ figclasses = self.options.pop('figclass', None)
+ align = self.options.pop('align', None)
+ (image_node,) = Image.run(self)
+ if isinstance(image_node, nodes.system_message):
+ return [image_node]
+ figure_node = nodes.figure('', image_node)
+ if figwidth == 'image':
+ if PIL and self.state.document.settings.file_insertion_enabled:
+ imagepath = url2pathname(image_node['uri'])
+ try:
+ img = PIL.Image.open(
+ imagepath.encode(sys.getfilesystemencoding()))
+ except (IOError, UnicodeEncodeError):
+ pass # TODO: warn?
+ else:
+ self.state.document.settings.record_dependencies.add(
+ imagepath.replace('\\', '/'))
+ figure_node['width'] = '%dpx' % img.size[0]
+ del img
+ elif figwidth is not None:
+ figure_node['width'] = figwidth
+ if figclasses:
+ figure_node['classes'] += figclasses
+ if align:
+ figure_node['align'] = align
+ if self.content:
+ node = nodes.Element() # anonymous container for parsing
+ self.state.nested_parse(self.content, self.content_offset, node)
+ first_node = node[0]
+ if isinstance(first_node, nodes.paragraph):
+ caption = nodes.caption(first_node.rawsource, '',
+ *first_node.children)
+ caption.source = first_node.source
+ caption.line = first_node.line
+ figure_node += caption
+ elif not (isinstance(first_node, nodes.comment)
+ and len(first_node) == 0):
+ error = self.state_machine.reporter.error(
+ 'Figure caption must be a paragraph or empty comment.',
+ nodes.literal_block(self.block_text, self.block_text),
+ line=self.lineno)
+ return [figure_node, error]
+ if len(node) > 1:
+ figure_node += nodes.legend('', *node[1:])
+ return [figure_node]
--- /dev/null
+# $Id: misc.py 8370 2019-08-27 12:10:39Z milde $
+# Authors: David Goodger <goodger@python.org>; Dethe Elza
+# Copyright: This module has been placed in the public domain.
+
+"""Miscellaneous directives."""
+
+__docformat__ = 'reStructuredText'
+
+import sys
+import os.path
+import re
+import time
+from docutils import io, nodes, statemachine, utils
+from docutils.utils.error_reporting import SafeString, ErrorString
+from docutils.utils.error_reporting import locale_encoding
+from docutils.parsers.rst import Directive, convert_directive_function
+from docutils.parsers.rst import directives, roles, states
+from docutils.parsers.rst.directives.body import CodeBlock, NumberLines
+from docutils.parsers.rst.roles import set_classes
+from docutils.transforms import misc
+
+class Include(Directive):
+
+ """
+ Include content read from a separate source file.
+
+ Content may be parsed by the parser, or included as a literal
+ block. The encoding of the included file can be specified. Only
+ a part of the given file argument may be included by specifying
+ start and end line or text to match before and/or after the text
+ to be used.
+ """
+
+ required_arguments = 1
+ optional_arguments = 0
+ final_argument_whitespace = True
+ option_spec = {'literal': directives.flag,
+ 'code': directives.unchanged,
+ 'encoding': directives.encoding,
+ 'tab-width': int,
+ 'start-line': int,
+ 'end-line': int,
+ 'start-after': directives.unchanged_required,
+ 'end-before': directives.unchanged_required,
+ # ignored except for 'literal' or 'code':
+ 'number-lines': directives.unchanged, # integer or None
+ 'class': directives.class_option,
+ 'name': directives.unchanged}
+
+ standard_include_path = os.path.join(os.path.dirname(states.__file__),
+ 'include')
+
+ def run(self):
+ """Include a file as part of the content of this reST file."""
+ if not self.state.document.settings.file_insertion_enabled:
+ raise self.warning('"%s" directive disabled.' % self.name)
+ source = self.state_machine.input_lines.source(
+ self.lineno - self.state_machine.input_offset - 1)
+ source_dir = os.path.dirname(os.path.abspath(source))
+ path = directives.path(self.arguments[0])
+ if path.startswith('<') and path.endswith('>'):
+ path = os.path.join(self.standard_include_path, path[1:-1])
+ path = os.path.normpath(os.path.join(source_dir, path))
+ path = utils.relative_path(None, path)
+ path = nodes.reprunicode(path)
+ encoding = self.options.get(
+ 'encoding', self.state.document.settings.input_encoding)
+ e_handler=self.state.document.settings.input_encoding_error_handler
+ tab_width = self.options.get(
+ 'tab-width', self.state.document.settings.tab_width)
+ try:
+ self.state.document.settings.record_dependencies.add(path)
+ include_file = io.FileInput(source_path=path,
+ encoding=encoding,
+ error_handler=e_handler)
+ except UnicodeEncodeError as error:
+ raise self.severe(u'Problems with "%s" directive path:\n'
+ 'Cannot encode input file path "%s" '
+ '(wrong locale?).' %
+ (self.name, SafeString(path)))
+ except IOError as error:
+ raise self.severe(u'Problems with "%s" directive path:\n%s.' %
+ (self.name, ErrorString(error)))
+ startline = self.options.get('start-line', None)
+ endline = self.options.get('end-line', None)
+ try:
+ if startline or (endline is not None):
+ lines = include_file.readlines()
+ rawtext = ''.join(lines[startline:endline])
+ else:
+ rawtext = include_file.read()
+ except UnicodeError as error:
+ raise self.severe(u'Problem with "%s" directive:\n%s' %
+ (self.name, ErrorString(error)))
+ # start-after/end-before: no restrictions on newlines in match-text,
+ # and no restrictions on matching inside lines vs. line boundaries
+ after_text = self.options.get('start-after', None)
+ if after_text:
+ # skip content in rawtext before *and incl.* a matching text
+ after_index = rawtext.find(after_text)
+ if after_index < 0:
+ raise self.severe('Problem with "start-after" option of "%s" '
+ 'directive:\nText not found.' % self.name)
+ rawtext = rawtext[after_index + len(after_text):]
+ before_text = self.options.get('end-before', None)
+ if before_text:
+ # skip content in rawtext after *and incl.* a matching text
+ before_index = rawtext.find(before_text)
+ if before_index < 0:
+ raise self.severe('Problem with "end-before" option of "%s" '
+ 'directive:\nText not found.' % self.name)
+ rawtext = rawtext[:before_index]
+
+ include_lines = statemachine.string2lines(rawtext, tab_width,
+ convert_whitespace=True)
+ if 'literal' in self.options:
+ # Don't convert tabs to spaces, if `tab_width` is positive.
+ if tab_width >= 0:
+ text = rawtext.expandtabs(tab_width)
+ else:
+ text = rawtext
+ literal_block = nodes.literal_block(rawtext, source=path,
+ classes=self.options.get('class', []))
+ literal_block.line = 1
+ self.add_name(literal_block)
+ if 'number-lines' in self.options:
+ try:
+ startline = int(self.options['number-lines'] or 1)
+ except ValueError:
+ raise self.error(':number-lines: with non-integer '
+ 'start value')
+ endline = startline + len(include_lines)
+ if text.endswith('\n'):
+ text = text[:-1]
+ tokens = NumberLines([([], text)], startline, endline)
+ for classes, value in tokens:
+ if classes:
+ literal_block += nodes.inline(value, value,
+ classes=classes)
+ else:
+ literal_block += nodes.Text(value)
+ else:
+ literal_block += nodes.Text(text)
+ return [literal_block]
+ if 'code' in self.options:
+ self.options['source'] = path
+ # Don't convert tabs to spaces, if `tab_width` is negative:
+ if tab_width < 0:
+ include_lines = rawtext.splitlines()
+ codeblock = CodeBlock(self.name,
+ [self.options.pop('code')], # arguments
+ self.options,
+ include_lines, # content
+ self.lineno,
+ self.content_offset,
+ self.block_text,
+ self.state,
+ self.state_machine)
+ return codeblock.run()
+ self.state_machine.insert_input(include_lines, path)
+ return []
+
+
+class Raw(Directive):
+
+ """
+ Pass through content unchanged
+
+ Content is included in output based on type argument
+
+ Content may be included inline (content section of directive) or
+ imported from a file or url.
+ """
+
+ required_arguments = 1
+ optional_arguments = 0
+ final_argument_whitespace = True
+ option_spec = {'file': directives.path,
+ 'url': directives.uri,
+ 'encoding': directives.encoding}
+ has_content = True
+
+ def run(self):
+ if (not self.state.document.settings.raw_enabled
+ or (not self.state.document.settings.file_insertion_enabled
+ and ('file' in self.options
+ or 'url' in self.options))):
+ raise self.warning('"%s" directive disabled.' % self.name)
+ attributes = {'format': ' '.join(self.arguments[0].lower().split())}
+ encoding = self.options.get(
+ 'encoding', self.state.document.settings.input_encoding)
+ e_handler=self.state.document.settings.input_encoding_error_handler
+ if self.content:
+ if 'file' in self.options or 'url' in self.options:
+ raise self.error(
+ '"%s" directive may not both specify an external file '
+ 'and have content.' % self.name)
+ text = '\n'.join(self.content)
+ elif 'file' in self.options:
+ if 'url' in self.options:
+ raise self.error(
+ 'The "file" and "url" options may not be simultaneously '
+ 'specified for the "%s" directive.' % self.name)
+ source_dir = os.path.dirname(
+ os.path.abspath(self.state.document.current_source))
+ path = os.path.normpath(os.path.join(source_dir,
+ self.options['file']))
+ path = utils.relative_path(None, path)
+ try:
+ raw_file = io.FileInput(source_path=path,
+ encoding=encoding,
+ error_handler=e_handler)
+ # TODO: currently, raw input files are recorded as
+ # dependencies even if not used for the chosen output format.
+ self.state.document.settings.record_dependencies.add(path)
+ except IOError as error:
+ raise self.severe(u'Problems with "%s" directive path:\n%s.'
+ % (self.name, ErrorString(error)))
+ try:
+ text = raw_file.read()
+ except UnicodeError as error:
+ raise self.severe(u'Problem with "%s" directive:\n%s'
+ % (self.name, ErrorString(error)))
+ attributes['source'] = path
+ elif 'url' in self.options:
+ source = self.options['url']
+ # Do not import urllib2 at the top of the module because
+ # it may fail due to broken SSL dependencies, and it takes
+ # about 0.15 seconds to load.
+ if sys.version_info >= (3, 0):
+ from urllib.request import urlopen
+ from urllib.error import URLError
+ else:
+ from urllib2 import urlopen, URLError
+ try:
+ raw_text = urlopen(source).read()
+ except (URLError, IOError, OSError) as error:
+ raise self.severe(u'Problems with "%s" directive URL "%s":\n%s.'
+ % (self.name, self.options['url'], ErrorString(error)))
+ raw_file = io.StringInput(source=raw_text, source_path=source,
+ encoding=encoding,
+ error_handler=e_handler)
+ try:
+ text = raw_file.read()
+ except UnicodeError as error:
+ raise self.severe(u'Problem with "%s" directive:\n%s'
+ % (self.name, ErrorString(error)))
+ attributes['source'] = source
+ else:
+ # This will always fail because there is no content.
+ self.assert_has_content()
+ raw_node = nodes.raw('', text, **attributes)
+ (raw_node.source,
+ raw_node.line) = self.state_machine.get_source_and_line(self.lineno)
+ return [raw_node]
+
+
+class Replace(Directive):
+
+ has_content = True
+
+ def run(self):
+ if not isinstance(self.state, states.SubstitutionDef):
+ raise self.error(
+ 'Invalid context: the "%s" directive can only be used within '
+ 'a substitution definition.' % self.name)
+ self.assert_has_content()
+ text = '\n'.join(self.content)
+ element = nodes.Element(text)
+ self.state.nested_parse(self.content, self.content_offset,
+ element)
+ # element might contain [paragraph] + system_message(s)
+ node = None
+ messages = []
+ for elem in element:
+ if not node and isinstance(elem, nodes.paragraph):
+ node = elem
+ elif isinstance(elem, nodes.system_message):
+ elem['backrefs'] = []
+ messages.append(elem)
+ else:
+ return [
+ self.state_machine.reporter.error(
+ 'Error in "%s" directive: may contain a single paragraph '
+ 'only.' % (self.name), line=self.lineno) ]
+ if node:
+ return messages + node.children
+ return messages
+
+class Unicode(Directive):
+
+ r"""
+ Convert Unicode character codes (numbers) to characters. Codes may be
+ decimal numbers, hexadecimal numbers (prefixed by ``0x``, ``x``, ``\x``,
+ ``U+``, ``u``, or ``\u``; e.g. ``U+262E``), or XML-style numeric character
+ entities (e.g. ``☮``). Text following ".." is a comment and is
+ ignored. Spaces are ignored, and any other text remains as-is.
+ """
+
+ required_arguments = 1
+ optional_arguments = 0
+ final_argument_whitespace = True
+ option_spec = {'trim': directives.flag,
+ 'ltrim': directives.flag,
+ 'rtrim': directives.flag}
+
+ comment_pattern = re.compile(r'( |\n|^)\.\. ')
+
+ def run(self):
+ if not isinstance(self.state, states.SubstitutionDef):
+ raise self.error(
+ 'Invalid context: the "%s" directive can only be used within '
+ 'a substitution definition.' % self.name)
+ substitution_definition = self.state_machine.node
+ if 'trim' in self.options:
+ substitution_definition.attributes['ltrim'] = 1
+ substitution_definition.attributes['rtrim'] = 1
+ if 'ltrim' in self.options:
+ substitution_definition.attributes['ltrim'] = 1
+ if 'rtrim' in self.options:
+ substitution_definition.attributes['rtrim'] = 1
+ codes = self.comment_pattern.split(self.arguments[0])[0].split()
+ element = nodes.Element()
+ for code in codes:
+ try:
+ decoded = directives.unicode_code(code)
+ except ValueError as error:
+ raise self.error(u'Invalid character code: %s\n%s'
+ % (code, ErrorString(error)))
+ element += nodes.Text(decoded)
+ return element.children
+
+
+class Class(Directive):
+
+ """
+ Set a "class" attribute on the directive content or the next element.
+ When applied to the next element, a "pending" element is inserted, and a
+ transform does the work later.
+ """
+
+ required_arguments = 1
+ optional_arguments = 0
+ final_argument_whitespace = True
+ has_content = True
+
+ def run(self):
+ try:
+ class_value = directives.class_option(self.arguments[0])
+ except ValueError:
+ raise self.error(
+ 'Invalid class attribute value for "%s" directive: "%s".'
+ % (self.name, self.arguments[0]))
+ node_list = []
+ if self.content:
+ container = nodes.Element()
+ self.state.nested_parse(self.content, self.content_offset,
+ container)
+ for node in container:
+ node['classes'].extend(class_value)
+ node_list.extend(container.children)
+ else:
+ pending = nodes.pending(
+ misc.ClassAttribute,
+ {'class': class_value, 'directive': self.name},
+ self.block_text)
+ self.state_machine.document.note_pending(pending)
+ node_list.append(pending)
+ return node_list
+
+
+class Role(Directive):
+
+ has_content = True
+
+ argument_pattern = re.compile(r'(%s)\s*(\(\s*(%s)\s*\)\s*)?$'
+ % ((states.Inliner.simplename,) * 2))
+
+ def run(self):
+ """Dynamically create and register a custom interpreted text role."""
+ if self.content_offset > self.lineno or not self.content:
+ raise self.error('"%s" directive requires arguments on the first '
+ 'line.' % self.name)
+ args = self.content[0]
+ match = self.argument_pattern.match(args)
+ if not match:
+ raise self.error('"%s" directive arguments not valid role names: '
+ '"%s".' % (self.name, args))
+ new_role_name = match.group(1)
+ base_role_name = match.group(3)
+ messages = []
+ if base_role_name:
+ base_role, messages = roles.role(
+ base_role_name, self.state_machine.language, self.lineno,
+ self.state.reporter)
+ if base_role is None:
+ error = self.state.reporter.error(
+ 'Unknown interpreted text role "%s".' % base_role_name,
+ nodes.literal_block(self.block_text, self.block_text),
+ line=self.lineno)
+ return messages + [error]
+ else:
+ base_role = roles.generic_custom_role
+ assert not hasattr(base_role, 'arguments'), (
+ 'Supplemental directive arguments for "%s" directive not '
+ 'supported (specified by "%r" role).' % (self.name, base_role))
+ try:
+ converted_role = convert_directive_function(base_role)
+ (arguments, options, content, content_offset) = (
+ self.state.parse_directive_block(
+ self.content[1:], self.content_offset, converted_role,
+ option_presets={}))
+ except states.MarkupError as detail:
+ error = self.state_machine.reporter.error(
+ 'Error in "%s" directive:\n%s.' % (self.name, detail),
+ nodes.literal_block(self.block_text, self.block_text),
+ line=self.lineno)
+ return messages + [error]
+ if 'class' not in options:
+ try:
+ options['class'] = directives.class_option(new_role_name)
+ except ValueError as detail:
+ error = self.state_machine.reporter.error(
+ u'Invalid argument for "%s" directive:\n%s.'
+ % (self.name, SafeString(detail)), nodes.literal_block(
+ self.block_text, self.block_text), line=self.lineno)
+ return messages + [error]
+ role = roles.CustomRole(new_role_name, base_role, options, content)
+ roles.register_local_role(new_role_name, role)
+ return messages
+
+
+class DefaultRole(Directive):
+
+ """Set the default interpreted text role."""
+
+ optional_arguments = 1
+ final_argument_whitespace = False
+
+ def run(self):
+ if not self.arguments:
+ if '' in roles._roles:
+ # restore the "default" default role
+ del roles._roles['']
+ return []
+ role_name = self.arguments[0]
+ role, messages = roles.role(role_name, self.state_machine.language,
+ self.lineno, self.state.reporter)
+ if role is None:
+ error = self.state.reporter.error(
+ 'Unknown interpreted text role "%s".' % role_name,
+ nodes.literal_block(self.block_text, self.block_text),
+ line=self.lineno)
+ return messages + [error]
+ roles._roles[''] = role
+ return messages
+
+
+class Title(Directive):
+
+ required_arguments = 1
+ optional_arguments = 0
+ final_argument_whitespace = True
+
+ def run(self):
+ self.state_machine.document['title'] = self.arguments[0]
+ return []
+
+
+class Date(Directive):
+
+ has_content = True
+
+ def run(self):
+ if not isinstance(self.state, states.SubstitutionDef):
+ raise self.error(
+ 'Invalid context: the "%s" directive can only be used within '
+ 'a substitution definition.' % self.name)
+ format_str = '\n'.join(self.content) or '%Y-%m-%d'
+ if sys.version_info< (3, 0):
+ try:
+ format_str = format_str.encode(locale_encoding or 'utf-8')
+ except UnicodeEncodeError:
+ raise self.warning(u'Cannot encode date format string '
+ u'with locale encoding "%s".' % locale_encoding)
+ # @@@
+ # Use timestamp from the `SOURCE_DATE_EPOCH`_ environment variable?
+ # Pro: Docutils-generated documentation
+ # can easily be part of `reproducible software builds`__
+ #
+ # __ https://reproducible-builds.org/
+ #
+ # Con: Changes the specs, hard to predict behaviour,
+ #
+ # See also the discussion about \date \time \year in TeX
+ # http://tug.org/pipermail/tex-k/2016-May/002704.html
+ # source_date_epoch = os.environ.get('SOURCE_DATE_EPOCH')
+ # if (source_date_epoch):
+ # text = time.strftime(format_str,
+ # time.gmtime(int(source_date_epoch)))
+ # else:
+ text = time.strftime(format_str)
+ if sys.version_info< (3, 0):
+ # `text` is a byte string that may contain non-ASCII characters:
+ try:
+ text = text.decode(locale_encoding or 'utf-8')
+ except UnicodeDecodeError:
+ text = text.decode(locale_encoding or 'utf-8', 'replace')
+ raise self.warning(u'Error decoding "%s"'
+ u'with locale encoding "%s".' % (text, locale_encoding))
+ return [nodes.Text(text)]
+
+
+class TestDirective(Directive):
+
+ """This directive is useful only for testing purposes."""
+
+ optional_arguments = 1
+ final_argument_whitespace = True
+ option_spec = {'option': directives.unchanged_required}
+ has_content = True
+
+ def run(self):
+ if self.content:
+ text = '\n'.join(self.content)
+ info = self.state_machine.reporter.info(
+ 'Directive processed. Type="%s", arguments=%r, options=%r, '
+ 'content:' % (self.name, self.arguments, self.options),
+ nodes.literal_block(text, text), line=self.lineno)
+ else:
+ info = self.state_machine.reporter.info(
+ 'Directive processed. Type="%s", arguments=%r, options=%r, '
+ 'content: None' % (self.name, self.arguments, self.options),
+ line=self.lineno)
+ return [info]
+
+# Old-style, functional definition:
+#
+# def directive_test_function(name, arguments, options, content, lineno,
+# content_offset, block_text, state, state_machine):
+# """This directive is useful only for testing purposes."""
+# if content:
+# text = '\n'.join(content)
+# info = state_machine.reporter.info(
+# 'Directive processed. Type="%s", arguments=%r, options=%r, '
+# 'content:' % (name, arguments, options),
+# nodes.literal_block(text, text), line=lineno)
+# else:
+# info = state_machine.reporter.info(
+# 'Directive processed. Type="%s", arguments=%r, options=%r, '
+# 'content: None' % (name, arguments, options), line=lineno)
+# return [info]
+#
+# directive_test_function.arguments = (0, 1, 1)
+# directive_test_function.options = {'option': directives.unchanged_required}
+# directive_test_function.content = 1
--- /dev/null
+# $Id: parts.py 7308 2012-01-06 12:08:43Z milde $
+# Authors: David Goodger <goodger@python.org>; Dmitry Jemerov
+# Copyright: This module has been placed in the public domain.
+
+"""
+Directives for document parts.
+"""
+
+__docformat__ = 'reStructuredText'
+
+from docutils import nodes, languages
+from docutils.transforms import parts
+from docutils.parsers.rst import Directive
+from docutils.parsers.rst import directives
+
+
+class Contents(Directive):
+
+ """
+ Table of contents.
+
+ The table of contents is generated in two passes: initial parse and
+ transform. During the initial parse, a 'pending' element is generated
+ which acts as a placeholder, storing the TOC title and any options
+ internally. At a later stage in the processing, the 'pending' element is
+ replaced by a 'topic' element, a title and the table of contents proper.
+ """
+
+ backlinks_values = ('top', 'entry', 'none')
+
+ def backlinks(arg):
+ value = directives.choice(arg, Contents.backlinks_values)
+ if value == 'none':
+ return None
+ else:
+ return value
+
+ optional_arguments = 1
+ final_argument_whitespace = True
+ option_spec = {'depth': directives.nonnegative_int,
+ 'local': directives.flag,
+ 'backlinks': backlinks,
+ 'class': directives.class_option}
+
+ def run(self):
+ if not (self.state_machine.match_titles
+ or isinstance(self.state_machine.node, nodes.sidebar)):
+ raise self.error('The "%s" directive may not be used within '
+ 'topics or body elements.' % self.name)
+ document = self.state_machine.document
+ language = languages.get_language(document.settings.language_code,
+ document.reporter)
+ if self.arguments:
+ title_text = self.arguments[0]
+ text_nodes, messages = self.state.inline_text(title_text,
+ self.lineno)
+ title = nodes.title(title_text, '', *text_nodes)
+ else:
+ messages = []
+ if 'local' in self.options:
+ title = None
+ else:
+ title = nodes.title('', language.labels['contents'])
+ topic = nodes.topic(classes=['contents'])
+ topic['classes'] += self.options.get('class', [])
+ # the latex2e writer needs source and line for a warning:
+ topic.source, topic.line = self.state_machine.get_source_and_line()
+ topic.line -= 1
+ if 'local' in self.options:
+ topic['classes'].append('local')
+ if title:
+ name = title.astext()
+ topic += title
+ else:
+ name = language.labels['contents']
+ name = nodes.fully_normalize_name(name)
+ if not document.has_name(name):
+ topic['names'].append(name)
+ document.note_implicit_target(topic)
+ pending = nodes.pending(parts.Contents, rawsource=self.block_text)
+ pending.details.update(self.options)
+ document.note_pending(pending)
+ topic += pending
+ return [topic] + messages
+
+
+class Sectnum(Directive):
+
+ """Automatic section numbering."""
+
+ option_spec = {'depth': int,
+ 'start': int,
+ 'prefix': directives.unchanged_required,
+ 'suffix': directives.unchanged_required}
+
+ def run(self):
+ pending = nodes.pending(parts.SectNum)
+ pending.details.update(self.options)
+ self.state_machine.document.note_pending(pending)
+ return [pending]
+
+
+class Header(Directive):
+
+ """Contents of document header."""
+
+ has_content = True
+
+ def run(self):
+ self.assert_has_content()
+ header = self.state_machine.document.get_decoration().get_header()
+ self.state.nested_parse(self.content, self.content_offset, header)
+ return []
+
+
+class Footer(Directive):
+
+ """Contents of document footer."""
+
+ has_content = True
+
+ def run(self):
+ self.assert_has_content()
+ footer = self.state_machine.document.get_decoration().get_footer()
+ self.state.nested_parse(self.content, self.content_offset, footer)
+ return []
--- /dev/null
+# $Id: references.py 7062 2011-06-30 22:14:29Z milde $
+# Authors: David Goodger <goodger@python.org>; Dmitry Jemerov
+# Copyright: This module has been placed in the public domain.
+
+"""
+Directives for references and targets.
+"""
+
+__docformat__ = 'reStructuredText'
+
+from docutils import nodes
+from docutils.transforms import references
+from docutils.parsers.rst import Directive
+from docutils.parsers.rst import directives
+
+
+class TargetNotes(Directive):
+
+ """Target footnote generation."""
+
+ option_spec = {'class': directives.class_option,
+ 'name': directives.unchanged}
+
+ def run(self):
+ pending = nodes.pending(references.TargetNotes)
+ self.add_name(pending)
+ pending.details.update(self.options)
+ self.state_machine.document.note_pending(pending)
+ return [pending]
--- /dev/null
+# $Id: tables.py 8377 2019-08-27 19:49:45Z milde $
+# Authors: David Goodger <goodger@python.org>; David Priest
+# Copyright: This module has been placed in the public domain.
+
+"""
+Directives for table elements.
+"""
+
+__docformat__ = 'reStructuredText'
+
+
+import sys
+import os.path
+import csv
+
+from docutils import io, nodes, statemachine, utils
+from docutils.utils.error_reporting import SafeString
+from docutils.utils import SystemMessagePropagation
+from docutils.parsers.rst import Directive
+from docutils.parsers.rst import directives
+
+
+def align(argument):
+ return directives.choice(argument, ('left', 'center', 'right'))
+
+
+class Table(Directive):
+
+ """
+ Generic table base class.
+ """
+
+ optional_arguments = 1
+ final_argument_whitespace = True
+ option_spec = {'class': directives.class_option,
+ 'name': directives.unchanged,
+ 'align': align,
+ 'width': directives.length_or_percentage_or_unitless,
+ 'widths': directives.value_or(('auto', 'grid'),
+ directives.positive_int_list)}
+ has_content = True
+
+ def make_title(self):
+ if self.arguments:
+ title_text = self.arguments[0]
+ text_nodes, messages = self.state.inline_text(title_text,
+ self.lineno)
+ title = nodes.title(title_text, '', *text_nodes)
+ (title.source,
+ title.line) = self.state_machine.get_source_and_line(self.lineno)
+ else:
+ title = None
+ messages = []
+ return title, messages
+
+ def process_header_option(self):
+ source = self.state_machine.get_source(self.lineno - 1)
+ table_head = []
+ max_header_cols = 0
+ if 'header' in self.options: # separate table header in option
+ rows, max_header_cols = self.parse_csv_data_into_rows(
+ self.options['header'].split('\n'), self.HeaderDialect(),
+ source)
+ table_head.extend(rows)
+ return table_head, max_header_cols
+
+ def check_table_dimensions(self, rows, header_rows, stub_columns):
+ if len(rows) < header_rows:
+ error = self.state_machine.reporter.error(
+ '%s header row(s) specified but only %s row(s) of data '
+ 'supplied ("%s" directive).'
+ % (header_rows, len(rows), self.name), nodes.literal_block(
+ self.block_text, self.block_text), line=self.lineno)
+ raise SystemMessagePropagation(error)
+ if len(rows) == header_rows > 0:
+ error = self.state_machine.reporter.error(
+ 'Insufficient data supplied (%s row(s)); no data remaining '
+ 'for table body, required by "%s" directive.'
+ % (len(rows), self.name), nodes.literal_block(
+ self.block_text, self.block_text), line=self.lineno)
+ raise SystemMessagePropagation(error)
+ for row in rows:
+ if len(row) < stub_columns:
+ error = self.state_machine.reporter.error(
+ '%s stub column(s) specified but only %s columns(s) of '
+ 'data supplied ("%s" directive).' %
+ (stub_columns, len(row), self.name), nodes.literal_block(
+ self.block_text, self.block_text), line=self.lineno)
+ raise SystemMessagePropagation(error)
+ if len(row) == stub_columns > 0:
+ error = self.state_machine.reporter.error(
+ 'Insufficient data supplied (%s columns(s)); no data remaining '
+ 'for table body, required by "%s" directive.'
+ % (len(row), self.name), nodes.literal_block(
+ self.block_text, self.block_text), line=self.lineno)
+ raise SystemMessagePropagation(error)
+
+ def set_table_width(self, table_node):
+ if 'width' in self.options:
+ table_node['width'] = self.options.get('width')
+
+ @property
+ def widths(self):
+ return self.options.get('widths', '')
+
+ def get_column_widths(self, max_cols):
+ if isinstance(self.widths, list):
+ if len(self.widths) != max_cols:
+ error = self.state_machine.reporter.error(
+ '"%s" widths do not match the number of columns in table '
+ '(%s).' % (self.name, max_cols), nodes.literal_block(
+ self.block_text, self.block_text), line=self.lineno)
+ raise SystemMessagePropagation(error)
+ col_widths = self.widths
+ elif max_cols:
+ col_widths = [100 // max_cols] * max_cols
+ else:
+ error = self.state_machine.reporter.error(
+ 'No table data detected in CSV file.', nodes.literal_block(
+ self.block_text, self.block_text), line=self.lineno)
+ raise SystemMessagePropagation(error)
+ return col_widths
+
+ def extend_short_rows_with_empty_cells(self, columns, parts):
+ for part in parts:
+ for row in part:
+ if len(row) < columns:
+ row.extend([(0, 0, 0, [])] * (columns - len(row)))
+
+
+class RSTTable(Table):
+
+ def run(self):
+ if not self.content:
+ warning = self.state_machine.reporter.warning(
+ 'Content block expected for the "%s" directive; none found.'
+ % self.name, nodes.literal_block(
+ self.block_text, self.block_text), line=self.lineno)
+ return [warning]
+ title, messages = self.make_title()
+ node = nodes.Element() # anonymous container for parsing
+ self.state.nested_parse(self.content, self.content_offset, node)
+ if len(node) != 1 or not isinstance(node[0], nodes.table):
+ error = self.state_machine.reporter.error(
+ 'Error parsing content block for the "%s" directive: exactly '
+ 'one table expected.' % self.name, nodes.literal_block(
+ self.block_text, self.block_text), line=self.lineno)
+ return [error]
+ table_node = node[0]
+ table_node['classes'] += self.options.get('class', [])
+ self.set_table_width(table_node)
+ if 'align' in self.options:
+ table_node['align'] = self.options.get('align')
+ tgroup = table_node[0]
+ if isinstance(self.widths, list):
+ colspecs = [child for child in tgroup.children
+ if child.tagname == 'colspec']
+ for colspec, col_width in zip(colspecs, self.widths):
+ colspec['colwidth'] = col_width
+ # @@@ the colwidths argument for <tgroup> is not part of the
+ # XML Exchange Table spec (https://www.oasis-open.org/specs/tm9901.htm)
+ # and hence violates the docutils.dtd.
+ if self.widths == 'auto':
+ table_node['classes'] += ['colwidths-auto']
+ elif self.widths: # "grid" or list of integers
+ table_node['classes'] += ['colwidths-given']
+ self.add_name(table_node)
+ if title:
+ table_node.insert(0, title)
+ return [table_node] + messages
+
+
+class CSVTable(Table):
+
+ option_spec = {'header-rows': directives.nonnegative_int,
+ 'stub-columns': directives.nonnegative_int,
+ 'header': directives.unchanged,
+ 'width': directives.length_or_percentage_or_unitless,
+ 'widths': directives.value_or(('auto', ),
+ directives.positive_int_list),
+ 'file': directives.path,
+ 'url': directives.uri,
+ 'encoding': directives.encoding,
+ 'class': directives.class_option,
+ 'name': directives.unchanged,
+ 'align': align,
+ # field delimiter char
+ 'delim': directives.single_char_or_whitespace_or_unicode,
+ # treat whitespace after delimiter as significant
+ 'keepspace': directives.flag,
+ # text field quote/unquote char:
+ 'quote': directives.single_char_or_unicode,
+ # char used to escape delim & quote as-needed:
+ 'escape': directives.single_char_or_unicode,}
+
+ class DocutilsDialect(csv.Dialect):
+
+ """CSV dialect for `csv_table` directive."""
+
+ delimiter = ','
+ quotechar = '"'
+ doublequote = True
+ skipinitialspace = True
+ strict = True
+ lineterminator = '\n'
+ quoting = csv.QUOTE_MINIMAL
+
+ def __init__(self, options):
+ if 'delim' in options:
+ self.delimiter = CSVTable.encode_for_csv(options['delim'])
+ if 'keepspace' in options:
+ self.skipinitialspace = False
+ if 'quote' in options:
+ self.quotechar = CSVTable.encode_for_csv(options['quote'])
+ if 'escape' in options:
+ self.doublequote = False
+ self.escapechar = CSVTable.encode_for_csv(options['escape'])
+ csv.Dialect.__init__(self)
+
+
+ class HeaderDialect(csv.Dialect):
+
+ """CSV dialect to use for the "header" option data."""
+
+ delimiter = ','
+ quotechar = '"'
+ escapechar = '\\'
+ doublequote = False
+ skipinitialspace = True
+ strict = True
+ lineterminator = '\n'
+ quoting = csv.QUOTE_MINIMAL
+
+ def check_requirements(self):
+ pass
+
+ def run(self):
+ try:
+ if (not self.state.document.settings.file_insertion_enabled
+ and ('file' in self.options
+ or 'url' in self.options)):
+ warning = self.state_machine.reporter.warning(
+ 'File and URL access deactivated; ignoring "%s" '
+ 'directive.' % self.name, nodes.literal_block(
+ self.block_text, self.block_text), line=self.lineno)
+ return [warning]
+ self.check_requirements()
+ title, messages = self.make_title()
+ csv_data, source = self.get_csv_data()
+ table_head, max_header_cols = self.process_header_option()
+ rows, max_cols = self.parse_csv_data_into_rows(
+ csv_data, self.DocutilsDialect(self.options), source)
+ max_cols = max(max_cols, max_header_cols)
+ header_rows = self.options.get('header-rows', 0)
+ stub_columns = self.options.get('stub-columns', 0)
+ self.check_table_dimensions(rows, header_rows, stub_columns)
+ table_head.extend(rows[:header_rows])
+ table_body = rows[header_rows:]
+ col_widths = self.get_column_widths(max_cols)
+ self.extend_short_rows_with_empty_cells(max_cols,
+ (table_head, table_body))
+ except SystemMessagePropagation as detail:
+ return [detail.args[0]]
+ except csv.Error as detail:
+ message = str(detail)
+ if sys.version_info < (3, 0) and '1-character string' in message:
+ message += '\nwith Python 2.x this must be an ASCII character.'
+ error = self.state_machine.reporter.error(
+ 'Error with CSV data in "%s" directive:\n%s'
+ % (self.name, message), nodes.literal_block(
+ self.block_text, self.block_text), line=self.lineno)
+ return [error]
+ table = (col_widths, table_head, table_body)
+ table_node = self.state.build_table(table, self.content_offset,
+ stub_columns, widths=self.widths)
+ table_node['classes'] += self.options.get('class', [])
+ if 'align' in self.options:
+ table_node['align'] = self.options.get('align')
+ self.set_table_width(table_node)
+ self.add_name(table_node)
+ if title:
+ table_node.insert(0, title)
+ return [table_node] + messages
+
+ def get_csv_data(self):
+ """
+ Get CSV data from the directive content, from an external
+ file, or from a URL reference.
+ """
+ encoding = self.options.get(
+ 'encoding', self.state.document.settings.input_encoding)
+ error_handler = self.state.document.settings.input_encoding_error_handler
+ if self.content:
+ # CSV data is from directive content.
+ if 'file' in self.options or 'url' in self.options:
+ error = self.state_machine.reporter.error(
+ '"%s" directive may not both specify an external file and'
+ ' have content.' % self.name, nodes.literal_block(
+ self.block_text, self.block_text), line=self.lineno)
+ raise SystemMessagePropagation(error)
+ source = self.content.source(0)
+ csv_data = self.content
+ elif 'file' in self.options:
+ # CSV data is from an external file.
+ if 'url' in self.options:
+ error = self.state_machine.reporter.error(
+ 'The "file" and "url" options may not be simultaneously'
+ ' specified for the "%s" directive.' % self.name,
+ nodes.literal_block(self.block_text, self.block_text),
+ line=self.lineno)
+ raise SystemMessagePropagation(error)
+ source_dir = os.path.dirname(
+ os.path.abspath(self.state.document.current_source))
+ source = os.path.normpath(os.path.join(source_dir,
+ self.options['file']))
+ source = utils.relative_path(None, source)
+ try:
+ self.state.document.settings.record_dependencies.add(source)
+ csv_file = io.FileInput(source_path=source,
+ encoding=encoding,
+ error_handler=error_handler)
+ csv_data = csv_file.read().splitlines()
+ except IOError as error:
+ severe = self.state_machine.reporter.severe(
+ u'Problems with "%s" directive path:\n%s.'
+ % (self.name, SafeString(error)),
+ nodes.literal_block(self.block_text, self.block_text),
+ line=self.lineno)
+ raise SystemMessagePropagation(severe)
+ elif 'url' in self.options:
+ # CSV data is from a URL.
+ # Do not import urllib2 at the top of the module because
+ # it may fail due to broken SSL dependencies, and it takes
+ # about 0.15 seconds to load.
+ if sys.version_info >= (3, 0):
+ from urllib.request import urlopen
+ from urllib.error import URLError
+ else:
+ from urllib2 import urlopen, URLError
+
+ source = self.options['url']
+ try:
+ csv_text = urlopen(source).read()
+ except (URLError, IOError, OSError, ValueError) as error:
+ severe = self.state_machine.reporter.severe(
+ 'Problems with "%s" directive URL "%s":\n%s.'
+ % (self.name, self.options['url'], SafeString(error)),
+ nodes.literal_block(self.block_text, self.block_text),
+ line=self.lineno)
+ raise SystemMessagePropagation(severe)
+ csv_file = io.StringInput(
+ source=csv_text, source_path=source, encoding=encoding,
+ error_handler=(self.state.document.settings.\
+ input_encoding_error_handler))
+ csv_data = csv_file.read().splitlines()
+ else:
+ error = self.state_machine.reporter.warning(
+ 'The "%s" directive requires content; none supplied.'
+ % self.name, nodes.literal_block(
+ self.block_text, self.block_text), line=self.lineno)
+ raise SystemMessagePropagation(error)
+ return csv_data, source
+
+ if sys.version_info < (3, 0):
+ # 2.x csv module doesn't do Unicode
+ def decode_from_csv(s):
+ return s.decode('utf-8')
+ def encode_for_csv(s):
+ return s.encode('utf-8')
+ else:
+ def decode_from_csv(s):
+ return s
+ def encode_for_csv(s):
+ return s
+ decode_from_csv = staticmethod(decode_from_csv)
+ encode_for_csv = staticmethod(encode_for_csv)
+
+ def parse_csv_data_into_rows(self, csv_data, dialect, source):
+ # csv.py doesn't do Unicode; encode temporarily as UTF-8
+ csv_reader = csv.reader([self.encode_for_csv(line + '\n')
+ for line in csv_data],
+ dialect=dialect)
+ rows = []
+ max_cols = 0
+ for row in csv_reader:
+ row_data = []
+ for cell in row:
+ # decode UTF-8 back to Unicode
+ cell_text = self.decode_from_csv(cell)
+ cell_data = (0, 0, 0, statemachine.StringList(
+ cell_text.splitlines(), source=source))
+ row_data.append(cell_data)
+ rows.append(row_data)
+ max_cols = max(max_cols, len(row))
+ return rows, max_cols
+
+
+class ListTable(Table):
+
+ """
+ Implement tables whose data is encoded as a uniform two-level bullet list.
+ For further ideas, see
+ http://docutils.sf.net/docs/dev/rst/alternatives.html#list-driven-tables
+ """
+
+ option_spec = {'header-rows': directives.nonnegative_int,
+ 'stub-columns': directives.nonnegative_int,
+ 'width': directives.length_or_percentage_or_unitless,
+ 'widths': directives.value_or(('auto', ),
+ directives.positive_int_list),
+ 'class': directives.class_option,
+ 'name': directives.unchanged,
+ 'align': align}
+
+ def run(self):
+ if not self.content:
+ error = self.state_machine.reporter.error(
+ 'The "%s" directive is empty; content required.' % self.name,
+ nodes.literal_block(self.block_text, self.block_text),
+ line=self.lineno)
+ return [error]
+ title, messages = self.make_title()
+ node = nodes.Element() # anonymous container for parsing
+ self.state.nested_parse(self.content, self.content_offset, node)
+ try:
+ num_cols, col_widths = self.check_list_content(node)
+ table_data = [[item.children for item in row_list[0]]
+ for row_list in node[0]]
+ header_rows = self.options.get('header-rows', 0)
+ stub_columns = self.options.get('stub-columns', 0)
+ self.check_table_dimensions(table_data, header_rows, stub_columns)
+ except SystemMessagePropagation as detail:
+ return [detail.args[0]]
+ table_node = self.build_table_from_list(table_data, col_widths,
+ header_rows, stub_columns)
+ if 'align' in self.options:
+ table_node['align'] = self.options.get('align')
+ table_node['classes'] += self.options.get('class', [])
+ self.set_table_width(table_node)
+ self.add_name(table_node)
+ if title:
+ table_node.insert(0, title)
+ return [table_node] + messages
+
+ def check_list_content(self, node):
+ if len(node) != 1 or not isinstance(node[0], nodes.bullet_list):
+ error = self.state_machine.reporter.error(
+ 'Error parsing content block for the "%s" directive: '
+ 'exactly one bullet list expected.' % self.name,
+ nodes.literal_block(self.block_text, self.block_text),
+ line=self.lineno)
+ raise SystemMessagePropagation(error)
+ list_node = node[0]
+ num_cols = 0
+ # Check for a uniform two-level bullet list:
+ for item_index in range(len(list_node)):
+ item = list_node[item_index]
+ if len(item) != 1 or not isinstance(item[0], nodes.bullet_list):
+ error = self.state_machine.reporter.error(
+ 'Error parsing content block for the "%s" directive: '
+ 'two-level bullet list expected, but row %s does not '
+ 'contain a second-level bullet list.'
+ % (self.name, item_index + 1), nodes.literal_block(
+ self.block_text, self.block_text), line=self.lineno)
+ raise SystemMessagePropagation(error)
+ elif item_index:
+ if len(item[0]) != num_cols:
+ error = self.state_machine.reporter.error(
+ 'Error parsing content block for the "%s" directive: '
+ 'uniform two-level bullet list expected, but row %s '
+ 'does not contain the same number of items as row 1 '
+ '(%s vs %s).'
+ % (self.name, item_index + 1, len(item[0]), num_cols),
+ nodes.literal_block(self.block_text, self.block_text),
+ line=self.lineno)
+ raise SystemMessagePropagation(error)
+ else:
+ num_cols = len(item[0])
+ col_widths = self.get_column_widths(num_cols)
+ return num_cols, col_widths
+
+ def build_table_from_list(self, table_data, col_widths, header_rows, stub_columns):
+ table = nodes.table()
+ if self.widths == 'auto':
+ table['classes'] += ['colwidths-auto']
+ elif self.widths: # "grid" or list of integers
+ table['classes'] += ['colwidths-given']
+ tgroup = nodes.tgroup(cols=len(col_widths))
+ table += tgroup
+ for col_width in col_widths:
+ colspec = nodes.colspec()
+ if col_width is not None:
+ colspec.attributes['colwidth'] = col_width
+ if stub_columns:
+ colspec.attributes['stub'] = 1
+ stub_columns -= 1
+ tgroup += colspec
+ rows = []
+ for row in table_data:
+ row_node = nodes.row()
+ for cell in row:
+ entry = nodes.entry()
+ entry += cell
+ row_node += entry
+ rows.append(row_node)
+ if header_rows:
+ thead = nodes.thead()
+ thead.extend(rows[:header_rows])
+ tgroup += thead
+ tbody = nodes.tbody()
+ tbody.extend(rows[header_rows:])
+ tgroup += tbody
+ return table
--- /dev/null
+============================================
+ ``docutils/parsers/rst/include`` Directory
+============================================
+
+This directory contains standard data files intended for inclusion in
+reStructuredText documents. To access these files, use the "include"
+directive with the special syntax for standard "include" data files,
+angle brackets around the file name::
+
+ .. include:: <isonum.txt>
+
+See the documentation for the `"include" directive`__ and
+`reStructuredText Standard Substitution Definition Sets`__ for
+details.
+
+__ http://docutils.sf.net/docs/ref/rst/directives.html#include
+__ http://docutils.sf.net/docs/ref/rst/substitutions.html
--- /dev/null
+.. This data file has been placed in the public domain.
+.. Derived from the Unicode character mappings available from
+ <http://www.w3.org/2003/entities/xml/>.
+ Processed by unicode2rstsubs.py, part of Docutils:
+ <http://docutils.sourceforge.net>.
+
+.. |angzarr| unicode:: U+0237C .. RIGHT ANGLE WITH DOWNWARDS ZIGZAG ARROW
+.. |cirmid| unicode:: U+02AEF .. VERTICAL LINE WITH CIRCLE ABOVE
+.. |cudarrl| unicode:: U+02938 .. RIGHT-SIDE ARC CLOCKWISE ARROW
+.. |cudarrr| unicode:: U+02935 .. ARROW POINTING RIGHTWARDS THEN CURVING DOWNWARDS
+.. |cularr| unicode:: U+021B6 .. ANTICLOCKWISE TOP SEMICIRCLE ARROW
+.. |cularrp| unicode:: U+0293D .. TOP ARC ANTICLOCKWISE ARROW WITH PLUS
+.. |curarr| unicode:: U+021B7 .. CLOCKWISE TOP SEMICIRCLE ARROW
+.. |curarrm| unicode:: U+0293C .. TOP ARC CLOCKWISE ARROW WITH MINUS
+.. |Darr| unicode:: U+021A1 .. DOWNWARDS TWO HEADED ARROW
+.. |dArr| unicode:: U+021D3 .. DOWNWARDS DOUBLE ARROW
+.. |darr2| unicode:: U+021CA .. DOWNWARDS PAIRED ARROWS
+.. |ddarr| unicode:: U+021CA .. DOWNWARDS PAIRED ARROWS
+.. |DDotrahd| unicode:: U+02911 .. RIGHTWARDS ARROW WITH DOTTED STEM
+.. |dfisht| unicode:: U+0297F .. DOWN FISH TAIL
+.. |dHar| unicode:: U+02965 .. DOWNWARDS HARPOON WITH BARB LEFT BESIDE DOWNWARDS HARPOON WITH BARB RIGHT
+.. |dharl| unicode:: U+021C3 .. DOWNWARDS HARPOON WITH BARB LEFTWARDS
+.. |dharr| unicode:: U+021C2 .. DOWNWARDS HARPOON WITH BARB RIGHTWARDS
+.. |dlarr| unicode:: U+02199 .. SOUTH WEST ARROW
+.. |drarr| unicode:: U+02198 .. SOUTH EAST ARROW
+.. |duarr| unicode:: U+021F5 .. DOWNWARDS ARROW LEFTWARDS OF UPWARDS ARROW
+.. |duhar| unicode:: U+0296F .. DOWNWARDS HARPOON WITH BARB LEFT BESIDE UPWARDS HARPOON WITH BARB RIGHT
+.. |dzigrarr| unicode:: U+027FF .. LONG RIGHTWARDS SQUIGGLE ARROW
+.. |erarr| unicode:: U+02971 .. EQUALS SIGN ABOVE RIGHTWARDS ARROW
+.. |hArr| unicode:: U+021D4 .. LEFT RIGHT DOUBLE ARROW
+.. |harr| unicode:: U+02194 .. LEFT RIGHT ARROW
+.. |harrcir| unicode:: U+02948 .. LEFT RIGHT ARROW THROUGH SMALL CIRCLE
+.. |harrw| unicode:: U+021AD .. LEFT RIGHT WAVE ARROW
+.. |hoarr| unicode:: U+021FF .. LEFT RIGHT OPEN-HEADED ARROW
+.. |imof| unicode:: U+022B7 .. IMAGE OF
+.. |lAarr| unicode:: U+021DA .. LEFTWARDS TRIPLE ARROW
+.. |Larr| unicode:: U+0219E .. LEFTWARDS TWO HEADED ARROW
+.. |larr2| unicode:: U+021C7 .. LEFTWARDS PAIRED ARROWS
+.. |larrbfs| unicode:: U+0291F .. LEFTWARDS ARROW FROM BAR TO BLACK DIAMOND
+.. |larrfs| unicode:: U+0291D .. LEFTWARDS ARROW TO BLACK DIAMOND
+.. |larrhk| unicode:: U+021A9 .. LEFTWARDS ARROW WITH HOOK
+.. |larrlp| unicode:: U+021AB .. LEFTWARDS ARROW WITH LOOP
+.. |larrpl| unicode:: U+02939 .. LEFT-SIDE ARC ANTICLOCKWISE ARROW
+.. |larrsim| unicode:: U+02973 .. LEFTWARDS ARROW ABOVE TILDE OPERATOR
+.. |larrtl| unicode:: U+021A2 .. LEFTWARDS ARROW WITH TAIL
+.. |lAtail| unicode:: U+0291B .. LEFTWARDS DOUBLE ARROW-TAIL
+.. |latail| unicode:: U+02919 .. LEFTWARDS ARROW-TAIL
+.. |lBarr| unicode:: U+0290E .. LEFTWARDS TRIPLE DASH ARROW
+.. |lbarr| unicode:: U+0290C .. LEFTWARDS DOUBLE DASH ARROW
+.. |ldca| unicode:: U+02936 .. ARROW POINTING DOWNWARDS THEN CURVING LEFTWARDS
+.. |ldrdhar| unicode:: U+02967 .. LEFTWARDS HARPOON WITH BARB DOWN ABOVE RIGHTWARDS HARPOON WITH BARB DOWN
+.. |ldrushar| unicode:: U+0294B .. LEFT BARB DOWN RIGHT BARB UP HARPOON
+.. |ldsh| unicode:: U+021B2 .. DOWNWARDS ARROW WITH TIP LEFTWARDS
+.. |lfisht| unicode:: U+0297C .. LEFT FISH TAIL
+.. |lHar| unicode:: U+02962 .. LEFTWARDS HARPOON WITH BARB UP ABOVE LEFTWARDS HARPOON WITH BARB DOWN
+.. |lhard| unicode:: U+021BD .. LEFTWARDS HARPOON WITH BARB DOWNWARDS
+.. |lharu| unicode:: U+021BC .. LEFTWARDS HARPOON WITH BARB UPWARDS
+.. |lharul| unicode:: U+0296A .. LEFTWARDS HARPOON WITH BARB UP ABOVE LONG DASH
+.. |llarr| unicode:: U+021C7 .. LEFTWARDS PAIRED ARROWS
+.. |llhard| unicode:: U+0296B .. LEFTWARDS HARPOON WITH BARB DOWN BELOW LONG DASH
+.. |loarr| unicode:: U+021FD .. LEFTWARDS OPEN-HEADED ARROW
+.. |lrarr| unicode:: U+021C6 .. LEFTWARDS ARROW OVER RIGHTWARDS ARROW
+.. |lrarr2| unicode:: U+021C6 .. LEFTWARDS ARROW OVER RIGHTWARDS ARROW
+.. |lrhar| unicode:: U+021CB .. LEFTWARDS HARPOON OVER RIGHTWARDS HARPOON
+.. |lrhar2| unicode:: U+021CB .. LEFTWARDS HARPOON OVER RIGHTWARDS HARPOON
+.. |lrhard| unicode:: U+0296D .. RIGHTWARDS HARPOON WITH BARB DOWN BELOW LONG DASH
+.. |lsh| unicode:: U+021B0 .. UPWARDS ARROW WITH TIP LEFTWARDS
+.. |lurdshar| unicode:: U+0294A .. LEFT BARB UP RIGHT BARB DOWN HARPOON
+.. |luruhar| unicode:: U+02966 .. LEFTWARDS HARPOON WITH BARB UP ABOVE RIGHTWARDS HARPOON WITH BARB UP
+.. |Map| unicode:: U+02905 .. RIGHTWARDS TWO-HEADED ARROW FROM BAR
+.. |map| unicode:: U+021A6 .. RIGHTWARDS ARROW FROM BAR
+.. |midcir| unicode:: U+02AF0 .. VERTICAL LINE WITH CIRCLE BELOW
+.. |mumap| unicode:: U+022B8 .. MULTIMAP
+.. |nearhk| unicode:: U+02924 .. NORTH EAST ARROW WITH HOOK
+.. |neArr| unicode:: U+021D7 .. NORTH EAST DOUBLE ARROW
+.. |nearr| unicode:: U+02197 .. NORTH EAST ARROW
+.. |nesear| unicode:: U+02928 .. NORTH EAST ARROW AND SOUTH EAST ARROW
+.. |nhArr| unicode:: U+021CE .. LEFT RIGHT DOUBLE ARROW WITH STROKE
+.. |nharr| unicode:: U+021AE .. LEFT RIGHT ARROW WITH STROKE
+.. |nlArr| unicode:: U+021CD .. LEFTWARDS DOUBLE ARROW WITH STROKE
+.. |nlarr| unicode:: U+0219A .. LEFTWARDS ARROW WITH STROKE
+.. |nrArr| unicode:: U+021CF .. RIGHTWARDS DOUBLE ARROW WITH STROKE
+.. |nrarr| unicode:: U+0219B .. RIGHTWARDS ARROW WITH STROKE
+.. |nrarrc| unicode:: U+02933 U+00338 .. WAVE ARROW POINTING DIRECTLY RIGHT with slash
+.. |nrarrw| unicode:: U+0219D U+00338 .. RIGHTWARDS WAVE ARROW with slash
+.. |nvHarr| unicode:: U+02904 .. LEFT RIGHT DOUBLE ARROW WITH VERTICAL STROKE
+.. |nvlArr| unicode:: U+02902 .. LEFTWARDS DOUBLE ARROW WITH VERTICAL STROKE
+.. |nvrArr| unicode:: U+02903 .. RIGHTWARDS DOUBLE ARROW WITH VERTICAL STROKE
+.. |nwarhk| unicode:: U+02923 .. NORTH WEST ARROW WITH HOOK
+.. |nwArr| unicode:: U+021D6 .. NORTH WEST DOUBLE ARROW
+.. |nwarr| unicode:: U+02196 .. NORTH WEST ARROW
+.. |nwnear| unicode:: U+02927 .. NORTH WEST ARROW AND NORTH EAST ARROW
+.. |olarr| unicode:: U+021BA .. ANTICLOCKWISE OPEN CIRCLE ARROW
+.. |orarr| unicode:: U+021BB .. CLOCKWISE OPEN CIRCLE ARROW
+.. |origof| unicode:: U+022B6 .. ORIGINAL OF
+.. |rAarr| unicode:: U+021DB .. RIGHTWARDS TRIPLE ARROW
+.. |Rarr| unicode:: U+021A0 .. RIGHTWARDS TWO HEADED ARROW
+.. |rarr2| unicode:: U+021C9 .. RIGHTWARDS PAIRED ARROWS
+.. |rarrap| unicode:: U+02975 .. RIGHTWARDS ARROW ABOVE ALMOST EQUAL TO
+.. |rarrbfs| unicode:: U+02920 .. RIGHTWARDS ARROW FROM BAR TO BLACK DIAMOND
+.. |rarrc| unicode:: U+02933 .. WAVE ARROW POINTING DIRECTLY RIGHT
+.. |rarrfs| unicode:: U+0291E .. RIGHTWARDS ARROW TO BLACK DIAMOND
+.. |rarrhk| unicode:: U+021AA .. RIGHTWARDS ARROW WITH HOOK
+.. |rarrlp| unicode:: U+021AC .. RIGHTWARDS ARROW WITH LOOP
+.. |rarrpl| unicode:: U+02945 .. RIGHTWARDS ARROW WITH PLUS BELOW
+.. |rarrsim| unicode:: U+02974 .. RIGHTWARDS ARROW ABOVE TILDE OPERATOR
+.. |Rarrtl| unicode:: U+02916 .. RIGHTWARDS TWO-HEADED ARROW WITH TAIL
+.. |rarrtl| unicode:: U+021A3 .. RIGHTWARDS ARROW WITH TAIL
+.. |rarrw| unicode:: U+0219D .. RIGHTWARDS WAVE ARROW
+.. |rAtail| unicode:: U+0291C .. RIGHTWARDS DOUBLE ARROW-TAIL
+.. |ratail| unicode:: U+0291A .. RIGHTWARDS ARROW-TAIL
+.. |RBarr| unicode:: U+02910 .. RIGHTWARDS TWO-HEADED TRIPLE DASH ARROW
+.. |rBarr| unicode:: U+0290F .. RIGHTWARDS TRIPLE DASH ARROW
+.. |rbarr| unicode:: U+0290D .. RIGHTWARDS DOUBLE DASH ARROW
+.. |rdca| unicode:: U+02937 .. ARROW POINTING DOWNWARDS THEN CURVING RIGHTWARDS
+.. |rdldhar| unicode:: U+02969 .. RIGHTWARDS HARPOON WITH BARB DOWN ABOVE LEFTWARDS HARPOON WITH BARB DOWN
+.. |rdsh| unicode:: U+021B3 .. DOWNWARDS ARROW WITH TIP RIGHTWARDS
+.. |rfisht| unicode:: U+0297D .. RIGHT FISH TAIL
+.. |rHar| unicode:: U+02964 .. RIGHTWARDS HARPOON WITH BARB UP ABOVE RIGHTWARDS HARPOON WITH BARB DOWN
+.. |rhard| unicode:: U+021C1 .. RIGHTWARDS HARPOON WITH BARB DOWNWARDS
+.. |rharu| unicode:: U+021C0 .. RIGHTWARDS HARPOON WITH BARB UPWARDS
+.. |rharul| unicode:: U+0296C .. RIGHTWARDS HARPOON WITH BARB UP ABOVE LONG DASH
+.. |rlarr| unicode:: U+021C4 .. RIGHTWARDS ARROW OVER LEFTWARDS ARROW
+.. |rlarr2| unicode:: U+021C4 .. RIGHTWARDS ARROW OVER LEFTWARDS ARROW
+.. |rlhar| unicode:: U+021CC .. RIGHTWARDS HARPOON OVER LEFTWARDS HARPOON
+.. |rlhar2| unicode:: U+021CC .. RIGHTWARDS HARPOON OVER LEFTWARDS HARPOON
+.. |roarr| unicode:: U+021FE .. RIGHTWARDS OPEN-HEADED ARROW
+.. |rrarr| unicode:: U+021C9 .. RIGHTWARDS PAIRED ARROWS
+.. |rsh| unicode:: U+021B1 .. UPWARDS ARROW WITH TIP RIGHTWARDS
+.. |ruluhar| unicode:: U+02968 .. RIGHTWARDS HARPOON WITH BARB UP ABOVE LEFTWARDS HARPOON WITH BARB UP
+.. |searhk| unicode:: U+02925 .. SOUTH EAST ARROW WITH HOOK
+.. |seArr| unicode:: U+021D8 .. SOUTH EAST DOUBLE ARROW
+.. |searr| unicode:: U+02198 .. SOUTH EAST ARROW
+.. |seswar| unicode:: U+02929 .. SOUTH EAST ARROW AND SOUTH WEST ARROW
+.. |simrarr| unicode:: U+02972 .. TILDE OPERATOR ABOVE RIGHTWARDS ARROW
+.. |slarr| unicode:: U+02190 .. LEFTWARDS ARROW
+.. |srarr| unicode:: U+02192 .. RIGHTWARDS ARROW
+.. |swarhk| unicode:: U+02926 .. SOUTH WEST ARROW WITH HOOK
+.. |swArr| unicode:: U+021D9 .. SOUTH WEST DOUBLE ARROW
+.. |swarr| unicode:: U+02199 .. SOUTH WEST ARROW
+.. |swnwar| unicode:: U+0292A .. SOUTH WEST ARROW AND NORTH WEST ARROW
+.. |Uarr| unicode:: U+0219F .. UPWARDS TWO HEADED ARROW
+.. |uArr| unicode:: U+021D1 .. UPWARDS DOUBLE ARROW
+.. |uarr2| unicode:: U+021C8 .. UPWARDS PAIRED ARROWS
+.. |Uarrocir| unicode:: U+02949 .. UPWARDS TWO-HEADED ARROW FROM SMALL CIRCLE
+.. |udarr| unicode:: U+021C5 .. UPWARDS ARROW LEFTWARDS OF DOWNWARDS ARROW
+.. |udhar| unicode:: U+0296E .. UPWARDS HARPOON WITH BARB LEFT BESIDE DOWNWARDS HARPOON WITH BARB RIGHT
+.. |ufisht| unicode:: U+0297E .. UP FISH TAIL
+.. |uHar| unicode:: U+02963 .. UPWARDS HARPOON WITH BARB LEFT BESIDE UPWARDS HARPOON WITH BARB RIGHT
+.. |uharl| unicode:: U+021BF .. UPWARDS HARPOON WITH BARB LEFTWARDS
+.. |uharr| unicode:: U+021BE .. UPWARDS HARPOON WITH BARB RIGHTWARDS
+.. |uuarr| unicode:: U+021C8 .. UPWARDS PAIRED ARROWS
+.. |vArr| unicode:: U+021D5 .. UP DOWN DOUBLE ARROW
+.. |varr| unicode:: U+02195 .. UP DOWN ARROW
+.. |xhArr| unicode:: U+027FA .. LONG LEFT RIGHT DOUBLE ARROW
+.. |xharr| unicode:: U+027F7 .. LONG LEFT RIGHT ARROW
+.. |xlArr| unicode:: U+027F8 .. LONG LEFTWARDS DOUBLE ARROW
+.. |xlarr| unicode:: U+027F5 .. LONG LEFTWARDS ARROW
+.. |xmap| unicode:: U+027FC .. LONG RIGHTWARDS ARROW FROM BAR
+.. |xrArr| unicode:: U+027F9 .. LONG RIGHTWARDS DOUBLE ARROW
+.. |xrarr| unicode:: U+027F6 .. LONG RIGHTWARDS ARROW
+.. |zigrarr| unicode:: U+021DD .. RIGHTWARDS SQUIGGLE ARROW
--- /dev/null
+.. This data file has been placed in the public domain.
+.. Derived from the Unicode character mappings available from
+ <http://www.w3.org/2003/entities/xml/>.
+ Processed by unicode2rstsubs.py, part of Docutils:
+ <http://docutils.sourceforge.net>.
+
+.. |ac| unicode:: U+0223E .. INVERTED LAZY S
+.. |acE| unicode:: U+0223E U+00333 .. INVERTED LAZY S with double underline
+.. |amalg| unicode:: U+02A3F .. AMALGAMATION OR COPRODUCT
+.. |barvee| unicode:: U+022BD .. NOR
+.. |Barwed| unicode:: U+02306 .. PERSPECTIVE
+.. |barwed| unicode:: U+02305 .. PROJECTIVE
+.. |bsolb| unicode:: U+029C5 .. SQUARED FALLING DIAGONAL SLASH
+.. |Cap| unicode:: U+022D2 .. DOUBLE INTERSECTION
+.. |capand| unicode:: U+02A44 .. INTERSECTION WITH LOGICAL AND
+.. |capbrcup| unicode:: U+02A49 .. INTERSECTION ABOVE BAR ABOVE UNION
+.. |capcap| unicode:: U+02A4B .. INTERSECTION BESIDE AND JOINED WITH INTERSECTION
+.. |capcup| unicode:: U+02A47 .. INTERSECTION ABOVE UNION
+.. |capdot| unicode:: U+02A40 .. INTERSECTION WITH DOT
+.. |caps| unicode:: U+02229 U+0FE00 .. INTERSECTION with serifs
+.. |ccaps| unicode:: U+02A4D .. CLOSED INTERSECTION WITH SERIFS
+.. |ccups| unicode:: U+02A4C .. CLOSED UNION WITH SERIFS
+.. |ccupssm| unicode:: U+02A50 .. CLOSED UNION WITH SERIFS AND SMASH PRODUCT
+.. |coprod| unicode:: U+02210 .. N-ARY COPRODUCT
+.. |Cup| unicode:: U+022D3 .. DOUBLE UNION
+.. |cupbrcap| unicode:: U+02A48 .. UNION ABOVE BAR ABOVE INTERSECTION
+.. |cupcap| unicode:: U+02A46 .. UNION ABOVE INTERSECTION
+.. |cupcup| unicode:: U+02A4A .. UNION BESIDE AND JOINED WITH UNION
+.. |cupdot| unicode:: U+0228D .. MULTISET MULTIPLICATION
+.. |cupor| unicode:: U+02A45 .. UNION WITH LOGICAL OR
+.. |cups| unicode:: U+0222A U+0FE00 .. UNION with serifs
+.. |cuvee| unicode:: U+022CE .. CURLY LOGICAL OR
+.. |cuwed| unicode:: U+022CF .. CURLY LOGICAL AND
+.. |Dagger| unicode:: U+02021 .. DOUBLE DAGGER
+.. |dagger| unicode:: U+02020 .. DAGGER
+.. |diam| unicode:: U+022C4 .. DIAMOND OPERATOR
+.. |divonx| unicode:: U+022C7 .. DIVISION TIMES
+.. |eplus| unicode:: U+02A71 .. EQUALS SIGN ABOVE PLUS SIGN
+.. |hercon| unicode:: U+022B9 .. HERMITIAN CONJUGATE MATRIX
+.. |intcal| unicode:: U+022BA .. INTERCALATE
+.. |iprod| unicode:: U+02A3C .. INTERIOR PRODUCT
+.. |loplus| unicode:: U+02A2D .. PLUS SIGN IN LEFT HALF CIRCLE
+.. |lotimes| unicode:: U+02A34 .. MULTIPLICATION SIGN IN LEFT HALF CIRCLE
+.. |lthree| unicode:: U+022CB .. LEFT SEMIDIRECT PRODUCT
+.. |ltimes| unicode:: U+022C9 .. LEFT NORMAL FACTOR SEMIDIRECT PRODUCT
+.. |midast| unicode:: U+0002A .. ASTERISK
+.. |minusb| unicode:: U+0229F .. SQUARED MINUS
+.. |minusd| unicode:: U+02238 .. DOT MINUS
+.. |minusdu| unicode:: U+02A2A .. MINUS SIGN WITH DOT BELOW
+.. |ncap| unicode:: U+02A43 .. INTERSECTION WITH OVERBAR
+.. |ncup| unicode:: U+02A42 .. UNION WITH OVERBAR
+.. |oast| unicode:: U+0229B .. CIRCLED ASTERISK OPERATOR
+.. |ocir| unicode:: U+0229A .. CIRCLED RING OPERATOR
+.. |odash| unicode:: U+0229D .. CIRCLED DASH
+.. |odiv| unicode:: U+02A38 .. CIRCLED DIVISION SIGN
+.. |odot| unicode:: U+02299 .. CIRCLED DOT OPERATOR
+.. |odsold| unicode:: U+029BC .. CIRCLED ANTICLOCKWISE-ROTATED DIVISION SIGN
+.. |ofcir| unicode:: U+029BF .. CIRCLED BULLET
+.. |ogt| unicode:: U+029C1 .. CIRCLED GREATER-THAN
+.. |ohbar| unicode:: U+029B5 .. CIRCLE WITH HORIZONTAL BAR
+.. |olcir| unicode:: U+029BE .. CIRCLED WHITE BULLET
+.. |olt| unicode:: U+029C0 .. CIRCLED LESS-THAN
+.. |omid| unicode:: U+029B6 .. CIRCLED VERTICAL BAR
+.. |ominus| unicode:: U+02296 .. CIRCLED MINUS
+.. |opar| unicode:: U+029B7 .. CIRCLED PARALLEL
+.. |operp| unicode:: U+029B9 .. CIRCLED PERPENDICULAR
+.. |oplus| unicode:: U+02295 .. CIRCLED PLUS
+.. |osol| unicode:: U+02298 .. CIRCLED DIVISION SLASH
+.. |Otimes| unicode:: U+02A37 .. MULTIPLICATION SIGN IN DOUBLE CIRCLE
+.. |otimes| unicode:: U+02297 .. CIRCLED TIMES
+.. |otimesas| unicode:: U+02A36 .. CIRCLED MULTIPLICATION SIGN WITH CIRCUMFLEX ACCENT
+.. |ovbar| unicode:: U+0233D .. APL FUNCTIONAL SYMBOL CIRCLE STILE
+.. |plusacir| unicode:: U+02A23 .. PLUS SIGN WITH CIRCUMFLEX ACCENT ABOVE
+.. |plusb| unicode:: U+0229E .. SQUARED PLUS
+.. |pluscir| unicode:: U+02A22 .. PLUS SIGN WITH SMALL CIRCLE ABOVE
+.. |plusdo| unicode:: U+02214 .. DOT PLUS
+.. |plusdu| unicode:: U+02A25 .. PLUS SIGN WITH DOT BELOW
+.. |pluse| unicode:: U+02A72 .. PLUS SIGN ABOVE EQUALS SIGN
+.. |plussim| unicode:: U+02A26 .. PLUS SIGN WITH TILDE BELOW
+.. |plustwo| unicode:: U+02A27 .. PLUS SIGN WITH SUBSCRIPT TWO
+.. |prod| unicode:: U+0220F .. N-ARY PRODUCT
+.. |race| unicode:: U+029DA .. LEFT DOUBLE WIGGLY FENCE
+.. |roplus| unicode:: U+02A2E .. PLUS SIGN IN RIGHT HALF CIRCLE
+.. |rotimes| unicode:: U+02A35 .. MULTIPLICATION SIGN IN RIGHT HALF CIRCLE
+.. |rthree| unicode:: U+022CC .. RIGHT SEMIDIRECT PRODUCT
+.. |rtimes| unicode:: U+022CA .. RIGHT NORMAL FACTOR SEMIDIRECT PRODUCT
+.. |sdot| unicode:: U+022C5 .. DOT OPERATOR
+.. |sdotb| unicode:: U+022A1 .. SQUARED DOT OPERATOR
+.. |setmn| unicode:: U+02216 .. SET MINUS
+.. |simplus| unicode:: U+02A24 .. PLUS SIGN WITH TILDE ABOVE
+.. |smashp| unicode:: U+02A33 .. SMASH PRODUCT
+.. |solb| unicode:: U+029C4 .. SQUARED RISING DIAGONAL SLASH
+.. |sqcap| unicode:: U+02293 .. SQUARE CAP
+.. |sqcaps| unicode:: U+02293 U+0FE00 .. SQUARE CAP with serifs
+.. |sqcup| unicode:: U+02294 .. SQUARE CUP
+.. |sqcups| unicode:: U+02294 U+0FE00 .. SQUARE CUP with serifs
+.. |ssetmn| unicode:: U+02216 .. SET MINUS
+.. |sstarf| unicode:: U+022C6 .. STAR OPERATOR
+.. |subdot| unicode:: U+02ABD .. SUBSET WITH DOT
+.. |sum| unicode:: U+02211 .. N-ARY SUMMATION
+.. |supdot| unicode:: U+02ABE .. SUPERSET WITH DOT
+.. |timesb| unicode:: U+022A0 .. SQUARED TIMES
+.. |timesbar| unicode:: U+02A31 .. MULTIPLICATION SIGN WITH UNDERBAR
+.. |timesd| unicode:: U+02A30 .. MULTIPLICATION SIGN WITH DOT ABOVE
+.. |top| unicode:: U+022A4 .. DOWN TACK
+.. |tridot| unicode:: U+025EC .. WHITE UP-POINTING TRIANGLE WITH DOT
+.. |triminus| unicode:: U+02A3A .. MINUS SIGN IN TRIANGLE
+.. |triplus| unicode:: U+02A39 .. PLUS SIGN IN TRIANGLE
+.. |trisb| unicode:: U+029CD .. TRIANGLE WITH SERIFS AT BOTTOM
+.. |tritime| unicode:: U+02A3B .. MULTIPLICATION SIGN IN TRIANGLE
+.. |uplus| unicode:: U+0228E .. MULTISET UNION
+.. |veebar| unicode:: U+022BB .. XOR
+.. |wedbar| unicode:: U+02A5F .. LOGICAL AND WITH UNDERBAR
+.. |wreath| unicode:: U+02240 .. WREATH PRODUCT
+.. |xcap| unicode:: U+022C2 .. N-ARY INTERSECTION
+.. |xcirc| unicode:: U+025EF .. LARGE CIRCLE
+.. |xcup| unicode:: U+022C3 .. N-ARY UNION
+.. |xdtri| unicode:: U+025BD .. WHITE DOWN-POINTING TRIANGLE
+.. |xodot| unicode:: U+02A00 .. N-ARY CIRCLED DOT OPERATOR
+.. |xoplus| unicode:: U+02A01 .. N-ARY CIRCLED PLUS OPERATOR
+.. |xotime| unicode:: U+02A02 .. N-ARY CIRCLED TIMES OPERATOR
+.. |xsqcup| unicode:: U+02A06 .. N-ARY SQUARE UNION OPERATOR
+.. |xuplus| unicode:: U+02A04 .. N-ARY UNION OPERATOR WITH PLUS
+.. |xutri| unicode:: U+025B3 .. WHITE UP-POINTING TRIANGLE
+.. |xvee| unicode:: U+022C1 .. N-ARY LOGICAL OR
+.. |xwedge| unicode:: U+022C0 .. N-ARY LOGICAL AND
--- /dev/null
+.. This data file has been placed in the public domain.
+.. Derived from the Unicode character mappings available from
+ <http://www.w3.org/2003/entities/xml/>.
+ Processed by unicode2rstsubs.py, part of Docutils:
+ <http://docutils.sourceforge.net>.
+
+.. |dlcorn| unicode:: U+0231E .. BOTTOM LEFT CORNER
+.. |drcorn| unicode:: U+0231F .. BOTTOM RIGHT CORNER
+.. |gtlPar| unicode:: U+02995 .. DOUBLE LEFT ARC GREATER-THAN BRACKET
+.. |langd| unicode:: U+02991 .. LEFT ANGLE BRACKET WITH DOT
+.. |lbrke| unicode:: U+0298B .. LEFT SQUARE BRACKET WITH UNDERBAR
+.. |lbrksld| unicode:: U+0298F .. LEFT SQUARE BRACKET WITH TICK IN BOTTOM CORNER
+.. |lbrkslu| unicode:: U+0298D .. LEFT SQUARE BRACKET WITH TICK IN TOP CORNER
+.. |lceil| unicode:: U+02308 .. LEFT CEILING
+.. |lfloor| unicode:: U+0230A .. LEFT FLOOR
+.. |lmoust| unicode:: U+023B0 .. UPPER LEFT OR LOWER RIGHT CURLY BRACKET SECTION
+.. |lpargt| unicode:: U+029A0 .. SPHERICAL ANGLE OPENING LEFT
+.. |lparlt| unicode:: U+02993 .. LEFT ARC LESS-THAN BRACKET
+.. |ltrPar| unicode:: U+02996 .. DOUBLE RIGHT ARC LESS-THAN BRACKET
+.. |rangd| unicode:: U+02992 .. RIGHT ANGLE BRACKET WITH DOT
+.. |rbrke| unicode:: U+0298C .. RIGHT SQUARE BRACKET WITH UNDERBAR
+.. |rbrksld| unicode:: U+0298E .. RIGHT SQUARE BRACKET WITH TICK IN BOTTOM CORNER
+.. |rbrkslu| unicode:: U+02990 .. RIGHT SQUARE BRACKET WITH TICK IN TOP CORNER
+.. |rceil| unicode:: U+02309 .. RIGHT CEILING
+.. |rfloor| unicode:: U+0230B .. RIGHT FLOOR
+.. |rmoust| unicode:: U+023B1 .. UPPER RIGHT OR LOWER LEFT CURLY BRACKET SECTION
+.. |rpargt| unicode:: U+02994 .. RIGHT ARC GREATER-THAN BRACKET
+.. |ulcorn| unicode:: U+0231C .. TOP LEFT CORNER
+.. |urcorn| unicode:: U+0231D .. TOP RIGHT CORNER
--- /dev/null
+.. This data file has been placed in the public domain.
+.. Derived from the Unicode character mappings available from
+ <http://www.w3.org/2003/entities/xml/>.
+ Processed by unicode2rstsubs.py, part of Docutils:
+ <http://docutils.sourceforge.net>.
+
+.. |gnap| unicode:: U+02A8A .. GREATER-THAN AND NOT APPROXIMATE
+.. |gnE| unicode:: U+02269 .. GREATER-THAN BUT NOT EQUAL TO
+.. |gne| unicode:: U+02A88 .. GREATER-THAN AND SINGLE-LINE NOT EQUAL TO
+.. |gnsim| unicode:: U+022E7 .. GREATER-THAN BUT NOT EQUIVALENT TO
+.. |gvnE| unicode:: U+02269 U+0FE00 .. GREATER-THAN BUT NOT EQUAL TO - with vertical stroke
+.. |lnap| unicode:: U+02A89 .. LESS-THAN AND NOT APPROXIMATE
+.. |lnE| unicode:: U+02268 .. LESS-THAN BUT NOT EQUAL TO
+.. |lne| unicode:: U+02A87 .. LESS-THAN AND SINGLE-LINE NOT EQUAL TO
+.. |lnsim| unicode:: U+022E6 .. LESS-THAN BUT NOT EQUIVALENT TO
+.. |lvnE| unicode:: U+02268 U+0FE00 .. LESS-THAN BUT NOT EQUAL TO - with vertical stroke
+.. |nap| unicode:: U+02249 .. NOT ALMOST EQUAL TO
+.. |napE| unicode:: U+02A70 U+00338 .. APPROXIMATELY EQUAL OR EQUAL TO with slash
+.. |napid| unicode:: U+0224B U+00338 .. TRIPLE TILDE with slash
+.. |ncong| unicode:: U+02247 .. NEITHER APPROXIMATELY NOR ACTUALLY EQUAL TO
+.. |ncongdot| unicode:: U+02A6D U+00338 .. CONGRUENT WITH DOT ABOVE with slash
+.. |nequiv| unicode:: U+02262 .. NOT IDENTICAL TO
+.. |ngE| unicode:: U+02267 U+00338 .. GREATER-THAN OVER EQUAL TO with slash
+.. |nge| unicode:: U+02271 .. NEITHER GREATER-THAN NOR EQUAL TO
+.. |nges| unicode:: U+02A7E U+00338 .. GREATER-THAN OR SLANTED EQUAL TO with slash
+.. |nGg| unicode:: U+022D9 U+00338 .. VERY MUCH GREATER-THAN with slash
+.. |ngsim| unicode:: U+02275 .. NEITHER GREATER-THAN NOR EQUIVALENT TO
+.. |nGt| unicode:: U+0226B U+020D2 .. MUCH GREATER THAN with vertical line
+.. |ngt| unicode:: U+0226F .. NOT GREATER-THAN
+.. |nGtv| unicode:: U+0226B U+00338 .. MUCH GREATER THAN with slash
+.. |nlE| unicode:: U+02266 U+00338 .. LESS-THAN OVER EQUAL TO with slash
+.. |nle| unicode:: U+02270 .. NEITHER LESS-THAN NOR EQUAL TO
+.. |nles| unicode:: U+02A7D U+00338 .. LESS-THAN OR SLANTED EQUAL TO with slash
+.. |nLl| unicode:: U+022D8 U+00338 .. VERY MUCH LESS-THAN with slash
+.. |nlsim| unicode:: U+02274 .. NEITHER LESS-THAN NOR EQUIVALENT TO
+.. |nLt| unicode:: U+0226A U+020D2 .. MUCH LESS THAN with vertical line
+.. |nlt| unicode:: U+0226E .. NOT LESS-THAN
+.. |nltri| unicode:: U+022EA .. NOT NORMAL SUBGROUP OF
+.. |nltrie| unicode:: U+022EC .. NOT NORMAL SUBGROUP OF OR EQUAL TO
+.. |nLtv| unicode:: U+0226A U+00338 .. MUCH LESS THAN with slash
+.. |nmid| unicode:: U+02224 .. DOES NOT DIVIDE
+.. |npar| unicode:: U+02226 .. NOT PARALLEL TO
+.. |npr| unicode:: U+02280 .. DOES NOT PRECEDE
+.. |nprcue| unicode:: U+022E0 .. DOES NOT PRECEDE OR EQUAL
+.. |npre| unicode:: U+02AAF U+00338 .. PRECEDES ABOVE SINGLE-LINE EQUALS SIGN with slash
+.. |nrtri| unicode:: U+022EB .. DOES NOT CONTAIN AS NORMAL SUBGROUP
+.. |nrtrie| unicode:: U+022ED .. DOES NOT CONTAIN AS NORMAL SUBGROUP OR EQUAL
+.. |nsc| unicode:: U+02281 .. DOES NOT SUCCEED
+.. |nsccue| unicode:: U+022E1 .. DOES NOT SUCCEED OR EQUAL
+.. |nsce| unicode:: U+02AB0 U+00338 .. SUCCEEDS ABOVE SINGLE-LINE EQUALS SIGN with slash
+.. |nsim| unicode:: U+02241 .. NOT TILDE
+.. |nsime| unicode:: U+02244 .. NOT ASYMPTOTICALLY EQUAL TO
+.. |nsmid| unicode:: U+02224 .. DOES NOT DIVIDE
+.. |nspar| unicode:: U+02226 .. NOT PARALLEL TO
+.. |nsqsube| unicode:: U+022E2 .. NOT SQUARE IMAGE OF OR EQUAL TO
+.. |nsqsupe| unicode:: U+022E3 .. NOT SQUARE ORIGINAL OF OR EQUAL TO
+.. |nsub| unicode:: U+02284 .. NOT A SUBSET OF
+.. |nsubE| unicode:: U+02AC5 U+00338 .. SUBSET OF ABOVE EQUALS SIGN with slash
+.. |nsube| unicode:: U+02288 .. NEITHER A SUBSET OF NOR EQUAL TO
+.. |nsup| unicode:: U+02285 .. NOT A SUPERSET OF
+.. |nsupE| unicode:: U+02AC6 U+00338 .. SUPERSET OF ABOVE EQUALS SIGN with slash
+.. |nsupe| unicode:: U+02289 .. NEITHER A SUPERSET OF NOR EQUAL TO
+.. |ntgl| unicode:: U+02279 .. NEITHER GREATER-THAN NOR LESS-THAN
+.. |ntlg| unicode:: U+02278 .. NEITHER LESS-THAN NOR GREATER-THAN
+.. |nvap| unicode:: U+0224D U+020D2 .. EQUIVALENT TO with vertical line
+.. |nVDash| unicode:: U+022AF .. NEGATED DOUBLE VERTICAL BAR DOUBLE RIGHT TURNSTILE
+.. |nVdash| unicode:: U+022AE .. DOES NOT FORCE
+.. |nvDash| unicode:: U+022AD .. NOT TRUE
+.. |nvdash| unicode:: U+022AC .. DOES NOT PROVE
+.. |nvge| unicode:: U+02265 U+020D2 .. GREATER-THAN OR EQUAL TO with vertical line
+.. |nvgt| unicode:: U+0003E U+020D2 .. GREATER-THAN SIGN with vertical line
+.. |nvle| unicode:: U+02264 U+020D2 .. LESS-THAN OR EQUAL TO with vertical line
+.. |nvlt| unicode:: U+0003C U+020D2 .. LESS-THAN SIGN with vertical line
+.. |nvltrie| unicode:: U+022B4 U+020D2 .. NORMAL SUBGROUP OF OR EQUAL TO with vertical line
+.. |nvrtrie| unicode:: U+022B5 U+020D2 .. CONTAINS AS NORMAL SUBGROUP OR EQUAL TO with vertical line
+.. |nvsim| unicode:: U+0223C U+020D2 .. TILDE OPERATOR with vertical line
+.. |parsim| unicode:: U+02AF3 .. PARALLEL WITH TILDE OPERATOR
+.. |prnap| unicode:: U+02AB9 .. PRECEDES ABOVE NOT ALMOST EQUAL TO
+.. |prnE| unicode:: U+02AB5 .. PRECEDES ABOVE NOT EQUAL TO
+.. |prnsim| unicode:: U+022E8 .. PRECEDES BUT NOT EQUIVALENT TO
+.. |rnmid| unicode:: U+02AEE .. DOES NOT DIVIDE WITH REVERSED NEGATION SLASH
+.. |scnap| unicode:: U+02ABA .. SUCCEEDS ABOVE NOT ALMOST EQUAL TO
+.. |scnE| unicode:: U+02AB6 .. SUCCEEDS ABOVE NOT EQUAL TO
+.. |scnsim| unicode:: U+022E9 .. SUCCEEDS BUT NOT EQUIVALENT TO
+.. |simne| unicode:: U+02246 .. APPROXIMATELY BUT NOT ACTUALLY EQUAL TO
+.. |solbar| unicode:: U+0233F .. APL FUNCTIONAL SYMBOL SLASH BAR
+.. |subnE| unicode:: U+02ACB .. SUBSET OF ABOVE NOT EQUAL TO
+.. |subne| unicode:: U+0228A .. SUBSET OF WITH NOT EQUAL TO
+.. |supnE| unicode:: U+02ACC .. SUPERSET OF ABOVE NOT EQUAL TO
+.. |supne| unicode:: U+0228B .. SUPERSET OF WITH NOT EQUAL TO
+.. |vnsub| unicode:: U+02282 U+020D2 .. SUBSET OF with vertical line
+.. |vnsup| unicode:: U+02283 U+020D2 .. SUPERSET OF with vertical line
+.. |vsubnE| unicode:: U+02ACB U+0FE00 .. SUBSET OF ABOVE NOT EQUAL TO - variant with stroke through bottom members
+.. |vsubne| unicode:: U+0228A U+0FE00 .. SUBSET OF WITH NOT EQUAL TO - variant with stroke through bottom members
+.. |vsupnE| unicode:: U+02ACC U+0FE00 .. SUPERSET OF ABOVE NOT EQUAL TO - variant with stroke through bottom members
+.. |vsupne| unicode:: U+0228B U+0FE00 .. SUPERSET OF WITH NOT EQUAL TO - variant with stroke through bottom members
--- /dev/null
+.. This data file has been placed in the public domain.
+.. Derived from the Unicode character mappings available from
+ <http://www.w3.org/2003/entities/xml/>.
+ Processed by unicode2rstsubs.py, part of Docutils:
+ <http://docutils.sourceforge.net>.
+
+.. |ang| unicode:: U+02220 .. ANGLE
+.. |ange| unicode:: U+029A4 .. ANGLE WITH UNDERBAR
+.. |angmsd| unicode:: U+02221 .. MEASURED ANGLE
+.. |angmsdaa| unicode:: U+029A8 .. MEASURED ANGLE WITH OPEN ARM ENDING IN ARROW POINTING UP AND RIGHT
+.. |angmsdab| unicode:: U+029A9 .. MEASURED ANGLE WITH OPEN ARM ENDING IN ARROW POINTING UP AND LEFT
+.. |angmsdac| unicode:: U+029AA .. MEASURED ANGLE WITH OPEN ARM ENDING IN ARROW POINTING DOWN AND RIGHT
+.. |angmsdad| unicode:: U+029AB .. MEASURED ANGLE WITH OPEN ARM ENDING IN ARROW POINTING DOWN AND LEFT
+.. |angmsdae| unicode:: U+029AC .. MEASURED ANGLE WITH OPEN ARM ENDING IN ARROW POINTING RIGHT AND UP
+.. |angmsdaf| unicode:: U+029AD .. MEASURED ANGLE WITH OPEN ARM ENDING IN ARROW POINTING LEFT AND UP
+.. |angmsdag| unicode:: U+029AE .. MEASURED ANGLE WITH OPEN ARM ENDING IN ARROW POINTING RIGHT AND DOWN
+.. |angmsdah| unicode:: U+029AF .. MEASURED ANGLE WITH OPEN ARM ENDING IN ARROW POINTING LEFT AND DOWN
+.. |angrtvb| unicode:: U+022BE .. RIGHT ANGLE WITH ARC
+.. |angrtvbd| unicode:: U+0299D .. MEASURED RIGHT ANGLE WITH DOT
+.. |bbrk| unicode:: U+023B5 .. BOTTOM SQUARE BRACKET
+.. |bbrktbrk| unicode:: U+023B6 .. BOTTOM SQUARE BRACKET OVER TOP SQUARE BRACKET
+.. |bemptyv| unicode:: U+029B0 .. REVERSED EMPTY SET
+.. |beth| unicode:: U+02136 .. BET SYMBOL
+.. |boxbox| unicode:: U+029C9 .. TWO JOINED SQUARES
+.. |bprime| unicode:: U+02035 .. REVERSED PRIME
+.. |bsemi| unicode:: U+0204F .. REVERSED SEMICOLON
+.. |cemptyv| unicode:: U+029B2 .. EMPTY SET WITH SMALL CIRCLE ABOVE
+.. |cirE| unicode:: U+029C3 .. CIRCLE WITH TWO HORIZONTAL STROKES TO THE RIGHT
+.. |cirscir| unicode:: U+029C2 .. CIRCLE WITH SMALL CIRCLE TO THE RIGHT
+.. |comp| unicode:: U+02201 .. COMPLEMENT
+.. |daleth| unicode:: U+02138 .. DALET SYMBOL
+.. |demptyv| unicode:: U+029B1 .. EMPTY SET WITH OVERBAR
+.. |ell| unicode:: U+02113 .. SCRIPT SMALL L
+.. |empty| unicode:: U+02205 .. EMPTY SET
+.. |emptyv| unicode:: U+02205 .. EMPTY SET
+.. |gimel| unicode:: U+02137 .. GIMEL SYMBOL
+.. |iiota| unicode:: U+02129 .. TURNED GREEK SMALL LETTER IOTA
+.. |image| unicode:: U+02111 .. BLACK-LETTER CAPITAL I
+.. |imath| unicode:: U+00131 .. LATIN SMALL LETTER DOTLESS I
+.. |inodot| unicode:: U+00131 .. LATIN SMALL LETTER DOTLESS I
+.. |jmath| unicode:: U+0006A .. LATIN SMALL LETTER J
+.. |jnodot| unicode:: U+0006A .. LATIN SMALL LETTER J
+.. |laemptyv| unicode:: U+029B4 .. EMPTY SET WITH LEFT ARROW ABOVE
+.. |lltri| unicode:: U+025FA .. LOWER LEFT TRIANGLE
+.. |lrtri| unicode:: U+022BF .. RIGHT TRIANGLE
+.. |mho| unicode:: U+02127 .. INVERTED OHM SIGN
+.. |nang| unicode:: U+02220 U+020D2 .. ANGLE with vertical line
+.. |nexist| unicode:: U+02204 .. THERE DOES NOT EXIST
+.. |oS| unicode:: U+024C8 .. CIRCLED LATIN CAPITAL LETTER S
+.. |planck| unicode:: U+0210F .. PLANCK CONSTANT OVER TWO PI
+.. |plankv| unicode:: U+0210F .. PLANCK CONSTANT OVER TWO PI
+.. |raemptyv| unicode:: U+029B3 .. EMPTY SET WITH RIGHT ARROW ABOVE
+.. |range| unicode:: U+029A5 .. REVERSED ANGLE WITH UNDERBAR
+.. |real| unicode:: U+0211C .. BLACK-LETTER CAPITAL R
+.. |sbsol| unicode:: U+0FE68 .. SMALL REVERSE SOLIDUS
+.. |tbrk| unicode:: U+023B4 .. TOP SQUARE BRACKET
+.. |trpezium| unicode:: U+0FFFD .. REPLACEMENT CHARACTER
+.. |ultri| unicode:: U+025F8 .. UPPER LEFT TRIANGLE
+.. |urtri| unicode:: U+025F9 .. UPPER RIGHT TRIANGLE
+.. |vprime| unicode:: U+02032 .. PRIME
+.. |vzigzag| unicode:: U+0299A .. VERTICAL ZIGZAG LINE
+.. |weierp| unicode:: U+02118 .. SCRIPT CAPITAL P
--- /dev/null
+.. This data file has been placed in the public domain.
+.. Derived from the Unicode character mappings available from
+ <http://www.w3.org/2003/entities/xml/>.
+ Processed by unicode2rstsubs.py, part of Docutils:
+ <http://docutils.sourceforge.net>.
+
+.. |apE| unicode:: U+02A70 .. APPROXIMATELY EQUAL OR EQUAL TO
+.. |ape| unicode:: U+0224A .. ALMOST EQUAL OR EQUAL TO
+.. |apid| unicode:: U+0224B .. TRIPLE TILDE
+.. |asymp| unicode:: U+02248 .. ALMOST EQUAL TO
+.. |Barv| unicode:: U+02AE7 .. SHORT DOWN TACK WITH OVERBAR
+.. |bcong| unicode:: U+0224C .. ALL EQUAL TO
+.. |bepsi| unicode:: U+003F6 .. GREEK REVERSED LUNATE EPSILON SYMBOL
+.. |bowtie| unicode:: U+022C8 .. BOWTIE
+.. |bsim| unicode:: U+0223D .. REVERSED TILDE
+.. |bsime| unicode:: U+022CD .. REVERSED TILDE EQUALS
+.. |bsolhsub| unicode:: U+0005C U+02282 .. REVERSE SOLIDUS, SUBSET OF
+.. |bump| unicode:: U+0224E .. GEOMETRICALLY EQUIVALENT TO
+.. |bumpE| unicode:: U+02AAE .. EQUALS SIGN WITH BUMPY ABOVE
+.. |bumpe| unicode:: U+0224F .. DIFFERENCE BETWEEN
+.. |cire| unicode:: U+02257 .. RING EQUAL TO
+.. |Colon| unicode:: U+02237 .. PROPORTION
+.. |Colone| unicode:: U+02A74 .. DOUBLE COLON EQUAL
+.. |colone| unicode:: U+02254 .. COLON EQUALS
+.. |congdot| unicode:: U+02A6D .. CONGRUENT WITH DOT ABOVE
+.. |csub| unicode:: U+02ACF .. CLOSED SUBSET
+.. |csube| unicode:: U+02AD1 .. CLOSED SUBSET OR EQUAL TO
+.. |csup| unicode:: U+02AD0 .. CLOSED SUPERSET
+.. |csupe| unicode:: U+02AD2 .. CLOSED SUPERSET OR EQUAL TO
+.. |cuepr| unicode:: U+022DE .. EQUAL TO OR PRECEDES
+.. |cuesc| unicode:: U+022DF .. EQUAL TO OR SUCCEEDS
+.. |cupre| unicode:: U+0227C .. PRECEDES OR EQUAL TO
+.. |Dashv| unicode:: U+02AE4 .. VERTICAL BAR DOUBLE LEFT TURNSTILE
+.. |dashv| unicode:: U+022A3 .. LEFT TACK
+.. |easter| unicode:: U+02A6E .. EQUALS WITH ASTERISK
+.. |ecir| unicode:: U+02256 .. RING IN EQUAL TO
+.. |ecolon| unicode:: U+02255 .. EQUALS COLON
+.. |eDDot| unicode:: U+02A77 .. EQUALS SIGN WITH TWO DOTS ABOVE AND TWO DOTS BELOW
+.. |eDot| unicode:: U+02251 .. GEOMETRICALLY EQUAL TO
+.. |efDot| unicode:: U+02252 .. APPROXIMATELY EQUAL TO OR THE IMAGE OF
+.. |eg| unicode:: U+02A9A .. DOUBLE-LINE EQUAL TO OR GREATER-THAN
+.. |egs| unicode:: U+02A96 .. SLANTED EQUAL TO OR GREATER-THAN
+.. |egsdot| unicode:: U+02A98 .. SLANTED EQUAL TO OR GREATER-THAN WITH DOT INSIDE
+.. |el| unicode:: U+02A99 .. DOUBLE-LINE EQUAL TO OR LESS-THAN
+.. |els| unicode:: U+02A95 .. SLANTED EQUAL TO OR LESS-THAN
+.. |elsdot| unicode:: U+02A97 .. SLANTED EQUAL TO OR LESS-THAN WITH DOT INSIDE
+.. |equest| unicode:: U+0225F .. QUESTIONED EQUAL TO
+.. |equivDD| unicode:: U+02A78 .. EQUIVALENT WITH FOUR DOTS ABOVE
+.. |erDot| unicode:: U+02253 .. IMAGE OF OR APPROXIMATELY EQUAL TO
+.. |esdot| unicode:: U+02250 .. APPROACHES THE LIMIT
+.. |Esim| unicode:: U+02A73 .. EQUALS SIGN ABOVE TILDE OPERATOR
+.. |esim| unicode:: U+02242 .. MINUS TILDE
+.. |fork| unicode:: U+022D4 .. PITCHFORK
+.. |forkv| unicode:: U+02AD9 .. ELEMENT OF OPENING DOWNWARDS
+.. |frown| unicode:: U+02322 .. FROWN
+.. |gap| unicode:: U+02A86 .. GREATER-THAN OR APPROXIMATE
+.. |gE| unicode:: U+02267 .. GREATER-THAN OVER EQUAL TO
+.. |gEl| unicode:: U+02A8C .. GREATER-THAN ABOVE DOUBLE-LINE EQUAL ABOVE LESS-THAN
+.. |gel| unicode:: U+022DB .. GREATER-THAN EQUAL TO OR LESS-THAN
+.. |ges| unicode:: U+02A7E .. GREATER-THAN OR SLANTED EQUAL TO
+.. |gescc| unicode:: U+02AA9 .. GREATER-THAN CLOSED BY CURVE ABOVE SLANTED EQUAL
+.. |gesdot| unicode:: U+02A80 .. GREATER-THAN OR SLANTED EQUAL TO WITH DOT INSIDE
+.. |gesdoto| unicode:: U+02A82 .. GREATER-THAN OR SLANTED EQUAL TO WITH DOT ABOVE
+.. |gesdotol| unicode:: U+02A84 .. GREATER-THAN OR SLANTED EQUAL TO WITH DOT ABOVE LEFT
+.. |gesl| unicode:: U+022DB U+0FE00 .. GREATER-THAN slanted EQUAL TO OR LESS-THAN
+.. |gesles| unicode:: U+02A94 .. GREATER-THAN ABOVE SLANTED EQUAL ABOVE LESS-THAN ABOVE SLANTED EQUAL
+.. |Gg| unicode:: U+022D9 .. VERY MUCH GREATER-THAN
+.. |gl| unicode:: U+02277 .. GREATER-THAN OR LESS-THAN
+.. |gla| unicode:: U+02AA5 .. GREATER-THAN BESIDE LESS-THAN
+.. |glE| unicode:: U+02A92 .. GREATER-THAN ABOVE LESS-THAN ABOVE DOUBLE-LINE EQUAL
+.. |glj| unicode:: U+02AA4 .. GREATER-THAN OVERLAPPING LESS-THAN
+.. |gsdot| unicode:: U+022D7 .. GREATER-THAN WITH DOT
+.. |gsim| unicode:: U+02273 .. GREATER-THAN OR EQUIVALENT TO
+.. |gsime| unicode:: U+02A8E .. GREATER-THAN ABOVE SIMILAR OR EQUAL
+.. |gsiml| unicode:: U+02A90 .. GREATER-THAN ABOVE SIMILAR ABOVE LESS-THAN
+.. |Gt| unicode:: U+0226B .. MUCH GREATER-THAN
+.. |gtcc| unicode:: U+02AA7 .. GREATER-THAN CLOSED BY CURVE
+.. |gtcir| unicode:: U+02A7A .. GREATER-THAN WITH CIRCLE INSIDE
+.. |gtdot| unicode:: U+022D7 .. GREATER-THAN WITH DOT
+.. |gtquest| unicode:: U+02A7C .. GREATER-THAN WITH QUESTION MARK ABOVE
+.. |gtrarr| unicode:: U+02978 .. GREATER-THAN ABOVE RIGHTWARDS ARROW
+.. |homtht| unicode:: U+0223B .. HOMOTHETIC
+.. |lap| unicode:: U+02A85 .. LESS-THAN OR APPROXIMATE
+.. |lat| unicode:: U+02AAB .. LARGER THAN
+.. |late| unicode:: U+02AAD .. LARGER THAN OR EQUAL TO
+.. |lates| unicode:: U+02AAD U+0FE00 .. LARGER THAN OR slanted EQUAL
+.. |ldot| unicode:: U+022D6 .. LESS-THAN WITH DOT
+.. |lE| unicode:: U+02266 .. LESS-THAN OVER EQUAL TO
+.. |lEg| unicode:: U+02A8B .. LESS-THAN ABOVE DOUBLE-LINE EQUAL ABOVE GREATER-THAN
+.. |leg| unicode:: U+022DA .. LESS-THAN EQUAL TO OR GREATER-THAN
+.. |les| unicode:: U+02A7D .. LESS-THAN OR SLANTED EQUAL TO
+.. |lescc| unicode:: U+02AA8 .. LESS-THAN CLOSED BY CURVE ABOVE SLANTED EQUAL
+.. |lesdot| unicode:: U+02A7F .. LESS-THAN OR SLANTED EQUAL TO WITH DOT INSIDE
+.. |lesdoto| unicode:: U+02A81 .. LESS-THAN OR SLANTED EQUAL TO WITH DOT ABOVE
+.. |lesdotor| unicode:: U+02A83 .. LESS-THAN OR SLANTED EQUAL TO WITH DOT ABOVE RIGHT
+.. |lesg| unicode:: U+022DA U+0FE00 .. LESS-THAN slanted EQUAL TO OR GREATER-THAN
+.. |lesges| unicode:: U+02A93 .. LESS-THAN ABOVE SLANTED EQUAL ABOVE GREATER-THAN ABOVE SLANTED EQUAL
+.. |lg| unicode:: U+02276 .. LESS-THAN OR GREATER-THAN
+.. |lgE| unicode:: U+02A91 .. LESS-THAN ABOVE GREATER-THAN ABOVE DOUBLE-LINE EQUAL
+.. |Ll| unicode:: U+022D8 .. VERY MUCH LESS-THAN
+.. |lsim| unicode:: U+02272 .. LESS-THAN OR EQUIVALENT TO
+.. |lsime| unicode:: U+02A8D .. LESS-THAN ABOVE SIMILAR OR EQUAL
+.. |lsimg| unicode:: U+02A8F .. LESS-THAN ABOVE SIMILAR ABOVE GREATER-THAN
+.. |Lt| unicode:: U+0226A .. MUCH LESS-THAN
+.. |ltcc| unicode:: U+02AA6 .. LESS-THAN CLOSED BY CURVE
+.. |ltcir| unicode:: U+02A79 .. LESS-THAN WITH CIRCLE INSIDE
+.. |ltdot| unicode:: U+022D6 .. LESS-THAN WITH DOT
+.. |ltlarr| unicode:: U+02976 .. LESS-THAN ABOVE LEFTWARDS ARROW
+.. |ltquest| unicode:: U+02A7B .. LESS-THAN WITH QUESTION MARK ABOVE
+.. |ltrie| unicode:: U+022B4 .. NORMAL SUBGROUP OF OR EQUAL TO
+.. |mcomma| unicode:: U+02A29 .. MINUS SIGN WITH COMMA ABOVE
+.. |mDDot| unicode:: U+0223A .. GEOMETRIC PROPORTION
+.. |mid| unicode:: U+02223 .. DIVIDES
+.. |mlcp| unicode:: U+02ADB .. TRANSVERSAL INTERSECTION
+.. |models| unicode:: U+022A7 .. MODELS
+.. |mstpos| unicode:: U+0223E .. INVERTED LAZY S
+.. |Pr| unicode:: U+02ABB .. DOUBLE PRECEDES
+.. |pr| unicode:: U+0227A .. PRECEDES
+.. |prap| unicode:: U+02AB7 .. PRECEDES ABOVE ALMOST EQUAL TO
+.. |prcue| unicode:: U+0227C .. PRECEDES OR EQUAL TO
+.. |prE| unicode:: U+02AB3 .. PRECEDES ABOVE EQUALS SIGN
+.. |pre| unicode:: U+02AAF .. PRECEDES ABOVE SINGLE-LINE EQUALS SIGN
+.. |prsim| unicode:: U+0227E .. PRECEDES OR EQUIVALENT TO
+.. |prurel| unicode:: U+022B0 .. PRECEDES UNDER RELATION
+.. |ratio| unicode:: U+02236 .. RATIO
+.. |rtrie| unicode:: U+022B5 .. CONTAINS AS NORMAL SUBGROUP OR EQUAL TO
+.. |rtriltri| unicode:: U+029CE .. RIGHT TRIANGLE ABOVE LEFT TRIANGLE
+.. |samalg| unicode:: U+02210 .. N-ARY COPRODUCT
+.. |Sc| unicode:: U+02ABC .. DOUBLE SUCCEEDS
+.. |sc| unicode:: U+0227B .. SUCCEEDS
+.. |scap| unicode:: U+02AB8 .. SUCCEEDS ABOVE ALMOST EQUAL TO
+.. |sccue| unicode:: U+0227D .. SUCCEEDS OR EQUAL TO
+.. |scE| unicode:: U+02AB4 .. SUCCEEDS ABOVE EQUALS SIGN
+.. |sce| unicode:: U+02AB0 .. SUCCEEDS ABOVE SINGLE-LINE EQUALS SIGN
+.. |scsim| unicode:: U+0227F .. SUCCEEDS OR EQUIVALENT TO
+.. |sdote| unicode:: U+02A66 .. EQUALS SIGN WITH DOT BELOW
+.. |sfrown| unicode:: U+02322 .. FROWN
+.. |simg| unicode:: U+02A9E .. SIMILAR OR GREATER-THAN
+.. |simgE| unicode:: U+02AA0 .. SIMILAR ABOVE GREATER-THAN ABOVE EQUALS SIGN
+.. |siml| unicode:: U+02A9D .. SIMILAR OR LESS-THAN
+.. |simlE| unicode:: U+02A9F .. SIMILAR ABOVE LESS-THAN ABOVE EQUALS SIGN
+.. |smid| unicode:: U+02223 .. DIVIDES
+.. |smile| unicode:: U+02323 .. SMILE
+.. |smt| unicode:: U+02AAA .. SMALLER THAN
+.. |smte| unicode:: U+02AAC .. SMALLER THAN OR EQUAL TO
+.. |smtes| unicode:: U+02AAC U+0FE00 .. SMALLER THAN OR slanted EQUAL
+.. |spar| unicode:: U+02225 .. PARALLEL TO
+.. |sqsub| unicode:: U+0228F .. SQUARE IMAGE OF
+.. |sqsube| unicode:: U+02291 .. SQUARE IMAGE OF OR EQUAL TO
+.. |sqsup| unicode:: U+02290 .. SQUARE ORIGINAL OF
+.. |sqsupe| unicode:: U+02292 .. SQUARE ORIGINAL OF OR EQUAL TO
+.. |ssmile| unicode:: U+02323 .. SMILE
+.. |Sub| unicode:: U+022D0 .. DOUBLE SUBSET
+.. |subE| unicode:: U+02AC5 .. SUBSET OF ABOVE EQUALS SIGN
+.. |subedot| unicode:: U+02AC3 .. SUBSET OF OR EQUAL TO WITH DOT ABOVE
+.. |submult| unicode:: U+02AC1 .. SUBSET WITH MULTIPLICATION SIGN BELOW
+.. |subplus| unicode:: U+02ABF .. SUBSET WITH PLUS SIGN BELOW
+.. |subrarr| unicode:: U+02979 .. SUBSET ABOVE RIGHTWARDS ARROW
+.. |subsim| unicode:: U+02AC7 .. SUBSET OF ABOVE TILDE OPERATOR
+.. |subsub| unicode:: U+02AD5 .. SUBSET ABOVE SUBSET
+.. |subsup| unicode:: U+02AD3 .. SUBSET ABOVE SUPERSET
+.. |Sup| unicode:: U+022D1 .. DOUBLE SUPERSET
+.. |supdsub| unicode:: U+02AD8 .. SUPERSET BESIDE AND JOINED BY DASH WITH SUBSET
+.. |supE| unicode:: U+02AC6 .. SUPERSET OF ABOVE EQUALS SIGN
+.. |supedot| unicode:: U+02AC4 .. SUPERSET OF OR EQUAL TO WITH DOT ABOVE
+.. |suphsol| unicode:: U+02283 U+0002F .. SUPERSET OF, SOLIDUS
+.. |suphsub| unicode:: U+02AD7 .. SUPERSET BESIDE SUBSET
+.. |suplarr| unicode:: U+0297B .. SUPERSET ABOVE LEFTWARDS ARROW
+.. |supmult| unicode:: U+02AC2 .. SUPERSET WITH MULTIPLICATION SIGN BELOW
+.. |supplus| unicode:: U+02AC0 .. SUPERSET WITH PLUS SIGN BELOW
+.. |supsim| unicode:: U+02AC8 .. SUPERSET OF ABOVE TILDE OPERATOR
+.. |supsub| unicode:: U+02AD4 .. SUPERSET ABOVE SUBSET
+.. |supsup| unicode:: U+02AD6 .. SUPERSET ABOVE SUPERSET
+.. |thkap| unicode:: U+02248 .. ALMOST EQUAL TO
+.. |thksim| unicode:: U+0223C .. TILDE OPERATOR
+.. |topfork| unicode:: U+02ADA .. PITCHFORK WITH TEE TOP
+.. |trie| unicode:: U+0225C .. DELTA EQUAL TO
+.. |twixt| unicode:: U+0226C .. BETWEEN
+.. |Vbar| unicode:: U+02AEB .. DOUBLE UP TACK
+.. |vBar| unicode:: U+02AE8 .. SHORT UP TACK WITH UNDERBAR
+.. |vBarv| unicode:: U+02AE9 .. SHORT UP TACK ABOVE SHORT DOWN TACK
+.. |VDash| unicode:: U+022AB .. DOUBLE VERTICAL BAR DOUBLE RIGHT TURNSTILE
+.. |Vdash| unicode:: U+022A9 .. FORCES
+.. |vDash| unicode:: U+022A8 .. TRUE
+.. |vdash| unicode:: U+022A2 .. RIGHT TACK
+.. |Vdashl| unicode:: U+02AE6 .. LONG DASH FROM LEFT MEMBER OF DOUBLE VERTICAL
+.. |veebar| unicode:: U+022BB .. XOR
+.. |vltri| unicode:: U+022B2 .. NORMAL SUBGROUP OF
+.. |vprop| unicode:: U+0221D .. PROPORTIONAL TO
+.. |vrtri| unicode:: U+022B3 .. CONTAINS AS NORMAL SUBGROUP
+.. |Vvdash| unicode:: U+022AA .. TRIPLE VERTICAL BAR RIGHT TURNSTILE
--- /dev/null
+.. This data file has been placed in the public domain.
+.. Derived from the Unicode character mappings available from
+ <http://www.w3.org/2003/entities/xml/>.
+ Processed by unicode2rstsubs.py, part of Docutils:
+ <http://docutils.sourceforge.net>.
+
+.. |boxDL| unicode:: U+02557 .. BOX DRAWINGS DOUBLE DOWN AND LEFT
+.. |boxDl| unicode:: U+02556 .. BOX DRAWINGS DOWN DOUBLE AND LEFT SINGLE
+.. |boxdL| unicode:: U+02555 .. BOX DRAWINGS DOWN SINGLE AND LEFT DOUBLE
+.. |boxdl| unicode:: U+02510 .. BOX DRAWINGS LIGHT DOWN AND LEFT
+.. |boxDR| unicode:: U+02554 .. BOX DRAWINGS DOUBLE DOWN AND RIGHT
+.. |boxDr| unicode:: U+02553 .. BOX DRAWINGS DOWN DOUBLE AND RIGHT SINGLE
+.. |boxdR| unicode:: U+02552 .. BOX DRAWINGS DOWN SINGLE AND RIGHT DOUBLE
+.. |boxdr| unicode:: U+0250C .. BOX DRAWINGS LIGHT DOWN AND RIGHT
+.. |boxH| unicode:: U+02550 .. BOX DRAWINGS DOUBLE HORIZONTAL
+.. |boxh| unicode:: U+02500 .. BOX DRAWINGS LIGHT HORIZONTAL
+.. |boxHD| unicode:: U+02566 .. BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL
+.. |boxHd| unicode:: U+02564 .. BOX DRAWINGS DOWN SINGLE AND HORIZONTAL DOUBLE
+.. |boxhD| unicode:: U+02565 .. BOX DRAWINGS DOWN DOUBLE AND HORIZONTAL SINGLE
+.. |boxhd| unicode:: U+0252C .. BOX DRAWINGS LIGHT DOWN AND HORIZONTAL
+.. |boxHU| unicode:: U+02569 .. BOX DRAWINGS DOUBLE UP AND HORIZONTAL
+.. |boxHu| unicode:: U+02567 .. BOX DRAWINGS UP SINGLE AND HORIZONTAL DOUBLE
+.. |boxhU| unicode:: U+02568 .. BOX DRAWINGS UP DOUBLE AND HORIZONTAL SINGLE
+.. |boxhu| unicode:: U+02534 .. BOX DRAWINGS LIGHT UP AND HORIZONTAL
+.. |boxUL| unicode:: U+0255D .. BOX DRAWINGS DOUBLE UP AND LEFT
+.. |boxUl| unicode:: U+0255C .. BOX DRAWINGS UP DOUBLE AND LEFT SINGLE
+.. |boxuL| unicode:: U+0255B .. BOX DRAWINGS UP SINGLE AND LEFT DOUBLE
+.. |boxul| unicode:: U+02518 .. BOX DRAWINGS LIGHT UP AND LEFT
+.. |boxUR| unicode:: U+0255A .. BOX DRAWINGS DOUBLE UP AND RIGHT
+.. |boxUr| unicode:: U+02559 .. BOX DRAWINGS UP DOUBLE AND RIGHT SINGLE
+.. |boxuR| unicode:: U+02558 .. BOX DRAWINGS UP SINGLE AND RIGHT DOUBLE
+.. |boxur| unicode:: U+02514 .. BOX DRAWINGS LIGHT UP AND RIGHT
+.. |boxV| unicode:: U+02551 .. BOX DRAWINGS DOUBLE VERTICAL
+.. |boxv| unicode:: U+02502 .. BOX DRAWINGS LIGHT VERTICAL
+.. |boxVH| unicode:: U+0256C .. BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL
+.. |boxVh| unicode:: U+0256B .. BOX DRAWINGS VERTICAL DOUBLE AND HORIZONTAL SINGLE
+.. |boxvH| unicode:: U+0256A .. BOX DRAWINGS VERTICAL SINGLE AND HORIZONTAL DOUBLE
+.. |boxvh| unicode:: U+0253C .. BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL
+.. |boxVL| unicode:: U+02563 .. BOX DRAWINGS DOUBLE VERTICAL AND LEFT
+.. |boxVl| unicode:: U+02562 .. BOX DRAWINGS VERTICAL DOUBLE AND LEFT SINGLE
+.. |boxvL| unicode:: U+02561 .. BOX DRAWINGS VERTICAL SINGLE AND LEFT DOUBLE
+.. |boxvl| unicode:: U+02524 .. BOX DRAWINGS LIGHT VERTICAL AND LEFT
+.. |boxVR| unicode:: U+02560 .. BOX DRAWINGS DOUBLE VERTICAL AND RIGHT
+.. |boxVr| unicode:: U+0255F .. BOX DRAWINGS VERTICAL DOUBLE AND RIGHT SINGLE
+.. |boxvR| unicode:: U+0255E .. BOX DRAWINGS VERTICAL SINGLE AND RIGHT DOUBLE
+.. |boxvr| unicode:: U+0251C .. BOX DRAWINGS LIGHT VERTICAL AND RIGHT
--- /dev/null
+.. This data file has been placed in the public domain.
+.. Derived from the Unicode character mappings available from
+ <http://www.w3.org/2003/entities/xml/>.
+ Processed by unicode2rstsubs.py, part of Docutils:
+ <http://docutils.sourceforge.net>.
+
+.. |Acy| unicode:: U+00410 .. CYRILLIC CAPITAL LETTER A
+.. |acy| unicode:: U+00430 .. CYRILLIC SMALL LETTER A
+.. |Bcy| unicode:: U+00411 .. CYRILLIC CAPITAL LETTER BE
+.. |bcy| unicode:: U+00431 .. CYRILLIC SMALL LETTER BE
+.. |CHcy| unicode:: U+00427 .. CYRILLIC CAPITAL LETTER CHE
+.. |chcy| unicode:: U+00447 .. CYRILLIC SMALL LETTER CHE
+.. |Dcy| unicode:: U+00414 .. CYRILLIC CAPITAL LETTER DE
+.. |dcy| unicode:: U+00434 .. CYRILLIC SMALL LETTER DE
+.. |Ecy| unicode:: U+0042D .. CYRILLIC CAPITAL LETTER E
+.. |ecy| unicode:: U+0044D .. CYRILLIC SMALL LETTER E
+.. |Fcy| unicode:: U+00424 .. CYRILLIC CAPITAL LETTER EF
+.. |fcy| unicode:: U+00444 .. CYRILLIC SMALL LETTER EF
+.. |Gcy| unicode:: U+00413 .. CYRILLIC CAPITAL LETTER GHE
+.. |gcy| unicode:: U+00433 .. CYRILLIC SMALL LETTER GHE
+.. |HARDcy| unicode:: U+0042A .. CYRILLIC CAPITAL LETTER HARD SIGN
+.. |hardcy| unicode:: U+0044A .. CYRILLIC SMALL LETTER HARD SIGN
+.. |Icy| unicode:: U+00418 .. CYRILLIC CAPITAL LETTER I
+.. |icy| unicode:: U+00438 .. CYRILLIC SMALL LETTER I
+.. |IEcy| unicode:: U+00415 .. CYRILLIC CAPITAL LETTER IE
+.. |iecy| unicode:: U+00435 .. CYRILLIC SMALL LETTER IE
+.. |IOcy| unicode:: U+00401 .. CYRILLIC CAPITAL LETTER IO
+.. |iocy| unicode:: U+00451 .. CYRILLIC SMALL LETTER IO
+.. |Jcy| unicode:: U+00419 .. CYRILLIC CAPITAL LETTER SHORT I
+.. |jcy| unicode:: U+00439 .. CYRILLIC SMALL LETTER SHORT I
+.. |Kcy| unicode:: U+0041A .. CYRILLIC CAPITAL LETTER KA
+.. |kcy| unicode:: U+0043A .. CYRILLIC SMALL LETTER KA
+.. |KHcy| unicode:: U+00425 .. CYRILLIC CAPITAL LETTER HA
+.. |khcy| unicode:: U+00445 .. CYRILLIC SMALL LETTER HA
+.. |Lcy| unicode:: U+0041B .. CYRILLIC CAPITAL LETTER EL
+.. |lcy| unicode:: U+0043B .. CYRILLIC SMALL LETTER EL
+.. |Mcy| unicode:: U+0041C .. CYRILLIC CAPITAL LETTER EM
+.. |mcy| unicode:: U+0043C .. CYRILLIC SMALL LETTER EM
+.. |Ncy| unicode:: U+0041D .. CYRILLIC CAPITAL LETTER EN
+.. |ncy| unicode:: U+0043D .. CYRILLIC SMALL LETTER EN
+.. |numero| unicode:: U+02116 .. NUMERO SIGN
+.. |Ocy| unicode:: U+0041E .. CYRILLIC CAPITAL LETTER O
+.. |ocy| unicode:: U+0043E .. CYRILLIC SMALL LETTER O
+.. |Pcy| unicode:: U+0041F .. CYRILLIC CAPITAL LETTER PE
+.. |pcy| unicode:: U+0043F .. CYRILLIC SMALL LETTER PE
+.. |Rcy| unicode:: U+00420 .. CYRILLIC CAPITAL LETTER ER
+.. |rcy| unicode:: U+00440 .. CYRILLIC SMALL LETTER ER
+.. |Scy| unicode:: U+00421 .. CYRILLIC CAPITAL LETTER ES
+.. |scy| unicode:: U+00441 .. CYRILLIC SMALL LETTER ES
+.. |SHCHcy| unicode:: U+00429 .. CYRILLIC CAPITAL LETTER SHCHA
+.. |shchcy| unicode:: U+00449 .. CYRILLIC SMALL LETTER SHCHA
+.. |SHcy| unicode:: U+00428 .. CYRILLIC CAPITAL LETTER SHA
+.. |shcy| unicode:: U+00448 .. CYRILLIC SMALL LETTER SHA
+.. |SOFTcy| unicode:: U+0042C .. CYRILLIC CAPITAL LETTER SOFT SIGN
+.. |softcy| unicode:: U+0044C .. CYRILLIC SMALL LETTER SOFT SIGN
+.. |Tcy| unicode:: U+00422 .. CYRILLIC CAPITAL LETTER TE
+.. |tcy| unicode:: U+00442 .. CYRILLIC SMALL LETTER TE
+.. |TScy| unicode:: U+00426 .. CYRILLIC CAPITAL LETTER TSE
+.. |tscy| unicode:: U+00446 .. CYRILLIC SMALL LETTER TSE
+.. |Ucy| unicode:: U+00423 .. CYRILLIC CAPITAL LETTER U
+.. |ucy| unicode:: U+00443 .. CYRILLIC SMALL LETTER U
+.. |Vcy| unicode:: U+00412 .. CYRILLIC CAPITAL LETTER VE
+.. |vcy| unicode:: U+00432 .. CYRILLIC SMALL LETTER VE
+.. |YAcy| unicode:: U+0042F .. CYRILLIC CAPITAL LETTER YA
+.. |yacy| unicode:: U+0044F .. CYRILLIC SMALL LETTER YA
+.. |Ycy| unicode:: U+0042B .. CYRILLIC CAPITAL LETTER YERU
+.. |ycy| unicode:: U+0044B .. CYRILLIC SMALL LETTER YERU
+.. |YUcy| unicode:: U+0042E .. CYRILLIC CAPITAL LETTER YU
+.. |yucy| unicode:: U+0044E .. CYRILLIC SMALL LETTER YU
+.. |Zcy| unicode:: U+00417 .. CYRILLIC CAPITAL LETTER ZE
+.. |zcy| unicode:: U+00437 .. CYRILLIC SMALL LETTER ZE
+.. |ZHcy| unicode:: U+00416 .. CYRILLIC CAPITAL LETTER ZHE
+.. |zhcy| unicode:: U+00436 .. CYRILLIC SMALL LETTER ZHE
--- /dev/null
+.. This data file has been placed in the public domain.
+.. Derived from the Unicode character mappings available from
+ <http://www.w3.org/2003/entities/xml/>.
+ Processed by unicode2rstsubs.py, part of Docutils:
+ <http://docutils.sourceforge.net>.
+
+.. |DJcy| unicode:: U+00402 .. CYRILLIC CAPITAL LETTER DJE
+.. |djcy| unicode:: U+00452 .. CYRILLIC SMALL LETTER DJE
+.. |DScy| unicode:: U+00405 .. CYRILLIC CAPITAL LETTER DZE
+.. |dscy| unicode:: U+00455 .. CYRILLIC SMALL LETTER DZE
+.. |DZcy| unicode:: U+0040F .. CYRILLIC CAPITAL LETTER DZHE
+.. |dzcy| unicode:: U+0045F .. CYRILLIC SMALL LETTER DZHE
+.. |GJcy| unicode:: U+00403 .. CYRILLIC CAPITAL LETTER GJE
+.. |gjcy| unicode:: U+00453 .. CYRILLIC SMALL LETTER GJE
+.. |Iukcy| unicode:: U+00406 .. CYRILLIC CAPITAL LETTER BYELORUSSIAN-UKRAINIAN I
+.. |iukcy| unicode:: U+00456 .. CYRILLIC SMALL LETTER BYELORUSSIAN-UKRAINIAN I
+.. |Jsercy| unicode:: U+00408 .. CYRILLIC CAPITAL LETTER JE
+.. |jsercy| unicode:: U+00458 .. CYRILLIC SMALL LETTER JE
+.. |Jukcy| unicode:: U+00404 .. CYRILLIC CAPITAL LETTER UKRAINIAN IE
+.. |jukcy| unicode:: U+00454 .. CYRILLIC SMALL LETTER UKRAINIAN IE
+.. |KJcy| unicode:: U+0040C .. CYRILLIC CAPITAL LETTER KJE
+.. |kjcy| unicode:: U+0045C .. CYRILLIC SMALL LETTER KJE
+.. |LJcy| unicode:: U+00409 .. CYRILLIC CAPITAL LETTER LJE
+.. |ljcy| unicode:: U+00459 .. CYRILLIC SMALL LETTER LJE
+.. |NJcy| unicode:: U+0040A .. CYRILLIC CAPITAL LETTER NJE
+.. |njcy| unicode:: U+0045A .. CYRILLIC SMALL LETTER NJE
+.. |TSHcy| unicode:: U+0040B .. CYRILLIC CAPITAL LETTER TSHE
+.. |tshcy| unicode:: U+0045B .. CYRILLIC SMALL LETTER TSHE
+.. |Ubrcy| unicode:: U+0040E .. CYRILLIC CAPITAL LETTER SHORT U
+.. |ubrcy| unicode:: U+0045E .. CYRILLIC SMALL LETTER SHORT U
+.. |YIcy| unicode:: U+00407 .. CYRILLIC CAPITAL LETTER YI
+.. |yicy| unicode:: U+00457 .. CYRILLIC SMALL LETTER YI
--- /dev/null
+.. This data file has been placed in the public domain.
+.. Derived from the Unicode character mappings available from
+ <http://www.w3.org/2003/entities/xml/>.
+ Processed by unicode2rstsubs.py, part of Docutils:
+ <http://docutils.sourceforge.net>.
+
+.. |acute| unicode:: U+000B4 .. ACUTE ACCENT
+.. |breve| unicode:: U+002D8 .. BREVE
+.. |caron| unicode:: U+002C7 .. CARON
+.. |cedil| unicode:: U+000B8 .. CEDILLA
+.. |circ| unicode:: U+002C6 .. MODIFIER LETTER CIRCUMFLEX ACCENT
+.. |dblac| unicode:: U+002DD .. DOUBLE ACUTE ACCENT
+.. |die| unicode:: U+000A8 .. DIAERESIS
+.. |dot| unicode:: U+002D9 .. DOT ABOVE
+.. |grave| unicode:: U+00060 .. GRAVE ACCENT
+.. |macr| unicode:: U+000AF .. MACRON
+.. |ogon| unicode:: U+002DB .. OGONEK
+.. |ring| unicode:: U+002DA .. RING ABOVE
+.. |tilde| unicode:: U+002DC .. SMALL TILDE
+.. |uml| unicode:: U+000A8 .. DIAERESIS
--- /dev/null
+.. This data file has been placed in the public domain.
+.. Derived from the Unicode character mappings available from
+ <http://www.w3.org/2003/entities/xml/>.
+ Processed by unicode2rstsubs.py, part of Docutils:
+ <http://docutils.sourceforge.net>.
+
+.. |Agr| unicode:: U+00391 .. GREEK CAPITAL LETTER ALPHA
+.. |agr| unicode:: U+003B1 .. GREEK SMALL LETTER ALPHA
+.. |Bgr| unicode:: U+00392 .. GREEK CAPITAL LETTER BETA
+.. |bgr| unicode:: U+003B2 .. GREEK SMALL LETTER BETA
+.. |Dgr| unicode:: U+00394 .. GREEK CAPITAL LETTER DELTA
+.. |dgr| unicode:: U+003B4 .. GREEK SMALL LETTER DELTA
+.. |EEgr| unicode:: U+00397 .. GREEK CAPITAL LETTER ETA
+.. |eegr| unicode:: U+003B7 .. GREEK SMALL LETTER ETA
+.. |Egr| unicode:: U+00395 .. GREEK CAPITAL LETTER EPSILON
+.. |egr| unicode:: U+003B5 .. GREEK SMALL LETTER EPSILON
+.. |Ggr| unicode:: U+00393 .. GREEK CAPITAL LETTER GAMMA
+.. |ggr| unicode:: U+003B3 .. GREEK SMALL LETTER GAMMA
+.. |Igr| unicode:: U+00399 .. GREEK CAPITAL LETTER IOTA
+.. |igr| unicode:: U+003B9 .. GREEK SMALL LETTER IOTA
+.. |Kgr| unicode:: U+0039A .. GREEK CAPITAL LETTER KAPPA
+.. |kgr| unicode:: U+003BA .. GREEK SMALL LETTER KAPPA
+.. |KHgr| unicode:: U+003A7 .. GREEK CAPITAL LETTER CHI
+.. |khgr| unicode:: U+003C7 .. GREEK SMALL LETTER CHI
+.. |Lgr| unicode:: U+0039B .. GREEK CAPITAL LETTER LAMDA
+.. |lgr| unicode:: U+003BB .. GREEK SMALL LETTER LAMDA
+.. |Mgr| unicode:: U+0039C .. GREEK CAPITAL LETTER MU
+.. |mgr| unicode:: U+003BC .. GREEK SMALL LETTER MU
+.. |Ngr| unicode:: U+0039D .. GREEK CAPITAL LETTER NU
+.. |ngr| unicode:: U+003BD .. GREEK SMALL LETTER NU
+.. |Ogr| unicode:: U+0039F .. GREEK CAPITAL LETTER OMICRON
+.. |ogr| unicode:: U+003BF .. GREEK SMALL LETTER OMICRON
+.. |OHgr| unicode:: U+003A9 .. GREEK CAPITAL LETTER OMEGA
+.. |ohgr| unicode:: U+003C9 .. GREEK SMALL LETTER OMEGA
+.. |Pgr| unicode:: U+003A0 .. GREEK CAPITAL LETTER PI
+.. |pgr| unicode:: U+003C0 .. GREEK SMALL LETTER PI
+.. |PHgr| unicode:: U+003A6 .. GREEK CAPITAL LETTER PHI
+.. |phgr| unicode:: U+003C6 .. GREEK SMALL LETTER PHI
+.. |PSgr| unicode:: U+003A8 .. GREEK CAPITAL LETTER PSI
+.. |psgr| unicode:: U+003C8 .. GREEK SMALL LETTER PSI
+.. |Rgr| unicode:: U+003A1 .. GREEK CAPITAL LETTER RHO
+.. |rgr| unicode:: U+003C1 .. GREEK SMALL LETTER RHO
+.. |sfgr| unicode:: U+003C2 .. GREEK SMALL LETTER FINAL SIGMA
+.. |Sgr| unicode:: U+003A3 .. GREEK CAPITAL LETTER SIGMA
+.. |sgr| unicode:: U+003C3 .. GREEK SMALL LETTER SIGMA
+.. |Tgr| unicode:: U+003A4 .. GREEK CAPITAL LETTER TAU
+.. |tgr| unicode:: U+003C4 .. GREEK SMALL LETTER TAU
+.. |THgr| unicode:: U+00398 .. GREEK CAPITAL LETTER THETA
+.. |thgr| unicode:: U+003B8 .. GREEK SMALL LETTER THETA
+.. |Ugr| unicode:: U+003A5 .. GREEK CAPITAL LETTER UPSILON
+.. |ugr| unicode:: U+003C5 .. GREEK SMALL LETTER UPSILON
+.. |Xgr| unicode:: U+0039E .. GREEK CAPITAL LETTER XI
+.. |xgr| unicode:: U+003BE .. GREEK SMALL LETTER XI
+.. |Zgr| unicode:: U+00396 .. GREEK CAPITAL LETTER ZETA
+.. |zgr| unicode:: U+003B6 .. GREEK SMALL LETTER ZETA
--- /dev/null
+.. This data file has been placed in the public domain.
+.. Derived from the Unicode character mappings available from
+ <http://www.w3.org/2003/entities/xml/>.
+ Processed by unicode2rstsubs.py, part of Docutils:
+ <http://docutils.sourceforge.net>.
+
+.. |Aacgr| unicode:: U+00386 .. GREEK CAPITAL LETTER ALPHA WITH TONOS
+.. |aacgr| unicode:: U+003AC .. GREEK SMALL LETTER ALPHA WITH TONOS
+.. |Eacgr| unicode:: U+00388 .. GREEK CAPITAL LETTER EPSILON WITH TONOS
+.. |eacgr| unicode:: U+003AD .. GREEK SMALL LETTER EPSILON WITH TONOS
+.. |EEacgr| unicode:: U+00389 .. GREEK CAPITAL LETTER ETA WITH TONOS
+.. |eeacgr| unicode:: U+003AE .. GREEK SMALL LETTER ETA WITH TONOS
+.. |Iacgr| unicode:: U+0038A .. GREEK CAPITAL LETTER IOTA WITH TONOS
+.. |iacgr| unicode:: U+003AF .. GREEK SMALL LETTER IOTA WITH TONOS
+.. |idiagr| unicode:: U+00390 .. GREEK SMALL LETTER IOTA WITH DIALYTIKA AND TONOS
+.. |Idigr| unicode:: U+003AA .. GREEK CAPITAL LETTER IOTA WITH DIALYTIKA
+.. |idigr| unicode:: U+003CA .. GREEK SMALL LETTER IOTA WITH DIALYTIKA
+.. |Oacgr| unicode:: U+0038C .. GREEK CAPITAL LETTER OMICRON WITH TONOS
+.. |oacgr| unicode:: U+003CC .. GREEK SMALL LETTER OMICRON WITH TONOS
+.. |OHacgr| unicode:: U+0038F .. GREEK CAPITAL LETTER OMEGA WITH TONOS
+.. |ohacgr| unicode:: U+003CE .. GREEK SMALL LETTER OMEGA WITH TONOS
+.. |Uacgr| unicode:: U+0038E .. GREEK CAPITAL LETTER UPSILON WITH TONOS
+.. |uacgr| unicode:: U+003CD .. GREEK SMALL LETTER UPSILON WITH TONOS
+.. |udiagr| unicode:: U+003B0 .. GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND TONOS
+.. |Udigr| unicode:: U+003AB .. GREEK CAPITAL LETTER UPSILON WITH DIALYTIKA
+.. |udigr| unicode:: U+003CB .. GREEK SMALL LETTER UPSILON WITH DIALYTIKA
--- /dev/null
+.. This data file has been placed in the public domain.
+.. Derived from the Unicode character mappings available from
+ <http://www.w3.org/2003/entities/xml/>.
+ Processed by unicode2rstsubs.py, part of Docutils:
+ <http://docutils.sourceforge.net>.
+
+.. |alpha| unicode:: U+003B1 .. GREEK SMALL LETTER ALPHA
+.. |beta| unicode:: U+003B2 .. GREEK SMALL LETTER BETA
+.. |chi| unicode:: U+003C7 .. GREEK SMALL LETTER CHI
+.. |Delta| unicode:: U+00394 .. GREEK CAPITAL LETTER DELTA
+.. |delta| unicode:: U+003B4 .. GREEK SMALL LETTER DELTA
+.. |epsi| unicode:: U+003F5 .. GREEK LUNATE EPSILON SYMBOL
+.. |epsis| unicode:: U+003F5 .. GREEK LUNATE EPSILON SYMBOL
+.. |epsiv| unicode:: U+003B5 .. GREEK SMALL LETTER EPSILON
+.. |eta| unicode:: U+003B7 .. GREEK SMALL LETTER ETA
+.. |Gamma| unicode:: U+00393 .. GREEK CAPITAL LETTER GAMMA
+.. |gamma| unicode:: U+003B3 .. GREEK SMALL LETTER GAMMA
+.. |Gammad| unicode:: U+003DC .. GREEK LETTER DIGAMMA
+.. |gammad| unicode:: U+003DD .. GREEK SMALL LETTER DIGAMMA
+.. |iota| unicode:: U+003B9 .. GREEK SMALL LETTER IOTA
+.. |kappa| unicode:: U+003BA .. GREEK SMALL LETTER KAPPA
+.. |kappav| unicode:: U+003F0 .. GREEK KAPPA SYMBOL
+.. |Lambda| unicode:: U+0039B .. GREEK CAPITAL LETTER LAMDA
+.. |lambda| unicode:: U+003BB .. GREEK SMALL LETTER LAMDA
+.. |mu| unicode:: U+003BC .. GREEK SMALL LETTER MU
+.. |nu| unicode:: U+003BD .. GREEK SMALL LETTER NU
+.. |Omega| unicode:: U+003A9 .. GREEK CAPITAL LETTER OMEGA
+.. |omega| unicode:: U+003C9 .. GREEK SMALL LETTER OMEGA
+.. |Phi| unicode:: U+003A6 .. GREEK CAPITAL LETTER PHI
+.. |phi| unicode:: U+003D5 .. GREEK PHI SYMBOL
+.. |phis| unicode:: U+003D5 .. GREEK PHI SYMBOL
+.. |phiv| unicode:: U+003C6 .. GREEK SMALL LETTER PHI
+.. |Pi| unicode:: U+003A0 .. GREEK CAPITAL LETTER PI
+.. |pi| unicode:: U+003C0 .. GREEK SMALL LETTER PI
+.. |piv| unicode:: U+003D6 .. GREEK PI SYMBOL
+.. |Psi| unicode:: U+003A8 .. GREEK CAPITAL LETTER PSI
+.. |psi| unicode:: U+003C8 .. GREEK SMALL LETTER PSI
+.. |rho| unicode:: U+003C1 .. GREEK SMALL LETTER RHO
+.. |rhov| unicode:: U+003F1 .. GREEK RHO SYMBOL
+.. |Sigma| unicode:: U+003A3 .. GREEK CAPITAL LETTER SIGMA
+.. |sigma| unicode:: U+003C3 .. GREEK SMALL LETTER SIGMA
+.. |sigmav| unicode:: U+003C2 .. GREEK SMALL LETTER FINAL SIGMA
+.. |tau| unicode:: U+003C4 .. GREEK SMALL LETTER TAU
+.. |Theta| unicode:: U+00398 .. GREEK CAPITAL LETTER THETA
+.. |theta| unicode:: U+003B8 .. GREEK SMALL LETTER THETA
+.. |thetas| unicode:: U+003B8 .. GREEK SMALL LETTER THETA
+.. |thetav| unicode:: U+003D1 .. GREEK THETA SYMBOL
+.. |Upsi| unicode:: U+003D2 .. GREEK UPSILON WITH HOOK SYMBOL
+.. |upsi| unicode:: U+003C5 .. GREEK SMALL LETTER UPSILON
+.. |Xi| unicode:: U+0039E .. GREEK CAPITAL LETTER XI
+.. |xi| unicode:: U+003BE .. GREEK SMALL LETTER XI
+.. |zeta| unicode:: U+003B6 .. GREEK SMALL LETTER ZETA
--- /dev/null
+.. This data file has been placed in the public domain.
+.. Derived from the Unicode character mappings available from
+ <http://www.w3.org/2003/entities/xml/>.
+ Processed by unicode2rstsubs.py, part of Docutils:
+ <http://docutils.sourceforge.net>.
+
+.. |b.alpha| unicode:: U+1D6C2 .. MATHEMATICAL BOLD SMALL ALPHA
+.. |b.beta| unicode:: U+1D6C3 .. MATHEMATICAL BOLD SMALL BETA
+.. |b.chi| unicode:: U+1D6D8 .. MATHEMATICAL BOLD SMALL CHI
+.. |b.Delta| unicode:: U+1D6AB .. MATHEMATICAL BOLD CAPITAL DELTA
+.. |b.delta| unicode:: U+1D6C5 .. MATHEMATICAL BOLD SMALL DELTA
+.. |b.epsi| unicode:: U+1D6C6 .. MATHEMATICAL BOLD SMALL EPSILON
+.. |b.epsiv| unicode:: U+1D6DC .. MATHEMATICAL BOLD EPSILON SYMBOL
+.. |b.eta| unicode:: U+1D6C8 .. MATHEMATICAL BOLD SMALL ETA
+.. |b.Gamma| unicode:: U+1D6AA .. MATHEMATICAL BOLD CAPITAL GAMMA
+.. |b.gamma| unicode:: U+1D6C4 .. MATHEMATICAL BOLD SMALL GAMMA
+.. |b.Gammad| unicode:: U+003DC .. GREEK LETTER DIGAMMA
+.. |b.gammad| unicode:: U+003DD .. GREEK SMALL LETTER DIGAMMA
+.. |b.iota| unicode:: U+1D6CA .. MATHEMATICAL BOLD SMALL IOTA
+.. |b.kappa| unicode:: U+1D6CB .. MATHEMATICAL BOLD SMALL KAPPA
+.. |b.kappav| unicode:: U+1D6DE .. MATHEMATICAL BOLD KAPPA SYMBOL
+.. |b.Lambda| unicode:: U+1D6B2 .. MATHEMATICAL BOLD CAPITAL LAMDA
+.. |b.lambda| unicode:: U+1D6CC .. MATHEMATICAL BOLD SMALL LAMDA
+.. |b.mu| unicode:: U+1D6CD .. MATHEMATICAL BOLD SMALL MU
+.. |b.nu| unicode:: U+1D6CE .. MATHEMATICAL BOLD SMALL NU
+.. |b.Omega| unicode:: U+1D6C0 .. MATHEMATICAL BOLD CAPITAL OMEGA
+.. |b.omega| unicode:: U+1D6DA .. MATHEMATICAL BOLD SMALL OMEGA
+.. |b.Phi| unicode:: U+1D6BD .. MATHEMATICAL BOLD CAPITAL PHI
+.. |b.phi| unicode:: U+1D6D7 .. MATHEMATICAL BOLD SMALL PHI
+.. |b.phiv| unicode:: U+1D6DF .. MATHEMATICAL BOLD PHI SYMBOL
+.. |b.Pi| unicode:: U+1D6B7 .. MATHEMATICAL BOLD CAPITAL PI
+.. |b.pi| unicode:: U+1D6D1 .. MATHEMATICAL BOLD SMALL PI
+.. |b.piv| unicode:: U+1D6E1 .. MATHEMATICAL BOLD PI SYMBOL
+.. |b.Psi| unicode:: U+1D6BF .. MATHEMATICAL BOLD CAPITAL PSI
+.. |b.psi| unicode:: U+1D6D9 .. MATHEMATICAL BOLD SMALL PSI
+.. |b.rho| unicode:: U+1D6D2 .. MATHEMATICAL BOLD SMALL RHO
+.. |b.rhov| unicode:: U+1D6E0 .. MATHEMATICAL BOLD RHO SYMBOL
+.. |b.Sigma| unicode:: U+1D6BA .. MATHEMATICAL BOLD CAPITAL SIGMA
+.. |b.sigma| unicode:: U+1D6D4 .. MATHEMATICAL BOLD SMALL SIGMA
+.. |b.sigmav| unicode:: U+1D6D3 .. MATHEMATICAL BOLD SMALL FINAL SIGMA
+.. |b.tau| unicode:: U+1D6D5 .. MATHEMATICAL BOLD SMALL TAU
+.. |b.Theta| unicode:: U+1D6AF .. MATHEMATICAL BOLD CAPITAL THETA
+.. |b.thetas| unicode:: U+1D6C9 .. MATHEMATICAL BOLD SMALL THETA
+.. |b.thetav| unicode:: U+1D6DD .. MATHEMATICAL BOLD THETA SYMBOL
+.. |b.Upsi| unicode:: U+1D6BC .. MATHEMATICAL BOLD CAPITAL UPSILON
+.. |b.upsi| unicode:: U+1D6D6 .. MATHEMATICAL BOLD SMALL UPSILON
+.. |b.Xi| unicode:: U+1D6B5 .. MATHEMATICAL BOLD CAPITAL XI
+.. |b.xi| unicode:: U+1D6CF .. MATHEMATICAL BOLD SMALL XI
+.. |b.zeta| unicode:: U+1D6C7 .. MATHEMATICAL BOLD SMALL ZETA
--- /dev/null
+.. This data file has been placed in the public domain.
+.. Derived from the Unicode character mappings available from
+ <http://www.w3.org/2003/entities/xml/>.
+ Processed by unicode2rstsubs.py, part of Docutils:
+ <http://docutils.sourceforge.net>.
+
+.. |b.Gammad| unicode:: U+003DC .. GREEK LETTER DIGAMMA
+.. |b.gammad| unicode:: U+003DD .. GREEK SMALL LETTER DIGAMMA
--- /dev/null
+.. This data file has been placed in the public domain.
+.. Derived from the Unicode character mappings available from
+ <http://www.w3.org/2003/entities/xml/>.
+ Processed by unicode2rstsubs.py, part of Docutils:
+ <http://docutils.sourceforge.net>.
+
+.. |Aacute| unicode:: U+000C1 .. LATIN CAPITAL LETTER A WITH ACUTE
+.. |aacute| unicode:: U+000E1 .. LATIN SMALL LETTER A WITH ACUTE
+.. |Acirc| unicode:: U+000C2 .. LATIN CAPITAL LETTER A WITH CIRCUMFLEX
+.. |acirc| unicode:: U+000E2 .. LATIN SMALL LETTER A WITH CIRCUMFLEX
+.. |AElig| unicode:: U+000C6 .. LATIN CAPITAL LETTER AE
+.. |aelig| unicode:: U+000E6 .. LATIN SMALL LETTER AE
+.. |Agrave| unicode:: U+000C0 .. LATIN CAPITAL LETTER A WITH GRAVE
+.. |agrave| unicode:: U+000E0 .. LATIN SMALL LETTER A WITH GRAVE
+.. |Aring| unicode:: U+000C5 .. LATIN CAPITAL LETTER A WITH RING ABOVE
+.. |aring| unicode:: U+000E5 .. LATIN SMALL LETTER A WITH RING ABOVE
+.. |Atilde| unicode:: U+000C3 .. LATIN CAPITAL LETTER A WITH TILDE
+.. |atilde| unicode:: U+000E3 .. LATIN SMALL LETTER A WITH TILDE
+.. |Auml| unicode:: U+000C4 .. LATIN CAPITAL LETTER A WITH DIAERESIS
+.. |auml| unicode:: U+000E4 .. LATIN SMALL LETTER A WITH DIAERESIS
+.. |Ccedil| unicode:: U+000C7 .. LATIN CAPITAL LETTER C WITH CEDILLA
+.. |ccedil| unicode:: U+000E7 .. LATIN SMALL LETTER C WITH CEDILLA
+.. |Eacute| unicode:: U+000C9 .. LATIN CAPITAL LETTER E WITH ACUTE
+.. |eacute| unicode:: U+000E9 .. LATIN SMALL LETTER E WITH ACUTE
+.. |Ecirc| unicode:: U+000CA .. LATIN CAPITAL LETTER E WITH CIRCUMFLEX
+.. |ecirc| unicode:: U+000EA .. LATIN SMALL LETTER E WITH CIRCUMFLEX
+.. |Egrave| unicode:: U+000C8 .. LATIN CAPITAL LETTER E WITH GRAVE
+.. |egrave| unicode:: U+000E8 .. LATIN SMALL LETTER E WITH GRAVE
+.. |ETH| unicode:: U+000D0 .. LATIN CAPITAL LETTER ETH
+.. |eth| unicode:: U+000F0 .. LATIN SMALL LETTER ETH
+.. |Euml| unicode:: U+000CB .. LATIN CAPITAL LETTER E WITH DIAERESIS
+.. |euml| unicode:: U+000EB .. LATIN SMALL LETTER E WITH DIAERESIS
+.. |Iacute| unicode:: U+000CD .. LATIN CAPITAL LETTER I WITH ACUTE
+.. |iacute| unicode:: U+000ED .. LATIN SMALL LETTER I WITH ACUTE
+.. |Icirc| unicode:: U+000CE .. LATIN CAPITAL LETTER I WITH CIRCUMFLEX
+.. |icirc| unicode:: U+000EE .. LATIN SMALL LETTER I WITH CIRCUMFLEX
+.. |Igrave| unicode:: U+000CC .. LATIN CAPITAL LETTER I WITH GRAVE
+.. |igrave| unicode:: U+000EC .. LATIN SMALL LETTER I WITH GRAVE
+.. |Iuml| unicode:: U+000CF .. LATIN CAPITAL LETTER I WITH DIAERESIS
+.. |iuml| unicode:: U+000EF .. LATIN SMALL LETTER I WITH DIAERESIS
+.. |Ntilde| unicode:: U+000D1 .. LATIN CAPITAL LETTER N WITH TILDE
+.. |ntilde| unicode:: U+000F1 .. LATIN SMALL LETTER N WITH TILDE
+.. |Oacute| unicode:: U+000D3 .. LATIN CAPITAL LETTER O WITH ACUTE
+.. |oacute| unicode:: U+000F3 .. LATIN SMALL LETTER O WITH ACUTE
+.. |Ocirc| unicode:: U+000D4 .. LATIN CAPITAL LETTER O WITH CIRCUMFLEX
+.. |ocirc| unicode:: U+000F4 .. LATIN SMALL LETTER O WITH CIRCUMFLEX
+.. |Ograve| unicode:: U+000D2 .. LATIN CAPITAL LETTER O WITH GRAVE
+.. |ograve| unicode:: U+000F2 .. LATIN SMALL LETTER O WITH GRAVE
+.. |Oslash| unicode:: U+000D8 .. LATIN CAPITAL LETTER O WITH STROKE
+.. |oslash| unicode:: U+000F8 .. LATIN SMALL LETTER O WITH STROKE
+.. |Otilde| unicode:: U+000D5 .. LATIN CAPITAL LETTER O WITH TILDE
+.. |otilde| unicode:: U+000F5 .. LATIN SMALL LETTER O WITH TILDE
+.. |Ouml| unicode:: U+000D6 .. LATIN CAPITAL LETTER O WITH DIAERESIS
+.. |ouml| unicode:: U+000F6 .. LATIN SMALL LETTER O WITH DIAERESIS
+.. |szlig| unicode:: U+000DF .. LATIN SMALL LETTER SHARP S
+.. |THORN| unicode:: U+000DE .. LATIN CAPITAL LETTER THORN
+.. |thorn| unicode:: U+000FE .. LATIN SMALL LETTER THORN
+.. |Uacute| unicode:: U+000DA .. LATIN CAPITAL LETTER U WITH ACUTE
+.. |uacute| unicode:: U+000FA .. LATIN SMALL LETTER U WITH ACUTE
+.. |Ucirc| unicode:: U+000DB .. LATIN CAPITAL LETTER U WITH CIRCUMFLEX
+.. |ucirc| unicode:: U+000FB .. LATIN SMALL LETTER U WITH CIRCUMFLEX
+.. |Ugrave| unicode:: U+000D9 .. LATIN CAPITAL LETTER U WITH GRAVE
+.. |ugrave| unicode:: U+000F9 .. LATIN SMALL LETTER U WITH GRAVE
+.. |Uuml| unicode:: U+000DC .. LATIN CAPITAL LETTER U WITH DIAERESIS
+.. |uuml| unicode:: U+000FC .. LATIN SMALL LETTER U WITH DIAERESIS
+.. |Yacute| unicode:: U+000DD .. LATIN CAPITAL LETTER Y WITH ACUTE
+.. |yacute| unicode:: U+000FD .. LATIN SMALL LETTER Y WITH ACUTE
+.. |yuml| unicode:: U+000FF .. LATIN SMALL LETTER Y WITH DIAERESIS
--- /dev/null
+.. This data file has been placed in the public domain.
+.. Derived from the Unicode character mappings available from
+ <http://www.w3.org/2003/entities/xml/>.
+ Processed by unicode2rstsubs.py, part of Docutils:
+ <http://docutils.sourceforge.net>.
+
+.. |Abreve| unicode:: U+00102 .. LATIN CAPITAL LETTER A WITH BREVE
+.. |abreve| unicode:: U+00103 .. LATIN SMALL LETTER A WITH BREVE
+.. |Amacr| unicode:: U+00100 .. LATIN CAPITAL LETTER A WITH MACRON
+.. |amacr| unicode:: U+00101 .. LATIN SMALL LETTER A WITH MACRON
+.. |Aogon| unicode:: U+00104 .. LATIN CAPITAL LETTER A WITH OGONEK
+.. |aogon| unicode:: U+00105 .. LATIN SMALL LETTER A WITH OGONEK
+.. |Cacute| unicode:: U+00106 .. LATIN CAPITAL LETTER C WITH ACUTE
+.. |cacute| unicode:: U+00107 .. LATIN SMALL LETTER C WITH ACUTE
+.. |Ccaron| unicode:: U+0010C .. LATIN CAPITAL LETTER C WITH CARON
+.. |ccaron| unicode:: U+0010D .. LATIN SMALL LETTER C WITH CARON
+.. |Ccirc| unicode:: U+00108 .. LATIN CAPITAL LETTER C WITH CIRCUMFLEX
+.. |ccirc| unicode:: U+00109 .. LATIN SMALL LETTER C WITH CIRCUMFLEX
+.. |Cdot| unicode:: U+0010A .. LATIN CAPITAL LETTER C WITH DOT ABOVE
+.. |cdot| unicode:: U+0010B .. LATIN SMALL LETTER C WITH DOT ABOVE
+.. |Dcaron| unicode:: U+0010E .. LATIN CAPITAL LETTER D WITH CARON
+.. |dcaron| unicode:: U+0010F .. LATIN SMALL LETTER D WITH CARON
+.. |Dstrok| unicode:: U+00110 .. LATIN CAPITAL LETTER D WITH STROKE
+.. |dstrok| unicode:: U+00111 .. LATIN SMALL LETTER D WITH STROKE
+.. |Ecaron| unicode:: U+0011A .. LATIN CAPITAL LETTER E WITH CARON
+.. |ecaron| unicode:: U+0011B .. LATIN SMALL LETTER E WITH CARON
+.. |Edot| unicode:: U+00116 .. LATIN CAPITAL LETTER E WITH DOT ABOVE
+.. |edot| unicode:: U+00117 .. LATIN SMALL LETTER E WITH DOT ABOVE
+.. |Emacr| unicode:: U+00112 .. LATIN CAPITAL LETTER E WITH MACRON
+.. |emacr| unicode:: U+00113 .. LATIN SMALL LETTER E WITH MACRON
+.. |ENG| unicode:: U+0014A .. LATIN CAPITAL LETTER ENG
+.. |eng| unicode:: U+0014B .. LATIN SMALL LETTER ENG
+.. |Eogon| unicode:: U+00118 .. LATIN CAPITAL LETTER E WITH OGONEK
+.. |eogon| unicode:: U+00119 .. LATIN SMALL LETTER E WITH OGONEK
+.. |gacute| unicode:: U+001F5 .. LATIN SMALL LETTER G WITH ACUTE
+.. |Gbreve| unicode:: U+0011E .. LATIN CAPITAL LETTER G WITH BREVE
+.. |gbreve| unicode:: U+0011F .. LATIN SMALL LETTER G WITH BREVE
+.. |Gcedil| unicode:: U+00122 .. LATIN CAPITAL LETTER G WITH CEDILLA
+.. |gcedil| unicode:: U+00123 .. LATIN SMALL LETTER G WITH CEDILLA
+.. |Gcirc| unicode:: U+0011C .. LATIN CAPITAL LETTER G WITH CIRCUMFLEX
+.. |gcirc| unicode:: U+0011D .. LATIN SMALL LETTER G WITH CIRCUMFLEX
+.. |Gdot| unicode:: U+00120 .. LATIN CAPITAL LETTER G WITH DOT ABOVE
+.. |gdot| unicode:: U+00121 .. LATIN SMALL LETTER G WITH DOT ABOVE
+.. |Hcirc| unicode:: U+00124 .. LATIN CAPITAL LETTER H WITH CIRCUMFLEX
+.. |hcirc| unicode:: U+00125 .. LATIN SMALL LETTER H WITH CIRCUMFLEX
+.. |Hstrok| unicode:: U+00126 .. LATIN CAPITAL LETTER H WITH STROKE
+.. |hstrok| unicode:: U+00127 .. LATIN SMALL LETTER H WITH STROKE
+.. |Idot| unicode:: U+00130 .. LATIN CAPITAL LETTER I WITH DOT ABOVE
+.. |IJlig| unicode:: U+00132 .. LATIN CAPITAL LIGATURE IJ
+.. |ijlig| unicode:: U+00133 .. LATIN SMALL LIGATURE IJ
+.. |Imacr| unicode:: U+0012A .. LATIN CAPITAL LETTER I WITH MACRON
+.. |imacr| unicode:: U+0012B .. LATIN SMALL LETTER I WITH MACRON
+.. |inodot| unicode:: U+00131 .. LATIN SMALL LETTER DOTLESS I
+.. |Iogon| unicode:: U+0012E .. LATIN CAPITAL LETTER I WITH OGONEK
+.. |iogon| unicode:: U+0012F .. LATIN SMALL LETTER I WITH OGONEK
+.. |Itilde| unicode:: U+00128 .. LATIN CAPITAL LETTER I WITH TILDE
+.. |itilde| unicode:: U+00129 .. LATIN SMALL LETTER I WITH TILDE
+.. |Jcirc| unicode:: U+00134 .. LATIN CAPITAL LETTER J WITH CIRCUMFLEX
+.. |jcirc| unicode:: U+00135 .. LATIN SMALL LETTER J WITH CIRCUMFLEX
+.. |Kcedil| unicode:: U+00136 .. LATIN CAPITAL LETTER K WITH CEDILLA
+.. |kcedil| unicode:: U+00137 .. LATIN SMALL LETTER K WITH CEDILLA
+.. |kgreen| unicode:: U+00138 .. LATIN SMALL LETTER KRA
+.. |Lacute| unicode:: U+00139 .. LATIN CAPITAL LETTER L WITH ACUTE
+.. |lacute| unicode:: U+0013A .. LATIN SMALL LETTER L WITH ACUTE
+.. |Lcaron| unicode:: U+0013D .. LATIN CAPITAL LETTER L WITH CARON
+.. |lcaron| unicode:: U+0013E .. LATIN SMALL LETTER L WITH CARON
+.. |Lcedil| unicode:: U+0013B .. LATIN CAPITAL LETTER L WITH CEDILLA
+.. |lcedil| unicode:: U+0013C .. LATIN SMALL LETTER L WITH CEDILLA
+.. |Lmidot| unicode:: U+0013F .. LATIN CAPITAL LETTER L WITH MIDDLE DOT
+.. |lmidot| unicode:: U+00140 .. LATIN SMALL LETTER L WITH MIDDLE DOT
+.. |Lstrok| unicode:: U+00141 .. LATIN CAPITAL LETTER L WITH STROKE
+.. |lstrok| unicode:: U+00142 .. LATIN SMALL LETTER L WITH STROKE
+.. |Nacute| unicode:: U+00143 .. LATIN CAPITAL LETTER N WITH ACUTE
+.. |nacute| unicode:: U+00144 .. LATIN SMALL LETTER N WITH ACUTE
+.. |napos| unicode:: U+00149 .. LATIN SMALL LETTER N PRECEDED BY APOSTROPHE
+.. |Ncaron| unicode:: U+00147 .. LATIN CAPITAL LETTER N WITH CARON
+.. |ncaron| unicode:: U+00148 .. LATIN SMALL LETTER N WITH CARON
+.. |Ncedil| unicode:: U+00145 .. LATIN CAPITAL LETTER N WITH CEDILLA
+.. |ncedil| unicode:: U+00146 .. LATIN SMALL LETTER N WITH CEDILLA
+.. |Odblac| unicode:: U+00150 .. LATIN CAPITAL LETTER O WITH DOUBLE ACUTE
+.. |odblac| unicode:: U+00151 .. LATIN SMALL LETTER O WITH DOUBLE ACUTE
+.. |OElig| unicode:: U+00152 .. LATIN CAPITAL LIGATURE OE
+.. |oelig| unicode:: U+00153 .. LATIN SMALL LIGATURE OE
+.. |Omacr| unicode:: U+0014C .. LATIN CAPITAL LETTER O WITH MACRON
+.. |omacr| unicode:: U+0014D .. LATIN SMALL LETTER O WITH MACRON
+.. |Racute| unicode:: U+00154 .. LATIN CAPITAL LETTER R WITH ACUTE
+.. |racute| unicode:: U+00155 .. LATIN SMALL LETTER R WITH ACUTE
+.. |Rcaron| unicode:: U+00158 .. LATIN CAPITAL LETTER R WITH CARON
+.. |rcaron| unicode:: U+00159 .. LATIN SMALL LETTER R WITH CARON
+.. |Rcedil| unicode:: U+00156 .. LATIN CAPITAL LETTER R WITH CEDILLA
+.. |rcedil| unicode:: U+00157 .. LATIN SMALL LETTER R WITH CEDILLA
+.. |Sacute| unicode:: U+0015A .. LATIN CAPITAL LETTER S WITH ACUTE
+.. |sacute| unicode:: U+0015B .. LATIN SMALL LETTER S WITH ACUTE
+.. |Scaron| unicode:: U+00160 .. LATIN CAPITAL LETTER S WITH CARON
+.. |scaron| unicode:: U+00161 .. LATIN SMALL LETTER S WITH CARON
+.. |Scedil| unicode:: U+0015E .. LATIN CAPITAL LETTER S WITH CEDILLA
+.. |scedil| unicode:: U+0015F .. LATIN SMALL LETTER S WITH CEDILLA
+.. |Scirc| unicode:: U+0015C .. LATIN CAPITAL LETTER S WITH CIRCUMFLEX
+.. |scirc| unicode:: U+0015D .. LATIN SMALL LETTER S WITH CIRCUMFLEX
+.. |Tcaron| unicode:: U+00164 .. LATIN CAPITAL LETTER T WITH CARON
+.. |tcaron| unicode:: U+00165 .. LATIN SMALL LETTER T WITH CARON
+.. |Tcedil| unicode:: U+00162 .. LATIN CAPITAL LETTER T WITH CEDILLA
+.. |tcedil| unicode:: U+00163 .. LATIN SMALL LETTER T WITH CEDILLA
+.. |Tstrok| unicode:: U+00166 .. LATIN CAPITAL LETTER T WITH STROKE
+.. |tstrok| unicode:: U+00167 .. LATIN SMALL LETTER T WITH STROKE
+.. |Ubreve| unicode:: U+0016C .. LATIN CAPITAL LETTER U WITH BREVE
+.. |ubreve| unicode:: U+0016D .. LATIN SMALL LETTER U WITH BREVE
+.. |Udblac| unicode:: U+00170 .. LATIN CAPITAL LETTER U WITH DOUBLE ACUTE
+.. |udblac| unicode:: U+00171 .. LATIN SMALL LETTER U WITH DOUBLE ACUTE
+.. |Umacr| unicode:: U+0016A .. LATIN CAPITAL LETTER U WITH MACRON
+.. |umacr| unicode:: U+0016B .. LATIN SMALL LETTER U WITH MACRON
+.. |Uogon| unicode:: U+00172 .. LATIN CAPITAL LETTER U WITH OGONEK
+.. |uogon| unicode:: U+00173 .. LATIN SMALL LETTER U WITH OGONEK
+.. |Uring| unicode:: U+0016E .. LATIN CAPITAL LETTER U WITH RING ABOVE
+.. |uring| unicode:: U+0016F .. LATIN SMALL LETTER U WITH RING ABOVE
+.. |Utilde| unicode:: U+00168 .. LATIN CAPITAL LETTER U WITH TILDE
+.. |utilde| unicode:: U+00169 .. LATIN SMALL LETTER U WITH TILDE
+.. |Wcirc| unicode:: U+00174 .. LATIN CAPITAL LETTER W WITH CIRCUMFLEX
+.. |wcirc| unicode:: U+00175 .. LATIN SMALL LETTER W WITH CIRCUMFLEX
+.. |Ycirc| unicode:: U+00176 .. LATIN CAPITAL LETTER Y WITH CIRCUMFLEX
+.. |ycirc| unicode:: U+00177 .. LATIN SMALL LETTER Y WITH CIRCUMFLEX
+.. |Yuml| unicode:: U+00178 .. LATIN CAPITAL LETTER Y WITH DIAERESIS
+.. |Zacute| unicode:: U+00179 .. LATIN CAPITAL LETTER Z WITH ACUTE
+.. |zacute| unicode:: U+0017A .. LATIN SMALL LETTER Z WITH ACUTE
+.. |Zcaron| unicode:: U+0017D .. LATIN CAPITAL LETTER Z WITH CARON
+.. |zcaron| unicode:: U+0017E .. LATIN SMALL LETTER Z WITH CARON
+.. |Zdot| unicode:: U+0017B .. LATIN CAPITAL LETTER Z WITH DOT ABOVE
+.. |zdot| unicode:: U+0017C .. LATIN SMALL LETTER Z WITH DOT ABOVE
--- /dev/null
+.. This data file has been placed in the public domain.
+.. Derived from the Unicode character mappings available from
+ <http://www.w3.org/2003/entities/xml/>.
+ Processed by unicode2rstsubs.py, part of Docutils:
+ <http://docutils.sourceforge.net>.
+
+.. |Afr| unicode:: U+1D504 .. MATHEMATICAL FRAKTUR CAPITAL A
+.. |afr| unicode:: U+1D51E .. MATHEMATICAL FRAKTUR SMALL A
+.. |Bfr| unicode:: U+1D505 .. MATHEMATICAL FRAKTUR CAPITAL B
+.. |bfr| unicode:: U+1D51F .. MATHEMATICAL FRAKTUR SMALL B
+.. |Cfr| unicode:: U+0212D .. BLACK-LETTER CAPITAL C
+.. |cfr| unicode:: U+1D520 .. MATHEMATICAL FRAKTUR SMALL C
+.. |Dfr| unicode:: U+1D507 .. MATHEMATICAL FRAKTUR CAPITAL D
+.. |dfr| unicode:: U+1D521 .. MATHEMATICAL FRAKTUR SMALL D
+.. |Efr| unicode:: U+1D508 .. MATHEMATICAL FRAKTUR CAPITAL E
+.. |efr| unicode:: U+1D522 .. MATHEMATICAL FRAKTUR SMALL E
+.. |Ffr| unicode:: U+1D509 .. MATHEMATICAL FRAKTUR CAPITAL F
+.. |ffr| unicode:: U+1D523 .. MATHEMATICAL FRAKTUR SMALL F
+.. |Gfr| unicode:: U+1D50A .. MATHEMATICAL FRAKTUR CAPITAL G
+.. |gfr| unicode:: U+1D524 .. MATHEMATICAL FRAKTUR SMALL G
+.. |Hfr| unicode:: U+0210C .. BLACK-LETTER CAPITAL H
+.. |hfr| unicode:: U+1D525 .. MATHEMATICAL FRAKTUR SMALL H
+.. |Ifr| unicode:: U+02111 .. BLACK-LETTER CAPITAL I
+.. |ifr| unicode:: U+1D526 .. MATHEMATICAL FRAKTUR SMALL I
+.. |Jfr| unicode:: U+1D50D .. MATHEMATICAL FRAKTUR CAPITAL J
+.. |jfr| unicode:: U+1D527 .. MATHEMATICAL FRAKTUR SMALL J
+.. |Kfr| unicode:: U+1D50E .. MATHEMATICAL FRAKTUR CAPITAL K
+.. |kfr| unicode:: U+1D528 .. MATHEMATICAL FRAKTUR SMALL K
+.. |Lfr| unicode:: U+1D50F .. MATHEMATICAL FRAKTUR CAPITAL L
+.. |lfr| unicode:: U+1D529 .. MATHEMATICAL FRAKTUR SMALL L
+.. |Mfr| unicode:: U+1D510 .. MATHEMATICAL FRAKTUR CAPITAL M
+.. |mfr| unicode:: U+1D52A .. MATHEMATICAL FRAKTUR SMALL M
+.. |Nfr| unicode:: U+1D511 .. MATHEMATICAL FRAKTUR CAPITAL N
+.. |nfr| unicode:: U+1D52B .. MATHEMATICAL FRAKTUR SMALL N
+.. |Ofr| unicode:: U+1D512 .. MATHEMATICAL FRAKTUR CAPITAL O
+.. |ofr| unicode:: U+1D52C .. MATHEMATICAL FRAKTUR SMALL O
+.. |Pfr| unicode:: U+1D513 .. MATHEMATICAL FRAKTUR CAPITAL P
+.. |pfr| unicode:: U+1D52D .. MATHEMATICAL FRAKTUR SMALL P
+.. |Qfr| unicode:: U+1D514 .. MATHEMATICAL FRAKTUR CAPITAL Q
+.. |qfr| unicode:: U+1D52E .. MATHEMATICAL FRAKTUR SMALL Q
+.. |Rfr| unicode:: U+0211C .. BLACK-LETTER CAPITAL R
+.. |rfr| unicode:: U+1D52F .. MATHEMATICAL FRAKTUR SMALL R
+.. |Sfr| unicode:: U+1D516 .. MATHEMATICAL FRAKTUR CAPITAL S
+.. |sfr| unicode:: U+1D530 .. MATHEMATICAL FRAKTUR SMALL S
+.. |Tfr| unicode:: U+1D517 .. MATHEMATICAL FRAKTUR CAPITAL T
+.. |tfr| unicode:: U+1D531 .. MATHEMATICAL FRAKTUR SMALL T
+.. |Ufr| unicode:: U+1D518 .. MATHEMATICAL FRAKTUR CAPITAL U
+.. |ufr| unicode:: U+1D532 .. MATHEMATICAL FRAKTUR SMALL U
+.. |Vfr| unicode:: U+1D519 .. MATHEMATICAL FRAKTUR CAPITAL V
+.. |vfr| unicode:: U+1D533 .. MATHEMATICAL FRAKTUR SMALL V
+.. |Wfr| unicode:: U+1D51A .. MATHEMATICAL FRAKTUR CAPITAL W
+.. |wfr| unicode:: U+1D534 .. MATHEMATICAL FRAKTUR SMALL W
+.. |Xfr| unicode:: U+1D51B .. MATHEMATICAL FRAKTUR CAPITAL X
+.. |xfr| unicode:: U+1D535 .. MATHEMATICAL FRAKTUR SMALL X
+.. |Yfr| unicode:: U+1D51C .. MATHEMATICAL FRAKTUR CAPITAL Y
+.. |yfr| unicode:: U+1D536 .. MATHEMATICAL FRAKTUR SMALL Y
+.. |Zfr| unicode:: U+02128 .. BLACK-LETTER CAPITAL Z
+.. |zfr| unicode:: U+1D537 .. MATHEMATICAL FRAKTUR SMALL Z
--- /dev/null
+.. This data file has been placed in the public domain.
+.. Derived from the Unicode character mappings available from
+ <http://www.w3.org/2003/entities/xml/>.
+ Processed by unicode2rstsubs.py, part of Docutils:
+ <http://docutils.sourceforge.net>.
+
+.. |Cfr| unicode:: U+0212D .. BLACK-LETTER CAPITAL C
+.. |Hfr| unicode:: U+0210C .. BLACK-LETTER CAPITAL H
+.. |Ifr| unicode:: U+02111 .. BLACK-LETTER CAPITAL I
+.. |Rfr| unicode:: U+0211C .. BLACK-LETTER CAPITAL R
+.. |Zfr| unicode:: U+02128 .. BLACK-LETTER CAPITAL Z
--- /dev/null
+.. This data file has been placed in the public domain.
+.. Derived from the Unicode character mappings available from
+ <http://www.w3.org/2003/entities/xml/>.
+ Processed by unicode2rstsubs.py, part of Docutils:
+ <http://docutils.sourceforge.net>.
+
+.. |Aopf| unicode:: U+1D538 .. MATHEMATICAL DOUBLE-STRUCK CAPITAL A
+.. |Bopf| unicode:: U+1D539 .. MATHEMATICAL DOUBLE-STRUCK CAPITAL B
+.. |Copf| unicode:: U+02102 .. DOUBLE-STRUCK CAPITAL C
+.. |Dopf| unicode:: U+1D53B .. MATHEMATICAL DOUBLE-STRUCK CAPITAL D
+.. |Eopf| unicode:: U+1D53C .. MATHEMATICAL DOUBLE-STRUCK CAPITAL E
+.. |Fopf| unicode:: U+1D53D .. MATHEMATICAL DOUBLE-STRUCK CAPITAL F
+.. |Gopf| unicode:: U+1D53E .. MATHEMATICAL DOUBLE-STRUCK CAPITAL G
+.. |Hopf| unicode:: U+0210D .. DOUBLE-STRUCK CAPITAL H
+.. |Iopf| unicode:: U+1D540 .. MATHEMATICAL DOUBLE-STRUCK CAPITAL I
+.. |Jopf| unicode:: U+1D541 .. MATHEMATICAL DOUBLE-STRUCK CAPITAL J
+.. |Kopf| unicode:: U+1D542 .. MATHEMATICAL DOUBLE-STRUCK CAPITAL K
+.. |Lopf| unicode:: U+1D543 .. MATHEMATICAL DOUBLE-STRUCK CAPITAL L
+.. |Mopf| unicode:: U+1D544 .. MATHEMATICAL DOUBLE-STRUCK CAPITAL M
+.. |Nopf| unicode:: U+02115 .. DOUBLE-STRUCK CAPITAL N
+.. |Oopf| unicode:: U+1D546 .. MATHEMATICAL DOUBLE-STRUCK CAPITAL O
+.. |Popf| unicode:: U+02119 .. DOUBLE-STRUCK CAPITAL P
+.. |Qopf| unicode:: U+0211A .. DOUBLE-STRUCK CAPITAL Q
+.. |Ropf| unicode:: U+0211D .. DOUBLE-STRUCK CAPITAL R
+.. |Sopf| unicode:: U+1D54A .. MATHEMATICAL DOUBLE-STRUCK CAPITAL S
+.. |Topf| unicode:: U+1D54B .. MATHEMATICAL DOUBLE-STRUCK CAPITAL T
+.. |Uopf| unicode:: U+1D54C .. MATHEMATICAL DOUBLE-STRUCK CAPITAL U
+.. |Vopf| unicode:: U+1D54D .. MATHEMATICAL DOUBLE-STRUCK CAPITAL V
+.. |Wopf| unicode:: U+1D54E .. MATHEMATICAL DOUBLE-STRUCK CAPITAL W
+.. |Xopf| unicode:: U+1D54F .. MATHEMATICAL DOUBLE-STRUCK CAPITAL X
+.. |Yopf| unicode:: U+1D550 .. MATHEMATICAL DOUBLE-STRUCK CAPITAL Y
+.. |Zopf| unicode:: U+02124 .. DOUBLE-STRUCK CAPITAL Z
--- /dev/null
+.. This data file has been placed in the public domain.
+.. Derived from the Unicode character mappings available from
+ <http://www.w3.org/2003/entities/xml/>.
+ Processed by unicode2rstsubs.py, part of Docutils:
+ <http://docutils.sourceforge.net>.
+
+.. |Copf| unicode:: U+02102 .. DOUBLE-STRUCK CAPITAL C
+.. |Hopf| unicode:: U+0210D .. DOUBLE-STRUCK CAPITAL H
+.. |Nopf| unicode:: U+02115 .. DOUBLE-STRUCK CAPITAL N
+.. |Popf| unicode:: U+02119 .. DOUBLE-STRUCK CAPITAL P
+.. |Qopf| unicode:: U+0211A .. DOUBLE-STRUCK CAPITAL Q
+.. |Ropf| unicode:: U+0211D .. DOUBLE-STRUCK CAPITAL R
+.. |Zopf| unicode:: U+02124 .. DOUBLE-STRUCK CAPITAL Z
--- /dev/null
+.. This data file has been placed in the public domain.
+.. Derived from the Unicode character mappings available from
+ <http://www.w3.org/2003/entities/xml/>.
+ Processed by unicode2rstsubs.py, part of Docutils:
+ <http://docutils.sourceforge.net>.
+
+.. |Ascr| unicode:: U+1D49C .. MATHEMATICAL SCRIPT CAPITAL A
+.. |ascr| unicode:: U+1D4B6 .. MATHEMATICAL SCRIPT SMALL A
+.. |Bscr| unicode:: U+0212C .. SCRIPT CAPITAL B
+.. |bscr| unicode:: U+1D4B7 .. MATHEMATICAL SCRIPT SMALL B
+.. |Cscr| unicode:: U+1D49E .. MATHEMATICAL SCRIPT CAPITAL C
+.. |cscr| unicode:: U+1D4B8 .. MATHEMATICAL SCRIPT SMALL C
+.. |Dscr| unicode:: U+1D49F .. MATHEMATICAL SCRIPT CAPITAL D
+.. |dscr| unicode:: U+1D4B9 .. MATHEMATICAL SCRIPT SMALL D
+.. |Escr| unicode:: U+02130 .. SCRIPT CAPITAL E
+.. |escr| unicode:: U+0212F .. SCRIPT SMALL E
+.. |Fscr| unicode:: U+02131 .. SCRIPT CAPITAL F
+.. |fscr| unicode:: U+1D4BB .. MATHEMATICAL SCRIPT SMALL F
+.. |Gscr| unicode:: U+1D4A2 .. MATHEMATICAL SCRIPT CAPITAL G
+.. |gscr| unicode:: U+0210A .. SCRIPT SMALL G
+.. |Hscr| unicode:: U+0210B .. SCRIPT CAPITAL H
+.. |hscr| unicode:: U+1D4BD .. MATHEMATICAL SCRIPT SMALL H
+.. |Iscr| unicode:: U+02110 .. SCRIPT CAPITAL I
+.. |iscr| unicode:: U+1D4BE .. MATHEMATICAL SCRIPT SMALL I
+.. |Jscr| unicode:: U+1D4A5 .. MATHEMATICAL SCRIPT CAPITAL J
+.. |jscr| unicode:: U+1D4BF .. MATHEMATICAL SCRIPT SMALL J
+.. |Kscr| unicode:: U+1D4A6 .. MATHEMATICAL SCRIPT CAPITAL K
+.. |kscr| unicode:: U+1D4C0 .. MATHEMATICAL SCRIPT SMALL K
+.. |Lscr| unicode:: U+02112 .. SCRIPT CAPITAL L
+.. |lscr| unicode:: U+1D4C1 .. MATHEMATICAL SCRIPT SMALL L
+.. |Mscr| unicode:: U+02133 .. SCRIPT CAPITAL M
+.. |mscr| unicode:: U+1D4C2 .. MATHEMATICAL SCRIPT SMALL M
+.. |Nscr| unicode:: U+1D4A9 .. MATHEMATICAL SCRIPT CAPITAL N
+.. |nscr| unicode:: U+1D4C3 .. MATHEMATICAL SCRIPT SMALL N
+.. |Oscr| unicode:: U+1D4AA .. MATHEMATICAL SCRIPT CAPITAL O
+.. |oscr| unicode:: U+02134 .. SCRIPT SMALL O
+.. |Pscr| unicode:: U+1D4AB .. MATHEMATICAL SCRIPT CAPITAL P
+.. |pscr| unicode:: U+1D4C5 .. MATHEMATICAL SCRIPT SMALL P
+.. |Qscr| unicode:: U+1D4AC .. MATHEMATICAL SCRIPT CAPITAL Q
+.. |qscr| unicode:: U+1D4C6 .. MATHEMATICAL SCRIPT SMALL Q
+.. |Rscr| unicode:: U+0211B .. SCRIPT CAPITAL R
+.. |rscr| unicode:: U+1D4C7 .. MATHEMATICAL SCRIPT SMALL R
+.. |Sscr| unicode:: U+1D4AE .. MATHEMATICAL SCRIPT CAPITAL S
+.. |sscr| unicode:: U+1D4C8 .. MATHEMATICAL SCRIPT SMALL S
+.. |Tscr| unicode:: U+1D4AF .. MATHEMATICAL SCRIPT CAPITAL T
+.. |tscr| unicode:: U+1D4C9 .. MATHEMATICAL SCRIPT SMALL T
+.. |Uscr| unicode:: U+1D4B0 .. MATHEMATICAL SCRIPT CAPITAL U
+.. |uscr| unicode:: U+1D4CA .. MATHEMATICAL SCRIPT SMALL U
+.. |Vscr| unicode:: U+1D4B1 .. MATHEMATICAL SCRIPT CAPITAL V
+.. |vscr| unicode:: U+1D4CB .. MATHEMATICAL SCRIPT SMALL V
+.. |Wscr| unicode:: U+1D4B2 .. MATHEMATICAL SCRIPT CAPITAL W
+.. |wscr| unicode:: U+1D4CC .. MATHEMATICAL SCRIPT SMALL W
+.. |Xscr| unicode:: U+1D4B3 .. MATHEMATICAL SCRIPT CAPITAL X
+.. |xscr| unicode:: U+1D4CD .. MATHEMATICAL SCRIPT SMALL X
+.. |Yscr| unicode:: U+1D4B4 .. MATHEMATICAL SCRIPT CAPITAL Y
+.. |yscr| unicode:: U+1D4CE .. MATHEMATICAL SCRIPT SMALL Y
+.. |Zscr| unicode:: U+1D4B5 .. MATHEMATICAL SCRIPT CAPITAL Z
+.. |zscr| unicode:: U+1D4CF .. MATHEMATICAL SCRIPT SMALL Z
--- /dev/null
+.. This data file has been placed in the public domain.
+.. Derived from the Unicode character mappings available from
+ <http://www.w3.org/2003/entities/xml/>.
+ Processed by unicode2rstsubs.py, part of Docutils:
+ <http://docutils.sourceforge.net>.
+
+.. |Bscr| unicode:: U+0212C .. SCRIPT CAPITAL B
+.. |Escr| unicode:: U+02130 .. SCRIPT CAPITAL E
+.. |escr| unicode:: U+0212F .. SCRIPT SMALL E
+.. |Fscr| unicode:: U+02131 .. SCRIPT CAPITAL F
+.. |gscr| unicode:: U+0210A .. SCRIPT SMALL G
+.. |Hscr| unicode:: U+0210B .. SCRIPT CAPITAL H
+.. |Iscr| unicode:: U+02110 .. SCRIPT CAPITAL I
+.. |Lscr| unicode:: U+02112 .. SCRIPT CAPITAL L
+.. |Mscr| unicode:: U+02133 .. SCRIPT CAPITAL M
+.. |oscr| unicode:: U+02134 .. SCRIPT SMALL O
+.. |Rscr| unicode:: U+0211B .. SCRIPT CAPITAL R
--- /dev/null
+.. This data file has been placed in the public domain.
+.. Derived from the Unicode character mappings available from
+ <http://www.w3.org/2003/entities/xml/>.
+ Processed by unicode2rstsubs.py, part of Docutils:
+ <http://docutils.sourceforge.net>.
+
+.. |amp| unicode:: U+00026 .. AMPERSAND
+.. |apos| unicode:: U+00027 .. APOSTROPHE
+.. |ast| unicode:: U+0002A .. ASTERISK
+.. |brvbar| unicode:: U+000A6 .. BROKEN BAR
+.. |bsol| unicode:: U+0005C .. REVERSE SOLIDUS
+.. |cent| unicode:: U+000A2 .. CENT SIGN
+.. |colon| unicode:: U+0003A .. COLON
+.. |comma| unicode:: U+0002C .. COMMA
+.. |commat| unicode:: U+00040 .. COMMERCIAL AT
+.. |copy| unicode:: U+000A9 .. COPYRIGHT SIGN
+.. |curren| unicode:: U+000A4 .. CURRENCY SIGN
+.. |darr| unicode:: U+02193 .. DOWNWARDS ARROW
+.. |deg| unicode:: U+000B0 .. DEGREE SIGN
+.. |divide| unicode:: U+000F7 .. DIVISION SIGN
+.. |dollar| unicode:: U+00024 .. DOLLAR SIGN
+.. |equals| unicode:: U+0003D .. EQUALS SIGN
+.. |excl| unicode:: U+00021 .. EXCLAMATION MARK
+.. |frac12| unicode:: U+000BD .. VULGAR FRACTION ONE HALF
+.. |frac14| unicode:: U+000BC .. VULGAR FRACTION ONE QUARTER
+.. |frac18| unicode:: U+0215B .. VULGAR FRACTION ONE EIGHTH
+.. |frac34| unicode:: U+000BE .. VULGAR FRACTION THREE QUARTERS
+.. |frac38| unicode:: U+0215C .. VULGAR FRACTION THREE EIGHTHS
+.. |frac58| unicode:: U+0215D .. VULGAR FRACTION FIVE EIGHTHS
+.. |frac78| unicode:: U+0215E .. VULGAR FRACTION SEVEN EIGHTHS
+.. |gt| unicode:: U+0003E .. GREATER-THAN SIGN
+.. |half| unicode:: U+000BD .. VULGAR FRACTION ONE HALF
+.. |horbar| unicode:: U+02015 .. HORIZONTAL BAR
+.. |hyphen| unicode:: U+02010 .. HYPHEN
+.. |iexcl| unicode:: U+000A1 .. INVERTED EXCLAMATION MARK
+.. |iquest| unicode:: U+000BF .. INVERTED QUESTION MARK
+.. |laquo| unicode:: U+000AB .. LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
+.. |larr| unicode:: U+02190 .. LEFTWARDS ARROW
+.. |lcub| unicode:: U+0007B .. LEFT CURLY BRACKET
+.. |ldquo| unicode:: U+0201C .. LEFT DOUBLE QUOTATION MARK
+.. |lowbar| unicode:: U+0005F .. LOW LINE
+.. |lpar| unicode:: U+00028 .. LEFT PARENTHESIS
+.. |lsqb| unicode:: U+0005B .. LEFT SQUARE BRACKET
+.. |lsquo| unicode:: U+02018 .. LEFT SINGLE QUOTATION MARK
+.. |lt| unicode:: U+0003C .. LESS-THAN SIGN
+.. |micro| unicode:: U+000B5 .. MICRO SIGN
+.. |middot| unicode:: U+000B7 .. MIDDLE DOT
+.. |nbsp| unicode:: U+000A0 .. NO-BREAK SPACE
+.. |not| unicode:: U+000AC .. NOT SIGN
+.. |num| unicode:: U+00023 .. NUMBER SIGN
+.. |ohm| unicode:: U+02126 .. OHM SIGN
+.. |ordf| unicode:: U+000AA .. FEMININE ORDINAL INDICATOR
+.. |ordm| unicode:: U+000BA .. MASCULINE ORDINAL INDICATOR
+.. |para| unicode:: U+000B6 .. PILCROW SIGN
+.. |percnt| unicode:: U+00025 .. PERCENT SIGN
+.. |period| unicode:: U+0002E .. FULL STOP
+.. |plus| unicode:: U+0002B .. PLUS SIGN
+.. |plusmn| unicode:: U+000B1 .. PLUS-MINUS SIGN
+.. |pound| unicode:: U+000A3 .. POUND SIGN
+.. |quest| unicode:: U+0003F .. QUESTION MARK
+.. |quot| unicode:: U+00022 .. QUOTATION MARK
+.. |raquo| unicode:: U+000BB .. RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
+.. |rarr| unicode:: U+02192 .. RIGHTWARDS ARROW
+.. |rcub| unicode:: U+0007D .. RIGHT CURLY BRACKET
+.. |rdquo| unicode:: U+0201D .. RIGHT DOUBLE QUOTATION MARK
+.. |reg| unicode:: U+000AE .. REGISTERED SIGN
+.. |rpar| unicode:: U+00029 .. RIGHT PARENTHESIS
+.. |rsqb| unicode:: U+0005D .. RIGHT SQUARE BRACKET
+.. |rsquo| unicode:: U+02019 .. RIGHT SINGLE QUOTATION MARK
+.. |sect| unicode:: U+000A7 .. SECTION SIGN
+.. |semi| unicode:: U+0003B .. SEMICOLON
+.. |shy| unicode:: U+000AD .. SOFT HYPHEN
+.. |sol| unicode:: U+0002F .. SOLIDUS
+.. |sung| unicode:: U+0266A .. EIGHTH NOTE
+.. |sup1| unicode:: U+000B9 .. SUPERSCRIPT ONE
+.. |sup2| unicode:: U+000B2 .. SUPERSCRIPT TWO
+.. |sup3| unicode:: U+000B3 .. SUPERSCRIPT THREE
+.. |times| unicode:: U+000D7 .. MULTIPLICATION SIGN
+.. |trade| unicode:: U+02122 .. TRADE MARK SIGN
+.. |uarr| unicode:: U+02191 .. UPWARDS ARROW
+.. |verbar| unicode:: U+0007C .. VERTICAL LINE
+.. |yen| unicode:: U+000A5 .. YEN SIGN
--- /dev/null
+.. This data file has been placed in the public domain.
+.. Derived from the Unicode character mappings available from
+ <http://www.w3.org/2003/entities/xml/>.
+ Processed by unicode2rstsubs.py, part of Docutils:
+ <http://docutils.sourceforge.net>.
+
+.. |blank| unicode:: U+02423 .. OPEN BOX
+.. |blk12| unicode:: U+02592 .. MEDIUM SHADE
+.. |blk14| unicode:: U+02591 .. LIGHT SHADE
+.. |blk34| unicode:: U+02593 .. DARK SHADE
+.. |block| unicode:: U+02588 .. FULL BLOCK
+.. |bull| unicode:: U+02022 .. BULLET
+.. |caret| unicode:: U+02041 .. CARET INSERTION POINT
+.. |check| unicode:: U+02713 .. CHECK MARK
+.. |cir| unicode:: U+025CB .. WHITE CIRCLE
+.. |clubs| unicode:: U+02663 .. BLACK CLUB SUIT
+.. |copysr| unicode:: U+02117 .. SOUND RECORDING COPYRIGHT
+.. |cross| unicode:: U+02717 .. BALLOT X
+.. |Dagger| unicode:: U+02021 .. DOUBLE DAGGER
+.. |dagger| unicode:: U+02020 .. DAGGER
+.. |dash| unicode:: U+02010 .. HYPHEN
+.. |diams| unicode:: U+02666 .. BLACK DIAMOND SUIT
+.. |dlcrop| unicode:: U+0230D .. BOTTOM LEFT CROP
+.. |drcrop| unicode:: U+0230C .. BOTTOM RIGHT CROP
+.. |dtri| unicode:: U+025BF .. WHITE DOWN-POINTING SMALL TRIANGLE
+.. |dtrif| unicode:: U+025BE .. BLACK DOWN-POINTING SMALL TRIANGLE
+.. |emsp| unicode:: U+02003 .. EM SPACE
+.. |emsp13| unicode:: U+02004 .. THREE-PER-EM SPACE
+.. |emsp14| unicode:: U+02005 .. FOUR-PER-EM SPACE
+.. |ensp| unicode:: U+02002 .. EN SPACE
+.. |female| unicode:: U+02640 .. FEMALE SIGN
+.. |ffilig| unicode:: U+0FB03 .. LATIN SMALL LIGATURE FFI
+.. |fflig| unicode:: U+0FB00 .. LATIN SMALL LIGATURE FF
+.. |ffllig| unicode:: U+0FB04 .. LATIN SMALL LIGATURE FFL
+.. |filig| unicode:: U+0FB01 .. LATIN SMALL LIGATURE FI
+.. |flat| unicode:: U+0266D .. MUSIC FLAT SIGN
+.. |fllig| unicode:: U+0FB02 .. LATIN SMALL LIGATURE FL
+.. |frac13| unicode:: U+02153 .. VULGAR FRACTION ONE THIRD
+.. |frac15| unicode:: U+02155 .. VULGAR FRACTION ONE FIFTH
+.. |frac16| unicode:: U+02159 .. VULGAR FRACTION ONE SIXTH
+.. |frac23| unicode:: U+02154 .. VULGAR FRACTION TWO THIRDS
+.. |frac25| unicode:: U+02156 .. VULGAR FRACTION TWO FIFTHS
+.. |frac35| unicode:: U+02157 .. VULGAR FRACTION THREE FIFTHS
+.. |frac45| unicode:: U+02158 .. VULGAR FRACTION FOUR FIFTHS
+.. |frac56| unicode:: U+0215A .. VULGAR FRACTION FIVE SIXTHS
+.. |hairsp| unicode:: U+0200A .. HAIR SPACE
+.. |hearts| unicode:: U+02665 .. BLACK HEART SUIT
+.. |hellip| unicode:: U+02026 .. HORIZONTAL ELLIPSIS
+.. |hybull| unicode:: U+02043 .. HYPHEN BULLET
+.. |incare| unicode:: U+02105 .. CARE OF
+.. |ldquor| unicode:: U+0201E .. DOUBLE LOW-9 QUOTATION MARK
+.. |lhblk| unicode:: U+02584 .. LOWER HALF BLOCK
+.. |loz| unicode:: U+025CA .. LOZENGE
+.. |lozf| unicode:: U+029EB .. BLACK LOZENGE
+.. |lsquor| unicode:: U+0201A .. SINGLE LOW-9 QUOTATION MARK
+.. |ltri| unicode:: U+025C3 .. WHITE LEFT-POINTING SMALL TRIANGLE
+.. |ltrif| unicode:: U+025C2 .. BLACK LEFT-POINTING SMALL TRIANGLE
+.. |male| unicode:: U+02642 .. MALE SIGN
+.. |malt| unicode:: U+02720 .. MALTESE CROSS
+.. |marker| unicode:: U+025AE .. BLACK VERTICAL RECTANGLE
+.. |mdash| unicode:: U+02014 .. EM DASH
+.. |mldr| unicode:: U+02026 .. HORIZONTAL ELLIPSIS
+.. |natur| unicode:: U+0266E .. MUSIC NATURAL SIGN
+.. |ndash| unicode:: U+02013 .. EN DASH
+.. |nldr| unicode:: U+02025 .. TWO DOT LEADER
+.. |numsp| unicode:: U+02007 .. FIGURE SPACE
+.. |phone| unicode:: U+0260E .. BLACK TELEPHONE
+.. |puncsp| unicode:: U+02008 .. PUNCTUATION SPACE
+.. |rdquor| unicode:: U+0201D .. RIGHT DOUBLE QUOTATION MARK
+.. |rect| unicode:: U+025AD .. WHITE RECTANGLE
+.. |rsquor| unicode:: U+02019 .. RIGHT SINGLE QUOTATION MARK
+.. |rtri| unicode:: U+025B9 .. WHITE RIGHT-POINTING SMALL TRIANGLE
+.. |rtrif| unicode:: U+025B8 .. BLACK RIGHT-POINTING SMALL TRIANGLE
+.. |rx| unicode:: U+0211E .. PRESCRIPTION TAKE
+.. |sext| unicode:: U+02736 .. SIX POINTED BLACK STAR
+.. |sharp| unicode:: U+0266F .. MUSIC SHARP SIGN
+.. |spades| unicode:: U+02660 .. BLACK SPADE SUIT
+.. |squ| unicode:: U+025A1 .. WHITE SQUARE
+.. |squf| unicode:: U+025AA .. BLACK SMALL SQUARE
+.. |star| unicode:: U+02606 .. WHITE STAR
+.. |starf| unicode:: U+02605 .. BLACK STAR
+.. |target| unicode:: U+02316 .. POSITION INDICATOR
+.. |telrec| unicode:: U+02315 .. TELEPHONE RECORDER
+.. |thinsp| unicode:: U+02009 .. THIN SPACE
+.. |uhblk| unicode:: U+02580 .. UPPER HALF BLOCK
+.. |ulcrop| unicode:: U+0230F .. TOP LEFT CROP
+.. |urcrop| unicode:: U+0230E .. TOP RIGHT CROP
+.. |utri| unicode:: U+025B5 .. WHITE UP-POINTING SMALL TRIANGLE
+.. |utrif| unicode:: U+025B4 .. BLACK UP-POINTING SMALL TRIANGLE
+.. |vellip| unicode:: U+022EE .. VERTICAL ELLIPSIS
--- /dev/null
+.. This data file has been placed in the public domain.
+.. Derived from the Unicode character mappings available from
+ <http://www.w3.org/2003/entities/xml/>.
+ Processed by unicode2rstsubs.py, part of Docutils:
+ <http://docutils.sourceforge.net>.
+
+.. |acd| unicode:: U+0223F .. SINE WAVE
+.. |aleph| unicode:: U+02135 .. ALEF SYMBOL
+.. |And| unicode:: U+02A53 .. DOUBLE LOGICAL AND
+.. |and| unicode:: U+02227 .. LOGICAL AND
+.. |andand| unicode:: U+02A55 .. TWO INTERSECTING LOGICAL AND
+.. |andd| unicode:: U+02A5C .. LOGICAL AND WITH HORIZONTAL DASH
+.. |andslope| unicode:: U+02A58 .. SLOPING LARGE AND
+.. |andv| unicode:: U+02A5A .. LOGICAL AND WITH MIDDLE STEM
+.. |ang90| unicode:: U+0221F .. RIGHT ANGLE
+.. |angrt| unicode:: U+0221F .. RIGHT ANGLE
+.. |angsph| unicode:: U+02222 .. SPHERICAL ANGLE
+.. |angst| unicode:: U+0212B .. ANGSTROM SIGN
+.. |ap| unicode:: U+02248 .. ALMOST EQUAL TO
+.. |apacir| unicode:: U+02A6F .. ALMOST EQUAL TO WITH CIRCUMFLEX ACCENT
+.. |awconint| unicode:: U+02233 .. ANTICLOCKWISE CONTOUR INTEGRAL
+.. |awint| unicode:: U+02A11 .. ANTICLOCKWISE INTEGRATION
+.. |becaus| unicode:: U+02235 .. BECAUSE
+.. |bernou| unicode:: U+0212C .. SCRIPT CAPITAL B
+.. |bne| unicode:: U+0003D U+020E5 .. EQUALS SIGN with reverse slash
+.. |bnequiv| unicode:: U+02261 U+020E5 .. IDENTICAL TO with reverse slash
+.. |bNot| unicode:: U+02AED .. REVERSED DOUBLE STROKE NOT SIGN
+.. |bnot| unicode:: U+02310 .. REVERSED NOT SIGN
+.. |bottom| unicode:: U+022A5 .. UP TACK
+.. |cap| unicode:: U+02229 .. INTERSECTION
+.. |Cconint| unicode:: U+02230 .. VOLUME INTEGRAL
+.. |cirfnint| unicode:: U+02A10 .. CIRCULATION FUNCTION
+.. |compfn| unicode:: U+02218 .. RING OPERATOR
+.. |cong| unicode:: U+02245 .. APPROXIMATELY EQUAL TO
+.. |Conint| unicode:: U+0222F .. SURFACE INTEGRAL
+.. |conint| unicode:: U+0222E .. CONTOUR INTEGRAL
+.. |ctdot| unicode:: U+022EF .. MIDLINE HORIZONTAL ELLIPSIS
+.. |cup| unicode:: U+0222A .. UNION
+.. |cwconint| unicode:: U+02232 .. CLOCKWISE CONTOUR INTEGRAL
+.. |cwint| unicode:: U+02231 .. CLOCKWISE INTEGRAL
+.. |cylcty| unicode:: U+0232D .. CYLINDRICITY
+.. |disin| unicode:: U+022F2 .. ELEMENT OF WITH LONG HORIZONTAL STROKE
+.. |Dot| unicode:: U+000A8 .. DIAERESIS
+.. |DotDot| unicode:: U+020DC .. COMBINING FOUR DOTS ABOVE
+.. |dsol| unicode:: U+029F6 .. SOLIDUS WITH OVERBAR
+.. |dtdot| unicode:: U+022F1 .. DOWN RIGHT DIAGONAL ELLIPSIS
+.. |dwangle| unicode:: U+029A6 .. OBLIQUE ANGLE OPENING UP
+.. |elinters| unicode:: U+0FFFD .. REPLACEMENT CHARACTER
+.. |epar| unicode:: U+022D5 .. EQUAL AND PARALLEL TO
+.. |eparsl| unicode:: U+029E3 .. EQUALS SIGN AND SLANTED PARALLEL
+.. |equiv| unicode:: U+02261 .. IDENTICAL TO
+.. |eqvparsl| unicode:: U+029E5 .. IDENTICAL TO AND SLANTED PARALLEL
+.. |exist| unicode:: U+02203 .. THERE EXISTS
+.. |fltns| unicode:: U+025B1 .. WHITE PARALLELOGRAM
+.. |fnof| unicode:: U+00192 .. LATIN SMALL LETTER F WITH HOOK
+.. |forall| unicode:: U+02200 .. FOR ALL
+.. |fpartint| unicode:: U+02A0D .. FINITE PART INTEGRAL
+.. |ge| unicode:: U+02265 .. GREATER-THAN OR EQUAL TO
+.. |hamilt| unicode:: U+0210B .. SCRIPT CAPITAL H
+.. |iff| unicode:: U+021D4 .. LEFT RIGHT DOUBLE ARROW
+.. |iinfin| unicode:: U+029DC .. INCOMPLETE INFINITY
+.. |imped| unicode:: U+001B5 .. LATIN CAPITAL LETTER Z WITH STROKE
+.. |infin| unicode:: U+0221E .. INFINITY
+.. |infintie| unicode:: U+029DD .. TIE OVER INFINITY
+.. |Int| unicode:: U+0222C .. DOUBLE INTEGRAL
+.. |int| unicode:: U+0222B .. INTEGRAL
+.. |intlarhk| unicode:: U+02A17 .. INTEGRAL WITH LEFTWARDS ARROW WITH HOOK
+.. |isin| unicode:: U+02208 .. ELEMENT OF
+.. |isindot| unicode:: U+022F5 .. ELEMENT OF WITH DOT ABOVE
+.. |isinE| unicode:: U+022F9 .. ELEMENT OF WITH TWO HORIZONTAL STROKES
+.. |isins| unicode:: U+022F4 .. SMALL ELEMENT OF WITH VERTICAL BAR AT END OF HORIZONTAL STROKE
+.. |isinsv| unicode:: U+022F3 .. ELEMENT OF WITH VERTICAL BAR AT END OF HORIZONTAL STROKE
+.. |isinv| unicode:: U+02208 .. ELEMENT OF
+.. |lagran| unicode:: U+02112 .. SCRIPT CAPITAL L
+.. |Lang| unicode:: U+0300A .. LEFT DOUBLE ANGLE BRACKET
+.. |lang| unicode:: U+02329 .. LEFT-POINTING ANGLE BRACKET
+.. |lArr| unicode:: U+021D0 .. LEFTWARDS DOUBLE ARROW
+.. |lbbrk| unicode:: U+03014 .. LEFT TORTOISE SHELL BRACKET
+.. |le| unicode:: U+02264 .. LESS-THAN OR EQUAL TO
+.. |loang| unicode:: U+03018 .. LEFT WHITE TORTOISE SHELL BRACKET
+.. |lobrk| unicode:: U+0301A .. LEFT WHITE SQUARE BRACKET
+.. |lopar| unicode:: U+02985 .. LEFT WHITE PARENTHESIS
+.. |lowast| unicode:: U+02217 .. ASTERISK OPERATOR
+.. |minus| unicode:: U+02212 .. MINUS SIGN
+.. |mnplus| unicode:: U+02213 .. MINUS-OR-PLUS SIGN
+.. |nabla| unicode:: U+02207 .. NABLA
+.. |ne| unicode:: U+02260 .. NOT EQUAL TO
+.. |nedot| unicode:: U+02250 U+00338 .. APPROACHES THE LIMIT with slash
+.. |nhpar| unicode:: U+02AF2 .. PARALLEL WITH HORIZONTAL STROKE
+.. |ni| unicode:: U+0220B .. CONTAINS AS MEMBER
+.. |nis| unicode:: U+022FC .. SMALL CONTAINS WITH VERTICAL BAR AT END OF HORIZONTAL STROKE
+.. |nisd| unicode:: U+022FA .. CONTAINS WITH LONG HORIZONTAL STROKE
+.. |niv| unicode:: U+0220B .. CONTAINS AS MEMBER
+.. |Not| unicode:: U+02AEC .. DOUBLE STROKE NOT SIGN
+.. |notin| unicode:: U+02209 .. NOT AN ELEMENT OF
+.. |notindot| unicode:: U+022F5 U+00338 .. ELEMENT OF WITH DOT ABOVE with slash
+.. |notinE| unicode:: U+022F9 U+00338 .. ELEMENT OF WITH TWO HORIZONTAL STROKES with slash
+.. |notinva| unicode:: U+02209 .. NOT AN ELEMENT OF
+.. |notinvb| unicode:: U+022F7 .. SMALL ELEMENT OF WITH OVERBAR
+.. |notinvc| unicode:: U+022F6 .. ELEMENT OF WITH OVERBAR
+.. |notni| unicode:: U+0220C .. DOES NOT CONTAIN AS MEMBER
+.. |notniva| unicode:: U+0220C .. DOES NOT CONTAIN AS MEMBER
+.. |notnivb| unicode:: U+022FE .. SMALL CONTAINS WITH OVERBAR
+.. |notnivc| unicode:: U+022FD .. CONTAINS WITH OVERBAR
+.. |nparsl| unicode:: U+02AFD U+020E5 .. DOUBLE SOLIDUS OPERATOR with reverse slash
+.. |npart| unicode:: U+02202 U+00338 .. PARTIAL DIFFERENTIAL with slash
+.. |npolint| unicode:: U+02A14 .. LINE INTEGRATION NOT INCLUDING THE POLE
+.. |nvinfin| unicode:: U+029DE .. INFINITY NEGATED WITH VERTICAL BAR
+.. |olcross| unicode:: U+029BB .. CIRCLE WITH SUPERIMPOSED X
+.. |Or| unicode:: U+02A54 .. DOUBLE LOGICAL OR
+.. |or| unicode:: U+02228 .. LOGICAL OR
+.. |ord| unicode:: U+02A5D .. LOGICAL OR WITH HORIZONTAL DASH
+.. |order| unicode:: U+02134 .. SCRIPT SMALL O
+.. |oror| unicode:: U+02A56 .. TWO INTERSECTING LOGICAL OR
+.. |orslope| unicode:: U+02A57 .. SLOPING LARGE OR
+.. |orv| unicode:: U+02A5B .. LOGICAL OR WITH MIDDLE STEM
+.. |par| unicode:: U+02225 .. PARALLEL TO
+.. |parsl| unicode:: U+02AFD .. DOUBLE SOLIDUS OPERATOR
+.. |part| unicode:: U+02202 .. PARTIAL DIFFERENTIAL
+.. |permil| unicode:: U+02030 .. PER MILLE SIGN
+.. |perp| unicode:: U+022A5 .. UP TACK
+.. |pertenk| unicode:: U+02031 .. PER TEN THOUSAND SIGN
+.. |phmmat| unicode:: U+02133 .. SCRIPT CAPITAL M
+.. |pointint| unicode:: U+02A15 .. INTEGRAL AROUND A POINT OPERATOR
+.. |Prime| unicode:: U+02033 .. DOUBLE PRIME
+.. |prime| unicode:: U+02032 .. PRIME
+.. |profalar| unicode:: U+0232E .. ALL AROUND-PROFILE
+.. |profline| unicode:: U+02312 .. ARC
+.. |profsurf| unicode:: U+02313 .. SEGMENT
+.. |prop| unicode:: U+0221D .. PROPORTIONAL TO
+.. |qint| unicode:: U+02A0C .. QUADRUPLE INTEGRAL OPERATOR
+.. |qprime| unicode:: U+02057 .. QUADRUPLE PRIME
+.. |quatint| unicode:: U+02A16 .. QUATERNION INTEGRAL OPERATOR
+.. |radic| unicode:: U+0221A .. SQUARE ROOT
+.. |Rang| unicode:: U+0300B .. RIGHT DOUBLE ANGLE BRACKET
+.. |rang| unicode:: U+0232A .. RIGHT-POINTING ANGLE BRACKET
+.. |rArr| unicode:: U+021D2 .. RIGHTWARDS DOUBLE ARROW
+.. |rbbrk| unicode:: U+03015 .. RIGHT TORTOISE SHELL BRACKET
+.. |roang| unicode:: U+03019 .. RIGHT WHITE TORTOISE SHELL BRACKET
+.. |robrk| unicode:: U+0301B .. RIGHT WHITE SQUARE BRACKET
+.. |ropar| unicode:: U+02986 .. RIGHT WHITE PARENTHESIS
+.. |rppolint| unicode:: U+02A12 .. LINE INTEGRATION WITH RECTANGULAR PATH AROUND POLE
+.. |scpolint| unicode:: U+02A13 .. LINE INTEGRATION WITH SEMICIRCULAR PATH AROUND POLE
+.. |sim| unicode:: U+0223C .. TILDE OPERATOR
+.. |simdot| unicode:: U+02A6A .. TILDE OPERATOR WITH DOT ABOVE
+.. |sime| unicode:: U+02243 .. ASYMPTOTICALLY EQUAL TO
+.. |smeparsl| unicode:: U+029E4 .. EQUALS SIGN AND SLANTED PARALLEL WITH TILDE ABOVE
+.. |square| unicode:: U+025A1 .. WHITE SQUARE
+.. |squarf| unicode:: U+025AA .. BLACK SMALL SQUARE
+.. |strns| unicode:: U+000AF .. MACRON
+.. |sub| unicode:: U+02282 .. SUBSET OF
+.. |sube| unicode:: U+02286 .. SUBSET OF OR EQUAL TO
+.. |sup| unicode:: U+02283 .. SUPERSET OF
+.. |supe| unicode:: U+02287 .. SUPERSET OF OR EQUAL TO
+.. |tdot| unicode:: U+020DB .. COMBINING THREE DOTS ABOVE
+.. |there4| unicode:: U+02234 .. THEREFORE
+.. |tint| unicode:: U+0222D .. TRIPLE INTEGRAL
+.. |top| unicode:: U+022A4 .. DOWN TACK
+.. |topbot| unicode:: U+02336 .. APL FUNCTIONAL SYMBOL I-BEAM
+.. |topcir| unicode:: U+02AF1 .. DOWN TACK WITH CIRCLE BELOW
+.. |tprime| unicode:: U+02034 .. TRIPLE PRIME
+.. |utdot| unicode:: U+022F0 .. UP RIGHT DIAGONAL ELLIPSIS
+.. |uwangle| unicode:: U+029A7 .. OBLIQUE ANGLE OPENING DOWN
+.. |vangrt| unicode:: U+0299C .. RIGHT ANGLE VARIANT WITH SQUARE
+.. |veeeq| unicode:: U+0225A .. EQUIANGULAR TO
+.. |Verbar| unicode:: U+02016 .. DOUBLE VERTICAL LINE
+.. |wedgeq| unicode:: U+02259 .. ESTIMATES
+.. |xnis| unicode:: U+022FB .. CONTAINS WITH VERTICAL BAR AT END OF HORIZONTAL STROKE
--- /dev/null
+.. This data file has been placed in the public domain.
+.. Derived from the Unicode character mappings available from
+ <http://www.w3.org/2003/entities/xml/>.
+ Processed by unicode2rstsubs.py, part of Docutils:
+ <http://docutils.sourceforge.net>.
+
+.. |angle| unicode:: U+02220 .. ANGLE
+.. |ApplyFunction| unicode:: U+02061 .. FUNCTION APPLICATION
+.. |approx| unicode:: U+02248 .. ALMOST EQUAL TO
+.. |approxeq| unicode:: U+0224A .. ALMOST EQUAL OR EQUAL TO
+.. |Assign| unicode:: U+02254 .. COLON EQUALS
+.. |backcong| unicode:: U+0224C .. ALL EQUAL TO
+.. |backepsilon| unicode:: U+003F6 .. GREEK REVERSED LUNATE EPSILON SYMBOL
+.. |backprime| unicode:: U+02035 .. REVERSED PRIME
+.. |backsim| unicode:: U+0223D .. REVERSED TILDE
+.. |backsimeq| unicode:: U+022CD .. REVERSED TILDE EQUALS
+.. |Backslash| unicode:: U+02216 .. SET MINUS
+.. |barwedge| unicode:: U+02305 .. PROJECTIVE
+.. |Because| unicode:: U+02235 .. BECAUSE
+.. |because| unicode:: U+02235 .. BECAUSE
+.. |Bernoullis| unicode:: U+0212C .. SCRIPT CAPITAL B
+.. |between| unicode:: U+0226C .. BETWEEN
+.. |bigcap| unicode:: U+022C2 .. N-ARY INTERSECTION
+.. |bigcirc| unicode:: U+025EF .. LARGE CIRCLE
+.. |bigcup| unicode:: U+022C3 .. N-ARY UNION
+.. |bigodot| unicode:: U+02A00 .. N-ARY CIRCLED DOT OPERATOR
+.. |bigoplus| unicode:: U+02A01 .. N-ARY CIRCLED PLUS OPERATOR
+.. |bigotimes| unicode:: U+02A02 .. N-ARY CIRCLED TIMES OPERATOR
+.. |bigsqcup| unicode:: U+02A06 .. N-ARY SQUARE UNION OPERATOR
+.. |bigstar| unicode:: U+02605 .. BLACK STAR
+.. |bigtriangledown| unicode:: U+025BD .. WHITE DOWN-POINTING TRIANGLE
+.. |bigtriangleup| unicode:: U+025B3 .. WHITE UP-POINTING TRIANGLE
+.. |biguplus| unicode:: U+02A04 .. N-ARY UNION OPERATOR WITH PLUS
+.. |bigvee| unicode:: U+022C1 .. N-ARY LOGICAL OR
+.. |bigwedge| unicode:: U+022C0 .. N-ARY LOGICAL AND
+.. |bkarow| unicode:: U+0290D .. RIGHTWARDS DOUBLE DASH ARROW
+.. |blacklozenge| unicode:: U+029EB .. BLACK LOZENGE
+.. |blacksquare| unicode:: U+025AA .. BLACK SMALL SQUARE
+.. |blacktriangle| unicode:: U+025B4 .. BLACK UP-POINTING SMALL TRIANGLE
+.. |blacktriangledown| unicode:: U+025BE .. BLACK DOWN-POINTING SMALL TRIANGLE
+.. |blacktriangleleft| unicode:: U+025C2 .. BLACK LEFT-POINTING SMALL TRIANGLE
+.. |blacktriangleright| unicode:: U+025B8 .. BLACK RIGHT-POINTING SMALL TRIANGLE
+.. |bot| unicode:: U+022A5 .. UP TACK
+.. |boxminus| unicode:: U+0229F .. SQUARED MINUS
+.. |boxplus| unicode:: U+0229E .. SQUARED PLUS
+.. |boxtimes| unicode:: U+022A0 .. SQUARED TIMES
+.. |Breve| unicode:: U+002D8 .. BREVE
+.. |bullet| unicode:: U+02022 .. BULLET
+.. |Bumpeq| unicode:: U+0224E .. GEOMETRICALLY EQUIVALENT TO
+.. |bumpeq| unicode:: U+0224F .. DIFFERENCE BETWEEN
+.. |CapitalDifferentialD| unicode:: U+02145 .. DOUBLE-STRUCK ITALIC CAPITAL D
+.. |Cayleys| unicode:: U+0212D .. BLACK-LETTER CAPITAL C
+.. |Cedilla| unicode:: U+000B8 .. CEDILLA
+.. |CenterDot| unicode:: U+000B7 .. MIDDLE DOT
+.. |centerdot| unicode:: U+000B7 .. MIDDLE DOT
+.. |checkmark| unicode:: U+02713 .. CHECK MARK
+.. |circeq| unicode:: U+02257 .. RING EQUAL TO
+.. |circlearrowleft| unicode:: U+021BA .. ANTICLOCKWISE OPEN CIRCLE ARROW
+.. |circlearrowright| unicode:: U+021BB .. CLOCKWISE OPEN CIRCLE ARROW
+.. |circledast| unicode:: U+0229B .. CIRCLED ASTERISK OPERATOR
+.. |circledcirc| unicode:: U+0229A .. CIRCLED RING OPERATOR
+.. |circleddash| unicode:: U+0229D .. CIRCLED DASH
+.. |CircleDot| unicode:: U+02299 .. CIRCLED DOT OPERATOR
+.. |circledR| unicode:: U+000AE .. REGISTERED SIGN
+.. |circledS| unicode:: U+024C8 .. CIRCLED LATIN CAPITAL LETTER S
+.. |CircleMinus| unicode:: U+02296 .. CIRCLED MINUS
+.. |CirclePlus| unicode:: U+02295 .. CIRCLED PLUS
+.. |CircleTimes| unicode:: U+02297 .. CIRCLED TIMES
+.. |ClockwiseContourIntegral| unicode:: U+02232 .. CLOCKWISE CONTOUR INTEGRAL
+.. |CloseCurlyDoubleQuote| unicode:: U+0201D .. RIGHT DOUBLE QUOTATION MARK
+.. |CloseCurlyQuote| unicode:: U+02019 .. RIGHT SINGLE QUOTATION MARK
+.. |clubsuit| unicode:: U+02663 .. BLACK CLUB SUIT
+.. |coloneq| unicode:: U+02254 .. COLON EQUALS
+.. |complement| unicode:: U+02201 .. COMPLEMENT
+.. |complexes| unicode:: U+02102 .. DOUBLE-STRUCK CAPITAL C
+.. |Congruent| unicode:: U+02261 .. IDENTICAL TO
+.. |ContourIntegral| unicode:: U+0222E .. CONTOUR INTEGRAL
+.. |Coproduct| unicode:: U+02210 .. N-ARY COPRODUCT
+.. |CounterClockwiseContourIntegral| unicode:: U+02233 .. ANTICLOCKWISE CONTOUR INTEGRAL
+.. |CupCap| unicode:: U+0224D .. EQUIVALENT TO
+.. |curlyeqprec| unicode:: U+022DE .. EQUAL TO OR PRECEDES
+.. |curlyeqsucc| unicode:: U+022DF .. EQUAL TO OR SUCCEEDS
+.. |curlyvee| unicode:: U+022CE .. CURLY LOGICAL OR
+.. |curlywedge| unicode:: U+022CF .. CURLY LOGICAL AND
+.. |curvearrowleft| unicode:: U+021B6 .. ANTICLOCKWISE TOP SEMICIRCLE ARROW
+.. |curvearrowright| unicode:: U+021B7 .. CLOCKWISE TOP SEMICIRCLE ARROW
+.. |dbkarow| unicode:: U+0290F .. RIGHTWARDS TRIPLE DASH ARROW
+.. |ddagger| unicode:: U+02021 .. DOUBLE DAGGER
+.. |ddotseq| unicode:: U+02A77 .. EQUALS SIGN WITH TWO DOTS ABOVE AND TWO DOTS BELOW
+.. |Del| unicode:: U+02207 .. NABLA
+.. |DiacriticalAcute| unicode:: U+000B4 .. ACUTE ACCENT
+.. |DiacriticalDot| unicode:: U+002D9 .. DOT ABOVE
+.. |DiacriticalDoubleAcute| unicode:: U+002DD .. DOUBLE ACUTE ACCENT
+.. |DiacriticalGrave| unicode:: U+00060 .. GRAVE ACCENT
+.. |DiacriticalTilde| unicode:: U+002DC .. SMALL TILDE
+.. |Diamond| unicode:: U+022C4 .. DIAMOND OPERATOR
+.. |diamond| unicode:: U+022C4 .. DIAMOND OPERATOR
+.. |diamondsuit| unicode:: U+02666 .. BLACK DIAMOND SUIT
+.. |DifferentialD| unicode:: U+02146 .. DOUBLE-STRUCK ITALIC SMALL D
+.. |digamma| unicode:: U+003DD .. GREEK SMALL LETTER DIGAMMA
+.. |div| unicode:: U+000F7 .. DIVISION SIGN
+.. |divideontimes| unicode:: U+022C7 .. DIVISION TIMES
+.. |doteq| unicode:: U+02250 .. APPROACHES THE LIMIT
+.. |doteqdot| unicode:: U+02251 .. GEOMETRICALLY EQUAL TO
+.. |DotEqual| unicode:: U+02250 .. APPROACHES THE LIMIT
+.. |dotminus| unicode:: U+02238 .. DOT MINUS
+.. |dotplus| unicode:: U+02214 .. DOT PLUS
+.. |dotsquare| unicode:: U+022A1 .. SQUARED DOT OPERATOR
+.. |doublebarwedge| unicode:: U+02306 .. PERSPECTIVE
+.. |DoubleContourIntegral| unicode:: U+0222F .. SURFACE INTEGRAL
+.. |DoubleDot| unicode:: U+000A8 .. DIAERESIS
+.. |DoubleDownArrow| unicode:: U+021D3 .. DOWNWARDS DOUBLE ARROW
+.. |DoubleLeftArrow| unicode:: U+021D0 .. LEFTWARDS DOUBLE ARROW
+.. |DoubleLeftRightArrow| unicode:: U+021D4 .. LEFT RIGHT DOUBLE ARROW
+.. |DoubleLeftTee| unicode:: U+02AE4 .. VERTICAL BAR DOUBLE LEFT TURNSTILE
+.. |DoubleLongLeftArrow| unicode:: U+027F8 .. LONG LEFTWARDS DOUBLE ARROW
+.. |DoubleLongLeftRightArrow| unicode:: U+027FA .. LONG LEFT RIGHT DOUBLE ARROW
+.. |DoubleLongRightArrow| unicode:: U+027F9 .. LONG RIGHTWARDS DOUBLE ARROW
+.. |DoubleRightArrow| unicode:: U+021D2 .. RIGHTWARDS DOUBLE ARROW
+.. |DoubleRightTee| unicode:: U+022A8 .. TRUE
+.. |DoubleUpArrow| unicode:: U+021D1 .. UPWARDS DOUBLE ARROW
+.. |DoubleUpDownArrow| unicode:: U+021D5 .. UP DOWN DOUBLE ARROW
+.. |DoubleVerticalBar| unicode:: U+02225 .. PARALLEL TO
+.. |DownArrow| unicode:: U+02193 .. DOWNWARDS ARROW
+.. |Downarrow| unicode:: U+021D3 .. DOWNWARDS DOUBLE ARROW
+.. |downarrow| unicode:: U+02193 .. DOWNWARDS ARROW
+.. |DownArrowUpArrow| unicode:: U+021F5 .. DOWNWARDS ARROW LEFTWARDS OF UPWARDS ARROW
+.. |downdownarrows| unicode:: U+021CA .. DOWNWARDS PAIRED ARROWS
+.. |downharpoonleft| unicode:: U+021C3 .. DOWNWARDS HARPOON WITH BARB LEFTWARDS
+.. |downharpoonright| unicode:: U+021C2 .. DOWNWARDS HARPOON WITH BARB RIGHTWARDS
+.. |DownLeftVector| unicode:: U+021BD .. LEFTWARDS HARPOON WITH BARB DOWNWARDS
+.. |DownRightVector| unicode:: U+021C1 .. RIGHTWARDS HARPOON WITH BARB DOWNWARDS
+.. |DownTee| unicode:: U+022A4 .. DOWN TACK
+.. |DownTeeArrow| unicode:: U+021A7 .. DOWNWARDS ARROW FROM BAR
+.. |drbkarow| unicode:: U+02910 .. RIGHTWARDS TWO-HEADED TRIPLE DASH ARROW
+.. |Element| unicode:: U+02208 .. ELEMENT OF
+.. |emptyset| unicode:: U+02205 .. EMPTY SET
+.. |eqcirc| unicode:: U+02256 .. RING IN EQUAL TO
+.. |eqcolon| unicode:: U+02255 .. EQUALS COLON
+.. |eqsim| unicode:: U+02242 .. MINUS TILDE
+.. |eqslantgtr| unicode:: U+02A96 .. SLANTED EQUAL TO OR GREATER-THAN
+.. |eqslantless| unicode:: U+02A95 .. SLANTED EQUAL TO OR LESS-THAN
+.. |EqualTilde| unicode:: U+02242 .. MINUS TILDE
+.. |Equilibrium| unicode:: U+021CC .. RIGHTWARDS HARPOON OVER LEFTWARDS HARPOON
+.. |Exists| unicode:: U+02203 .. THERE EXISTS
+.. |expectation| unicode:: U+02130 .. SCRIPT CAPITAL E
+.. |ExponentialE| unicode:: U+02147 .. DOUBLE-STRUCK ITALIC SMALL E
+.. |exponentiale| unicode:: U+02147 .. DOUBLE-STRUCK ITALIC SMALL E
+.. |fallingdotseq| unicode:: U+02252 .. APPROXIMATELY EQUAL TO OR THE IMAGE OF
+.. |ForAll| unicode:: U+02200 .. FOR ALL
+.. |Fouriertrf| unicode:: U+02131 .. SCRIPT CAPITAL F
+.. |geq| unicode:: U+02265 .. GREATER-THAN OR EQUAL TO
+.. |geqq| unicode:: U+02267 .. GREATER-THAN OVER EQUAL TO
+.. |geqslant| unicode:: U+02A7E .. GREATER-THAN OR SLANTED EQUAL TO
+.. |gg| unicode:: U+0226B .. MUCH GREATER-THAN
+.. |ggg| unicode:: U+022D9 .. VERY MUCH GREATER-THAN
+.. |gnapprox| unicode:: U+02A8A .. GREATER-THAN AND NOT APPROXIMATE
+.. |gneq| unicode:: U+02A88 .. GREATER-THAN AND SINGLE-LINE NOT EQUAL TO
+.. |gneqq| unicode:: U+02269 .. GREATER-THAN BUT NOT EQUAL TO
+.. |GreaterEqual| unicode:: U+02265 .. GREATER-THAN OR EQUAL TO
+.. |GreaterEqualLess| unicode:: U+022DB .. GREATER-THAN EQUAL TO OR LESS-THAN
+.. |GreaterFullEqual| unicode:: U+02267 .. GREATER-THAN OVER EQUAL TO
+.. |GreaterLess| unicode:: U+02277 .. GREATER-THAN OR LESS-THAN
+.. |GreaterSlantEqual| unicode:: U+02A7E .. GREATER-THAN OR SLANTED EQUAL TO
+.. |GreaterTilde| unicode:: U+02273 .. GREATER-THAN OR EQUIVALENT TO
+.. |gtrapprox| unicode:: U+02A86 .. GREATER-THAN OR APPROXIMATE
+.. |gtrdot| unicode:: U+022D7 .. GREATER-THAN WITH DOT
+.. |gtreqless| unicode:: U+022DB .. GREATER-THAN EQUAL TO OR LESS-THAN
+.. |gtreqqless| unicode:: U+02A8C .. GREATER-THAN ABOVE DOUBLE-LINE EQUAL ABOVE LESS-THAN
+.. |gtrless| unicode:: U+02277 .. GREATER-THAN OR LESS-THAN
+.. |gtrsim| unicode:: U+02273 .. GREATER-THAN OR EQUIVALENT TO
+.. |gvertneqq| unicode:: U+02269 U+0FE00 .. GREATER-THAN BUT NOT EQUAL TO - with vertical stroke
+.. |Hacek| unicode:: U+002C7 .. CARON
+.. |hbar| unicode:: U+0210F .. PLANCK CONSTANT OVER TWO PI
+.. |heartsuit| unicode:: U+02665 .. BLACK HEART SUIT
+.. |HilbertSpace| unicode:: U+0210B .. SCRIPT CAPITAL H
+.. |hksearow| unicode:: U+02925 .. SOUTH EAST ARROW WITH HOOK
+.. |hkswarow| unicode:: U+02926 .. SOUTH WEST ARROW WITH HOOK
+.. |hookleftarrow| unicode:: U+021A9 .. LEFTWARDS ARROW WITH HOOK
+.. |hookrightarrow| unicode:: U+021AA .. RIGHTWARDS ARROW WITH HOOK
+.. |hslash| unicode:: U+0210F .. PLANCK CONSTANT OVER TWO PI
+.. |HumpDownHump| unicode:: U+0224E .. GEOMETRICALLY EQUIVALENT TO
+.. |HumpEqual| unicode:: U+0224F .. DIFFERENCE BETWEEN
+.. |iiiint| unicode:: U+02A0C .. QUADRUPLE INTEGRAL OPERATOR
+.. |iiint| unicode:: U+0222D .. TRIPLE INTEGRAL
+.. |Im| unicode:: U+02111 .. BLACK-LETTER CAPITAL I
+.. |ImaginaryI| unicode:: U+02148 .. DOUBLE-STRUCK ITALIC SMALL I
+.. |imagline| unicode:: U+02110 .. SCRIPT CAPITAL I
+.. |imagpart| unicode:: U+02111 .. BLACK-LETTER CAPITAL I
+.. |Implies| unicode:: U+021D2 .. RIGHTWARDS DOUBLE ARROW
+.. |in| unicode:: U+02208 .. ELEMENT OF
+.. |integers| unicode:: U+02124 .. DOUBLE-STRUCK CAPITAL Z
+.. |Integral| unicode:: U+0222B .. INTEGRAL
+.. |intercal| unicode:: U+022BA .. INTERCALATE
+.. |Intersection| unicode:: U+022C2 .. N-ARY INTERSECTION
+.. |intprod| unicode:: U+02A3C .. INTERIOR PRODUCT
+.. |InvisibleComma| unicode:: U+02063 .. INVISIBLE SEPARATOR
+.. |InvisibleTimes| unicode:: U+02062 .. INVISIBLE TIMES
+.. |langle| unicode:: U+02329 .. LEFT-POINTING ANGLE BRACKET
+.. |Laplacetrf| unicode:: U+02112 .. SCRIPT CAPITAL L
+.. |lbrace| unicode:: U+0007B .. LEFT CURLY BRACKET
+.. |lbrack| unicode:: U+0005B .. LEFT SQUARE BRACKET
+.. |LeftAngleBracket| unicode:: U+02329 .. LEFT-POINTING ANGLE BRACKET
+.. |LeftArrow| unicode:: U+02190 .. LEFTWARDS ARROW
+.. |Leftarrow| unicode:: U+021D0 .. LEFTWARDS DOUBLE ARROW
+.. |leftarrow| unicode:: U+02190 .. LEFTWARDS ARROW
+.. |LeftArrowBar| unicode:: U+021E4 .. LEFTWARDS ARROW TO BAR
+.. |LeftArrowRightArrow| unicode:: U+021C6 .. LEFTWARDS ARROW OVER RIGHTWARDS ARROW
+.. |leftarrowtail| unicode:: U+021A2 .. LEFTWARDS ARROW WITH TAIL
+.. |LeftCeiling| unicode:: U+02308 .. LEFT CEILING
+.. |LeftDoubleBracket| unicode:: U+0301A .. LEFT WHITE SQUARE BRACKET
+.. |LeftDownVector| unicode:: U+021C3 .. DOWNWARDS HARPOON WITH BARB LEFTWARDS
+.. |LeftFloor| unicode:: U+0230A .. LEFT FLOOR
+.. |leftharpoondown| unicode:: U+021BD .. LEFTWARDS HARPOON WITH BARB DOWNWARDS
+.. |leftharpoonup| unicode:: U+021BC .. LEFTWARDS HARPOON WITH BARB UPWARDS
+.. |leftleftarrows| unicode:: U+021C7 .. LEFTWARDS PAIRED ARROWS
+.. |LeftRightArrow| unicode:: U+02194 .. LEFT RIGHT ARROW
+.. |Leftrightarrow| unicode:: U+021D4 .. LEFT RIGHT DOUBLE ARROW
+.. |leftrightarrow| unicode:: U+02194 .. LEFT RIGHT ARROW
+.. |leftrightarrows| unicode:: U+021C6 .. LEFTWARDS ARROW OVER RIGHTWARDS ARROW
+.. |leftrightharpoons| unicode:: U+021CB .. LEFTWARDS HARPOON OVER RIGHTWARDS HARPOON
+.. |leftrightsquigarrow| unicode:: U+021AD .. LEFT RIGHT WAVE ARROW
+.. |LeftTee| unicode:: U+022A3 .. LEFT TACK
+.. |LeftTeeArrow| unicode:: U+021A4 .. LEFTWARDS ARROW FROM BAR
+.. |leftthreetimes| unicode:: U+022CB .. LEFT SEMIDIRECT PRODUCT
+.. |LeftTriangle| unicode:: U+022B2 .. NORMAL SUBGROUP OF
+.. |LeftTriangleEqual| unicode:: U+022B4 .. NORMAL SUBGROUP OF OR EQUAL TO
+.. |LeftUpVector| unicode:: U+021BF .. UPWARDS HARPOON WITH BARB LEFTWARDS
+.. |LeftVector| unicode:: U+021BC .. LEFTWARDS HARPOON WITH BARB UPWARDS
+.. |leq| unicode:: U+02264 .. LESS-THAN OR EQUAL TO
+.. |leqq| unicode:: U+02266 .. LESS-THAN OVER EQUAL TO
+.. |leqslant| unicode:: U+02A7D .. LESS-THAN OR SLANTED EQUAL TO
+.. |lessapprox| unicode:: U+02A85 .. LESS-THAN OR APPROXIMATE
+.. |lessdot| unicode:: U+022D6 .. LESS-THAN WITH DOT
+.. |lesseqgtr| unicode:: U+022DA .. LESS-THAN EQUAL TO OR GREATER-THAN
+.. |lesseqqgtr| unicode:: U+02A8B .. LESS-THAN ABOVE DOUBLE-LINE EQUAL ABOVE GREATER-THAN
+.. |LessEqualGreater| unicode:: U+022DA .. LESS-THAN EQUAL TO OR GREATER-THAN
+.. |LessFullEqual| unicode:: U+02266 .. LESS-THAN OVER EQUAL TO
+.. |LessGreater| unicode:: U+02276 .. LESS-THAN OR GREATER-THAN
+.. |lessgtr| unicode:: U+02276 .. LESS-THAN OR GREATER-THAN
+.. |lesssim| unicode:: U+02272 .. LESS-THAN OR EQUIVALENT TO
+.. |LessSlantEqual| unicode:: U+02A7D .. LESS-THAN OR SLANTED EQUAL TO
+.. |LessTilde| unicode:: U+02272 .. LESS-THAN OR EQUIVALENT TO
+.. |ll| unicode:: U+0226A .. MUCH LESS-THAN
+.. |llcorner| unicode:: U+0231E .. BOTTOM LEFT CORNER
+.. |Lleftarrow| unicode:: U+021DA .. LEFTWARDS TRIPLE ARROW
+.. |lmoustache| unicode:: U+023B0 .. UPPER LEFT OR LOWER RIGHT CURLY BRACKET SECTION
+.. |lnapprox| unicode:: U+02A89 .. LESS-THAN AND NOT APPROXIMATE
+.. |lneq| unicode:: U+02A87 .. LESS-THAN AND SINGLE-LINE NOT EQUAL TO
+.. |lneqq| unicode:: U+02268 .. LESS-THAN BUT NOT EQUAL TO
+.. |LongLeftArrow| unicode:: U+027F5 .. LONG LEFTWARDS ARROW
+.. |Longleftarrow| unicode:: U+027F8 .. LONG LEFTWARDS DOUBLE ARROW
+.. |longleftarrow| unicode:: U+027F5 .. LONG LEFTWARDS ARROW
+.. |LongLeftRightArrow| unicode:: U+027F7 .. LONG LEFT RIGHT ARROW
+.. |Longleftrightarrow| unicode:: U+027FA .. LONG LEFT RIGHT DOUBLE ARROW
+.. |longleftrightarrow| unicode:: U+027F7 .. LONG LEFT RIGHT ARROW
+.. |longmapsto| unicode:: U+027FC .. LONG RIGHTWARDS ARROW FROM BAR
+.. |LongRightArrow| unicode:: U+027F6 .. LONG RIGHTWARDS ARROW
+.. |Longrightarrow| unicode:: U+027F9 .. LONG RIGHTWARDS DOUBLE ARROW
+.. |longrightarrow| unicode:: U+027F6 .. LONG RIGHTWARDS ARROW
+.. |looparrowleft| unicode:: U+021AB .. LEFTWARDS ARROW WITH LOOP
+.. |looparrowright| unicode:: U+021AC .. RIGHTWARDS ARROW WITH LOOP
+.. |LowerLeftArrow| unicode:: U+02199 .. SOUTH WEST ARROW
+.. |LowerRightArrow| unicode:: U+02198 .. SOUTH EAST ARROW
+.. |lozenge| unicode:: U+025CA .. LOZENGE
+.. |lrcorner| unicode:: U+0231F .. BOTTOM RIGHT CORNER
+.. |Lsh| unicode:: U+021B0 .. UPWARDS ARROW WITH TIP LEFTWARDS
+.. |lvertneqq| unicode:: U+02268 U+0FE00 .. LESS-THAN BUT NOT EQUAL TO - with vertical stroke
+.. |maltese| unicode:: U+02720 .. MALTESE CROSS
+.. |mapsto| unicode:: U+021A6 .. RIGHTWARDS ARROW FROM BAR
+.. |measuredangle| unicode:: U+02221 .. MEASURED ANGLE
+.. |Mellintrf| unicode:: U+02133 .. SCRIPT CAPITAL M
+.. |MinusPlus| unicode:: U+02213 .. MINUS-OR-PLUS SIGN
+.. |mp| unicode:: U+02213 .. MINUS-OR-PLUS SIGN
+.. |multimap| unicode:: U+022B8 .. MULTIMAP
+.. |napprox| unicode:: U+02249 .. NOT ALMOST EQUAL TO
+.. |natural| unicode:: U+0266E .. MUSIC NATURAL SIGN
+.. |naturals| unicode:: U+02115 .. DOUBLE-STRUCK CAPITAL N
+.. |nearrow| unicode:: U+02197 .. NORTH EAST ARROW
+.. |NegativeMediumSpace| unicode:: U+0200B .. ZERO WIDTH SPACE
+.. |NegativeThickSpace| unicode:: U+0200B .. ZERO WIDTH SPACE
+.. |NegativeThinSpace| unicode:: U+0200B .. ZERO WIDTH SPACE
+.. |NegativeVeryThinSpace| unicode:: U+0200B .. ZERO WIDTH SPACE
+.. |NestedGreaterGreater| unicode:: U+0226B .. MUCH GREATER-THAN
+.. |NestedLessLess| unicode:: U+0226A .. MUCH LESS-THAN
+.. |nexists| unicode:: U+02204 .. THERE DOES NOT EXIST
+.. |ngeq| unicode:: U+02271 .. NEITHER GREATER-THAN NOR EQUAL TO
+.. |ngeqq| unicode:: U+02267 U+00338 .. GREATER-THAN OVER EQUAL TO with slash
+.. |ngeqslant| unicode:: U+02A7E U+00338 .. GREATER-THAN OR SLANTED EQUAL TO with slash
+.. |ngtr| unicode:: U+0226F .. NOT GREATER-THAN
+.. |nLeftarrow| unicode:: U+021CD .. LEFTWARDS DOUBLE ARROW WITH STROKE
+.. |nleftarrow| unicode:: U+0219A .. LEFTWARDS ARROW WITH STROKE
+.. |nLeftrightarrow| unicode:: U+021CE .. LEFT RIGHT DOUBLE ARROW WITH STROKE
+.. |nleftrightarrow| unicode:: U+021AE .. LEFT RIGHT ARROW WITH STROKE
+.. |nleq| unicode:: U+02270 .. NEITHER LESS-THAN NOR EQUAL TO
+.. |nleqq| unicode:: U+02266 U+00338 .. LESS-THAN OVER EQUAL TO with slash
+.. |nleqslant| unicode:: U+02A7D U+00338 .. LESS-THAN OR SLANTED EQUAL TO with slash
+.. |nless| unicode:: U+0226E .. NOT LESS-THAN
+.. |NonBreakingSpace| unicode:: U+000A0 .. NO-BREAK SPACE
+.. |NotCongruent| unicode:: U+02262 .. NOT IDENTICAL TO
+.. |NotDoubleVerticalBar| unicode:: U+02226 .. NOT PARALLEL TO
+.. |NotElement| unicode:: U+02209 .. NOT AN ELEMENT OF
+.. |NotEqual| unicode:: U+02260 .. NOT EQUAL TO
+.. |NotEqualTilde| unicode:: U+02242 U+00338 .. MINUS TILDE with slash
+.. |NotExists| unicode:: U+02204 .. THERE DOES NOT EXIST
+.. |NotGreater| unicode:: U+0226F .. NOT GREATER-THAN
+.. |NotGreaterEqual| unicode:: U+02271 .. NEITHER GREATER-THAN NOR EQUAL TO
+.. |NotGreaterFullEqual| unicode:: U+02266 U+00338 .. LESS-THAN OVER EQUAL TO with slash
+.. |NotGreaterGreater| unicode:: U+0226B U+00338 .. MUCH GREATER THAN with slash
+.. |NotGreaterLess| unicode:: U+02279 .. NEITHER GREATER-THAN NOR LESS-THAN
+.. |NotGreaterSlantEqual| unicode:: U+02A7E U+00338 .. GREATER-THAN OR SLANTED EQUAL TO with slash
+.. |NotGreaterTilde| unicode:: U+02275 .. NEITHER GREATER-THAN NOR EQUIVALENT TO
+.. |NotHumpDownHump| unicode:: U+0224E U+00338 .. GEOMETRICALLY EQUIVALENT TO with slash
+.. |NotLeftTriangle| unicode:: U+022EA .. NOT NORMAL SUBGROUP OF
+.. |NotLeftTriangleEqual| unicode:: U+022EC .. NOT NORMAL SUBGROUP OF OR EQUAL TO
+.. |NotLess| unicode:: U+0226E .. NOT LESS-THAN
+.. |NotLessEqual| unicode:: U+02270 .. NEITHER LESS-THAN NOR EQUAL TO
+.. |NotLessGreater| unicode:: U+02278 .. NEITHER LESS-THAN NOR GREATER-THAN
+.. |NotLessLess| unicode:: U+0226A U+00338 .. MUCH LESS THAN with slash
+.. |NotLessSlantEqual| unicode:: U+02A7D U+00338 .. LESS-THAN OR SLANTED EQUAL TO with slash
+.. |NotLessTilde| unicode:: U+02274 .. NEITHER LESS-THAN NOR EQUIVALENT TO
+.. |NotPrecedes| unicode:: U+02280 .. DOES NOT PRECEDE
+.. |NotPrecedesEqual| unicode:: U+02AAF U+00338 .. PRECEDES ABOVE SINGLE-LINE EQUALS SIGN with slash
+.. |NotPrecedesSlantEqual| unicode:: U+022E0 .. DOES NOT PRECEDE OR EQUAL
+.. |NotReverseElement| unicode:: U+0220C .. DOES NOT CONTAIN AS MEMBER
+.. |NotRightTriangle| unicode:: U+022EB .. DOES NOT CONTAIN AS NORMAL SUBGROUP
+.. |NotRightTriangleEqual| unicode:: U+022ED .. DOES NOT CONTAIN AS NORMAL SUBGROUP OR EQUAL
+.. |NotSquareSubsetEqual| unicode:: U+022E2 .. NOT SQUARE IMAGE OF OR EQUAL TO
+.. |NotSquareSupersetEqual| unicode:: U+022E3 .. NOT SQUARE ORIGINAL OF OR EQUAL TO
+.. |NotSubset| unicode:: U+02282 U+020D2 .. SUBSET OF with vertical line
+.. |NotSubsetEqual| unicode:: U+02288 .. NEITHER A SUBSET OF NOR EQUAL TO
+.. |NotSucceeds| unicode:: U+02281 .. DOES NOT SUCCEED
+.. |NotSucceedsEqual| unicode:: U+02AB0 U+00338 .. SUCCEEDS ABOVE SINGLE-LINE EQUALS SIGN with slash
+.. |NotSucceedsSlantEqual| unicode:: U+022E1 .. DOES NOT SUCCEED OR EQUAL
+.. |NotSuperset| unicode:: U+02283 U+020D2 .. SUPERSET OF with vertical line
+.. |NotSupersetEqual| unicode:: U+02289 .. NEITHER A SUPERSET OF NOR EQUAL TO
+.. |NotTilde| unicode:: U+02241 .. NOT TILDE
+.. |NotTildeEqual| unicode:: U+02244 .. NOT ASYMPTOTICALLY EQUAL TO
+.. |NotTildeFullEqual| unicode:: U+02247 .. NEITHER APPROXIMATELY NOR ACTUALLY EQUAL TO
+.. |NotTildeTilde| unicode:: U+02249 .. NOT ALMOST EQUAL TO
+.. |NotVerticalBar| unicode:: U+02224 .. DOES NOT DIVIDE
+.. |nparallel| unicode:: U+02226 .. NOT PARALLEL TO
+.. |nprec| unicode:: U+02280 .. DOES NOT PRECEDE
+.. |npreceq| unicode:: U+02AAF U+00338 .. PRECEDES ABOVE SINGLE-LINE EQUALS SIGN with slash
+.. |nRightarrow| unicode:: U+021CF .. RIGHTWARDS DOUBLE ARROW WITH STROKE
+.. |nrightarrow| unicode:: U+0219B .. RIGHTWARDS ARROW WITH STROKE
+.. |nshortmid| unicode:: U+02224 .. DOES NOT DIVIDE
+.. |nshortparallel| unicode:: U+02226 .. NOT PARALLEL TO
+.. |nsimeq| unicode:: U+02244 .. NOT ASYMPTOTICALLY EQUAL TO
+.. |nsubset| unicode:: U+02282 U+020D2 .. SUBSET OF with vertical line
+.. |nsubseteq| unicode:: U+02288 .. NEITHER A SUBSET OF NOR EQUAL TO
+.. |nsubseteqq| unicode:: U+02AC5 U+00338 .. SUBSET OF ABOVE EQUALS SIGN with slash
+.. |nsucc| unicode:: U+02281 .. DOES NOT SUCCEED
+.. |nsucceq| unicode:: U+02AB0 U+00338 .. SUCCEEDS ABOVE SINGLE-LINE EQUALS SIGN with slash
+.. |nsupset| unicode:: U+02283 U+020D2 .. SUPERSET OF with vertical line
+.. |nsupseteq| unicode:: U+02289 .. NEITHER A SUPERSET OF NOR EQUAL TO
+.. |nsupseteqq| unicode:: U+02AC6 U+00338 .. SUPERSET OF ABOVE EQUALS SIGN with slash
+.. |ntriangleleft| unicode:: U+022EA .. NOT NORMAL SUBGROUP OF
+.. |ntrianglelefteq| unicode:: U+022EC .. NOT NORMAL SUBGROUP OF OR EQUAL TO
+.. |ntriangleright| unicode:: U+022EB .. DOES NOT CONTAIN AS NORMAL SUBGROUP
+.. |ntrianglerighteq| unicode:: U+022ED .. DOES NOT CONTAIN AS NORMAL SUBGROUP OR EQUAL
+.. |nwarrow| unicode:: U+02196 .. NORTH WEST ARROW
+.. |oint| unicode:: U+0222E .. CONTOUR INTEGRAL
+.. |OpenCurlyDoubleQuote| unicode:: U+0201C .. LEFT DOUBLE QUOTATION MARK
+.. |OpenCurlyQuote| unicode:: U+02018 .. LEFT SINGLE QUOTATION MARK
+.. |orderof| unicode:: U+02134 .. SCRIPT SMALL O
+.. |parallel| unicode:: U+02225 .. PARALLEL TO
+.. |PartialD| unicode:: U+02202 .. PARTIAL DIFFERENTIAL
+.. |pitchfork| unicode:: U+022D4 .. PITCHFORK
+.. |PlusMinus| unicode:: U+000B1 .. PLUS-MINUS SIGN
+.. |pm| unicode:: U+000B1 .. PLUS-MINUS SIGN
+.. |Poincareplane| unicode:: U+0210C .. BLACK-LETTER CAPITAL H
+.. |prec| unicode:: U+0227A .. PRECEDES
+.. |precapprox| unicode:: U+02AB7 .. PRECEDES ABOVE ALMOST EQUAL TO
+.. |preccurlyeq| unicode:: U+0227C .. PRECEDES OR EQUAL TO
+.. |Precedes| unicode:: U+0227A .. PRECEDES
+.. |PrecedesEqual| unicode:: U+02AAF .. PRECEDES ABOVE SINGLE-LINE EQUALS SIGN
+.. |PrecedesSlantEqual| unicode:: U+0227C .. PRECEDES OR EQUAL TO
+.. |PrecedesTilde| unicode:: U+0227E .. PRECEDES OR EQUIVALENT TO
+.. |preceq| unicode:: U+02AAF .. PRECEDES ABOVE SINGLE-LINE EQUALS SIGN
+.. |precnapprox| unicode:: U+02AB9 .. PRECEDES ABOVE NOT ALMOST EQUAL TO
+.. |precneqq| unicode:: U+02AB5 .. PRECEDES ABOVE NOT EQUAL TO
+.. |precnsim| unicode:: U+022E8 .. PRECEDES BUT NOT EQUIVALENT TO
+.. |precsim| unicode:: U+0227E .. PRECEDES OR EQUIVALENT TO
+.. |primes| unicode:: U+02119 .. DOUBLE-STRUCK CAPITAL P
+.. |Proportion| unicode:: U+02237 .. PROPORTION
+.. |Proportional| unicode:: U+0221D .. PROPORTIONAL TO
+.. |propto| unicode:: U+0221D .. PROPORTIONAL TO
+.. |quaternions| unicode:: U+0210D .. DOUBLE-STRUCK CAPITAL H
+.. |questeq| unicode:: U+0225F .. QUESTIONED EQUAL TO
+.. |rangle| unicode:: U+0232A .. RIGHT-POINTING ANGLE BRACKET
+.. |rationals| unicode:: U+0211A .. DOUBLE-STRUCK CAPITAL Q
+.. |rbrace| unicode:: U+0007D .. RIGHT CURLY BRACKET
+.. |rbrack| unicode:: U+0005D .. RIGHT SQUARE BRACKET
+.. |Re| unicode:: U+0211C .. BLACK-LETTER CAPITAL R
+.. |realine| unicode:: U+0211B .. SCRIPT CAPITAL R
+.. |realpart| unicode:: U+0211C .. BLACK-LETTER CAPITAL R
+.. |reals| unicode:: U+0211D .. DOUBLE-STRUCK CAPITAL R
+.. |ReverseElement| unicode:: U+0220B .. CONTAINS AS MEMBER
+.. |ReverseEquilibrium| unicode:: U+021CB .. LEFTWARDS HARPOON OVER RIGHTWARDS HARPOON
+.. |ReverseUpEquilibrium| unicode:: U+0296F .. DOWNWARDS HARPOON WITH BARB LEFT BESIDE UPWARDS HARPOON WITH BARB RIGHT
+.. |RightAngleBracket| unicode:: U+0232A .. RIGHT-POINTING ANGLE BRACKET
+.. |RightArrow| unicode:: U+02192 .. RIGHTWARDS ARROW
+.. |Rightarrow| unicode:: U+021D2 .. RIGHTWARDS DOUBLE ARROW
+.. |rightarrow| unicode:: U+02192 .. RIGHTWARDS ARROW
+.. |RightArrowBar| unicode:: U+021E5 .. RIGHTWARDS ARROW TO BAR
+.. |RightArrowLeftArrow| unicode:: U+021C4 .. RIGHTWARDS ARROW OVER LEFTWARDS ARROW
+.. |rightarrowtail| unicode:: U+021A3 .. RIGHTWARDS ARROW WITH TAIL
+.. |RightCeiling| unicode:: U+02309 .. RIGHT CEILING
+.. |RightDoubleBracket| unicode:: U+0301B .. RIGHT WHITE SQUARE BRACKET
+.. |RightDownVector| unicode:: U+021C2 .. DOWNWARDS HARPOON WITH BARB RIGHTWARDS
+.. |RightFloor| unicode:: U+0230B .. RIGHT FLOOR
+.. |rightharpoondown| unicode:: U+021C1 .. RIGHTWARDS HARPOON WITH BARB DOWNWARDS
+.. |rightharpoonup| unicode:: U+021C0 .. RIGHTWARDS HARPOON WITH BARB UPWARDS
+.. |rightleftarrows| unicode:: U+021C4 .. RIGHTWARDS ARROW OVER LEFTWARDS ARROW
+.. |rightleftharpoons| unicode:: U+021CC .. RIGHTWARDS HARPOON OVER LEFTWARDS HARPOON
+.. |rightrightarrows| unicode:: U+021C9 .. RIGHTWARDS PAIRED ARROWS
+.. |rightsquigarrow| unicode:: U+0219D .. RIGHTWARDS WAVE ARROW
+.. |RightTee| unicode:: U+022A2 .. RIGHT TACK
+.. |RightTeeArrow| unicode:: U+021A6 .. RIGHTWARDS ARROW FROM BAR
+.. |rightthreetimes| unicode:: U+022CC .. RIGHT SEMIDIRECT PRODUCT
+.. |RightTriangle| unicode:: U+022B3 .. CONTAINS AS NORMAL SUBGROUP
+.. |RightTriangleEqual| unicode:: U+022B5 .. CONTAINS AS NORMAL SUBGROUP OR EQUAL TO
+.. |RightUpVector| unicode:: U+021BE .. UPWARDS HARPOON WITH BARB RIGHTWARDS
+.. |RightVector| unicode:: U+021C0 .. RIGHTWARDS HARPOON WITH BARB UPWARDS
+.. |risingdotseq| unicode:: U+02253 .. IMAGE OF OR APPROXIMATELY EQUAL TO
+.. |rmoustache| unicode:: U+023B1 .. UPPER RIGHT OR LOWER LEFT CURLY BRACKET SECTION
+.. |Rrightarrow| unicode:: U+021DB .. RIGHTWARDS TRIPLE ARROW
+.. |Rsh| unicode:: U+021B1 .. UPWARDS ARROW WITH TIP RIGHTWARDS
+.. |searrow| unicode:: U+02198 .. SOUTH EAST ARROW
+.. |setminus| unicode:: U+02216 .. SET MINUS
+.. |ShortDownArrow| unicode:: U+02193 .. DOWNWARDS ARROW
+.. |ShortLeftArrow| unicode:: U+02190 .. LEFTWARDS ARROW
+.. |shortmid| unicode:: U+02223 .. DIVIDES
+.. |shortparallel| unicode:: U+02225 .. PARALLEL TO
+.. |ShortRightArrow| unicode:: U+02192 .. RIGHTWARDS ARROW
+.. |ShortUpArrow| unicode:: U+02191 .. UPWARDS ARROW
+.. |simeq| unicode:: U+02243 .. ASYMPTOTICALLY EQUAL TO
+.. |SmallCircle| unicode:: U+02218 .. RING OPERATOR
+.. |smallsetminus| unicode:: U+02216 .. SET MINUS
+.. |spadesuit| unicode:: U+02660 .. BLACK SPADE SUIT
+.. |Sqrt| unicode:: U+0221A .. SQUARE ROOT
+.. |sqsubset| unicode:: U+0228F .. SQUARE IMAGE OF
+.. |sqsubseteq| unicode:: U+02291 .. SQUARE IMAGE OF OR EQUAL TO
+.. |sqsupset| unicode:: U+02290 .. SQUARE ORIGINAL OF
+.. |sqsupseteq| unicode:: U+02292 .. SQUARE ORIGINAL OF OR EQUAL TO
+.. |Square| unicode:: U+025A1 .. WHITE SQUARE
+.. |SquareIntersection| unicode:: U+02293 .. SQUARE CAP
+.. |SquareSubset| unicode:: U+0228F .. SQUARE IMAGE OF
+.. |SquareSubsetEqual| unicode:: U+02291 .. SQUARE IMAGE OF OR EQUAL TO
+.. |SquareSuperset| unicode:: U+02290 .. SQUARE ORIGINAL OF
+.. |SquareSupersetEqual| unicode:: U+02292 .. SQUARE ORIGINAL OF OR EQUAL TO
+.. |SquareUnion| unicode:: U+02294 .. SQUARE CUP
+.. |Star| unicode:: U+022C6 .. STAR OPERATOR
+.. |straightepsilon| unicode:: U+003F5 .. GREEK LUNATE EPSILON SYMBOL
+.. |straightphi| unicode:: U+003D5 .. GREEK PHI SYMBOL
+.. |Subset| unicode:: U+022D0 .. DOUBLE SUBSET
+.. |subset| unicode:: U+02282 .. SUBSET OF
+.. |subseteq| unicode:: U+02286 .. SUBSET OF OR EQUAL TO
+.. |subseteqq| unicode:: U+02AC5 .. SUBSET OF ABOVE EQUALS SIGN
+.. |SubsetEqual| unicode:: U+02286 .. SUBSET OF OR EQUAL TO
+.. |subsetneq| unicode:: U+0228A .. SUBSET OF WITH NOT EQUAL TO
+.. |subsetneqq| unicode:: U+02ACB .. SUBSET OF ABOVE NOT EQUAL TO
+.. |succ| unicode:: U+0227B .. SUCCEEDS
+.. |succapprox| unicode:: U+02AB8 .. SUCCEEDS ABOVE ALMOST EQUAL TO
+.. |succcurlyeq| unicode:: U+0227D .. SUCCEEDS OR EQUAL TO
+.. |Succeeds| unicode:: U+0227B .. SUCCEEDS
+.. |SucceedsEqual| unicode:: U+02AB0 .. SUCCEEDS ABOVE SINGLE-LINE EQUALS SIGN
+.. |SucceedsSlantEqual| unicode:: U+0227D .. SUCCEEDS OR EQUAL TO
+.. |SucceedsTilde| unicode:: U+0227F .. SUCCEEDS OR EQUIVALENT TO
+.. |succeq| unicode:: U+02AB0 .. SUCCEEDS ABOVE SINGLE-LINE EQUALS SIGN
+.. |succnapprox| unicode:: U+02ABA .. SUCCEEDS ABOVE NOT ALMOST EQUAL TO
+.. |succneqq| unicode:: U+02AB6 .. SUCCEEDS ABOVE NOT EQUAL TO
+.. |succnsim| unicode:: U+022E9 .. SUCCEEDS BUT NOT EQUIVALENT TO
+.. |succsim| unicode:: U+0227F .. SUCCEEDS OR EQUIVALENT TO
+.. |SuchThat| unicode:: U+0220B .. CONTAINS AS MEMBER
+.. |Sum| unicode:: U+02211 .. N-ARY SUMMATION
+.. |Superset| unicode:: U+02283 .. SUPERSET OF
+.. |SupersetEqual| unicode:: U+02287 .. SUPERSET OF OR EQUAL TO
+.. |Supset| unicode:: U+022D1 .. DOUBLE SUPERSET
+.. |supset| unicode:: U+02283 .. SUPERSET OF
+.. |supseteq| unicode:: U+02287 .. SUPERSET OF OR EQUAL TO
+.. |supseteqq| unicode:: U+02AC6 .. SUPERSET OF ABOVE EQUALS SIGN
+.. |supsetneq| unicode:: U+0228B .. SUPERSET OF WITH NOT EQUAL TO
+.. |supsetneqq| unicode:: U+02ACC .. SUPERSET OF ABOVE NOT EQUAL TO
+.. |swarrow| unicode:: U+02199 .. SOUTH WEST ARROW
+.. |Therefore| unicode:: U+02234 .. THEREFORE
+.. |therefore| unicode:: U+02234 .. THEREFORE
+.. |thickapprox| unicode:: U+02248 .. ALMOST EQUAL TO
+.. |thicksim| unicode:: U+0223C .. TILDE OPERATOR
+.. |ThinSpace| unicode:: U+02009 .. THIN SPACE
+.. |Tilde| unicode:: U+0223C .. TILDE OPERATOR
+.. |TildeEqual| unicode:: U+02243 .. ASYMPTOTICALLY EQUAL TO
+.. |TildeFullEqual| unicode:: U+02245 .. APPROXIMATELY EQUAL TO
+.. |TildeTilde| unicode:: U+02248 .. ALMOST EQUAL TO
+.. |toea| unicode:: U+02928 .. NORTH EAST ARROW AND SOUTH EAST ARROW
+.. |tosa| unicode:: U+02929 .. SOUTH EAST ARROW AND SOUTH WEST ARROW
+.. |triangle| unicode:: U+025B5 .. WHITE UP-POINTING SMALL TRIANGLE
+.. |triangledown| unicode:: U+025BF .. WHITE DOWN-POINTING SMALL TRIANGLE
+.. |triangleleft| unicode:: U+025C3 .. WHITE LEFT-POINTING SMALL TRIANGLE
+.. |trianglelefteq| unicode:: U+022B4 .. NORMAL SUBGROUP OF OR EQUAL TO
+.. |triangleq| unicode:: U+0225C .. DELTA EQUAL TO
+.. |triangleright| unicode:: U+025B9 .. WHITE RIGHT-POINTING SMALL TRIANGLE
+.. |trianglerighteq| unicode:: U+022B5 .. CONTAINS AS NORMAL SUBGROUP OR EQUAL TO
+.. |TripleDot| unicode:: U+020DB .. COMBINING THREE DOTS ABOVE
+.. |twoheadleftarrow| unicode:: U+0219E .. LEFTWARDS TWO HEADED ARROW
+.. |twoheadrightarrow| unicode:: U+021A0 .. RIGHTWARDS TWO HEADED ARROW
+.. |ulcorner| unicode:: U+0231C .. TOP LEFT CORNER
+.. |Union| unicode:: U+022C3 .. N-ARY UNION
+.. |UnionPlus| unicode:: U+0228E .. MULTISET UNION
+.. |UpArrow| unicode:: U+02191 .. UPWARDS ARROW
+.. |Uparrow| unicode:: U+021D1 .. UPWARDS DOUBLE ARROW
+.. |uparrow| unicode:: U+02191 .. UPWARDS ARROW
+.. |UpArrowDownArrow| unicode:: U+021C5 .. UPWARDS ARROW LEFTWARDS OF DOWNWARDS ARROW
+.. |UpDownArrow| unicode:: U+02195 .. UP DOWN ARROW
+.. |Updownarrow| unicode:: U+021D5 .. UP DOWN DOUBLE ARROW
+.. |updownarrow| unicode:: U+02195 .. UP DOWN ARROW
+.. |UpEquilibrium| unicode:: U+0296E .. UPWARDS HARPOON WITH BARB LEFT BESIDE DOWNWARDS HARPOON WITH BARB RIGHT
+.. |upharpoonleft| unicode:: U+021BF .. UPWARDS HARPOON WITH BARB LEFTWARDS
+.. |upharpoonright| unicode:: U+021BE .. UPWARDS HARPOON WITH BARB RIGHTWARDS
+.. |UpperLeftArrow| unicode:: U+02196 .. NORTH WEST ARROW
+.. |UpperRightArrow| unicode:: U+02197 .. NORTH EAST ARROW
+.. |upsilon| unicode:: U+003C5 .. GREEK SMALL LETTER UPSILON
+.. |UpTee| unicode:: U+022A5 .. UP TACK
+.. |UpTeeArrow| unicode:: U+021A5 .. UPWARDS ARROW FROM BAR
+.. |upuparrows| unicode:: U+021C8 .. UPWARDS PAIRED ARROWS
+.. |urcorner| unicode:: U+0231D .. TOP RIGHT CORNER
+.. |varepsilon| unicode:: U+003B5 .. GREEK SMALL LETTER EPSILON
+.. |varkappa| unicode:: U+003F0 .. GREEK KAPPA SYMBOL
+.. |varnothing| unicode:: U+02205 .. EMPTY SET
+.. |varphi| unicode:: U+003C6 .. GREEK SMALL LETTER PHI
+.. |varpi| unicode:: U+003D6 .. GREEK PI SYMBOL
+.. |varpropto| unicode:: U+0221D .. PROPORTIONAL TO
+.. |varrho| unicode:: U+003F1 .. GREEK RHO SYMBOL
+.. |varsigma| unicode:: U+003C2 .. GREEK SMALL LETTER FINAL SIGMA
+.. |varsubsetneq| unicode:: U+0228A U+0FE00 .. SUBSET OF WITH NOT EQUAL TO - variant with stroke through bottom members
+.. |varsubsetneqq| unicode:: U+02ACB U+0FE00 .. SUBSET OF ABOVE NOT EQUAL TO - variant with stroke through bottom members
+.. |varsupsetneq| unicode:: U+0228B U+0FE00 .. SUPERSET OF WITH NOT EQUAL TO - variant with stroke through bottom members
+.. |varsupsetneqq| unicode:: U+02ACC U+0FE00 .. SUPERSET OF ABOVE NOT EQUAL TO - variant with stroke through bottom members
+.. |vartheta| unicode:: U+003D1 .. GREEK THETA SYMBOL
+.. |vartriangleleft| unicode:: U+022B2 .. NORMAL SUBGROUP OF
+.. |vartriangleright| unicode:: U+022B3 .. CONTAINS AS NORMAL SUBGROUP
+.. |Vee| unicode:: U+022C1 .. N-ARY LOGICAL OR
+.. |vee| unicode:: U+02228 .. LOGICAL OR
+.. |Vert| unicode:: U+02016 .. DOUBLE VERTICAL LINE
+.. |vert| unicode:: U+0007C .. VERTICAL LINE
+.. |VerticalBar| unicode:: U+02223 .. DIVIDES
+.. |VerticalTilde| unicode:: U+02240 .. WREATH PRODUCT
+.. |VeryThinSpace| unicode:: U+0200A .. HAIR SPACE
+.. |Wedge| unicode:: U+022C0 .. N-ARY LOGICAL AND
+.. |wedge| unicode:: U+02227 .. LOGICAL AND
+.. |wp| unicode:: U+02118 .. SCRIPT CAPITAL P
+.. |wr| unicode:: U+02240 .. WREATH PRODUCT
+.. |zeetrf| unicode:: U+02128 .. BLACK-LETTER CAPITAL Z
--- /dev/null
+.. This data file has been placed in the public domain.
+.. Derived from the Unicode character mappings available from
+ <http://www.w3.org/2003/entities/xml/>.
+ Processed by unicode2rstsubs.py, part of Docutils:
+ <http://docutils.sourceforge.net>.
+
+.. |af| unicode:: U+02061 .. FUNCTION APPLICATION
+.. |aopf| unicode:: U+1D552 .. MATHEMATICAL DOUBLE-STRUCK SMALL A
+.. |asympeq| unicode:: U+0224D .. EQUIVALENT TO
+.. |bopf| unicode:: U+1D553 .. MATHEMATICAL DOUBLE-STRUCK SMALL B
+.. |copf| unicode:: U+1D554 .. MATHEMATICAL DOUBLE-STRUCK SMALL C
+.. |Cross| unicode:: U+02A2F .. VECTOR OR CROSS PRODUCT
+.. |DD| unicode:: U+02145 .. DOUBLE-STRUCK ITALIC CAPITAL D
+.. |dd| unicode:: U+02146 .. DOUBLE-STRUCK ITALIC SMALL D
+.. |dopf| unicode:: U+1D555 .. MATHEMATICAL DOUBLE-STRUCK SMALL D
+.. |DownArrowBar| unicode:: U+02913 .. DOWNWARDS ARROW TO BAR
+.. |DownBreve| unicode:: U+00311 .. COMBINING INVERTED BREVE
+.. |DownLeftRightVector| unicode:: U+02950 .. LEFT BARB DOWN RIGHT BARB DOWN HARPOON
+.. |DownLeftTeeVector| unicode:: U+0295E .. LEFTWARDS HARPOON WITH BARB DOWN FROM BAR
+.. |DownLeftVectorBar| unicode:: U+02956 .. LEFTWARDS HARPOON WITH BARB DOWN TO BAR
+.. |DownRightTeeVector| unicode:: U+0295F .. RIGHTWARDS HARPOON WITH BARB DOWN FROM BAR
+.. |DownRightVectorBar| unicode:: U+02957 .. RIGHTWARDS HARPOON WITH BARB DOWN TO BAR
+.. |ee| unicode:: U+02147 .. DOUBLE-STRUCK ITALIC SMALL E
+.. |EmptySmallSquare| unicode:: U+025FB .. WHITE MEDIUM SQUARE
+.. |EmptyVerySmallSquare| unicode:: U+025AB .. WHITE SMALL SQUARE
+.. |eopf| unicode:: U+1D556 .. MATHEMATICAL DOUBLE-STRUCK SMALL E
+.. |Equal| unicode:: U+02A75 .. TWO CONSECUTIVE EQUALS SIGNS
+.. |FilledSmallSquare| unicode:: U+025FC .. BLACK MEDIUM SQUARE
+.. |FilledVerySmallSquare| unicode:: U+025AA .. BLACK SMALL SQUARE
+.. |fopf| unicode:: U+1D557 .. MATHEMATICAL DOUBLE-STRUCK SMALL F
+.. |gopf| unicode:: U+1D558 .. MATHEMATICAL DOUBLE-STRUCK SMALL G
+.. |GreaterGreater| unicode:: U+02AA2 .. DOUBLE NESTED GREATER-THAN
+.. |Hat| unicode:: U+0005E .. CIRCUMFLEX ACCENT
+.. |hopf| unicode:: U+1D559 .. MATHEMATICAL DOUBLE-STRUCK SMALL H
+.. |HorizontalLine| unicode:: U+02500 .. BOX DRAWINGS LIGHT HORIZONTAL
+.. |ic| unicode:: U+02063 .. INVISIBLE SEPARATOR
+.. |ii| unicode:: U+02148 .. DOUBLE-STRUCK ITALIC SMALL I
+.. |iopf| unicode:: U+1D55A .. MATHEMATICAL DOUBLE-STRUCK SMALL I
+.. |it| unicode:: U+02062 .. INVISIBLE TIMES
+.. |jopf| unicode:: U+1D55B .. MATHEMATICAL DOUBLE-STRUCK SMALL J
+.. |kopf| unicode:: U+1D55C .. MATHEMATICAL DOUBLE-STRUCK SMALL K
+.. |larrb| unicode:: U+021E4 .. LEFTWARDS ARROW TO BAR
+.. |LeftDownTeeVector| unicode:: U+02961 .. DOWNWARDS HARPOON WITH BARB LEFT FROM BAR
+.. |LeftDownVectorBar| unicode:: U+02959 .. DOWNWARDS HARPOON WITH BARB LEFT TO BAR
+.. |LeftRightVector| unicode:: U+0294E .. LEFT BARB UP RIGHT BARB UP HARPOON
+.. |LeftTeeVector| unicode:: U+0295A .. LEFTWARDS HARPOON WITH BARB UP FROM BAR
+.. |LeftTriangleBar| unicode:: U+029CF .. LEFT TRIANGLE BESIDE VERTICAL BAR
+.. |LeftUpDownVector| unicode:: U+02951 .. UP BARB LEFT DOWN BARB LEFT HARPOON
+.. |LeftUpTeeVector| unicode:: U+02960 .. UPWARDS HARPOON WITH BARB LEFT FROM BAR
+.. |LeftUpVectorBar| unicode:: U+02958 .. UPWARDS HARPOON WITH BARB LEFT TO BAR
+.. |LeftVectorBar| unicode:: U+02952 .. LEFTWARDS HARPOON WITH BARB UP TO BAR
+.. |LessLess| unicode:: U+02AA1 .. DOUBLE NESTED LESS-THAN
+.. |lopf| unicode:: U+1D55D .. MATHEMATICAL DOUBLE-STRUCK SMALL L
+.. |mapstodown| unicode:: U+021A7 .. DOWNWARDS ARROW FROM BAR
+.. |mapstoleft| unicode:: U+021A4 .. LEFTWARDS ARROW FROM BAR
+.. |mapstoup| unicode:: U+021A5 .. UPWARDS ARROW FROM BAR
+.. |MediumSpace| unicode:: U+0205F .. MEDIUM MATHEMATICAL SPACE
+.. |mopf| unicode:: U+1D55E .. MATHEMATICAL DOUBLE-STRUCK SMALL M
+.. |nbump| unicode:: U+0224E U+00338 .. GEOMETRICALLY EQUIVALENT TO with slash
+.. |nbumpe| unicode:: U+0224F U+00338 .. DIFFERENCE BETWEEN with slash
+.. |nesim| unicode:: U+02242 U+00338 .. MINUS TILDE with slash
+.. |NewLine| unicode:: U+0000A .. LINE FEED (LF)
+.. |NoBreak| unicode:: U+02060 .. WORD JOINER
+.. |nopf| unicode:: U+1D55F .. MATHEMATICAL DOUBLE-STRUCK SMALL N
+.. |NotCupCap| unicode:: U+0226D .. NOT EQUIVALENT TO
+.. |NotHumpEqual| unicode:: U+0224F U+00338 .. DIFFERENCE BETWEEN with slash
+.. |NotLeftTriangleBar| unicode:: U+029CF U+00338 .. LEFT TRIANGLE BESIDE VERTICAL BAR with slash
+.. |NotNestedGreaterGreater| unicode:: U+02AA2 U+00338 .. DOUBLE NESTED GREATER-THAN with slash
+.. |NotNestedLessLess| unicode:: U+02AA1 U+00338 .. DOUBLE NESTED LESS-THAN with slash
+.. |NotRightTriangleBar| unicode:: U+029D0 U+00338 .. VERTICAL BAR BESIDE RIGHT TRIANGLE with slash
+.. |NotSquareSubset| unicode:: U+0228F U+00338 .. SQUARE IMAGE OF with slash
+.. |NotSquareSuperset| unicode:: U+02290 U+00338 .. SQUARE ORIGINAL OF with slash
+.. |NotSucceedsTilde| unicode:: U+0227F U+00338 .. SUCCEEDS OR EQUIVALENT TO with slash
+.. |oopf| unicode:: U+1D560 .. MATHEMATICAL DOUBLE-STRUCK SMALL O
+.. |OverBar| unicode:: U+000AF .. MACRON
+.. |OverBrace| unicode:: U+0FE37 .. PRESENTATION FORM FOR VERTICAL LEFT CURLY BRACKET
+.. |OverBracket| unicode:: U+023B4 .. TOP SQUARE BRACKET
+.. |OverParenthesis| unicode:: U+0FE35 .. PRESENTATION FORM FOR VERTICAL LEFT PARENTHESIS
+.. |planckh| unicode:: U+0210E .. PLANCK CONSTANT
+.. |popf| unicode:: U+1D561 .. MATHEMATICAL DOUBLE-STRUCK SMALL P
+.. |Product| unicode:: U+0220F .. N-ARY PRODUCT
+.. |qopf| unicode:: U+1D562 .. MATHEMATICAL DOUBLE-STRUCK SMALL Q
+.. |rarrb| unicode:: U+021E5 .. RIGHTWARDS ARROW TO BAR
+.. |RightDownTeeVector| unicode:: U+0295D .. DOWNWARDS HARPOON WITH BARB RIGHT FROM BAR
+.. |RightDownVectorBar| unicode:: U+02955 .. DOWNWARDS HARPOON WITH BARB RIGHT TO BAR
+.. |RightTeeVector| unicode:: U+0295B .. RIGHTWARDS HARPOON WITH BARB UP FROM BAR
+.. |RightTriangleBar| unicode:: U+029D0 .. VERTICAL BAR BESIDE RIGHT TRIANGLE
+.. |RightUpDownVector| unicode:: U+0294F .. UP BARB RIGHT DOWN BARB RIGHT HARPOON
+.. |RightUpTeeVector| unicode:: U+0295C .. UPWARDS HARPOON WITH BARB RIGHT FROM BAR
+.. |RightUpVectorBar| unicode:: U+02954 .. UPWARDS HARPOON WITH BARB RIGHT TO BAR
+.. |RightVectorBar| unicode:: U+02953 .. RIGHTWARDS HARPOON WITH BARB UP TO BAR
+.. |ropf| unicode:: U+1D563 .. MATHEMATICAL DOUBLE-STRUCK SMALL R
+.. |RoundImplies| unicode:: U+02970 .. RIGHT DOUBLE ARROW WITH ROUNDED HEAD
+.. |RuleDelayed| unicode:: U+029F4 .. RULE-DELAYED
+.. |sopf| unicode:: U+1D564 .. MATHEMATICAL DOUBLE-STRUCK SMALL S
+.. |Tab| unicode:: U+00009 .. CHARACTER TABULATION
+.. |ThickSpace| unicode:: U+02009 U+0200A U+0200A .. space of width 5/18 em
+.. |topf| unicode:: U+1D565 .. MATHEMATICAL DOUBLE-STRUCK SMALL T
+.. |UnderBar| unicode:: U+00332 .. COMBINING LOW LINE
+.. |UnderBrace| unicode:: U+0FE38 .. PRESENTATION FORM FOR VERTICAL RIGHT CURLY BRACKET
+.. |UnderBracket| unicode:: U+023B5 .. BOTTOM SQUARE BRACKET
+.. |UnderParenthesis| unicode:: U+0FE36 .. PRESENTATION FORM FOR VERTICAL RIGHT PARENTHESIS
+.. |uopf| unicode:: U+1D566 .. MATHEMATICAL DOUBLE-STRUCK SMALL U
+.. |UpArrowBar| unicode:: U+02912 .. UPWARDS ARROW TO BAR
+.. |Upsilon| unicode:: U+003A5 .. GREEK CAPITAL LETTER UPSILON
+.. |VerticalLine| unicode:: U+0007C .. VERTICAL LINE
+.. |VerticalSeparator| unicode:: U+02758 .. LIGHT VERTICAL BAR
+.. |vopf| unicode:: U+1D567 .. MATHEMATICAL DOUBLE-STRUCK SMALL V
+.. |wopf| unicode:: U+1D568 .. MATHEMATICAL DOUBLE-STRUCK SMALL W
+.. |xopf| unicode:: U+1D569 .. MATHEMATICAL DOUBLE-STRUCK SMALL X
+.. |yopf| unicode:: U+1D56A .. MATHEMATICAL DOUBLE-STRUCK SMALL Y
+.. |ZeroWidthSpace| unicode:: U+0200B .. ZERO WIDTH SPACE
+.. |zopf| unicode:: U+1D56B .. MATHEMATICAL DOUBLE-STRUCK SMALL Z
--- /dev/null
+.. This data file has been placed in the public domain.
+.. Derived from the Unicode character mappings available from
+ <http://www.w3.org/2003/entities/xml/>.
+ Processed by unicode2rstsubs.py, part of Docutils:
+ <http://docutils.sourceforge.net>.
+
+.. |af| unicode:: U+02061 .. FUNCTION APPLICATION
+.. |asympeq| unicode:: U+0224D .. EQUIVALENT TO
+.. |Cross| unicode:: U+02A2F .. VECTOR OR CROSS PRODUCT
+.. |DD| unicode:: U+02145 .. DOUBLE-STRUCK ITALIC CAPITAL D
+.. |dd| unicode:: U+02146 .. DOUBLE-STRUCK ITALIC SMALL D
+.. |DownArrowBar| unicode:: U+02913 .. DOWNWARDS ARROW TO BAR
+.. |DownBreve| unicode:: U+00311 .. COMBINING INVERTED BREVE
+.. |DownLeftRightVector| unicode:: U+02950 .. LEFT BARB DOWN RIGHT BARB DOWN HARPOON
+.. |DownLeftTeeVector| unicode:: U+0295E .. LEFTWARDS HARPOON WITH BARB DOWN FROM BAR
+.. |DownLeftVectorBar| unicode:: U+02956 .. LEFTWARDS HARPOON WITH BARB DOWN TO BAR
+.. |DownRightTeeVector| unicode:: U+0295F .. RIGHTWARDS HARPOON WITH BARB DOWN FROM BAR
+.. |DownRightVectorBar| unicode:: U+02957 .. RIGHTWARDS HARPOON WITH BARB DOWN TO BAR
+.. |ee| unicode:: U+02147 .. DOUBLE-STRUCK ITALIC SMALL E
+.. |EmptySmallSquare| unicode:: U+025FB .. WHITE MEDIUM SQUARE
+.. |EmptyVerySmallSquare| unicode:: U+025AB .. WHITE SMALL SQUARE
+.. |Equal| unicode:: U+02A75 .. TWO CONSECUTIVE EQUALS SIGNS
+.. |FilledSmallSquare| unicode:: U+025FC .. BLACK MEDIUM SQUARE
+.. |FilledVerySmallSquare| unicode:: U+025AA .. BLACK SMALL SQUARE
+.. |GreaterGreater| unicode:: U+02AA2 .. DOUBLE NESTED GREATER-THAN
+.. |Hat| unicode:: U+0005E .. CIRCUMFLEX ACCENT
+.. |HorizontalLine| unicode:: U+02500 .. BOX DRAWINGS LIGHT HORIZONTAL
+.. |ic| unicode:: U+02063 .. INVISIBLE SEPARATOR
+.. |ii| unicode:: U+02148 .. DOUBLE-STRUCK ITALIC SMALL I
+.. |it| unicode:: U+02062 .. INVISIBLE TIMES
+.. |larrb| unicode:: U+021E4 .. LEFTWARDS ARROW TO BAR
+.. |LeftDownTeeVector| unicode:: U+02961 .. DOWNWARDS HARPOON WITH BARB LEFT FROM BAR
+.. |LeftDownVectorBar| unicode:: U+02959 .. DOWNWARDS HARPOON WITH BARB LEFT TO BAR
+.. |LeftRightVector| unicode:: U+0294E .. LEFT BARB UP RIGHT BARB UP HARPOON
+.. |LeftTeeVector| unicode:: U+0295A .. LEFTWARDS HARPOON WITH BARB UP FROM BAR
+.. |LeftTriangleBar| unicode:: U+029CF .. LEFT TRIANGLE BESIDE VERTICAL BAR
+.. |LeftUpDownVector| unicode:: U+02951 .. UP BARB LEFT DOWN BARB LEFT HARPOON
+.. |LeftUpTeeVector| unicode:: U+02960 .. UPWARDS HARPOON WITH BARB LEFT FROM BAR
+.. |LeftUpVectorBar| unicode:: U+02958 .. UPWARDS HARPOON WITH BARB LEFT TO BAR
+.. |LeftVectorBar| unicode:: U+02952 .. LEFTWARDS HARPOON WITH BARB UP TO BAR
+.. |LessLess| unicode:: U+02AA1 .. DOUBLE NESTED LESS-THAN
+.. |mapstodown| unicode:: U+021A7 .. DOWNWARDS ARROW FROM BAR
+.. |mapstoleft| unicode:: U+021A4 .. LEFTWARDS ARROW FROM BAR
+.. |mapstoup| unicode:: U+021A5 .. UPWARDS ARROW FROM BAR
+.. |MediumSpace| unicode:: U+0205F .. MEDIUM MATHEMATICAL SPACE
+.. |nbump| unicode:: U+0224E U+00338 .. GEOMETRICALLY EQUIVALENT TO with slash
+.. |nbumpe| unicode:: U+0224F U+00338 .. DIFFERENCE BETWEEN with slash
+.. |nesim| unicode:: U+02242 U+00338 .. MINUS TILDE with slash
+.. |NewLine| unicode:: U+0000A .. LINE FEED (LF)
+.. |NoBreak| unicode:: U+02060 .. WORD JOINER
+.. |NotCupCap| unicode:: U+0226D .. NOT EQUIVALENT TO
+.. |NotHumpEqual| unicode:: U+0224F U+00338 .. DIFFERENCE BETWEEN with slash
+.. |NotLeftTriangleBar| unicode:: U+029CF U+00338 .. LEFT TRIANGLE BESIDE VERTICAL BAR with slash
+.. |NotNestedGreaterGreater| unicode:: U+02AA2 U+00338 .. DOUBLE NESTED GREATER-THAN with slash
+.. |NotNestedLessLess| unicode:: U+02AA1 U+00338 .. DOUBLE NESTED LESS-THAN with slash
+.. |NotRightTriangleBar| unicode:: U+029D0 U+00338 .. VERTICAL BAR BESIDE RIGHT TRIANGLE with slash
+.. |NotSquareSubset| unicode:: U+0228F U+00338 .. SQUARE IMAGE OF with slash
+.. |NotSquareSuperset| unicode:: U+02290 U+00338 .. SQUARE ORIGINAL OF with slash
+.. |NotSucceedsTilde| unicode:: U+0227F U+00338 .. SUCCEEDS OR EQUIVALENT TO with slash
+.. |OverBar| unicode:: U+000AF .. MACRON
+.. |OverBrace| unicode:: U+0FE37 .. PRESENTATION FORM FOR VERTICAL LEFT CURLY BRACKET
+.. |OverBracket| unicode:: U+023B4 .. TOP SQUARE BRACKET
+.. |OverParenthesis| unicode:: U+0FE35 .. PRESENTATION FORM FOR VERTICAL LEFT PARENTHESIS
+.. |planckh| unicode:: U+0210E .. PLANCK CONSTANT
+.. |Product| unicode:: U+0220F .. N-ARY PRODUCT
+.. |rarrb| unicode:: U+021E5 .. RIGHTWARDS ARROW TO BAR
+.. |RightDownTeeVector| unicode:: U+0295D .. DOWNWARDS HARPOON WITH BARB RIGHT FROM BAR
+.. |RightDownVectorBar| unicode:: U+02955 .. DOWNWARDS HARPOON WITH BARB RIGHT TO BAR
+.. |RightTeeVector| unicode:: U+0295B .. RIGHTWARDS HARPOON WITH BARB UP FROM BAR
+.. |RightTriangleBar| unicode:: U+029D0 .. VERTICAL BAR BESIDE RIGHT TRIANGLE
+.. |RightUpDownVector| unicode:: U+0294F .. UP BARB RIGHT DOWN BARB RIGHT HARPOON
+.. |RightUpTeeVector| unicode:: U+0295C .. UPWARDS HARPOON WITH BARB RIGHT FROM BAR
+.. |RightUpVectorBar| unicode:: U+02954 .. UPWARDS HARPOON WITH BARB RIGHT TO BAR
+.. |RightVectorBar| unicode:: U+02953 .. RIGHTWARDS HARPOON WITH BARB UP TO BAR
+.. |RoundImplies| unicode:: U+02970 .. RIGHT DOUBLE ARROW WITH ROUNDED HEAD
+.. |RuleDelayed| unicode:: U+029F4 .. RULE-DELAYED
+.. |Tab| unicode:: U+00009 .. CHARACTER TABULATION
+.. |ThickSpace| unicode:: U+02009 U+0200A U+0200A .. space of width 5/18 em
+.. |UnderBar| unicode:: U+00332 .. COMBINING LOW LINE
+.. |UnderBrace| unicode:: U+0FE38 .. PRESENTATION FORM FOR VERTICAL RIGHT CURLY BRACKET
+.. |UnderBracket| unicode:: U+023B5 .. BOTTOM SQUARE BRACKET
+.. |UnderParenthesis| unicode:: U+0FE36 .. PRESENTATION FORM FOR VERTICAL RIGHT PARENTHESIS
+.. |UpArrowBar| unicode:: U+02912 .. UPWARDS ARROW TO BAR
+.. |Upsilon| unicode:: U+003A5 .. GREEK CAPITAL LETTER UPSILON
+.. |VerticalLine| unicode:: U+0007C .. VERTICAL LINE
+.. |VerticalSeparator| unicode:: U+02758 .. LIGHT VERTICAL BAR
+.. |ZeroWidthSpace| unicode:: U+0200B .. ZERO WIDTH SPACE
--- /dev/null
+.. Definitions of interpreted text roles (classes) for S5/HTML data.
+.. This data file has been placed in the public domain.
+
+.. Colours
+ =======
+
+.. role:: black
+.. role:: gray
+.. role:: silver
+.. role:: white
+
+.. role:: maroon
+.. role:: red
+.. role:: magenta
+.. role:: fuchsia
+.. role:: pink
+.. role:: orange
+.. role:: yellow
+.. role:: lime
+.. role:: green
+.. role:: olive
+.. role:: teal
+.. role:: cyan
+.. role:: aqua
+.. role:: blue
+.. role:: navy
+.. role:: purple
+
+
+.. Text Sizes
+ ==========
+
+.. role:: huge
+.. role:: big
+.. role:: small
+.. role:: tiny
+
+
+.. Display in Slides (Presentation Mode) Only
+ ==========================================
+
+.. role:: slide
+ :class: slide-display
+
+
+.. Display in Outline Mode Only
+ ============================
+
+.. role:: outline
+
+
+.. Display in Print Only
+ =====================
+
+.. role:: print
+
+
+.. Display in Handout Mode Only
+ ============================
+
+.. role:: handout
+
+
+.. Incremental Display
+ ===================
+
+.. role:: incremental
+.. default-role:: incremental
--- /dev/null
+.. This data file has been placed in the public domain.
+.. Derived from the Unicode character mappings available from
+ <http://www.w3.org/2003/entities/xml/>.
+ Processed by unicode2rstsubs.py, part of Docutils:
+ <http://docutils.sourceforge.net>.
+
+.. |Aacute| unicode:: U+000C1 .. LATIN CAPITAL LETTER A WITH ACUTE
+.. |aacute| unicode:: U+000E1 .. LATIN SMALL LETTER A WITH ACUTE
+.. |Acirc| unicode:: U+000C2 .. LATIN CAPITAL LETTER A WITH CIRCUMFLEX
+.. |acirc| unicode:: U+000E2 .. LATIN SMALL LETTER A WITH CIRCUMFLEX
+.. |acute| unicode:: U+000B4 .. ACUTE ACCENT
+.. |AElig| unicode:: U+000C6 .. LATIN CAPITAL LETTER AE
+.. |aelig| unicode:: U+000E6 .. LATIN SMALL LETTER AE
+.. |Agrave| unicode:: U+000C0 .. LATIN CAPITAL LETTER A WITH GRAVE
+.. |agrave| unicode:: U+000E0 .. LATIN SMALL LETTER A WITH GRAVE
+.. |Aring| unicode:: U+000C5 .. LATIN CAPITAL LETTER A WITH RING ABOVE
+.. |aring| unicode:: U+000E5 .. LATIN SMALL LETTER A WITH RING ABOVE
+.. |Atilde| unicode:: U+000C3 .. LATIN CAPITAL LETTER A WITH TILDE
+.. |atilde| unicode:: U+000E3 .. LATIN SMALL LETTER A WITH TILDE
+.. |Auml| unicode:: U+000C4 .. LATIN CAPITAL LETTER A WITH DIAERESIS
+.. |auml| unicode:: U+000E4 .. LATIN SMALL LETTER A WITH DIAERESIS
+.. |brvbar| unicode:: U+000A6 .. BROKEN BAR
+.. |Ccedil| unicode:: U+000C7 .. LATIN CAPITAL LETTER C WITH CEDILLA
+.. |ccedil| unicode:: U+000E7 .. LATIN SMALL LETTER C WITH CEDILLA
+.. |cedil| unicode:: U+000B8 .. CEDILLA
+.. |cent| unicode:: U+000A2 .. CENT SIGN
+.. |copy| unicode:: U+000A9 .. COPYRIGHT SIGN
+.. |curren| unicode:: U+000A4 .. CURRENCY SIGN
+.. |deg| unicode:: U+000B0 .. DEGREE SIGN
+.. |divide| unicode:: U+000F7 .. DIVISION SIGN
+.. |Eacute| unicode:: U+000C9 .. LATIN CAPITAL LETTER E WITH ACUTE
+.. |eacute| unicode:: U+000E9 .. LATIN SMALL LETTER E WITH ACUTE
+.. |Ecirc| unicode:: U+000CA .. LATIN CAPITAL LETTER E WITH CIRCUMFLEX
+.. |ecirc| unicode:: U+000EA .. LATIN SMALL LETTER E WITH CIRCUMFLEX
+.. |Egrave| unicode:: U+000C8 .. LATIN CAPITAL LETTER E WITH GRAVE
+.. |egrave| unicode:: U+000E8 .. LATIN SMALL LETTER E WITH GRAVE
+.. |ETH| unicode:: U+000D0 .. LATIN CAPITAL LETTER ETH
+.. |eth| unicode:: U+000F0 .. LATIN SMALL LETTER ETH
+.. |Euml| unicode:: U+000CB .. LATIN CAPITAL LETTER E WITH DIAERESIS
+.. |euml| unicode:: U+000EB .. LATIN SMALL LETTER E WITH DIAERESIS
+.. |frac12| unicode:: U+000BD .. VULGAR FRACTION ONE HALF
+.. |frac14| unicode:: U+000BC .. VULGAR FRACTION ONE QUARTER
+.. |frac34| unicode:: U+000BE .. VULGAR FRACTION THREE QUARTERS
+.. |Iacute| unicode:: U+000CD .. LATIN CAPITAL LETTER I WITH ACUTE
+.. |iacute| unicode:: U+000ED .. LATIN SMALL LETTER I WITH ACUTE
+.. |Icirc| unicode:: U+000CE .. LATIN CAPITAL LETTER I WITH CIRCUMFLEX
+.. |icirc| unicode:: U+000EE .. LATIN SMALL LETTER I WITH CIRCUMFLEX
+.. |iexcl| unicode:: U+000A1 .. INVERTED EXCLAMATION MARK
+.. |Igrave| unicode:: U+000CC .. LATIN CAPITAL LETTER I WITH GRAVE
+.. |igrave| unicode:: U+000EC .. LATIN SMALL LETTER I WITH GRAVE
+.. |iquest| unicode:: U+000BF .. INVERTED QUESTION MARK
+.. |Iuml| unicode:: U+000CF .. LATIN CAPITAL LETTER I WITH DIAERESIS
+.. |iuml| unicode:: U+000EF .. LATIN SMALL LETTER I WITH DIAERESIS
+.. |laquo| unicode:: U+000AB .. LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
+.. |macr| unicode:: U+000AF .. MACRON
+.. |micro| unicode:: U+000B5 .. MICRO SIGN
+.. |middot| unicode:: U+000B7 .. MIDDLE DOT
+.. |nbsp| unicode:: U+000A0 .. NO-BREAK SPACE
+.. |not| unicode:: U+000AC .. NOT SIGN
+.. |Ntilde| unicode:: U+000D1 .. LATIN CAPITAL LETTER N WITH TILDE
+.. |ntilde| unicode:: U+000F1 .. LATIN SMALL LETTER N WITH TILDE
+.. |Oacute| unicode:: U+000D3 .. LATIN CAPITAL LETTER O WITH ACUTE
+.. |oacute| unicode:: U+000F3 .. LATIN SMALL LETTER O WITH ACUTE
+.. |Ocirc| unicode:: U+000D4 .. LATIN CAPITAL LETTER O WITH CIRCUMFLEX
+.. |ocirc| unicode:: U+000F4 .. LATIN SMALL LETTER O WITH CIRCUMFLEX
+.. |Ograve| unicode:: U+000D2 .. LATIN CAPITAL LETTER O WITH GRAVE
+.. |ograve| unicode:: U+000F2 .. LATIN SMALL LETTER O WITH GRAVE
+.. |ordf| unicode:: U+000AA .. FEMININE ORDINAL INDICATOR
+.. |ordm| unicode:: U+000BA .. MASCULINE ORDINAL INDICATOR
+.. |Oslash| unicode:: U+000D8 .. LATIN CAPITAL LETTER O WITH STROKE
+.. |oslash| unicode:: U+000F8 .. LATIN SMALL LETTER O WITH STROKE
+.. |Otilde| unicode:: U+000D5 .. LATIN CAPITAL LETTER O WITH TILDE
+.. |otilde| unicode:: U+000F5 .. LATIN SMALL LETTER O WITH TILDE
+.. |Ouml| unicode:: U+000D6 .. LATIN CAPITAL LETTER O WITH DIAERESIS
+.. |ouml| unicode:: U+000F6 .. LATIN SMALL LETTER O WITH DIAERESIS
+.. |para| unicode:: U+000B6 .. PILCROW SIGN
+.. |plusmn| unicode:: U+000B1 .. PLUS-MINUS SIGN
+.. |pound| unicode:: U+000A3 .. POUND SIGN
+.. |raquo| unicode:: U+000BB .. RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
+.. |reg| unicode:: U+000AE .. REGISTERED SIGN
+.. |sect| unicode:: U+000A7 .. SECTION SIGN
+.. |shy| unicode:: U+000AD .. SOFT HYPHEN
+.. |sup1| unicode:: U+000B9 .. SUPERSCRIPT ONE
+.. |sup2| unicode:: U+000B2 .. SUPERSCRIPT TWO
+.. |sup3| unicode:: U+000B3 .. SUPERSCRIPT THREE
+.. |szlig| unicode:: U+000DF .. LATIN SMALL LETTER SHARP S
+.. |THORN| unicode:: U+000DE .. LATIN CAPITAL LETTER THORN
+.. |thorn| unicode:: U+000FE .. LATIN SMALL LETTER THORN
+.. |times| unicode:: U+000D7 .. MULTIPLICATION SIGN
+.. |Uacute| unicode:: U+000DA .. LATIN CAPITAL LETTER U WITH ACUTE
+.. |uacute| unicode:: U+000FA .. LATIN SMALL LETTER U WITH ACUTE
+.. |Ucirc| unicode:: U+000DB .. LATIN CAPITAL LETTER U WITH CIRCUMFLEX
+.. |ucirc| unicode:: U+000FB .. LATIN SMALL LETTER U WITH CIRCUMFLEX
+.. |Ugrave| unicode:: U+000D9 .. LATIN CAPITAL LETTER U WITH GRAVE
+.. |ugrave| unicode:: U+000F9 .. LATIN SMALL LETTER U WITH GRAVE
+.. |uml| unicode:: U+000A8 .. DIAERESIS
+.. |Uuml| unicode:: U+000DC .. LATIN CAPITAL LETTER U WITH DIAERESIS
+.. |uuml| unicode:: U+000FC .. LATIN SMALL LETTER U WITH DIAERESIS
+.. |Yacute| unicode:: U+000DD .. LATIN CAPITAL LETTER Y WITH ACUTE
+.. |yacute| unicode:: U+000FD .. LATIN SMALL LETTER Y WITH ACUTE
+.. |yen| unicode:: U+000A5 .. YEN SIGN
+.. |yuml| unicode:: U+000FF .. LATIN SMALL LETTER Y WITH DIAERESIS
--- /dev/null
+.. This data file has been placed in the public domain.
+.. Derived from the Unicode character mappings available from
+ <http://www.w3.org/2003/entities/xml/>.
+ Processed by unicode2rstsubs.py, part of Docutils:
+ <http://docutils.sourceforge.net>.
+
+.. |bdquo| unicode:: U+0201E .. DOUBLE LOW-9 QUOTATION MARK
+.. |circ| unicode:: U+002C6 .. MODIFIER LETTER CIRCUMFLEX ACCENT
+.. |Dagger| unicode:: U+02021 .. DOUBLE DAGGER
+.. |dagger| unicode:: U+02020 .. DAGGER
+.. |emsp| unicode:: U+02003 .. EM SPACE
+.. |ensp| unicode:: U+02002 .. EN SPACE
+.. |euro| unicode:: U+020AC .. EURO SIGN
+.. |gt| unicode:: U+0003E .. GREATER-THAN SIGN
+.. |ldquo| unicode:: U+0201C .. LEFT DOUBLE QUOTATION MARK
+.. |lrm| unicode:: U+0200E .. LEFT-TO-RIGHT MARK
+.. |lsaquo| unicode:: U+02039 .. SINGLE LEFT-POINTING ANGLE QUOTATION MARK
+.. |lsquo| unicode:: U+02018 .. LEFT SINGLE QUOTATION MARK
+.. |lt| unicode:: U+0003C .. LESS-THAN SIGN
+.. |mdash| unicode:: U+02014 .. EM DASH
+.. |ndash| unicode:: U+02013 .. EN DASH
+.. |OElig| unicode:: U+00152 .. LATIN CAPITAL LIGATURE OE
+.. |oelig| unicode:: U+00153 .. LATIN SMALL LIGATURE OE
+.. |permil| unicode:: U+02030 .. PER MILLE SIGN
+.. |quot| unicode:: U+00022 .. QUOTATION MARK
+.. |rdquo| unicode:: U+0201D .. RIGHT DOUBLE QUOTATION MARK
+.. |rlm| unicode:: U+0200F .. RIGHT-TO-LEFT MARK
+.. |rsaquo| unicode:: U+0203A .. SINGLE RIGHT-POINTING ANGLE QUOTATION MARK
+.. |rsquo| unicode:: U+02019 .. RIGHT SINGLE QUOTATION MARK
+.. |sbquo| unicode:: U+0201A .. SINGLE LOW-9 QUOTATION MARK
+.. |Scaron| unicode:: U+00160 .. LATIN CAPITAL LETTER S WITH CARON
+.. |scaron| unicode:: U+00161 .. LATIN SMALL LETTER S WITH CARON
+.. |thinsp| unicode:: U+02009 .. THIN SPACE
+.. |tilde| unicode:: U+002DC .. SMALL TILDE
+.. |Yuml| unicode:: U+00178 .. LATIN CAPITAL LETTER Y WITH DIAERESIS
+.. |zwj| unicode:: U+0200D .. ZERO WIDTH JOINER
+.. |zwnj| unicode:: U+0200C .. ZERO WIDTH NON-JOINER
--- /dev/null
+.. This data file has been placed in the public domain.
+.. Derived from the Unicode character mappings available from
+ <http://www.w3.org/2003/entities/xml/>.
+ Processed by unicode2rstsubs.py, part of Docutils:
+ <http://docutils.sourceforge.net>.
+
+.. |alefsym| unicode:: U+02135 .. ALEF SYMBOL
+.. |Alpha| unicode:: U+00391 .. GREEK CAPITAL LETTER ALPHA
+.. |alpha| unicode:: U+003B1 .. GREEK SMALL LETTER ALPHA
+.. |and| unicode:: U+02227 .. LOGICAL AND
+.. |ang| unicode:: U+02220 .. ANGLE
+.. |asymp| unicode:: U+02248 .. ALMOST EQUAL TO
+.. |Beta| unicode:: U+00392 .. GREEK CAPITAL LETTER BETA
+.. |beta| unicode:: U+003B2 .. GREEK SMALL LETTER BETA
+.. |bull| unicode:: U+02022 .. BULLET
+.. |cap| unicode:: U+02229 .. INTERSECTION
+.. |Chi| unicode:: U+003A7 .. GREEK CAPITAL LETTER CHI
+.. |chi| unicode:: U+003C7 .. GREEK SMALL LETTER CHI
+.. |clubs| unicode:: U+02663 .. BLACK CLUB SUIT
+.. |cong| unicode:: U+02245 .. APPROXIMATELY EQUAL TO
+.. |crarr| unicode:: U+021B5 .. DOWNWARDS ARROW WITH CORNER LEFTWARDS
+.. |cup| unicode:: U+0222A .. UNION
+.. |dArr| unicode:: U+021D3 .. DOWNWARDS DOUBLE ARROW
+.. |darr| unicode:: U+02193 .. DOWNWARDS ARROW
+.. |Delta| unicode:: U+00394 .. GREEK CAPITAL LETTER DELTA
+.. |delta| unicode:: U+003B4 .. GREEK SMALL LETTER DELTA
+.. |diams| unicode:: U+02666 .. BLACK DIAMOND SUIT
+.. |empty| unicode:: U+02205 .. EMPTY SET
+.. |Epsilon| unicode:: U+00395 .. GREEK CAPITAL LETTER EPSILON
+.. |epsilon| unicode:: U+003B5 .. GREEK SMALL LETTER EPSILON
+.. |equiv| unicode:: U+02261 .. IDENTICAL TO
+.. |Eta| unicode:: U+00397 .. GREEK CAPITAL LETTER ETA
+.. |eta| unicode:: U+003B7 .. GREEK SMALL LETTER ETA
+.. |exist| unicode:: U+02203 .. THERE EXISTS
+.. |fnof| unicode:: U+00192 .. LATIN SMALL LETTER F WITH HOOK
+.. |forall| unicode:: U+02200 .. FOR ALL
+.. |frasl| unicode:: U+02044 .. FRACTION SLASH
+.. |Gamma| unicode:: U+00393 .. GREEK CAPITAL LETTER GAMMA
+.. |gamma| unicode:: U+003B3 .. GREEK SMALL LETTER GAMMA
+.. |ge| unicode:: U+02265 .. GREATER-THAN OR EQUAL TO
+.. |hArr| unicode:: U+021D4 .. LEFT RIGHT DOUBLE ARROW
+.. |harr| unicode:: U+02194 .. LEFT RIGHT ARROW
+.. |hearts| unicode:: U+02665 .. BLACK HEART SUIT
+.. |hellip| unicode:: U+02026 .. HORIZONTAL ELLIPSIS
+.. |image| unicode:: U+02111 .. BLACK-LETTER CAPITAL I
+.. |infin| unicode:: U+0221E .. INFINITY
+.. |int| unicode:: U+0222B .. INTEGRAL
+.. |Iota| unicode:: U+00399 .. GREEK CAPITAL LETTER IOTA
+.. |iota| unicode:: U+003B9 .. GREEK SMALL LETTER IOTA
+.. |isin| unicode:: U+02208 .. ELEMENT OF
+.. |Kappa| unicode:: U+0039A .. GREEK CAPITAL LETTER KAPPA
+.. |kappa| unicode:: U+003BA .. GREEK SMALL LETTER KAPPA
+.. |Lambda| unicode:: U+0039B .. GREEK CAPITAL LETTER LAMDA
+.. |lambda| unicode:: U+003BB .. GREEK SMALL LETTER LAMDA
+.. |lang| unicode:: U+02329 .. LEFT-POINTING ANGLE BRACKET
+.. |lArr| unicode:: U+021D0 .. LEFTWARDS DOUBLE ARROW
+.. |larr| unicode:: U+02190 .. LEFTWARDS ARROW
+.. |lceil| unicode:: U+02308 .. LEFT CEILING
+.. |le| unicode:: U+02264 .. LESS-THAN OR EQUAL TO
+.. |lfloor| unicode:: U+0230A .. LEFT FLOOR
+.. |lowast| unicode:: U+02217 .. ASTERISK OPERATOR
+.. |loz| unicode:: U+025CA .. LOZENGE
+.. |minus| unicode:: U+02212 .. MINUS SIGN
+.. |Mu| unicode:: U+0039C .. GREEK CAPITAL LETTER MU
+.. |mu| unicode:: U+003BC .. GREEK SMALL LETTER MU
+.. |nabla| unicode:: U+02207 .. NABLA
+.. |ne| unicode:: U+02260 .. NOT EQUAL TO
+.. |ni| unicode:: U+0220B .. CONTAINS AS MEMBER
+.. |notin| unicode:: U+02209 .. NOT AN ELEMENT OF
+.. |nsub| unicode:: U+02284 .. NOT A SUBSET OF
+.. |Nu| unicode:: U+0039D .. GREEK CAPITAL LETTER NU
+.. |nu| unicode:: U+003BD .. GREEK SMALL LETTER NU
+.. |oline| unicode:: U+0203E .. OVERLINE
+.. |Omega| unicode:: U+003A9 .. GREEK CAPITAL LETTER OMEGA
+.. |omega| unicode:: U+003C9 .. GREEK SMALL LETTER OMEGA
+.. |Omicron| unicode:: U+0039F .. GREEK CAPITAL LETTER OMICRON
+.. |omicron| unicode:: U+003BF .. GREEK SMALL LETTER OMICRON
+.. |oplus| unicode:: U+02295 .. CIRCLED PLUS
+.. |or| unicode:: U+02228 .. LOGICAL OR
+.. |otimes| unicode:: U+02297 .. CIRCLED TIMES
+.. |part| unicode:: U+02202 .. PARTIAL DIFFERENTIAL
+.. |perp| unicode:: U+022A5 .. UP TACK
+.. |Phi| unicode:: U+003A6 .. GREEK CAPITAL LETTER PHI
+.. |phi| unicode:: U+003D5 .. GREEK PHI SYMBOL
+.. |Pi| unicode:: U+003A0 .. GREEK CAPITAL LETTER PI
+.. |pi| unicode:: U+003C0 .. GREEK SMALL LETTER PI
+.. |piv| unicode:: U+003D6 .. GREEK PI SYMBOL
+.. |Prime| unicode:: U+02033 .. DOUBLE PRIME
+.. |prime| unicode:: U+02032 .. PRIME
+.. |prod| unicode:: U+0220F .. N-ARY PRODUCT
+.. |prop| unicode:: U+0221D .. PROPORTIONAL TO
+.. |Psi| unicode:: U+003A8 .. GREEK CAPITAL LETTER PSI
+.. |psi| unicode:: U+003C8 .. GREEK SMALL LETTER PSI
+.. |radic| unicode:: U+0221A .. SQUARE ROOT
+.. |rang| unicode:: U+0232A .. RIGHT-POINTING ANGLE BRACKET
+.. |rArr| unicode:: U+021D2 .. RIGHTWARDS DOUBLE ARROW
+.. |rarr| unicode:: U+02192 .. RIGHTWARDS ARROW
+.. |rceil| unicode:: U+02309 .. RIGHT CEILING
+.. |real| unicode:: U+0211C .. BLACK-LETTER CAPITAL R
+.. |rfloor| unicode:: U+0230B .. RIGHT FLOOR
+.. |Rho| unicode:: U+003A1 .. GREEK CAPITAL LETTER RHO
+.. |rho| unicode:: U+003C1 .. GREEK SMALL LETTER RHO
+.. |sdot| unicode:: U+022C5 .. DOT OPERATOR
+.. |Sigma| unicode:: U+003A3 .. GREEK CAPITAL LETTER SIGMA
+.. |sigma| unicode:: U+003C3 .. GREEK SMALL LETTER SIGMA
+.. |sigmaf| unicode:: U+003C2 .. GREEK SMALL LETTER FINAL SIGMA
+.. |sim| unicode:: U+0223C .. TILDE OPERATOR
+.. |spades| unicode:: U+02660 .. BLACK SPADE SUIT
+.. |sub| unicode:: U+02282 .. SUBSET OF
+.. |sube| unicode:: U+02286 .. SUBSET OF OR EQUAL TO
+.. |sum| unicode:: U+02211 .. N-ARY SUMMATION
+.. |sup| unicode:: U+02283 .. SUPERSET OF
+.. |supe| unicode:: U+02287 .. SUPERSET OF OR EQUAL TO
+.. |Tau| unicode:: U+003A4 .. GREEK CAPITAL LETTER TAU
+.. |tau| unicode:: U+003C4 .. GREEK SMALL LETTER TAU
+.. |there4| unicode:: U+02234 .. THEREFORE
+.. |Theta| unicode:: U+00398 .. GREEK CAPITAL LETTER THETA
+.. |theta| unicode:: U+003B8 .. GREEK SMALL LETTER THETA
+.. |thetasym| unicode:: U+003D1 .. GREEK THETA SYMBOL
+.. |trade| unicode:: U+02122 .. TRADE MARK SIGN
+.. |uArr| unicode:: U+021D1 .. UPWARDS DOUBLE ARROW
+.. |uarr| unicode:: U+02191 .. UPWARDS ARROW
+.. |upsih| unicode:: U+003D2 .. GREEK UPSILON WITH HOOK SYMBOL
+.. |Upsilon| unicode:: U+003A5 .. GREEK CAPITAL LETTER UPSILON
+.. |upsilon| unicode:: U+003C5 .. GREEK SMALL LETTER UPSILON
+.. |weierp| unicode:: U+02118 .. SCRIPT CAPITAL P
+.. |Xi| unicode:: U+0039E .. GREEK CAPITAL LETTER XI
+.. |xi| unicode:: U+003BE .. GREEK SMALL LETTER XI
+.. |Zeta| unicode:: U+00396 .. GREEK CAPITAL LETTER ZETA
+.. |zeta| unicode:: U+003B6 .. GREEK SMALL LETTER ZETA
--- /dev/null
+# $Id: __init__.py 8376 2019-08-27 19:49:29Z milde $
+# Author: David Goodger <goodger@python.org>
+# Copyright: This module has been placed in the public domain.
+
+# Internationalization details are documented in
+# <http://docutils.sf.net/docs/howto/i18n.html>.
+
+"""
+This package contains modules for language-dependent features of
+reStructuredText.
+"""
+
+__docformat__ = 'reStructuredText'
+
+import sys
+
+from docutils.utils import normalize_language_tag
+
+
+_languages = {}
+
+def get_language(language_code):
+ for tag in normalize_language_tag(language_code):
+ tag = tag.replace('-', '_') # '-' not valid in module names
+ if tag in _languages:
+ return _languages[tag]
+ try:
+ module = __import__(tag, globals(), locals(), level=1)
+ except ImportError:
+ try:
+ module = __import__(tag, globals(), locals(), level=0)
+ except ImportError:
+ continue
+ _languages[tag] = module
+ return module
+ return None
--- /dev/null
+# $Id: af.py 7119 2011-09-02 13:00:23Z milde $
+# Author: Jannie Hofmeyr <jhsh@sun.ac.za>
+# Copyright: This module has been placed in the public domain.
+
+# New language mappings are welcome. Before doing a new translation, please
+# read <http://docutils.sf.net/docs/howto/i18n.html>. Two files must be
+# translated for each language: one in docutils/languages, the other in
+# docutils/parsers/rst/languages.
+
+"""
+Afrikaans-language mappings for language-dependent features of
+reStructuredText.
+"""
+
+__docformat__ = 'reStructuredText'
+
+
+directives = {
+ 'aandag': 'attention',
+ 'versigtig': 'caution',
+ 'code (translation required)': 'code',
+ 'gevaar': 'danger',
+ 'fout': 'error',
+ 'wenk': 'hint',
+ 'belangrik': 'important',
+ 'nota': 'note',
+ 'tip': 'tip', # hint and tip both have the same translation: wenk
+ 'waarskuwing': 'warning',
+ 'vermaning': 'admonition',
+ 'kantstreep': 'sidebar',
+ 'onderwerp': 'topic',
+ 'lynblok': 'line-block',
+ 'math (translation required)': 'math',
+ 'parsed-literal (translation required)': 'parsed-literal',
+ 'rubriek': 'rubric',
+ 'epigraaf': 'epigraph',
+ 'hoogtepunte': 'highlights',
+ 'pull-quote (translation required)': 'pull-quote',
+ u'compound (translation required)': 'compound',
+ u'container (translation required)': 'container',
+ #'vrae': 'questions',
+ #'qa': 'questions',
+ #'faq': 'questions',
+ 'table (translation required)': 'table',
+ 'csv-table (translation required)': 'csv-table',
+ 'list-table (translation required)': 'list-table',
+ 'meta': 'meta',
+ #'beeldkaart': 'imagemap',
+ 'beeld': 'image',
+ 'figuur': 'figure',
+ 'insluiting': 'include',
+ 'rou': 'raw',
+ 'vervang': 'replace',
+ 'unicode': 'unicode', # should this be translated? unikode
+ 'datum': 'date',
+ 'klas': 'class',
+ 'role (translation required)': 'role',
+ 'default-role (translation required)': 'default-role',
+ 'title (translation required)': 'title',
+ 'inhoud': 'contents',
+ 'sectnum': 'sectnum',
+ 'section-numbering': 'sectnum',
+ u'header (translation required)': 'header',
+ u'footer (translation required)': 'footer',
+ #'voetnote': 'footnotes',
+ #'aanhalings': 'citations',
+ 'teikennotas': 'target-notes',
+ 'restructuredtext-test-directive': 'restructuredtext-test-directive'}
+"""Afrikaans name to registered (in directives/__init__.py) directive name
+mapping."""
+
+roles = {
+ 'afkorting': 'abbreviation',
+ 'ab': 'abbreviation',
+ 'akroniem': 'acronym',
+ 'ac': 'acronym',
+ u'code (translation required)': 'code',
+ 'indeks': 'index',
+ 'i': 'index',
+ 'voetskrif': 'subscript',
+ 'sub': 'subscript',
+ 'boskrif': 'superscript',
+ 'sup': 'superscript',
+ 'titelverwysing': 'title-reference',
+ 'titel': 'title-reference',
+ 't': 'title-reference',
+ 'pep-verwysing': 'pep-reference',
+ 'pep': 'pep-reference',
+ 'rfc-verwysing': 'rfc-reference',
+ 'rfc': 'rfc-reference',
+ 'nadruk': 'emphasis',
+ 'sterk': 'strong',
+ 'literal (translation required)': 'literal',
+ 'math (translation required)': 'math',
+ 'benoemde verwysing': 'named-reference',
+ 'anonieme verwysing': 'anonymous-reference',
+ 'voetnootverwysing': 'footnote-reference',
+ 'aanhalingverwysing': 'citation-reference',
+ 'vervangingsverwysing': 'substitution-reference',
+ 'teiken': 'target',
+ 'uri-verwysing': 'uri-reference',
+ 'uri': 'uri-reference',
+ 'url': 'uri-reference',
+ 'rou': 'raw',}
+"""Mapping of Afrikaans role names to canonical role names for interpreted text.
+"""
--- /dev/null
+# $Id: ca.py 7119 2011-09-02 13:00:23Z milde $
+# Author: Ivan Vilata i Balaguer <ivan@selidor.net>
+# Copyright: This module has been placed in the public domain.
+
+# New language mappings are welcome. Before doing a new translation, please
+# read <http://docutils.sf.net/docs/howto/i18n.html>. Two files must be
+# translated for each language: one in docutils/languages, the other in
+# docutils/parsers/rst/languages.
+
+"""
+Catalan-language mappings for language-dependent features of
+reStructuredText.
+"""
+
+__docformat__ = 'reStructuredText'
+
+
+directives = {
+ # language-dependent: fixed
+ u'atenci\u00F3': 'attention',
+ u'compte': 'caution',
+ u'code (translation required)': 'code',
+ u'perill': 'danger',
+ u'error': 'error',
+ u'suggeriment': 'hint',
+ u'important': 'important',
+ u'nota': 'note',
+ u'consell': 'tip',
+ u'av\u00EDs': 'warning',
+ u'advertiment': 'admonition',
+ u'nota-al-marge': 'sidebar',
+ u'nota-marge': 'sidebar',
+ u'tema': 'topic',
+ u'bloc-de-l\u00EDnies': 'line-block',
+ u'bloc-l\u00EDnies': 'line-block',
+ u'literal-analitzat': 'parsed-literal',
+ u'r\u00FAbrica': 'rubric',
+ u'ep\u00EDgraf': 'epigraph',
+ u'sumari': 'highlights',
+ u'cita-destacada': 'pull-quote',
+ u'compost': 'compound',
+ u'container (translation required)': 'container',
+ #'questions': 'questions',
+ u'taula': 'table',
+ u'taula-csv': 'csv-table',
+ u'taula-llista': 'list-table',
+ #'qa': 'questions',
+ #'faq': 'questions',
+ u'math (translation required)': 'math',
+ u'meta': 'meta',
+ #'imagemap': 'imagemap',
+ u'imatge': 'image',
+ u'figura': 'figure',
+ u'inclou': 'include',
+ u'incloure': 'include',
+ u'cru': 'raw',
+ u'reempla\u00E7a': 'replace',
+ u'reempla\u00E7ar': 'replace',
+ u'unicode': 'unicode',
+ u'data': 'date',
+ u'classe': 'class',
+ u'rol': 'role',
+ u'default-role (translation required)': 'default-role',
+ u'title (translation required)': 'title',
+ u'contingut': 'contents',
+ u'numsec': 'sectnum',
+ u'numeraci\u00F3-de-seccions': 'sectnum',
+ u'numeraci\u00F3-seccions': 'sectnum',
+ u'cap\u00E7alera': 'header',
+ u'peu-de-p\u00E0gina': 'footer',
+ u'peu-p\u00E0gina': 'footer',
+ #'footnotes': 'footnotes',
+ #'citations': 'citations',
+ u'notes-amb-destinacions': 'target-notes',
+ u'notes-destinacions': 'target-notes',
+ u'directiva-de-prova-de-restructuredtext': 'restructuredtext-test-directive'}
+"""Catalan name to registered (in directives/__init__.py) directive name
+mapping."""
+
+roles = {
+ # language-dependent: fixed
+ u'abreviatura': 'abbreviation',
+ u'abreviaci\u00F3': 'abbreviation',
+ u'abrev': 'abbreviation',
+ u'ab': 'abbreviation',
+ u'acr\u00F2nim': 'acronym',
+ u'ac': 'acronym',
+ u'code (translation required)': 'code',
+ u'\u00EDndex': 'index',
+ u'i': 'index',
+ u'sub\u00EDndex': 'subscript',
+ u'sub': 'subscript',
+ u'super\u00EDndex': 'superscript',
+ u'sup': 'superscript',
+ u'refer\u00E8ncia-a-t\u00EDtol': 'title-reference',
+ u'refer\u00E8ncia-t\u00EDtol': 'title-reference',
+ u't\u00EDtol': 'title-reference',
+ u't': 'title-reference',
+ u'refer\u00E8ncia-a-pep': 'pep-reference',
+ u'refer\u00E8ncia-pep': 'pep-reference',
+ u'pep': 'pep-reference',
+ u'refer\u00E8ncia-a-rfc': 'rfc-reference',
+ u'refer\u00E8ncia-rfc': 'rfc-reference',
+ u'rfc': 'rfc-reference',
+ u'\u00E8mfasi': 'emphasis',
+ u'destacat': 'strong',
+ u'literal': 'literal',
+ u'math (translation required)': 'math',
+ u'refer\u00E8ncia-amb-nom': 'named-reference',
+ u'refer\u00E8ncia-nom': 'named-reference',
+ u'refer\u00E8ncia-an\u00F2nima': 'anonymous-reference',
+ u'refer\u00E8ncia-a-nota-al-peu': 'footnote-reference',
+ u'refer\u00E8ncia-nota-al-peu': 'footnote-reference',
+ u'refer\u00E8ncia-a-cita': 'citation-reference',
+ u'refer\u00E8ncia-cita': 'citation-reference',
+ u'refer\u00E8ncia-a-substituci\u00F3': 'substitution-reference',
+ u'refer\u00E8ncia-substituci\u00F3': 'substitution-reference',
+ u'destinaci\u00F3': 'target',
+ u'refer\u00E8ncia-a-uri': 'uri-reference',
+ u'refer\u00E8ncia-uri': 'uri-reference',
+ u'uri': 'uri-reference',
+ u'url': 'uri-reference',
+ u'cru': 'raw',}
+"""Mapping of Catalan role names to canonical role names for interpreted text.
+"""
--- /dev/null
+# $Id: cs.py 7119 2011-09-02 13:00:23Z milde $
+# Author: Marek Blaha <mb@dat.cz>
+# Copyright: This module has been placed in the public domain.
+
+# New language mappings are welcome. Before doing a new translation, please
+# read <http://docutils.sf.net/docs/howto/i18n.html>. Two files must be
+# translated for each language: one in docutils/languages, the other in
+# docutils/parsers/rst/languages.
+
+"""
+Czech-language mappings for language-dependent features of
+reStructuredText.
+"""
+
+__docformat__ = 'reStructuredText'
+
+
+directives = {
+ # language-dependent: fixed
+ u'pozor': 'attention',
+ u'caution (translation required)': 'caution', # jak rozlisit caution a warning?
+ u'code (translation required)': 'code',
+ u'nebezpe\u010D\u00ED': 'danger',
+ u'chyba': 'error',
+ u'rada': 'hint',
+ u'd\u016Fle\u017Eit\u00E9': 'important',
+ u'pozn\u00E1mka': 'note',
+ u'tip (translation required)': 'tip',
+ u'varov\u00E1n\u00ED': 'warning',
+ u'admonition (translation required)': 'admonition',
+ u'sidebar (translation required)': 'sidebar',
+ u't\u00E9ma': 'topic',
+ u'line-block (translation required)': 'line-block',
+ u'parsed-literal (translation required)': 'parsed-literal',
+ u'odd\u00EDl': 'rubric',
+ u'moto': 'epigraph',
+ u'highlights (translation required)': 'highlights',
+ u'pull-quote (translation required)': 'pull-quote',
+ u'compound (translation required)': 'compound',
+ u'container (translation required)': 'container',
+ #'questions': 'questions',
+ #'qa': 'questions',
+ #'faq': 'questions',
+ u'table (translation required)': 'table',
+ u'csv-table (translation required)': 'csv-table',
+ u'list-table (translation required)': 'list-table',
+ u'math (translation required)': 'math',
+ u'meta (translation required)': 'meta',
+ #'imagemap': 'imagemap',
+ u'image (translation required)': 'image', # obrazek
+ u'figure (translation required)': 'figure', # a tady?
+ u'include (translation required)': 'include',
+ u'raw (translation required)': 'raw',
+ u'replace (translation required)': 'replace',
+ u'unicode (translation required)': 'unicode',
+ u'datum': 'date',
+ u't\u0159\u00EDda': 'class',
+ u'role (translation required)': 'role',
+ u'default-role (translation required)': 'default-role',
+ u'title (translation required)': 'title',
+ u'obsah': 'contents',
+ u'sectnum (translation required)': 'sectnum',
+ u'section-numbering (translation required)': 'sectnum',
+ u'header (translation required)': 'header',
+ u'footer (translation required)': 'footer',
+ #'footnotes': 'footnotes',
+ #'citations': 'citations',
+ u'target-notes (translation required)': 'target-notes',
+ u'restructuredtext-test-directive': 'restructuredtext-test-directive'}
+"""Czech name to registered (in directives/__init__.py) directive name
+mapping."""
+
+roles = {
+ # language-dependent: fixed
+ u'abbreviation (translation required)': 'abbreviation',
+ u'ab (translation required)': 'abbreviation',
+ u'acronym (translation required)': 'acronym',
+ u'ac (translation required)': 'acronym',
+ u'code (translation required)': 'code',
+ u'index (translation required)': 'index',
+ u'i (translation required)': 'index',
+ u'subscript (translation required)': 'subscript',
+ u'sub (translation required)': 'subscript',
+ u'superscript (translation required)': 'superscript',
+ u'sup (translation required)': 'superscript',
+ u'title-reference (translation required)': 'title-reference',
+ u'title (translation required)': 'title-reference',
+ u't (translation required)': 'title-reference',
+ u'pep-reference (translation required)': 'pep-reference',
+ u'pep (translation required)': 'pep-reference',
+ u'rfc-reference (translation required)': 'rfc-reference',
+ u'rfc (translation required)': 'rfc-reference',
+ u'emphasis (translation required)': 'emphasis',
+ u'strong (translation required)': 'strong',
+ u'literal (translation required)': 'literal',
+ u'math (translation required)': 'math',
+ u'named-reference (translation required)': 'named-reference',
+ u'anonymous-reference (translation required)': 'anonymous-reference',
+ u'footnote-reference (translation required)': 'footnote-reference',
+ u'citation-reference (translation required)': 'citation-reference',
+ u'substitution-reference (translation required)': 'substitution-reference',
+ u'target (translation required)': 'target',
+ u'uri-reference (translation required)': 'uri-reference',
+ u'uri (translation required)': 'uri-reference',
+ u'url (translation required)': 'uri-reference',
+ u'raw (translation required)': 'raw',}
+"""Mapping of Czech role names to canonical role names for interpreted text.
+"""
--- /dev/null
+# -*- coding: utf-8 -*-
+# $Id: da.py 7678 2013-07-03 09:57:36Z milde $
+# Author: E D
+# Copyright: This module has been placed in the public domain.
+
+# New language mappings are welcome. Before doing a new translation, please
+# read <http://docutils.sf.net/docs/howto/i18n.html>. Two files must be
+# translated for each language: one in docutils/languages, the other in
+# docutils/parsers/rst/languages.
+
+"""
+Danish-language mappings for language-dependent features of
+reStructuredText.
+"""
+
+__docformat__ = 'reStructuredText'
+
+
+directives = {
+ # language-dependent: fixed
+ u'giv agt': 'attention',
+ u'pas på': 'caution',
+ u'kode': 'code',
+ u'kode-blok': 'code',
+ u'kildekode': 'code',
+ u'fare': 'danger',
+ u'fejl': 'error',
+ u'vink': 'hint',
+ u'vigtigt': 'important',
+ u'bemærk': 'note',
+ u'tips': 'tip',
+ u'advarsel': 'warning',
+ u'formaning': 'admonition',
+ u'sidebjælke': 'sidebar',
+ u'emne': 'topic',
+ u'linje-blok': 'line-block',
+ u'linie-blok': 'line-block',
+ u'parset-literal': 'parsed-literal',
+ u'rubrik': 'rubric',
+ u'epigraf': 'epigraph',
+ u'fremhævninger': 'highlights',
+ u'pull-quote (translation required)': 'pull-quote',
+ u'compound (translation required)': 'compound',
+ u'container (translation required)': 'container',
+ #'questions': 'questions',
+ u'tabel': 'table',
+ u'csv-tabel': 'csv-table',
+ u'liste-tabel': 'list-table',
+ #'qa': 'questions',
+ #'faq': 'questions',
+ u'meta': 'meta',
+ u'math (translation required)': 'math',
+ #'imagemap': 'imagemap',
+ u'billede': 'image',
+ u'figur': 'figure',
+ u'inkludér': 'include',
+ u'inkluder': 'include',
+ u'rå': 'raw',
+ u'erstat': 'replace',
+ u'unicode': 'unicode',
+ u'dato': 'date',
+ u'klasse': 'class',
+ u'rolle': 'role',
+ u'forvalgt-rolle': 'default-role',
+ u'titel': 'title',
+ u'indhold': 'contents',
+ u'sektnum': 'sectnum',
+ u'sektions-nummerering': 'sectnum',
+ u'sidehovede': 'header',
+ u'sidefod': 'footer',
+ #'footnotes': 'footnotes',
+ #'citations': 'citations',
+ u'target-notes (translation required)': 'target-notes',
+ u'restructuredtext-test-direktiv': 'restructuredtext-test-directive'}
+"""Danish name to registered (in directives/__init__.py) directive name
+mapping."""
+
+roles = {
+ # language-dependent: fixed
+ u'forkortelse': 'abbreviation',
+ u'fork': 'abbreviation',
+ u'akronym': 'acronym',
+ u'ac (translation required)': 'acronym',
+ u'kode': 'code',
+ u'indeks': 'index',
+ u'i': 'index',
+ u'subscript (translation required)': 'subscript',
+ u'sub (translation required)': 'subscript',
+ u'superscript (translation required)': 'superscript',
+ u'sup (translation required)': 'superscript',
+ u'titel-reference': 'title-reference',
+ u'titel': 'title-reference',
+ u't': 'title-reference',
+ u'pep-reference': 'pep-reference',
+ u'pep': 'pep-reference',
+ u'rfc-reference': 'rfc-reference',
+ u'rfc': 'rfc-reference',
+ u'emfase': 'emphasis',
+ u'kraftig': 'strong',
+ u'literal': 'literal',
+ u'math (translation required)': 'math',
+ u'navngivet-reference': 'named-reference',
+ u'anonym-reference': 'anonymous-reference',
+ u'fodnote-reference': 'footnote-reference',
+ u'citation-reference (translation required)': 'citation-reference',
+ u'substitutions-reference': 'substitution-reference',
+ u'target (translation required)': 'target',
+ u'uri-reference': 'uri-reference',
+ u'uri': 'uri-reference',
+ u'url': 'uri-reference',
+ u'rå': 'raw',}
+"""Mapping of Danish role names to canonical role names for interpreted text.
+"""
--- /dev/null
+# -*- coding: utf-8 -*-
+# $Id: de.py 8006 2016-12-22 23:02:44Z milde $
+# Authors: Engelbert Gruber <grubert@users.sourceforge.net>;
+# Lea Wiemann <LeWiemann@gmail.com>
+# Copyright: This module has been placed in the public domain.
+
+# New language mappings are welcome. Before doing a new translation, please
+# read <http://docutils.sf.net/docs/howto/i18n.html>. Two files must be
+# translated for each language: one in docutils/languages, the other in
+# docutils/parsers/rst/languages.
+
+"""
+German-language mappings for language-dependent features of
+reStructuredText.
+"""
+
+__docformat__ = 'reStructuredText'
+
+
+directives = {
+ 'achtung': 'attention',
+ 'vorsicht': 'caution',
+ 'code': 'code',
+ 'gefahr': 'danger',
+ 'fehler': 'error',
+ 'hinweis': 'hint',
+ 'wichtig': 'important',
+ 'notiz': 'note',
+ 'tipp': 'tip',
+ 'warnung': 'warning',
+ 'ermahnung': 'admonition',
+ 'kasten': 'sidebar',
+ 'seitenkasten': 'sidebar', # kept for backwards compatibiltity
+ 'seitenleiste': 'sidebar',
+ 'thema': 'topic',
+ 'zeilenblock': 'line-block',
+ 'parsed-literal (translation required)': 'parsed-literal',
+ 'rubrik': 'rubric',
+ 'epigraph': 'epigraph',
+ 'highlights': 'highlights',
+ u'pull-quote': 'pull-quote', # commonly used in German too
+ u'seitenansprache': 'pull-quote', # cf. http://www.typografie.info/2/wiki.php?title=Seitenansprache
+ 'zusammengesetzt': 'compound',
+ 'verbund': 'compound',
+ u'container': 'container',
+ #'fragen': 'questions',
+ 'tabelle': 'table',
+ 'csv-tabelle': 'csv-table',
+ 'listentabelle': 'list-table',
+ u'mathe': 'math',
+ u'formel': 'math',
+ 'meta': 'meta',
+ #'imagemap': 'imagemap',
+ 'bild': 'image',
+ 'abbildung': 'figure',
+ u'unverändert': 'raw',
+ u'roh': 'raw',
+ u'einfügen': 'include',
+ 'ersetzung': 'replace',
+ 'ersetzen': 'replace',
+ 'ersetze': 'replace',
+ 'unicode': 'unicode',
+ 'datum': 'date',
+ 'klasse': 'class',
+ 'rolle': 'role',
+ u'standardrolle': 'default-role',
+ u'titel': 'title',
+ 'inhalt': 'contents',
+ u'kapitelnummerierung': 'sectnum',
+ u'abschnittsnummerierung': 'sectnum',
+ u'linkziel-fußnoten': 'target-notes',
+ u'kopfzeilen': 'header',
+ u'fußzeilen': 'footer',
+ #u'fußfnoten': 'footnotes',
+ #'zitate': 'citations',
+ }
+"""German name to registered (in directives/__init__.py) directive name
+mapping."""
+
+roles = {
+ u'abkürzung': 'abbreviation',
+ 'akronym': 'acronym',
+ u'code': 'code',
+ 'index': 'index',
+ 'tiefgestellt': 'subscript',
+ 'hochgestellt': 'superscript',
+ 'titel-referenz': 'title-reference',
+ 'pep-referenz': 'pep-reference',
+ 'rfc-referenz': 'rfc-reference',
+ 'betonung': 'emphasis', # for backwards compatibility
+ 'betont': 'emphasis',
+ 'fett': 'strong',
+ u'wörtlich': 'literal',
+ u'mathe': 'math',
+ 'benannte-referenz': 'named-reference',
+ 'unbenannte-referenz': 'anonymous-reference',
+ u'fußfnoten-referenz': 'footnote-reference',
+ 'zitat-referenz': 'citation-reference',
+ 'ersetzungs-referenz': 'substitution-reference',
+ 'ziel': 'target',
+ 'uri-referenz': 'uri-reference',
+ u'unverändert': 'raw',
+ u'roh': 'raw',}
+"""Mapping of German role names to canonical role names for interpreted text.
+"""
--- /dev/null
+# $Id: en.py 7179 2011-10-15 22:06:45Z milde $
+# Author: David Goodger <goodger@python.org>
+# Copyright: This module has been placed in the public domain.
+
+# New language mappings are welcome. Before doing a new translation, please
+# read <http://docutils.sf.net/docs/howto/i18n.html>. Two files must be
+# translated for each language: one in docutils/languages, the other in
+# docutils/parsers/rst/languages.
+
+"""
+English-language mappings for language-dependent features of
+reStructuredText.
+"""
+
+__docformat__ = 'reStructuredText'
+
+
+directives = {
+ # language-dependent: fixed
+ 'attention': 'attention',
+ 'caution': 'caution',
+ 'code': 'code',
+ 'code-block': 'code',
+ 'sourcecode': 'code',
+ 'danger': 'danger',
+ 'error': 'error',
+ 'hint': 'hint',
+ 'important': 'important',
+ 'note': 'note',
+ 'tip': 'tip',
+ 'warning': 'warning',
+ 'admonition': 'admonition',
+ 'sidebar': 'sidebar',
+ 'topic': 'topic',
+ 'line-block': 'line-block',
+ 'parsed-literal': 'parsed-literal',
+ 'rubric': 'rubric',
+ 'epigraph': 'epigraph',
+ 'highlights': 'highlights',
+ 'pull-quote': 'pull-quote',
+ 'compound': 'compound',
+ 'container': 'container',
+ #'questions': 'questions',
+ 'table': 'table',
+ 'csv-table': 'csv-table',
+ 'list-table': 'list-table',
+ #'qa': 'questions',
+ #'faq': 'questions',
+ 'meta': 'meta',
+ 'math': 'math',
+ #'imagemap': 'imagemap',
+ 'image': 'image',
+ 'figure': 'figure',
+ 'include': 'include',
+ 'raw': 'raw',
+ 'replace': 'replace',
+ 'unicode': 'unicode',
+ 'date': 'date',
+ 'class': 'class',
+ 'role': 'role',
+ 'default-role': 'default-role',
+ 'title': 'title',
+ 'contents': 'contents',
+ 'sectnum': 'sectnum',
+ 'section-numbering': 'sectnum',
+ 'header': 'header',
+ 'footer': 'footer',
+ #'footnotes': 'footnotes',
+ #'citations': 'citations',
+ 'target-notes': 'target-notes',
+ 'restructuredtext-test-directive': 'restructuredtext-test-directive'}
+"""English name to registered (in directives/__init__.py) directive name
+mapping."""
+
+roles = {
+ # language-dependent: fixed
+ 'abbreviation': 'abbreviation',
+ 'ab': 'abbreviation',
+ 'acronym': 'acronym',
+ 'ac': 'acronym',
+ 'code': 'code',
+ 'index': 'index',
+ 'i': 'index',
+ 'subscript': 'subscript',
+ 'sub': 'subscript',
+ 'superscript': 'superscript',
+ 'sup': 'superscript',
+ 'title-reference': 'title-reference',
+ 'title': 'title-reference',
+ 't': 'title-reference',
+ 'pep-reference': 'pep-reference',
+ 'pep': 'pep-reference',
+ 'rfc-reference': 'rfc-reference',
+ 'rfc': 'rfc-reference',
+ 'emphasis': 'emphasis',
+ 'strong': 'strong',
+ 'literal': 'literal',
+ 'math': 'math',
+ 'named-reference': 'named-reference',
+ 'anonymous-reference': 'anonymous-reference',
+ 'footnote-reference': 'footnote-reference',
+ 'citation-reference': 'citation-reference',
+ 'substitution-reference': 'substitution-reference',
+ 'target': 'target',
+ 'uri-reference': 'uri-reference',
+ 'uri': 'uri-reference',
+ 'url': 'uri-reference',
+ 'raw': 'raw',}
+"""Mapping of English role names to canonical role names for interpreted text.
+"""
--- /dev/null
+# $Id: eo.py 7119 2011-09-02 13:00:23Z milde $
+# Author: Marcelo Huerta San Martin <richieadler@users.sourceforge.net>
+# Copyright: This module has been placed in the public domain.
+
+# New language mappings are welcome. Before doing a new translation, please
+# read <http://docutils.sf.net/docs/howto/i18n.html>. Two files must be
+# translated for each language: one in docutils/languages, the other in
+# docutils/parsers/rst/languages.
+
+"""
+Esperanto-language mappings for language-dependent features of
+reStructuredText.
+"""
+
+__docformat__ = 'reStructuredText'
+
+
+directives = {
+ # language-dependent: fixed
+ u'atentu': 'attention',
+ u'zorgu': 'caution',
+ u'code (translation required)': 'code',
+ u'dangxero': 'danger',
+ u'dan\u011dero': 'danger',
+ u'eraro': 'error',
+ u'spuro': 'hint',
+ u'grava': 'important',
+ u'noto': 'note',
+ u'helpeto': 'tip',
+ u'averto': 'warning',
+ u'admono': 'admonition',
+ u'flankteksto': 'sidebar',
+ u'temo': 'topic',
+ u'linea-bloko': 'line-block',
+ u'analizota-literalo': 'parsed-literal',
+ u'rubriko': 'rubric',
+ u'epigrafo': 'epigraph',
+ u'elstarajxoj': 'highlights',
+ u'elstara\u0135oj': 'highlights',
+ u'ekstera-citajxo': 'pull-quote',
+ u'ekstera-cita\u0135o': 'pull-quote',
+ u'kombinajxo': 'compound',
+ u'kombina\u0135o': 'compound',
+ u'tekstingo': 'container',
+ u'enhavilo': 'container',
+ #'questions': 'questions',
+ #'qa': 'questions',
+ #'faq': 'questions',
+ u'tabelo': 'table',
+ u'tabelo-vdk': 'csv-table', # "valoroj disigitaj per komoj"
+ u'tabelo-csv': 'csv-table',
+ u'tabelo-lista': 'list-table',
+ u'meta': 'meta',
+ 'math (translation required)': 'math',
+ #'imagemap': 'imagemap',
+ u'bildo': 'image',
+ u'figuro': 'figure',
+ u'inkludi': 'include',
+ u'senanaliza': 'raw',
+ u'anstatauxi': 'replace',
+ u'anstata\u016di': 'replace',
+ u'unicode': 'unicode',
+ u'dato': 'date',
+ u'klaso': 'class',
+ u'rolo': 'role',
+ u'preterlasita-rolo': 'default-role',
+ u'titolo': 'title',
+ u'enhavo': 'contents',
+ u'seknum': 'sectnum',
+ u'sekcia-numerado': 'sectnum',
+ u'kapsekcio': 'header',
+ u'piedsekcio': 'footer',
+ #'footnotes': 'footnotes',
+ #'citations': 'citations',
+ u'celaj-notoj': 'target-notes',
+ u'restructuredtext-test-directive': 'restructuredtext-test-directive'}
+"""Esperanto name to registered (in directives/__init__.py) directive name
+mapping."""
+
+roles = {
+ # language-dependent: fixed
+ u'mallongigo': 'abbreviation',
+ u'mall': 'abbreviation',
+ u'komenclitero': 'acronym',
+ u'kl': 'acronym',
+ u'code (translation required)': 'code',
+ u'indekso': 'index',
+ u'i': 'index',
+ u'subskribo': 'subscript',
+ u'sub': 'subscript',
+ u'supraskribo': 'superscript',
+ u'sup': 'superscript',
+ u'titola-referenco': 'title-reference',
+ u'titolo': 'title-reference',
+ u't': 'title-reference',
+ u'pep-referenco': 'pep-reference',
+ u'pep': 'pep-reference',
+ u'rfc-referenco': 'rfc-reference',
+ u'rfc': 'rfc-reference',
+ u'emfazo': 'emphasis',
+ u'forta': 'strong',
+ u'litera': 'literal',
+ 'math (translation required)': 'math',
+ u'nomita-referenco': 'named-reference',
+ u'nenomita-referenco': 'anonymous-reference',
+ u'piednota-referenco': 'footnote-reference',
+ u'citajxo-referenco': 'citation-reference',
+ u'cita\u0135o-referenco': 'citation-reference',
+ u'anstatauxa-referenco': 'substitution-reference',
+ u'anstata\u016da-referenco': 'substitution-reference',
+ u'celo': 'target',
+ u'uri-referenco': 'uri-reference',
+ u'uri': 'uri-reference',
+ u'url': 'uri-reference',
+ u'senanaliza': 'raw',
+}
+"""Mapping of Esperanto role names to canonical role names for interpreted text.
+"""
--- /dev/null
+# -*- coding: utf-8 -*-
+# $Id: es.py 7119 2011-09-02 13:00:23Z milde $
+# Author: Marcelo Huerta San Martín <richieadler@users.sourceforge.net>
+# Copyright: This module has been placed in the public domain.
+
+# New language mappings are welcome. Before doing a new translation, please
+# read <http://docutils.sf.net/docs/howto/i18n.html>. Two files must be
+# translated for each language: one in docutils/languages, the other in
+# docutils/parsers/rst/languages.
+
+"""
+Spanish-language mappings for language-dependent features of
+reStructuredText.
+"""
+
+__docformat__ = 'reStructuredText'
+
+
+directives = {
+ u'atenci\u00f3n': 'attention',
+ u'atencion': 'attention',
+ u'precauci\u00f3n': 'caution',
+ u'code (translation required)': 'code',
+ u'precaucion': 'caution',
+ u'peligro': 'danger',
+ u'error': 'error',
+ u'sugerencia': 'hint',
+ u'importante': 'important',
+ u'nota': 'note',
+ u'consejo': 'tip',
+ u'advertencia': 'warning',
+ u'exhortacion': 'admonition',
+ u'exhortaci\u00f3n': 'admonition',
+ u'nota-al-margen': 'sidebar',
+ u'tema': 'topic',
+ u'bloque-de-lineas': 'line-block',
+ u'bloque-de-l\u00edneas': 'line-block',
+ u'literal-evaluado': 'parsed-literal',
+ u'firma': 'rubric',
+ u'ep\u00edgrafe': 'epigraph',
+ u'epigrafe': 'epigraph',
+ u'destacado': 'highlights',
+ u'cita-destacada': 'pull-quote',
+ u'combinacion': 'compound',
+ u'combinaci\u00f3n': 'compound',
+ u'contenedor': 'container',
+ #'questions': 'questions',
+ #'qa': 'questions',
+ #'faq': 'questions',
+ u'tabla': 'table',
+ u'tabla-vsc': 'csv-table',
+ u'tabla-csv': 'csv-table',
+ u'tabla-lista': 'list-table',
+ u'meta': 'meta',
+ 'math (translation required)': 'math',
+ #'imagemap': 'imagemap',
+ u'imagen': 'image',
+ u'figura': 'figure',
+ u'incluir': 'include',
+ u'sin-analisis': 'raw',
+ u'sin-an\u00e1lisis': 'raw',
+ u'reemplazar': 'replace',
+ u'unicode': 'unicode',
+ u'fecha': 'date',
+ u'clase': 'class',
+ u'rol': 'role',
+ u'rol-por-omision': 'default-role',
+ u'rol-por-omisi\u00f3n': 'default-role',
+ u'titulo': 'title',
+ u't\u00edtulo': 'title',
+ u'contenido': 'contents',
+ u'numseccion': 'sectnum',
+ u'numsecci\u00f3n': 'sectnum',
+ u'numeracion-seccion': 'sectnum',
+ u'numeraci\u00f3n-secci\u00f3n': 'sectnum',
+ u'notas-destino': 'target-notes',
+ u'cabecera': 'header',
+ u'pie': 'footer',
+ #'footnotes': 'footnotes',
+ #'citations': 'citations',
+ u'restructuredtext-test-directive': 'restructuredtext-test-directive'}
+"""Spanish name to registered (in directives/__init__.py) directive name
+mapping."""
+
+roles = {
+ u'abreviatura': 'abbreviation',
+ u'ab': 'abbreviation',
+ u'acronimo': 'acronym',
+ u'acronimo': 'acronym',
+ u'ac': 'acronym',
+ u'code (translation required)': 'code',
+ u'indice': 'index',
+ u'i': 'index',
+ u'subindice': 'subscript',
+ u'sub\u00edndice': 'subscript',
+ u'superindice': 'superscript',
+ u'super\u00edndice': 'superscript',
+ u'referencia-titulo': 'title-reference',
+ u'titulo': 'title-reference',
+ u't': 'title-reference',
+ u'referencia-pep': 'pep-reference',
+ u'pep': 'pep-reference',
+ u'referencia-rfc': 'rfc-reference',
+ u'rfc': 'rfc-reference',
+ u'enfasis': 'emphasis',
+ u'\u00e9nfasis': 'emphasis',
+ u'destacado': 'strong',
+ u'literal': 'literal', # "literal" is also a word in Spanish :-)
+ u'math (translation required)': 'math',
+ u'referencia-con-nombre': 'named-reference',
+ u'referencia-anonima': 'anonymous-reference',
+ u'referencia-an\u00f3nima': 'anonymous-reference',
+ u'referencia-nota-al-pie': 'footnote-reference',
+ u'referencia-cita': 'citation-reference',
+ u'referencia-sustitucion': 'substitution-reference',
+ u'referencia-sustituci\u00f3n': 'substitution-reference',
+ u'destino': 'target',
+ u'referencia-uri': 'uri-reference',
+ u'uri': 'uri-reference',
+ u'url': 'uri-reference',
+ u'sin-analisis': 'raw',
+ u'sin-an\u00e1lisis': 'raw',
+}
+"""Mapping of Spanish role names to canonical role names for interpreted text.
+"""
--- /dev/null
+# -*- coding: utf-8 -*-
+# $Id: fa.py 4564 2016-08-10 11:48:42Z
+# Author: Shahin <me@5hah.in>
+# Copyright: This module has been placed in the public domain.
+
+# New language mappings are welcome. Before doing a new translation, please
+# read <http://docutils.sf.net/docs/howto/i18n.html>. Two files must be
+# translated for each language: one in docutils/languages, the other in
+# docutils/parsers/rst/languages.
+
+"""
+Persian-language mappings for language-dependent features of
+reStructuredText.
+"""
+
+__docformat__ = 'reStructuredText'
+
+
+directives = {
+ # language-dependent: fixed
+ u'توجه': u'attention',
+ u'احتیاط': u'caution',
+ u'کد': u'code',
+ u'بلوک-کد': u'code',
+ u'کد-منبع': u'code',
+ u'خطر': u'danger',
+ u'خطا': u'error',
+ u'راهنما': u'hint',
+ u'مهم': u'important',
+ u'یادداشت': u'note',
+ u'نکته': u'tip',
+ u'اخطار': u'warning',
+ u'تذکر': u'admonition',
+ u'نوار-کناری': u'sidebar',
+ u'موضوع': u'topic',
+ u'بلوک-خط': u'line-block',
+ u'تلفظ-پردازش-شده': u'parsed-literal',
+ u'سر-فصل': u'rubric',
+ u'کتیبه': u'epigraph',
+ u'نکات-برجسته': u'highlights',
+ u'نقل-قول': u'pull-quote',
+ u'ترکیب': u'compound',
+ u'ظرف': u'container',
+ #'questions': u'questions',
+ u'جدول': u'table',
+ u'جدول-csv': u'csv-table',
+ u'جدول-لیست': u'list-table',
+ #'qa': u'questions',
+ #'faq': u'questions',
+ u'متا': u'meta',
+ u'ریاضی': u'math',
+ #'imagemap': u'imagemap',
+ u'تصویر': u'image',
+ u'شکل': u'figure',
+ u'شامل': u'include',
+ u'خام': u'raw',
+ u'جایگزین': u'replace',
+ u'یونیکد': u'unicode',
+ u'تاریخ': u'date',
+ u'کلاس': u'class',
+ u'قانون': u'role',
+ u'قانون-پیشفرض': u'default-role',
+ u'عنوان': u'title',
+ u'محتوا': u'contents',
+ u'شماره-فصل': u'sectnum',
+ u'شمارهگذاری-فصل': u'sectnum',
+ u'سرآیند': u'header',
+ u'پاصفحه': u'footer',
+ #'footnotes': u'footnotes',
+ #'citations': u'citations',
+ u'یادداشت-هدف': u'target-notes',
+ }
+"""Persian name to registered (in directives/__init__.py) directive name
+mapping."""
+
+roles = {
+ # language-dependent: fixed
+ u'مخفف': u'abbreviation',
+ u'سرنام': u'acronym',
+ u'کد': u'code',
+ u'شاخص': u'index',
+ u'زیرنویس': u'subscript',
+ u'بالانویس': u'superscript',
+ u'عنوان': u'title-reference',
+ u'نیرو': u'pep-reference',
+ u'rfc-reference (translation required)': u'rfc-reference',
+ u'تاکید': u'emphasis',
+ u'قوی': u'strong',
+ u'لفظی': u'literal',
+ u'ریاضی': u'math',
+ u'منبع-نامگذاری': u'named-reference',
+ u'منبع-ناشناس': u'anonymous-reference',
+ u'منبع-پانویس': u'footnote-reference',
+ u'منبع-نقلفول': u'citation-reference',
+ u'منبع-جایگزینی': u'substitution-reference',
+ u'هدف': u'target',
+ u'منبع-uri': u'uri-reference',
+ u'uri': u'uri-reference',
+ u'url': u'uri-reference',
+ u'خام': u'raw',}
+"""Mapping of Persian role names to canonical role names for interpreted text.
+"""
--- /dev/null
+# -*- coding: utf-8 -*-
+# $Id: fi.py 7119 2011-09-02 13:00:23Z milde $
+# Author: Asko Soukka <asko.soukka@iki.fi>
+# Copyright: This module has been placed in the public domain.
+
+# New language mappings are welcome. Before doing a new translation, please
+# read <http://docutils.sf.net/docs/howto/i18n.html>. Two files must be
+# translated for each language: one in docutils/languages, the other in
+# docutils/parsers/rst/languages.
+
+"""
+Finnish-language mappings for language-dependent features of
+reStructuredText.
+"""
+
+__docformat__ = 'reStructuredText'
+
+
+directives = {
+ # language-dependent: fixed
+ u'huomio': u'attention',
+ u'varo': u'caution',
+ u'code (translation required)': 'code',
+ u'vaara': u'danger',
+ u'virhe': u'error',
+ u'vihje': u'hint',
+ u't\u00e4rke\u00e4\u00e4': u'important',
+ u'huomautus': u'note',
+ u'neuvo': u'tip',
+ u'varoitus': u'warning',
+ u'kehotus': u'admonition',
+ u'sivupalkki': u'sidebar',
+ u'aihe': u'topic',
+ u'rivi': u'line-block',
+ u'tasalevyinen': u'parsed-literal',
+ u'ohje': u'rubric',
+ u'epigraafi': u'epigraph',
+ u'kohokohdat': u'highlights',
+ u'lainaus': u'pull-quote',
+ u'taulukko': u'table',
+ u'csv-taulukko': u'csv-table',
+ u'list-table (translation required)': 'list-table',
+ u'compound (translation required)': 'compound',
+ u'container (translation required)': 'container',
+ #u'kysymykset': u'questions',
+ u'meta': u'meta',
+ 'math (translation required)': 'math',
+ #u'kuvakartta': u'imagemap',
+ u'kuva': u'image',
+ u'kaavio': u'figure',
+ u'sis\u00e4llyt\u00e4': u'include',
+ u'raaka': u'raw',
+ u'korvaa': u'replace',
+ u'unicode': u'unicode',
+ u'p\u00e4iv\u00e4ys': u'date',
+ u'luokka': u'class',
+ u'rooli': u'role',
+ u'default-role (translation required)': 'default-role',
+ u'title (translation required)': 'title',
+ u'sis\u00e4llys': u'contents',
+ u'kappale': u'sectnum',
+ u'header (translation required)': 'header',
+ u'footer (translation required)': 'footer',
+ #u'alaviitteet': u'footnotes',
+ #u'viitaukset': u'citations',
+ u'target-notes (translation required)': u'target-notes'}
+"""Finnish name to registered (in directives/__init__.py) directive name
+mapping."""
+
+roles = {
+ # language-dependent: fixed
+ u'lyhennys': u'abbreviation',
+ u'akronyymi': u'acronym',
+ u'kirjainsana': u'acronym',
+ u'code (translation required)': 'code',
+ u'hakemisto': u'index',
+ u'luettelo': u'index',
+ u'alaindeksi': u'subscript',
+ u'indeksi': u'subscript',
+ u'yl\u00e4indeksi': u'superscript',
+ u'title-reference (translation required)': u'title-reference',
+ u'title (translation required)': u'title-reference',
+ u'pep-reference (translation required)': u'pep-reference',
+ u'rfc-reference (translation required)': u'rfc-reference',
+ u'korostus': u'emphasis',
+ u'vahvistus': u'strong',
+ u'tasalevyinen': u'literal',
+ 'math (translation required)': 'math',
+ u'named-reference (translation required)': u'named-reference',
+ u'anonymous-reference (translation required)': u'anonymous-reference',
+ u'footnote-reference (translation required)': u'footnote-reference',
+ u'citation-reference (translation required)': u'citation-reference',
+ u'substitution-reference (translation required)': u'substitution-reference',
+ u'kohde': u'target',
+ u'uri-reference (translation required)': u'uri-reference',
+ u'raw (translation required)': 'raw',}
+"""Mapping of Finnish role names to canonical role names for interpreted text.
+"""
--- /dev/null
+# $Id: fr.py 7119 2011-09-02 13:00:23Z milde $
+# Authors: David Goodger <goodger@python.org>; William Dode
+# Copyright: This module has been placed in the public domain.
+
+# New language mappings are welcome. Before doing a new translation, please
+# read <http://docutils.sf.net/docs/howto/i18n.html>. Two files must be
+# translated for each language: one in docutils/languages, the other in
+# docutils/parsers/rst/languages.
+
+"""
+French-language mappings for language-dependent features of
+reStructuredText.
+"""
+
+__docformat__ = 'reStructuredText'
+
+
+directives = {
+ u'attention': 'attention',
+ u'pr\u00E9caution': 'caution',
+ u'code': 'code',
+ u'danger': 'danger',
+ u'erreur': 'error',
+ u'conseil': 'hint',
+ u'important': 'important',
+ u'note': 'note',
+ u'astuce': 'tip',
+ u'avertissement': 'warning',
+ u'admonition': 'admonition',
+ u'encadr\u00E9': 'sidebar',
+ u'sujet': 'topic',
+ u'bloc-textuel': 'line-block',
+ u'bloc-interpr\u00E9t\u00E9': 'parsed-literal',
+ u'code-interpr\u00E9t\u00E9': 'parsed-literal',
+ u'intertitre': 'rubric',
+ u'exergue': 'epigraph',
+ u'\u00E9pigraphe': 'epigraph',
+ u'chapeau': 'highlights',
+ u'accroche': 'pull-quote',
+ u'compound (translation required)': 'compound',
+ u'container (translation required)': 'container',
+ #u'questions': 'questions',
+ #u'qr': 'questions',
+ #u'faq': 'questions',
+ u'tableau': 'table',
+ u'csv-table (translation required)': 'csv-table',
+ u'list-table (translation required)': 'list-table',
+ u'm\u00E9ta': 'meta',
+ 'math (translation required)': 'math',
+ #u'imagemap (translation required)': 'imagemap',
+ u'image': 'image',
+ u'figure': 'figure',
+ u'inclure': 'include',
+ u'brut': 'raw',
+ u'remplacer': 'replace',
+ u'remplace': 'replace',
+ u'unicode': 'unicode',
+ u'date': 'date',
+ u'classe': 'class',
+ u'role (translation required)': 'role',
+ u'default-role (translation required)': 'default-role',
+ u'titre (translation required)': 'title',
+ u'sommaire': 'contents',
+ u'table-des-mati\u00E8res': 'contents',
+ u'sectnum': 'sectnum',
+ u'section-num\u00E9rot\u00E9e': 'sectnum',
+ u'liens': 'target-notes',
+ u'header (translation required)': 'header',
+ u'footer (translation required)': 'footer',
+ #u'footnotes (translation required)': 'footnotes',
+ #u'citations (translation required)': 'citations',
+ }
+"""French name to registered (in directives/__init__.py) directive name
+mapping."""
+
+roles = {
+ u'abr\u00E9viation': 'abbreviation',
+ u'acronyme': 'acronym',
+ u'sigle': 'acronym',
+ u'code': 'code',
+ u'index': 'index',
+ u'indice': 'subscript',
+ u'ind': 'subscript',
+ u'exposant': 'superscript',
+ u'exp': 'superscript',
+ u'titre-r\u00E9f\u00E9rence': 'title-reference',
+ u'titre': 'title-reference',
+ u'pep-r\u00E9f\u00E9rence': 'pep-reference',
+ u'rfc-r\u00E9f\u00E9rence': 'rfc-reference',
+ u'emphase': 'emphasis',
+ u'fort': 'strong',
+ u'litt\u00E9ral': 'literal',
+ 'math (translation required)': 'math',
+ u'nomm\u00E9e-r\u00E9f\u00E9rence': 'named-reference',
+ u'anonyme-r\u00E9f\u00E9rence': 'anonymous-reference',
+ u'note-r\u00E9f\u00E9rence': 'footnote-reference',
+ u'citation-r\u00E9f\u00E9rence': 'citation-reference',
+ u'substitution-r\u00E9f\u00E9rence': 'substitution-reference',
+ u'lien': 'target',
+ u'uri-r\u00E9f\u00E9rence': 'uri-reference',
+ u'brut': 'raw',}
+"""Mapping of French role names to canonical role names for interpreted text.
+"""
--- /dev/null
+# -*- coding: utf-8 -*-
+# Author: David Goodger
+# Contact: goodger@users.sourceforge.net
+# Revision: $Revision: 4229 $
+# Date: $Date: 2005-12-23 00:46:16 +0100 (Fri, 23 Dec 2005) $
+# Copyright: This module has been placed in the public domain.
+
+# New language mappings are welcome. Before doing a new translation, please
+# read <http://docutils.sf.net/docs/howto/i18n.html>. Two files must be
+# translated for each language: one in docutils/languages, the other in
+# docutils/parsers/rst/languages.
+
+"""
+Galician-language mappings for language-dependent features of
+reStructuredText.
+"""
+
+__docformat__ = 'reStructuredText'
+
+
+directives = {
+ # language-dependent: fixed
+ u'atenci\u00f3n': 'attention',
+ u'advertencia': 'caution',
+ u'code (translation required)': 'code',
+ u'perigo': 'danger',
+ u'erro': 'error',
+ u'pista': 'hint',
+ u'importante': 'important',
+ u'nota': 'note',
+ u'consello': 'tip',
+ u'aviso': 'warning',
+ u'admonici\u00f3n': 'admonition',
+ u'barra lateral': 'sidebar',
+ u't\u00f3pico': 'topic',
+ u'bloque-li\u00f1a': 'line-block',
+ u'literal-analizado': 'parsed-literal',
+ u'r\u00fabrica': 'rubric',
+ u'ep\u00edgrafe': 'epigraph',
+ u'realzados': 'highlights',
+ u'coller-citaci\u00f3n': 'pull-quote',
+ u'compor': 'compound',
+ u'recipiente': 'container',
+ #'questions': 'questions',
+ u't\u00e1boa': 'table',
+ u't\u00e1boa-csv': 'csv-table',
+ u't\u00e1boa-listaxe': 'list-table',
+ #'qa': 'questions',
+ #'faq': 'questions',
+ u'meta': 'meta',
+ 'math (translation required)': 'math',
+ #'imagemap': 'imagemap',
+ u'imaxe': 'image',
+ u'figura': 'figure',
+ u'inclu\u00edr': 'include',
+ u'cru': 'raw',
+ u'substitu\u00edr': 'replace',
+ u'unicode': 'unicode',
+ u'data': 'date',
+ u'clase': 'class',
+ u'regra': 'role',
+ u'regra-predeterminada': 'default-role',
+ u't\u00edtulo': 'title',
+ u'contido': 'contents',
+ u'seccnum': 'sectnum',
+ u'secci\u00f3n-numerar': 'sectnum',
+ u'cabeceira': 'header',
+ u'p\u00e9 de p\u00e1xina': 'footer',
+ #'footnotes': 'footnotes',
+ #'citations': 'citations',
+ u'notas-destino': 'target-notes',
+ u'texto restruturado-proba-directiva': 'restructuredtext-test-directive'}
+"""Galician name to registered (in directives/__init__.py) directive name
+mapping."""
+
+roles = {
+ # language-dependent: fixed
+ u'abreviatura': 'abbreviation',
+ u'ab': 'abbreviation',
+ u'acr\u00f3nimo': 'acronym',
+ u'ac': 'acronym',
+ u'code (translation required)': 'code',
+ u'\u00edndice': 'index',
+ u'i': 'index',
+ u'sub\u00edndice': 'subscript',
+ u'sub': 'subscript',
+ u'super\u00edndice': 'superscript',
+ u'sup': 'superscript',
+ u'referencia t\u00edtulo': 'title-reference',
+ u't\u00edtulo': 'title-reference',
+ u't': 'title-reference',
+ u'referencia-pep': 'pep-reference',
+ u'pep': 'pep-reference',
+ u'referencia-rfc': 'rfc-reference',
+ u'rfc': 'rfc-reference',
+ u'\u00e9nfase': 'emphasis',
+ u'forte': 'strong',
+ u'literal': 'literal',
+ 'math (translation required)': 'math',
+ u'referencia-nome': 'named-reference',
+ u'referencia-an\u00f3nimo': 'anonymous-reference',
+ u'referencia-nota ao p\u00e9': 'footnote-reference',
+ u'referencia-citaci\u00f3n': 'citation-reference',
+ u'referencia-substituci\u00f3n': 'substitution-reference',
+ u'destino': 'target',
+ u'referencia-uri': 'uri-reference',
+ u'uri': 'uri-reference',
+ u'url': 'uri-reference',
+ u'cru': 'raw',}
+"""Mapping of Galician role names to canonical role names for interpreted text.
+"""
--- /dev/null
+# Author: Meir Kriheli
+# Id: $Id: he.py 7119 2011-09-02 13:00:23Z milde $
+# Copyright: This module has been placed in the public domain.
+
+# New language mappings are welcome. Before doing a new translation, please
+# read <http://docutils.sf.net/docs/howto/i18n.html>. Two files must be
+# translated for each language: one in docutils/languages, the other in
+# docutils/parsers/rst/languages.
+
+"""
+English-language mappings for language-dependent features of
+reStructuredText.
+"""
+
+__docformat__ = 'reStructuredText'
+
+
+directives = {
+ # language-dependent: fixed
+ u'\u05ea\u05e9\u05d5\u05de\u05ea \u05dc\u05d1': 'attention',
+ u'\u05d6\u05d4\u05d9\u05e8\u05d5\u05ea': 'caution',
+ u'code (translation required)': 'code',
+ u'\u05e1\u05db\u05e0\u05d4': 'danger',
+ u'\u05e9\u05d2\u05d9\u05d0\u05d4' : 'error',
+ u'\u05e8\u05de\u05d6': 'hint',
+ u'\u05d7\u05e9\u05d5\u05d1': 'important',
+ u'\u05d4\u05e2\u05e8\u05d4': 'note',
+ u'\u05d8\u05d9\u05e4': 'tip',
+ u'\u05d0\u05d6\u05d4\u05e8\u05d4': 'warning',
+ 'admonition': 'admonition',
+ 'sidebar': 'sidebar',
+ 'topic': 'topic',
+ 'line-block': 'line-block',
+ 'parsed-literal': 'parsed-literal',
+ 'rubric': 'rubric',
+ 'epigraph': 'epigraph',
+ 'highlights': 'highlights',
+ 'pull-quote': 'pull-quote',
+ 'compound': 'compound',
+ 'container': 'container',
+ #'questions': 'questions',
+ 'table': 'table',
+ 'csv-table': 'csv-table',
+ 'list-table': 'list-table',
+ #'qa': 'questions',
+ #'faq': 'questions',
+ 'meta': 'meta',
+ 'math (translation required)': 'math',
+ #'imagemap': 'imagemap',
+ u'\u05ea\u05de\u05d5\u05e0\u05d4': 'image',
+ 'figure': 'figure',
+ 'include': 'include',
+ 'raw': 'raw',
+ 'replace': 'replace',
+ 'unicode': 'unicode',
+ 'date': 'date',
+ u'\u05e1\u05d2\u05e0\u05d5\u05df': 'class',
+ 'role': 'role',
+ 'default-role': 'default-role',
+ 'title': 'title',
+ u'\u05ea\u05d5\u05db\u05df': 'contents',
+ 'sectnum': 'sectnum',
+ 'section-numbering': 'sectnum',
+ 'header': 'header',
+ 'footer': 'footer',
+ #'footnotes': 'footnotes',
+ #'citations': 'citations',
+ 'target-notes': 'target-notes',
+ 'restructuredtext-test-directive': 'restructuredtext-test-directive'}
+"""English name to registered (in directives/__init__.py) directive name
+mapping."""
+
+roles = {
+ # language-dependent: fixed
+ 'abbreviation': 'abbreviation',
+ 'ab': 'abbreviation',
+ 'acronym': 'acronym',
+ 'ac': 'acronym',
+ u'code (translation required)': 'code',
+ 'index': 'index',
+ 'i': 'index',
+ u'\u05ea\u05d7\u05ea\u05d9': 'subscript',
+ 'sub': 'subscript',
+ u'\u05e2\u05d9\u05dc\u05d9': 'superscript',
+ 'sup': 'superscript',
+ 'title-reference': 'title-reference',
+ 'title': 'title-reference',
+ 't': 'title-reference',
+ 'pep-reference': 'pep-reference',
+ 'pep': 'pep-reference',
+ 'rfc-reference': 'rfc-reference',
+ 'rfc': 'rfc-reference',
+ 'emphasis': 'emphasis',
+ 'strong': 'strong',
+ 'literal': 'literal',
+ 'math (translation required)': 'math',
+ 'named-reference': 'named-reference',
+ 'anonymous-reference': 'anonymous-reference',
+ 'footnote-reference': 'footnote-reference',
+ 'citation-reference': 'citation-reference',
+ 'substitution-reference': 'substitution-reference',
+ 'target': 'target',
+ 'uri-reference': 'uri-reference',
+ 'uri': 'uri-reference',
+ 'url': 'uri-reference',
+ 'raw': 'raw',}
+"""Mapping of English role names to canonical role names for interpreted text.
+"""
--- /dev/null
+# $Id: it.py 7119 2011-09-02 13:00:23Z milde $
+# Authors: Nicola Larosa <docutils@tekNico.net>;
+# Lele Gaifax <lele@seldati.it>
+# Copyright: This module has been placed in the public domain.
+
+# Beware: the italian translation of the reStructuredText documentation
+# at http://docit.bice.dyndns.org/static/ReST, in particular
+# http://docit.bice.dyndns.org/static/ReST/ref/rst/directives.html, needs
+# to be synced with the content of this file.
+
+"""
+Italian-language mappings for language-dependent features of
+reStructuredText.
+"""
+
+__docformat__ = 'reStructuredText'
+
+
+directives = {
+ 'attenzione': 'attention',
+ 'cautela': 'caution',
+ 'code (translation required)': 'code',
+ 'pericolo': 'danger',
+ 'errore': 'error',
+ 'suggerimento': 'hint',
+ 'importante': 'important',
+ 'nota': 'note',
+ 'consiglio': 'tip',
+ 'avvertenza': 'warning',
+ 'ammonizione': 'admonition',
+ 'riquadro': 'sidebar',
+ 'argomento': 'topic',
+ 'blocco-di-righe': 'line-block',
+ 'blocco-interpretato': 'parsed-literal',
+ 'rubrica': 'rubric',
+ 'epigrafe': 'epigraph',
+ 'punti-salienti': 'highlights',
+ 'estratto-evidenziato': 'pull-quote',
+ 'composito': 'compound',
+ u'container (translation required)': 'container',
+ #'questions': 'questions',
+ #'qa': 'questions',
+ #'faq': 'questions',
+ 'tabella': 'table',
+ 'tabella-csv': 'csv-table',
+ 'tabella-elenco': 'list-table',
+ 'meta': 'meta',
+ 'math (translation required)': 'math',
+ #'imagemap': 'imagemap',
+ 'immagine': 'image',
+ 'figura': 'figure',
+ 'includi': 'include',
+ 'grezzo': 'raw',
+ 'sostituisci': 'replace',
+ 'unicode': 'unicode',
+ 'data': 'date',
+ 'classe': 'class',
+ 'ruolo': 'role',
+ 'ruolo-predefinito': 'default-role',
+ 'titolo': 'title',
+ 'indice': 'contents',
+ 'contenuti': 'contents',
+ 'seznum': 'sectnum',
+ 'sezioni-autonumerate': 'sectnum',
+ 'annota-riferimenti-esterni': 'target-notes',
+ 'intestazione': 'header',
+ 'piede-pagina': 'footer',
+ #'footnotes': 'footnotes',
+ #'citations': 'citations',
+ 'restructuredtext-test-directive': 'restructuredtext-test-directive'}
+"""Italian name to registered (in directives/__init__.py) directive name
+mapping."""
+
+roles = {
+ 'abbreviazione': 'abbreviation',
+ 'acronimo': 'acronym',
+ u'code (translation required)': 'code',
+ 'indice': 'index',
+ 'deponente': 'subscript',
+ 'esponente': 'superscript',
+ 'riferimento-titolo': 'title-reference',
+ 'riferimento-pep': 'pep-reference',
+ 'riferimento-rfc': 'rfc-reference',
+ 'enfasi': 'emphasis',
+ 'forte': 'strong',
+ 'letterale': 'literal',
+ 'math (translation required)': 'math',
+ 'riferimento-con-nome': 'named-reference',
+ 'riferimento-anonimo': 'anonymous-reference',
+ 'riferimento-nota': 'footnote-reference',
+ 'riferimento-citazione': 'citation-reference',
+ 'riferimento-sostituzione': 'substitution-reference',
+ 'destinazione': 'target',
+ 'riferimento-uri': 'uri-reference',
+ 'grezzo': 'raw',}
+"""Mapping of Italian role names to canonical role names for interpreted text.
+"""
--- /dev/null
+# -*- coding: utf-8 -*-
+# $Id: ja.py 7119 2011-09-02 13:00:23Z milde $
+# Author: David Goodger <goodger@python.org>
+# Copyright: This module has been placed in the public domain.
+
+# New language mappings are welcome. Before doing a new translation, please
+# read <http://docutils.sf.net/docs/howto/i18n.html>. Two files must be
+# translated for each language: one in docutils/languages, the other in
+# docutils/parsers/rst/languages.
+
+"""
+Japanese-language mappings for language-dependent features of
+reStructuredText.
+"""
+
+__docformat__ = 'reStructuredText'
+
+# Corrections to these translations are welcome!
+# 間違いがあれば、どうぞ正しい翻訳を教えて下さい。
+
+directives = {
+ # language-dependent: fixed
+ u'注目': 'attention',
+ u'注意': 'caution',
+ u'code (translation required)': 'code',
+ u'危険': 'danger',
+ u'エラー': 'error',
+ u'ヒント': 'hint',
+ u'重要': 'important',
+ u'備考': 'note',
+ u'通報': 'tip',
+ u'警告': 'warning',
+ u'戒告': 'admonition',
+ u'サイドバー': 'sidebar',
+ u'トピック': 'topic',
+ u'ラインブロック': 'line-block',
+ u'パーズドリテラル': 'parsed-literal',
+ u'ルブリック': 'rubric',
+ u'エピグラフ': 'epigraph',
+ u'題言': 'epigraph',
+ u'ハイライト': 'highlights',
+ u'見所': 'highlights',
+ u'プルクオート': 'pull-quote',
+ u'合成': 'compound',
+ u'コンテナー': 'container',
+ u'容器': 'container',
+ u'表': 'table',
+ u'csv表': 'csv-table',
+ u'リスト表': 'list-table',
+ #u'質問': 'questions',
+ #u'問答': 'questions',
+ #u'faq': 'questions',
+ u'math (translation required)': 'math',
+ u'メタ': 'meta',
+ #u'イメージマプ': 'imagemap',
+ u'イメージ': 'image',
+ u'画像': 'image',
+ u'フィグア': 'figure',
+ u'図版': 'figure',
+ u'インクルード': 'include',
+ u'含む': 'include',
+ u'組み込み': 'include',
+ u'生': 'raw',
+ u'原': 'raw',
+ u'換える': 'replace',
+ u'取り換える': 'replace',
+ u'掛け替える': 'replace',
+ u'ユニコード': 'unicode',
+ u'日付': 'date',
+ u'クラス': 'class',
+ u'ロール': 'role',
+ u'役': 'role',
+ u'ディフォルトロール': 'default-role',
+ u'既定役': 'default-role',
+ u'タイトル': 'title',
+ u'題': 'title', # 題名 件名
+ u'目次': 'contents',
+ u'節数': 'sectnum',
+ u'ヘッダ': 'header',
+ u'フッタ': 'footer',
+ #u'脚注': 'footnotes', # 脚註?
+ #u'サイテーション': 'citations', # 出典 引証 引用
+ u'ターゲットノート': 'target-notes', # 的注 的脚注
+ }
+"""Japanese name to registered (in directives/__init__.py) directive name
+mapping."""
+
+roles = {
+ # language-dependent: fixed
+ u'略': 'abbreviation',
+ u'頭字語': 'acronym',
+ u'code (translation required)': 'code',
+ u'インデックス': 'index',
+ u'索引': 'index',
+ u'添字': 'subscript',
+ u'下付': 'subscript',
+ u'下': 'subscript',
+ u'上付': 'superscript',
+ u'上': 'superscript',
+ u'題参照': 'title-reference',
+ u'pep参照': 'pep-reference',
+ u'rfc参照': 'rfc-reference',
+ u'強調': 'emphasis',
+ u'強い': 'strong',
+ u'リテラル': 'literal',
+ u'整形済み': 'literal',
+ u'math (translation required)': 'math',
+ u'名付参照': 'named-reference',
+ u'無名参照': 'anonymous-reference',
+ u'脚注参照': 'footnote-reference',
+ u'出典参照': 'citation-reference',
+ u'代入参照': 'substitution-reference',
+ u'的': 'target',
+ u'uri参照': 'uri-reference',
+ u'uri': 'uri-reference',
+ u'url': 'uri-reference',
+ u'生': 'raw',}
+"""Mapping of Japanese role names to canonical role names for interpreted
+text."""
--- /dev/null
+# -*- coding: utf-8 -*-
+# $Id: ko.py 8253 2019-04-15 10:01:10Z milde $
+# Author: Thomas SJ Kang <thomas.kangsj@ujuc.kr>
+# Copyright: This module has been placed in the public domain.
+
+# New language mappings are welcome. Before doing a new translation, please
+# read <http://docutils.sf.net/docs/howto/i18n.html>. Two files must be
+# translated for each language: one in docutils/languages, the other in
+# docutils/parsers/rst/languages.
+
+"""
+Korean-language mappings for language-dependent features of
+reStructuredText.
+"""
+
+__docformat__ = 'reStructuredText'
+
+
+directives = {
+ # language-dependent: fixed
+ u'집중': 'attention',
+ u'주의': 'caution',
+ u'코드': 'code',
+ u'코드-블록': 'code',
+ u'소스코드': 'code',
+ u'위험': 'danger',
+ u'오류': 'error',
+ u'실마리': 'hint',
+ u'중요한': 'important',
+ u'비고': 'note',
+ u'팁': 'tip',
+ u'경고': 'warning',
+ u'권고': 'admonition',
+ u'사이드바': 'sidebar',
+ u'주제': 'topic',
+ u'라인-블록': 'line-block',
+ u'파싱된-리터럴': 'parsed-literal',
+ u'지시문': 'rubric',
+ u'제명': 'epigraph',
+ u'하이라이': 'highlights',
+ u'발췌문': 'pull-quote',
+ u'합성어': 'compound',
+ u'컨테이너': 'container',
+ #u'질문': 'questions',
+ u'표': 'table',
+ u'csv-표': 'csv-table',
+ u'list-표': 'list-table',
+ #u'qa': 'questions',
+ #u'faq': 'questions',
+ u'메타': 'meta',
+ u'수학': 'math',
+ #u'이미지맵': 'imagemap',
+ u'이미지': 'image',
+ u'도표': 'figure',
+ u'포함': 'include',
+ 'raw': 'raw',
+ u'대신하다': 'replace',
+ 'unicode': 'unicode',
+ u'날짜': 'date',
+ 'class': 'class',
+ u'역할': 'role',
+ u'기본-역할': 'default-role',
+ u'제목': 'title',
+ u'내용': 'contents',
+ 'sectnum': 'sectnum',
+ u'섹션-번호-매기기': 'sectnum',
+ u'머리말': 'header',
+ u'꼬리말': 'footer',
+ #u'긱주': 'footnotes',
+ #u'인용구': 'citations',
+ u'목표-노트': 'target-notes',
+ u'restructuredtext 테스트 지시어': 'restructuredtext-test-directive'}
+"""Korean name to registered (in directives/__init__.py) directive name
+mapping."""
+
+roles = {
+ # language-dependent: fixed
+ u'약어': 'abbreviation',
+ u'ab': 'abbreviation',
+ u'두음문자': 'acronym',
+ u'ac': 'acronym',
+ u'코드': 'code',
+ u'색인': 'index',
+ u'i': 'index',
+ u'다리-글자': 'subscript',
+ u'sub': 'subscript',
+ u'어깨-글자': 'superscript',
+ u'sup': 'superscript',
+ u'제목-참조': 'title-reference',
+ u'제목': 'title-reference',
+ u't': 'title-reference',
+ u'pep-참조': 'pep-reference',
+ u'pep': 'pep-reference',
+ u'rfc-참조': 'rfc-reference',
+ u'rfc': 'rfc-reference',
+ u'강조': 'emphasis',
+ u'굵게': 'strong',
+ u'기울기': 'literal',
+ u'수학': 'math',
+ u'명명된-참조': 'named-reference',
+ u'익명-참조': 'anonymous-reference',
+ u'각주-참조': 'footnote-reference',
+ u'인용-참조': 'citation-reference',
+ u'대리-참조': 'substitution-reference',
+ u'대상': 'target',
+ u'uri-참조': 'uri-reference',
+ u'uri': 'uri-reference',
+ u'url': 'uri-reference',
+ 'raw': 'raw',}
+"""Mapping of Korean role names to canonical role names for interpreted text.
+"""
--- /dev/null
+# -*- coding: utf-8 -*-
+# $Id: lt.py 7668 2013-06-04 12:46:30Z milde $
+# Author: Dalius Dobravolskas <dalius.do...@gmail.com>
+# Copyright: This module has been placed in the public domain.
+
+# New language mappings are welcome. Before doing a new translation, please
+# read <http://docutils.sf.net/docs/howto/i18n.html>. Two files must be
+# translated for each language: one in docutils/languages, the other in
+# docutils/parsers/rst/languages.
+
+"""
+Lithuanian-language mappings for language-dependent features of
+reStructuredText.
+"""
+
+__docformat__ = 'reStructuredText'
+
+
+directives = {
+ # language-dependent: fixed
+ u'dėmesio': 'attention',
+ u'atsargiai': 'caution',
+ u'code (translation required)': 'code',
+ u'pavojinga': 'danger',
+ u'klaida': 'error',
+ u'užuomina': 'hint',
+ u'svarbu': 'important',
+ u'pastaba': 'note',
+ u'patarimas': 'tip',
+ u'įspėjimas': 'warning',
+ u'perspėjimas': 'admonition',
+ u'šoninė-juosta': 'sidebar',
+ u'tema': 'topic',
+ u'linijinis-blokas': 'line-block',
+ u'išanalizuotas-literalas': 'parsed-literal',
+ u'rubrika': 'rubric',
+ u'epigrafas': 'epigraph',
+ u'pagridiniai-momentai': 'highlights',
+ u'atitraukta-citata': 'pull-quote',
+ u'sudėtinis-darinys': 'compound',
+ u'konteineris': 'container',
+ #'questions': 'questions',
+ u'lentelė': 'table',
+ u'csv-lentelė': 'csv-table',
+ u'sąrašo-lentelė': 'list-table',
+ #'qa': 'questions',
+ #'faq': 'questions',
+ u'meta': 'meta',
+ u'matematika': 'math',
+ #'imagemap': 'imagemap',
+ u'paveiksliukas': 'image',
+ u'iliustracija': 'figure',
+ u'pridėti': 'include',
+ u'žalia': 'raw',
+ u'pakeisti': 'replace',
+ u'unikodas': 'unicode',
+ u'data': 'date',
+ u'klasė': 'class',
+ u'rolė': 'role',
+ u'numatytoji-rolė': 'default-role',
+ u'titulas': 'title',
+ u'turinys': 'contents',
+ u'seknum': 'sectnum',
+ u'sekcijos-numeravimas': 'sectnum',
+ u'antraštė': 'header',
+ u'poraštė': 'footer',
+ #'footnotes': 'footnotes',
+ #'citations': 'citations',
+ u'nutaikytos-pastaba': 'target-notes',
+ u'restructuredtext-testinė-direktyva': 'restructuredtext-test-directive'}
+"""Lithuanian name to registered (in directives/__init__.py) directive name
+mapping."""
+
+roles = {
+ # language-dependent: fixed
+ 'santrumpa': 'abbreviation',
+ 'sa': 'abbreviation',
+ 'akronimas': 'acronym',
+ 'ak': 'acronym',
+ u'code (translation required)': 'code',
+ 'indeksas': 'index',
+ 'i': 'index',
+ u'apatinis-indeksas': 'subscript',
+ 'sub': 'subscript',
+ u'viršutinis-indeksas': 'superscript',
+ 'sup': 'superscript',
+ u'antrašės-nuoroda': 'title-reference',
+ u'antraštė': 'title-reference',
+ 'a': 'title-reference',
+ 'pep-nuoroda': 'pep-reference',
+ 'pep': 'pep-reference',
+ 'rfc-nuoroda': 'rfc-reference',
+ 'rfc': 'rfc-reference',
+ u'paryškinimas': 'emphasis',
+ u'sustiprintas': 'strong',
+ u'literalas': 'literal',
+ u'matematika': 'math',
+ u'vardinė-nuoroda': 'named-reference',
+ u'anoniminė-nuoroda': 'anonymous-reference',
+ u'išnašos-nuoroda': 'footnote-reference',
+ u'citatos-nuoroda': 'citation-reference',
+ u'pakeitimo-nuoroda': 'substitution-reference',
+ u'taikinys': 'target',
+ u'uri-nuoroda': 'uri-reference',
+ 'uri': 'uri-reference',
+ 'url': 'uri-reference',
+ 'žalia': 'raw',}
+"""Mapping of English role names to canonical role names for interpreted text.
+"""
--- /dev/null
+# -*- coding: utf-8 -*-
+# $Id: lv.py 7975 2016-10-20 20:00:19Z milde $
+# Copyright: This module has been placed in the public domain.
+
+# New language mappings are welcome. Before doing a new translation, please
+# read <http://docutils.sf.net/docs/howto/i18n.html>. Two files must be
+# translated for each language: one in docutils/languages, the other in
+# docutils/parsers/rst/languages.
+
+"""
+Latvian-language mappings for language-dependent features of
+reStructuredText.
+"""
+
+__docformat__ = 'reStructuredText'
+
+
+directives = {
+ # language-dependent: fixed
+ 'uzmanību': 'attention',
+ 'piesardzību': 'caution',
+ 'kods': 'code',
+ 'koda-bloks': 'code',
+ 'pirmkods': 'code',
+ 'bīstami': 'danger',
+ 'kļūda': 'error',
+ 'ieteikums': 'hint',
+ 'svarīgi': 'important',
+ 'piezīme': 'note',
+ 'padoms': 'tip',
+ 'brīdinājums': 'warning',
+ 'aizrādījums': 'admonition',
+ 'sānjosla': 'sidebar',
+ 'tēma': 'topic',
+ 'rindu-bloks': 'line-block',
+ 'parsēts-literālis': 'parsed-literal',
+ 'rubrika': 'rubric',
+ 'epigrāfs': 'epigraph',
+ 'apskats': 'highlights',
+ 'izvilkuma-citāts': 'pull-quote',
+ 'savienojums': 'compound',
+ 'konteiners': 'container',
+ #'questions': 'questions',
+ 'tabula': 'table',
+ 'csv-tabula': 'csv-table',
+ 'sarakstveida-tabula': 'list-table',
+ #'qa': 'questions',
+ #'faq': 'questions',
+ 'meta': 'meta',
+ 'matemātika': 'math',
+ #'imagemap': 'imagemap',
+ 'attēls': 'image',
+ 'figūra': 'figure',
+ 'ietvert': 'include',
+ 'burtiski': 'raw',
+ 'aizvieto': 'replace',
+ 'unicode': 'unicode',
+ 'datums': 'date',
+ 'klase': 'class',
+ 'role': 'role',
+ 'noklusējuma-role': 'default-role',
+ 'virsraksts': 'title',
+ 'saturs': 'contents',
+ 'numurēt-sekcijas': 'sectnum',
+ 'galvene': 'header',
+ 'kājene': 'footer',
+ #'footnotes': 'footnotes',
+ #'citations': 'citations',
+ 'atsauces-apakšā': 'target-notes',
+ 'restructuredtext-testa-direktīva': 'restructuredtext-test-directive'}
+"""English name to registered (in directives/__init__.py) directive name
+mapping."""
+
+roles = {
+ # language-dependent: fixed
+ 'saīsinājums': 'abbreviation',
+ 'īsi': 'abbreviation',
+ 'akronīms': 'acronym',
+ 'kods': 'code',
+ 'indekss': 'index',
+ 'i': 'index',
+ 'apakšraksts': 'subscript',
+ 'apakšā': 'subscript',
+ 'augšraksts': 'superscript',
+ 'augšā': 'superscript',
+ 'virsraksta-atsauce': 'title-reference',
+ 'virsraksts': 'title-reference',
+ 'v': 'title-reference',
+ 'atsauce-uz-pep': 'pep-reference',
+ 'pep': 'pep-reference',
+ 'atsauce-uz-rfc': 'rfc-reference',
+ 'rfc': 'rfc-reference',
+ 'izcēlums': 'emphasis',
+ 'blīvs': 'strong',
+ 'literālis': 'literal',
+ 'matemātika': 'math',
+ 'nosaukta-atsauce': 'named-reference',
+ 'nenosaukta-atsauce': 'anonymous-reference',
+ 'kājenes-atsauce': 'footnote-reference',
+ 'citātā-atsauce': 'citation-reference',
+ 'aizvietojuma-atsauce': 'substitution-reference',
+ 'mēr''kis': 'target',
+ 'atsauce-uz-uri': 'uri-reference',
+ 'uri': 'uri-reference',
+ 'url': 'uri-reference',
+ 'burtiski': 'raw',}
+"""Mapping of English role names to canonical role names for interpreted text.
+"""
--- /dev/null
+# $Id: nl.py 7119 2011-09-02 13:00:23Z milde $
+# Author: Martijn Pieters <mjpieters@users.sourceforge.net>
+# Copyright: This module has been placed in the public domain.
+
+# New language mappings are welcome. Before doing a new translation, please
+# read <http://docutils.sf.net/docs/howto/i18n.html>. Two files must be
+# translated for each language: one in docutils/languages, the other in
+# docutils/parsers/rst/languages.
+
+"""
+Dutch-language mappings for language-dependent features of
+reStructuredText.
+"""
+
+__docformat__ = 'reStructuredText'
+
+
+directives = {
+ # language-dependent: fixed
+ 'attentie': 'attention',
+ 'let-op': 'caution',
+ 'code (translation required)': 'code',
+ 'gevaar': 'danger',
+ 'fout': 'error',
+ 'hint': 'hint',
+ 'belangrijk': 'important',
+ 'opmerking': 'note',
+ 'tip': 'tip',
+ 'waarschuwing': 'warning',
+ 'aanmaning': 'admonition',
+ 'katern': 'sidebar',
+ 'onderwerp': 'topic',
+ 'lijn-blok': 'line-block',
+ 'letterlijk-ontleed': 'parsed-literal',
+ 'rubriek': 'rubric',
+ 'opschrift': 'epigraph',
+ 'hoogtepunten': 'highlights',
+ 'pull-quote': 'pull-quote', # Dutch printers use the english term
+ 'samenstelling': 'compound',
+ 'verbinding': 'compound',
+ u'container (translation required)': 'container',
+ #'vragen': 'questions',
+ 'tabel': 'table',
+ 'csv-tabel': 'csv-table',
+ 'lijst-tabel': 'list-table',
+ #'veelgestelde-vragen': 'questions',
+ 'meta': 'meta',
+ 'math (translation required)': 'math',
+ #'imagemap': 'imagemap',
+ 'beeld': 'image',
+ 'figuur': 'figure',
+ 'opnemen': 'include',
+ 'onbewerkt': 'raw',
+ 'vervang': 'replace',
+ 'vervanging': 'replace',
+ 'unicode': 'unicode',
+ 'datum': 'date',
+ 'klasse': 'class',
+ 'rol': 'role',
+ u'default-role (translation required)': 'default-role',
+ 'title (translation required)': 'title',
+ 'inhoud': 'contents',
+ 'sectnum': 'sectnum',
+ 'sectie-nummering': 'sectnum',
+ 'hoofdstuk-nummering': 'sectnum',
+ u'header (translation required)': 'header',
+ u'footer (translation required)': 'footer',
+ #'voetnoten': 'footnotes',
+ #'citaten': 'citations',
+ 'verwijzing-voetnoten': 'target-notes',
+ 'restructuredtext-test-instructie': 'restructuredtext-test-directive'}
+"""Dutch name to registered (in directives/__init__.py) directive name
+mapping."""
+
+roles = {
+ # language-dependent: fixed
+ 'afkorting': 'abbreviation',
+ # 'ab': 'abbreviation',
+ 'acroniem': 'acronym',
+ 'ac': 'acronym',
+ u'code (translation required)': 'code',
+ 'index': 'index',
+ 'i': 'index',
+ 'inferieur': 'subscript',
+ 'inf': 'subscript',
+ 'superieur': 'superscript',
+ 'sup': 'superscript',
+ 'titel-referentie': 'title-reference',
+ 'titel': 'title-reference',
+ 't': 'title-reference',
+ 'pep-referentie': 'pep-reference',
+ 'pep': 'pep-reference',
+ 'rfc-referentie': 'rfc-reference',
+ 'rfc': 'rfc-reference',
+ 'nadruk': 'emphasis',
+ 'extra': 'strong',
+ 'extra-nadruk': 'strong',
+ 'vet': 'strong',
+ 'letterlijk': 'literal',
+ 'math (translation required)': 'math',
+ 'benoemde-referentie': 'named-reference',
+ 'anonieme-referentie': 'anonymous-reference',
+ 'voetnoot-referentie': 'footnote-reference',
+ 'citaat-referentie': 'citation-reference',
+ 'substitie-reference': 'substitution-reference',
+ 'verwijzing': 'target',
+ 'uri-referentie': 'uri-reference',
+ 'uri': 'uri-reference',
+ 'url': 'uri-reference',
+ 'onbewerkt': 'raw',}
+"""Mapping of Dutch role names to canonical role names for interpreted text.
+"""
--- /dev/null
+# $Id$
+# Author: Robert Wojciechowicz <rw@smsnet.pl>
+# Copyright: This module has been placed in the public domain.
+
+# New language mappings are welcome. Before doing a new translation, please
+# read <http://docutils.sf.net/docs/howto/i18n.html>. Two files must be
+# translated for each language: one in docutils/languages, the other in
+# docutils/parsers/rst/languages.
+
+"""
+Polish-language mappings for language-dependent features of
+reStructuredText.
+"""
+
+__docformat__ = 'reStructuredText'
+
+
+directives = {
+ # language-dependent: fixed
+ u'uwaga': 'attention',
+ u'ostro\u017cnie': 'caution',
+ u'code (translation required)': 'code',
+ u'niebezpiecze\u0144stwo': 'danger',
+ u'b\u0142\u0105d': 'error',
+ u'wskaz\u00f3wka': 'hint',
+ u'wa\u017cne': 'important',
+ u'przypis': 'note',
+ u'rada': 'tip',
+ u'ostrze\u017cenie': 'warning',
+ u'upomnienie': 'admonition',
+ u'ramka': 'sidebar',
+ u'temat': 'topic',
+ u'blok-linii': 'line-block',
+ u'sparsowany-litera\u0142': 'parsed-literal',
+ u'rubryka': 'rubric',
+ u'epigraf': 'epigraph',
+ u'highlights': 'highlights', # FIXME no polish equivalent?
+ u'pull-quote': 'pull-quote', # FIXME no polish equivalent?
+ u'z\u0142o\u017cony': 'compound',
+ u'kontener': 'container',
+ #'questions': 'questions',
+ u'tabela': 'table',
+ u'tabela-csv': 'csv-table',
+ u'tabela-listowa': 'list-table',
+ #'qa': 'questions',
+ #'faq': 'questions',
+ u'meta': 'meta',
+ 'math (translation required)': 'math',
+ #'imagemap': 'imagemap',
+ u'obraz': 'image',
+ u'rycina': 'figure',
+ u'do\u0142\u0105cz': 'include',
+ u'surowe': 'raw',
+ u'zast\u0105p': 'replace',
+ u'unikod': 'unicode',
+ u'data': 'date',
+ u'klasa': 'class',
+ u'rola': 'role',
+ u'rola-domy\u015blna': 'default-role',
+ u'tytu\u0142': 'title',
+ u'tre\u015b\u0107': 'contents',
+ u'sectnum': 'sectnum',
+ u'numeracja-sekcji': 'sectnum',
+ u'nag\u0142\u00f3wek': 'header',
+ u'stopka': 'footer',
+ #'footnotes': 'footnotes',
+ #'citations': 'citations',
+ u'target-notes': 'target-notes', # FIXME no polish equivalent?
+ u'restructuredtext-test-directive': 'restructuredtext-test-directive'}
+"""Polish name to registered (in directives/__init__.py) directive name
+mapping."""
+
+roles = {
+ # language-dependent: fixed
+ u'skr\u00f3t': 'abbreviation',
+ u'akronim': 'acronym',
+ u'code (translation required)': 'code',
+ u'indeks': 'index',
+ u'indeks-dolny': 'subscript',
+ u'indeks-g\u00f3rny': 'superscript',
+ u'referencja-tytu\u0142': 'title-reference',
+ u'referencja-pep': 'pep-reference',
+ u'referencja-rfc': 'rfc-reference',
+ u'podkre\u015blenie': 'emphasis',
+ u'wyt\u0142uszczenie': 'strong',
+ u'dos\u0142ownie': 'literal',
+ 'math (translation required)': 'math',
+ u'referencja-nazwana': 'named-reference',
+ u'referencja-anonimowa': 'anonymous-reference',
+ u'referencja-przypis': 'footnote-reference',
+ u'referencja-cytat': 'citation-reference',
+ u'referencja-podstawienie': 'substitution-reference',
+ u'cel': 'target',
+ u'referencja-uri': 'uri-reference',
+ u'uri': 'uri-reference',
+ u'url': 'uri-reference',
+ u'surowe': 'raw',}
+"""Mapping of Polish role names to canonical role names for interpreted text.
+"""
+
+
+
--- /dev/null
+# $Id: pt_br.py 7119 2011-09-02 13:00:23Z milde $
+# Author: David Goodger <goodger@python.org>
+# Copyright: This module has been placed in the public domain.
+
+# New language mappings are welcome. Before doing a new translation, please
+# read <http://docutils.sf.net/docs/howto/i18n.html>. Two files must be
+# translated for each language: one in docutils/languages, the other in
+# docutils/parsers/rst/languages.
+
+"""
+Brazilian Portuguese-language mappings for language-dependent features of
+reStructuredText.
+"""
+
+__docformat__ = 'reStructuredText'
+
+
+directives = {
+ # language-dependent: fixed
+ u'aten\u00E7\u00E3o': 'attention',
+ 'cuidado': 'caution',
+ u'code (translation required)': 'code',
+ 'perigo': 'danger',
+ 'erro': 'error',
+ u'sugest\u00E3o': 'hint',
+ 'importante': 'important',
+ 'nota': 'note',
+ 'dica': 'tip',
+ 'aviso': 'warning',
+ u'exorta\u00E7\u00E3o': 'admonition',
+ 'barra-lateral': 'sidebar',
+ u't\u00F3pico': 'topic',
+ 'bloco-de-linhas': 'line-block',
+ 'literal-interpretado': 'parsed-literal',
+ 'rubrica': 'rubric',
+ u'ep\u00EDgrafo': 'epigraph',
+ 'destaques': 'highlights',
+ u'cita\u00E7\u00E3o-destacada': 'pull-quote',
+ u'compound (translation required)': 'compound',
+ u'container (translation required)': 'container',
+ #'perguntas': 'questions',
+ #'qa': 'questions',
+ #'faq': 'questions',
+ u'table (translation required)': 'table',
+ u'csv-table (translation required)': 'csv-table',
+ u'list-table (translation required)': 'list-table',
+ 'meta': 'meta',
+ 'math (translation required)': 'math',
+ #'imagemap': 'imagemap',
+ 'imagem': 'image',
+ 'figura': 'figure',
+ u'inclus\u00E3o': 'include',
+ 'cru': 'raw',
+ u'substitui\u00E7\u00E3o': 'replace',
+ 'unicode': 'unicode',
+ 'data': 'date',
+ 'classe': 'class',
+ 'role (translation required)': 'role',
+ u'default-role (translation required)': 'default-role',
+ u'title (translation required)': 'title',
+ u'\u00EDndice': 'contents',
+ 'numsec': 'sectnum',
+ u'numera\u00E7\u00E3o-de-se\u00E7\u00F5es': 'sectnum',
+ u'header (translation required)': 'header',
+ u'footer (translation required)': 'footer',
+ #u'notas-de-rorap\u00E9': 'footnotes',
+ #u'cita\u00E7\u00F5es': 'citations',
+ u'links-no-rodap\u00E9': 'target-notes',
+ 'restructuredtext-test-directive': 'restructuredtext-test-directive'}
+"""Brazilian Portuguese name to registered (in directives/__init__.py)
+directive name mapping."""
+
+roles = {
+ # language-dependent: fixed
+ u'abbrevia\u00E7\u00E3o': 'abbreviation',
+ 'ab': 'abbreviation',
+ u'acr\u00F4nimo': 'acronym',
+ 'ac': 'acronym',
+ u'code (translation required)': 'code',
+ u'\u00EDndice-remissivo': 'index',
+ 'i': 'index',
+ 'subscrito': 'subscript',
+ 'sub': 'subscript',
+ 'sobrescrito': 'superscript',
+ 'sob': 'superscript',
+ u'refer\u00EAncia-a-t\u00EDtulo': 'title-reference',
+ u't\u00EDtulo': 'title-reference',
+ 't': 'title-reference',
+ u'refer\u00EAncia-a-pep': 'pep-reference',
+ 'pep': 'pep-reference',
+ u'refer\u00EAncia-a-rfc': 'rfc-reference',
+ 'rfc': 'rfc-reference',
+ u'\u00EAnfase': 'emphasis',
+ 'forte': 'strong',
+ 'literal': 'literal',
+ 'math (translation required)': 'math', # translation required?
+ u'refer\u00EAncia-por-nome': 'named-reference',
+ u'refer\u00EAncia-an\u00F4nima': 'anonymous-reference',
+ u'refer\u00EAncia-a-nota-de-rodap\u00E9': 'footnote-reference',
+ u'refer\u00EAncia-a-cita\u00E7\u00E3o': 'citation-reference',
+ u'refer\u00EAncia-a-substitui\u00E7\u00E3o': 'substitution-reference',
+ 'alvo': 'target',
+ u'refer\u00EAncia-a-uri': 'uri-reference',
+ 'uri': 'uri-reference',
+ 'url': 'uri-reference',
+ 'cru': 'raw',}
+"""Mapping of Brazilian Portuguese role names to canonical role names
+for interpreted text."""
--- /dev/null
+# -*- coding: utf-8 -*-
+# $Id: ru.py 7123 2011-09-12 08:28:31Z milde $
+# Author: Roman Suzi <rnd@onego.ru>
+# Copyright: This module has been placed in the public domain.
+
+# New language mappings are welcome. Before doing a new translation, please
+# read <http://docutils.sf.net/docs/howto/i18n.html>. Two files must be
+# translated for each language: one in docutils/languages, the other in
+# docutils/parsers/rst/languages.
+
+"""
+Russian-language mappings for language-dependent features of
+reStructuredText.
+"""
+
+__docformat__ = 'reStructuredText'
+
+directives = {
+ u'блок-строк': u'line-block',
+ u'meta': u'meta',
+ u'математика': 'math',
+ u'обработанный-литерал': u'parsed-literal',
+ u'выделенная-цитата': u'pull-quote',
+ u'код': 'code',
+ u'compound (translation required)': 'compound',
+ u'контейнер': 'container',
+ u'таблица': 'table',
+ u'csv-table (translation required)': 'csv-table',
+ u'list-table (translation required)': 'list-table',
+ u'сырой': u'raw',
+ u'замена': u'replace',
+ u'тестовая-директива-restructuredtext': u'restructuredtext-test-directive',
+ u'целевые-сноски': u'target-notes',
+ u'unicode': u'unicode',
+ u'дата': u'date',
+ u'боковая-полоса': u'sidebar',
+ u'важно': u'important',
+ u'включать': u'include',
+ u'внимание': u'attention',
+ u'выделение': u'highlights',
+ u'замечание': u'admonition',
+ u'изображение': u'image',
+ u'класс': u'class',
+ u'роль': 'role',
+ u'default-role (translation required)': 'default-role',
+ u'титул': 'title',
+ u'номер-раздела': u'sectnum',
+ u'нумерация-разделов': u'sectnum',
+ u'опасно': u'danger',
+ u'осторожно': u'caution',
+ u'ошибка': u'error',
+ u'подсказка': u'tip',
+ u'предупреждение': u'warning',
+ u'примечание': u'note',
+ u'рисунок': u'figure',
+ u'рубрика': u'rubric',
+ u'совет': u'hint',
+ u'содержание': u'contents',
+ u'тема': u'topic',
+ u'эпиграф': u'epigraph',
+ u'header (translation required)': 'header',
+ u'footer (translation required)': 'footer',}
+"""Russian name to registered (in directives/__init__.py) directive name
+mapping."""
+
+roles = {
+ u'акроним': 'acronym',
+ u'код': 'code',
+ u'анонимная-ссылка': 'anonymous-reference',
+ u'буквально': 'literal',
+ u'математика': 'math',
+ u'верхний-индекс': 'superscript',
+ u'выделение': 'emphasis',
+ u'именованная-ссылка': 'named-reference',
+ u'индекс': 'index',
+ u'нижний-индекс': 'subscript',
+ u'сильное-выделение': 'strong',
+ u'сокращение': 'abbreviation',
+ u'ссылка-замена': 'substitution-reference',
+ u'ссылка-на-pep': 'pep-reference',
+ u'ссылка-на-rfc': 'rfc-reference',
+ u'ссылка-на-uri': 'uri-reference',
+ u'ссылка-на-заглавие': 'title-reference',
+ u'ссылка-на-сноску': 'footnote-reference',
+ u'цитатная-ссылка': 'citation-reference',
+ u'цель': 'target',
+ u'сырой': 'raw',}
+"""Mapping of Russian role names to canonical role names for interpreted text.
+"""
--- /dev/null
+# $Id: sk.py 7119 2011-09-02 13:00:23Z milde $
+# Author: Miroslav Vasko <zemiak@zoznam.sk>
+# Copyright: This module has been placed in the public domain.
+
+# New language mappings are welcome. Before doing a new translation, please
+# read <http://docutils.sf.net/docs/howto/i18n.html>. Two files must be
+# translated for each language: one in docutils/languages, the other in
+# docutils/parsers/rst/languages.
+
+"""
+Slovak-language mappings for language-dependent features of
+reStructuredText.
+"""
+
+__docformat__ = 'reStructuredText'
+
+
+directives = {
+ u'pozor': 'attention',
+ u'opatrne': 'caution',
+ u'code (translation required)': 'code',
+ u'nebezpe\xe8enstvo': 'danger',
+ u'chyba': 'error',
+ u'rada': 'hint',
+ u'd\xf4le\x9eit\xe9': 'important',
+ u'pozn\xe1mka': 'note',
+ u'tip (translation required)': 'tip',
+ u'varovanie': 'warning',
+ u'admonition (translation required)': 'admonition',
+ u'sidebar (translation required)': 'sidebar',
+ u't\xe9ma': 'topic',
+ u'blok-riadkov': 'line-block',
+ u'parsed-literal': 'parsed-literal',
+ u'rubric (translation required)': 'rubric',
+ u'epigraph (translation required)': 'epigraph',
+ u'highlights (translation required)': 'highlights',
+ u'pull-quote (translation required)': 'pull-quote',
+ u'compound (translation required)': 'compound',
+ u'container (translation required)': 'container',
+ #u'questions': 'questions',
+ #u'qa': 'questions',
+ #u'faq': 'questions',
+ u'table (translation required)': 'table',
+ u'csv-table (translation required)': 'csv-table',
+ u'list-table (translation required)': 'list-table',
+ u'meta': 'meta',
+ 'math (translation required)': 'math',
+ #u'imagemap': 'imagemap',
+ u'obr\xe1zok': 'image',
+ u'tvar': 'figure',
+ u'vlo\x9ei\x9d': 'include',
+ u'raw (translation required)': 'raw',
+ u'nahradi\x9d': 'replace',
+ u'unicode': 'unicode',
+ u'd\u00E1tum': 'date',
+ u'class (translation required)': 'class',
+ u'role (translation required)': 'role',
+ u'default-role (translation required)': 'default-role',
+ u'title (translation required)': 'title',
+ u'obsah': 'contents',
+ u'\xe8as\x9d': 'sectnum',
+ u'\xe8as\x9d-\xe8\xedslovanie': 'sectnum',
+ u'cie\xbeov\xe9-pozn\xe1mky': 'target-notes',
+ u'header (translation required)': 'header',
+ u'footer (translation required)': 'footer',
+ #u'footnotes': 'footnotes',
+ #u'citations': 'citations',
+ }
+"""Slovak name to registered (in directives/__init__.py) directive name
+mapping."""
+
+roles = {
+ u'abbreviation (translation required)': 'abbreviation',
+ u'acronym (translation required)': 'acronym',
+ u'code (translation required)': 'code',
+ u'index (translation required)': 'index',
+ u'subscript (translation required)': 'subscript',
+ u'superscript (translation required)': 'superscript',
+ u'title-reference (translation required)': 'title-reference',
+ u'pep-reference (translation required)': 'pep-reference',
+ u'rfc-reference (translation required)': 'rfc-reference',
+ u'emphasis (translation required)': 'emphasis',
+ u'strong (translation required)': 'strong',
+ u'literal (translation required)': 'literal',
+ 'math (translation required)': 'math',
+ u'named-reference (translation required)': 'named-reference',
+ u'anonymous-reference (translation required)': 'anonymous-reference',
+ u'footnote-reference (translation required)': 'footnote-reference',
+ u'citation-reference (translation required)': 'citation-reference',
+ u'substitution-reference (translation required)': 'substitution-reference',
+ u'target (translation required)': 'target',
+ u'uri-reference (translation required)': 'uri-reference',
+ u'raw (translation required)': 'raw',}
+"""Mapping of Slovak role names to canonical role names for interpreted text.
+"""
--- /dev/null
+# -*- coding: utf-8 -*-
+# $Id: sv.py 8012 2017-01-03 23:08:19Z milde $
+# Author: Adam Chodorowski <chodorowski@users.sourceforge.net>
+# Copyright: This module has been placed in the public domain.
+
+# New language mappings are welcome. Before doing a new translation, please
+# read <http://docutils.sf.net/docs/howto/i18n.html>. Two files must be
+# translated for each language: one in docutils/languages, the other in
+# docutils/parsers/rst/languages.
+
+"""
+Swedish language mappings for language-dependent features of reStructuredText.
+"""
+
+__docformat__ = 'reStructuredText'
+
+directives = {
+ u'observera': 'attention',
+ u'akta': 'caution', # also 'försiktigt'
+ u'kod': 'code',
+ u'fara': 'danger',
+ u'fel': 'error',
+ u'vink': 'hint', # also 'hint'
+ u'viktigt': 'important',
+ u'notera': 'note',
+ u'tips': 'tip',
+ u'varning': 'warning',
+ u'anmärkning': 'admonition', # literal 'tillrättavisning', 'förmaning'
+ u'sidorad': 'sidebar',
+ u'ämne': 'topic',
+ u'tema': 'topic',
+ u'rad-block': 'line-block',
+ u'parsed-literal (translation required)': 'parsed-literal', # 'tolkad-bokstavlig'?
+ u'rubrik': 'rubric',
+ u'epigraf': 'epigraph',
+ u'höjdpunkter': 'highlights',
+ u'pull-quote (translation required)': 'pull-quote',
+ u'sammansatt': 'compound',
+ u'container': 'container',
+ # u'frågor': 'questions',
+ # NOTE: A bit long, but recommended by http://www.nada.kth.se/dataterm/:
+ # u'frågor-och-svar': 'questions',
+ # u'vanliga-frågor': 'questions',
+ u'tabell': 'table',
+ u'csv-tabell': 'csv-table',
+ u'list-tabell': 'list-table',
+ u'meta': 'meta',
+ u'matematik': 'math',
+ # u'bildkarta': 'imagemap', # FIXME: Translation might be too literal.
+ u'bild': 'image',
+ u'figur': 'figure',
+ u'inkludera': 'include',
+ u'rå': 'raw',
+ u'ersätta': 'replace',
+ u'unicode': 'unicode',
+ u'datum': 'date',
+ u'klass': 'class',
+ u'roll': 'role',
+ u'standardroll': 'default-role',
+ u'titel': 'title',
+ u'innehåll': 'contents',
+ u'sektionsnumrering': 'sectnum',
+ u'target-notes (translation required)': 'target-notes',
+ u'sidhuvud': 'header',
+ u'sidfot': 'footer',
+ # u'fotnoter': 'footnotes',
+ # u'citeringar': 'citations',
+ }
+"""Swedish name to registered (in directives/__init__.py) directive name
+mapping."""
+
+roles = {
+ u'förkortning': 'abbreviation',
+ u'akronym': 'acronym',
+ u'kod': 'code',
+ u'index': 'index',
+ u'nedsänkt': 'subscript',
+ u'upphöjd': 'superscript',
+ u'titel-referens': 'title-reference',
+ u'pep-referens': 'pep-reference',
+ u'rfc-referens': 'rfc-reference',
+ u'betoning': 'emphasis',
+ u'stark': 'strong',
+ u'bokstavlig': 'literal', # also 'ordagranna'
+ u'matematik': 'math',
+ u'namngiven-referens': 'named-reference',
+ u'anonym-referens': 'anonymous-reference',
+ u'fotnot-referens': 'footnote-reference',
+ u'citat-referens': 'citation-reference',
+ u'ersättnings-referens': 'substitution-reference',
+ u'mål': 'target',
+ u'uri-referens': 'uri-reference',
+ u'rå': 'raw',}
+"""Mapping of Swedish role names to canonical role names for interpreted text.
+"""
--- /dev/null
+# -*- coding: utf-8 -*-
+# $Id: zh_cn.py 7119 2011-09-02 13:00:23Z milde $
+# Author: Panjunyong <panjy@zopechina.com>
+# Copyright: This module has been placed in the public domain.
+
+# New language mappings are welcome. Before doing a new translation, please
+# read <http://docutils.sf.net/docs/howto/i18n.html>. Two files must be
+# translated for each language: one in docutils/languages, the other in
+# docutils/parsers/rst/languages.
+
+"""
+Simplified Chinese language mappings for language-dependent features of
+reStructuredText.
+"""
+
+__docformat__ = 'reStructuredText'
+
+
+directives = {
+ # language-dependent: fixed
+ u'注意': 'attention',
+ u'小心': 'caution',
+ u'code (translation required)': 'code',
+ u'危险': 'danger',
+ u'错误': 'error',
+ u'提示': 'hint',
+ u'重要': 'important',
+ u'注解': 'note',
+ u'技巧': 'tip',
+ u'警告': 'warning',
+ u'忠告': 'admonition',
+ u'侧框': 'sidebar',
+ u'主题': 'topic',
+ u'line-block (translation required)': 'line-block',
+ u'parsed-literal (translation required)': 'parsed-literal',
+ u'醒目': 'rubric',
+ u'铭文': 'epigraph',
+ u'要点': 'highlights',
+ u'pull-quote (translation required)': 'pull-quote',
+ u'复合': 'compound',
+ u'容器': 'container',
+ #u'questions (translation required)': 'questions',
+ u'表格': 'table',
+ u'csv表格': 'csv-table',
+ u'列表表格': 'list-table',
+ #u'qa (translation required)': 'questions',
+ #u'faq (translation required)': 'questions',
+ u'元数据': 'meta',
+ u'math (translation required)': 'math',
+ #u'imagemap (translation required)': 'imagemap',
+ u'图片': 'image',
+ u'图例': 'figure',
+ u'包含': 'include',
+ u'原文': 'raw',
+ u'代替': 'replace',
+ u'统一码': 'unicode',
+ u'日期': 'date',
+ u'类型': 'class',
+ u'角色': 'role',
+ u'默认角色': 'default-role',
+ u'标题': 'title',
+ u'目录': 'contents',
+ u'章节序号': 'sectnum',
+ u'题头': 'header',
+ u'页脚': 'footer',
+ #u'footnotes (translation required)': 'footnotes',
+ #u'citations (translation required)': 'citations',
+ u'target-notes (translation required)': 'target-notes',
+ u'restructuredtext-test-directive': 'restructuredtext-test-directive'}
+"""Simplified Chinese name to registered (in directives/__init__.py)
+directive name mapping."""
+
+roles = {
+ # language-dependent: fixed
+ u'缩写': 'abbreviation',
+ u'简称': 'acronym',
+ u'code (translation required)': 'code',
+ u'index (translation required)': 'index',
+ u'i (translation required)': 'index',
+ u'下标': 'subscript',
+ u'上标': 'superscript',
+ u'title-reference (translation required)': 'title-reference',
+ u'title (translation required)': 'title-reference',
+ u't (translation required)': 'title-reference',
+ u'pep-reference (translation required)': 'pep-reference',
+ u'pep (translation required)': 'pep-reference',
+ u'rfc-reference (translation required)': 'rfc-reference',
+ u'rfc (translation required)': 'rfc-reference',
+ u'强调': 'emphasis',
+ u'加粗': 'strong',
+ u'字面': 'literal',
+ u'math (translation required)': 'math',
+ u'named-reference (translation required)': 'named-reference',
+ u'anonymous-reference (translation required)': 'anonymous-reference',
+ u'footnote-reference (translation required)': 'footnote-reference',
+ u'citation-reference (translation required)': 'citation-reference',
+ u'substitution-reference (translation required)': 'substitution-reference',
+ u'target (translation required)': 'target',
+ u'uri-reference (translation required)': 'uri-reference',
+ u'uri (translation required)': 'uri-reference',
+ u'url (translation required)': 'uri-reference',
+ u'raw (translation required)': 'raw',}
+"""Mapping of Simplified Chinese role names to canonical role names
+for interpreted text."""
--- /dev/null
+# -*- coding: utf-8 -*-
+# $Id: zh_tw.py 7119 2011-09-02 13:00:23Z milde $
+# Author: David Goodger <goodger@python.org>
+# Copyright: This module has been placed in the public domain.
+
+# New language mappings are welcome. Before doing a new translation, please
+# read <http://docutils.sf.net/docs/howto/i18n.html>. Two files must be
+# translated for each language: one in docutils/languages, the other in
+# docutils/parsers/rst/languages.
+
+"""
+Traditional Chinese language mappings for language-dependent features of
+reStructuredText.
+"""
+
+__docformat__ = 'reStructuredText'
+
+
+directives = {
+ # language-dependent: fixed
+ 'attention (translation required)': 'attention',
+ 'caution (translation required)': 'caution',
+ 'code (translation required)': 'code',
+ 'danger (translation required)': 'danger',
+ 'error (translation required)': 'error',
+ 'hint (translation required)': 'hint',
+ 'important (translation required)': 'important',
+ 'note (translation required)': 'note',
+ 'tip (translation required)': 'tip',
+ 'warning (translation required)': 'warning',
+ 'admonition (translation required)': 'admonition',
+ 'sidebar (translation required)': 'sidebar',
+ 'topic (translation required)': 'topic',
+ 'line-block (translation required)': 'line-block',
+ 'parsed-literal (translation required)': 'parsed-literal',
+ 'rubric (translation required)': 'rubric',
+ 'epigraph (translation required)': 'epigraph',
+ 'highlights (translation required)': 'highlights',
+ 'pull-quote (translation required)': 'pull-quote',
+ 'compound (translation required)': 'compound',
+ u'container (translation required)': 'container',
+ #'questions (translation required)': 'questions',
+ 'table (translation required)': 'table',
+ 'csv-table (translation required)': 'csv-table',
+ 'list-table (translation required)': 'list-table',
+ #'qa (translation required)': 'questions',
+ #'faq (translation required)': 'questions',
+ 'meta (translation required)': 'meta',
+ 'math (translation required)': 'math',
+ #'imagemap (translation required)': 'imagemap',
+ 'image (translation required)': 'image',
+ 'figure (translation required)': 'figure',
+ 'include (translation required)': 'include',
+ 'raw (translation required)': 'raw',
+ 'replace (translation required)': 'replace',
+ 'unicode (translation required)': 'unicode',
+ u'日期': 'date',
+ 'class (translation required)': 'class',
+ 'role (translation required)': 'role',
+ u'default-role (translation required)': 'default-role',
+ u'title (translation required)': 'title',
+ 'contents (translation required)': 'contents',
+ 'sectnum (translation required)': 'sectnum',
+ 'section-numbering (translation required)': 'sectnum',
+ u'header (translation required)': 'header',
+ u'footer (translation required)': 'footer',
+ #'footnotes (translation required)': 'footnotes',
+ #'citations (translation required)': 'citations',
+ 'target-notes (translation required)': 'target-notes',
+ 'restructuredtext-test-directive': 'restructuredtext-test-directive'}
+"""Traditional Chinese name to registered (in directives/__init__.py)
+directive name mapping."""
+
+roles = {
+ # language-dependent: fixed
+ 'abbreviation (translation required)': 'abbreviation',
+ 'ab (translation required)': 'abbreviation',
+ 'acronym (translation required)': 'acronym',
+ 'ac (translation required)': 'acronym',
+ u'code (translation required)': 'code',
+ 'index (translation required)': 'index',
+ 'i (translation required)': 'index',
+ 'subscript (translation required)': 'subscript',
+ 'sub (translation required)': 'subscript',
+ 'superscript (translation required)': 'superscript',
+ 'sup (translation required)': 'superscript',
+ 'title-reference (translation required)': 'title-reference',
+ 'title (translation required)': 'title-reference',
+ 't (translation required)': 'title-reference',
+ 'pep-reference (translation required)': 'pep-reference',
+ 'pep (translation required)': 'pep-reference',
+ 'rfc-reference (translation required)': 'rfc-reference',
+ 'rfc (translation required)': 'rfc-reference',
+ 'emphasis (translation required)': 'emphasis',
+ 'strong (translation required)': 'strong',
+ 'literal (translation required)': 'literal',
+ 'math (translation required)': 'math',
+ 'named-reference (translation required)': 'named-reference',
+ 'anonymous-reference (translation required)': 'anonymous-reference',
+ 'footnote-reference (translation required)': 'footnote-reference',
+ 'citation-reference (translation required)': 'citation-reference',
+ 'substitution-reference (translation required)': 'substitution-reference',
+ 'target (translation required)': 'target',
+ 'uri-reference (translation required)': 'uri-reference',
+ 'uri (translation required)': 'uri-reference',
+ 'url (translation required)': 'uri-reference',
+ 'raw (translation required)': 'raw',}
+"""Mapping of Traditional Chinese role names to canonical role names for
+interpreted text."""
--- /dev/null
+# $Id: roles.py 8347 2019-08-26 12:12:02Z milde $
+# Author: Edward Loper <edloper@gradient.cis.upenn.edu>
+# Copyright: This module has been placed in the public domain.
+
+"""
+This module defines standard interpreted text role functions, a registry for
+interpreted text roles, and an API for adding to and retrieving from the
+registry.
+
+The interface for interpreted role functions is as follows::
+
+ def role_fn(name, rawtext, text, lineno, inliner,
+ options={}, content=[]):
+ code...
+
+ # Set function attributes for customization:
+ role_fn.options = ...
+ role_fn.content = ...
+
+Parameters:
+
+- ``name`` is the local name of the interpreted text role, the role name
+ actually used in the document.
+
+- ``rawtext`` is a string containing the entire interpreted text construct.
+ Return it as a ``problematic`` node linked to a system message if there is a
+ problem.
+
+- ``text`` is the interpreted text content, with backslash escapes converted
+ to nulls (``\x00``).
+
+- ``lineno`` is the line number where the interpreted text beings.
+
+- ``inliner`` is the Inliner object that called the role function.
+ It defines the following useful attributes: ``reporter``,
+ ``problematic``, ``memo``, ``parent``, ``document``.
+
+- ``options``: A dictionary of directive options for customization, to be
+ interpreted by the role function. Used for additional attributes for the
+ generated elements and other functionality.
+
+- ``content``: A list of strings, the directive content for customization
+ ("role" directive). To be interpreted by the role function.
+
+Function attributes for customization, interpreted by the "role" directive:
+
+- ``options``: A dictionary, mapping known option names to conversion
+ functions such as `int` or `float`. ``None`` or an empty dict implies no
+ options to parse. Several directive option conversion functions are defined
+ in the `directives` module.
+
+ All role functions implicitly support the "class" option, unless disabled
+ with an explicit ``{'class': None}``.
+
+- ``content``: A boolean; true if content is allowed. Client code must handle
+ the case where content is required but not supplied (an empty content list
+ will be supplied).
+
+Note that unlike directives, the "arguments" function attribute is not
+supported for role customization. Directive arguments are handled by the
+"role" directive itself.
+
+Interpreted role functions return a tuple of two values:
+
+- A list of nodes which will be inserted into the document tree at the
+ point where the interpreted role was encountered (can be an empty
+ list).
+
+- A list of system messages, which will be inserted into the document tree
+ immediately after the end of the current inline block (can also be empty).
+"""
+
+__docformat__ = 'reStructuredText'
+
+from docutils import nodes, utils
+from docutils.parsers.rst import directives
+from docutils.parsers.rst.languages import en as _fallback_language_module
+from docutils.utils.code_analyzer import Lexer, LexerError
+
+DEFAULT_INTERPRETED_ROLE = 'title-reference'
+"""
+The canonical name of the default interpreted role. This role is used
+when no role is specified for a piece of interpreted text.
+"""
+
+_role_registry = {}
+"""Mapping of canonical role names to role functions. Language-dependent role
+names are defined in the ``language`` subpackage."""
+
+_roles = {}
+"""Mapping of local or language-dependent interpreted text role names to role
+functions."""
+
+def role(role_name, language_module, lineno, reporter):
+ """
+ Locate and return a role function from its language-dependent name, along
+ with a list of system messages. If the role is not found in the current
+ language, check English. Return a 2-tuple: role function (``None`` if the
+ named role cannot be found) and a list of system messages.
+ """
+ normname = role_name.lower()
+ messages = []
+ msg_text = []
+
+ if normname in _roles:
+ return _roles[normname], messages
+
+ if role_name:
+ canonicalname = None
+ try:
+ canonicalname = language_module.roles[normname]
+ except AttributeError as error:
+ msg_text.append('Problem retrieving role entry from language '
+ 'module %r: %s.' % (language_module, error))
+ except KeyError:
+ msg_text.append('No role entry for "%s" in module "%s".'
+ % (role_name, language_module.__name__))
+ else:
+ canonicalname = DEFAULT_INTERPRETED_ROLE
+
+ # If we didn't find it, try English as a fallback.
+ if not canonicalname:
+ try:
+ canonicalname = _fallback_language_module.roles[normname]
+ msg_text.append('Using English fallback for role "%s".'
+ % role_name)
+ except KeyError:
+ msg_text.append('Trying "%s" as canonical role name.'
+ % role_name)
+ # The canonical name should be an English name, but just in case:
+ canonicalname = normname
+
+ # Collect any messages that we generated.
+ if msg_text:
+ message = reporter.info('\n'.join(msg_text), line=lineno)
+ messages.append(message)
+
+ # Look the role up in the registry, and return it.
+ if canonicalname in _role_registry:
+ role_fn = _role_registry[canonicalname]
+ register_local_role(normname, role_fn)
+ return role_fn, messages
+ else:
+ return None, messages # Error message will be generated by caller.
+
+def register_canonical_role(name, role_fn):
+ """
+ Register an interpreted text role by its canonical name.
+
+ :Parameters:
+ - `name`: The canonical name of the interpreted role.
+ - `role_fn`: The role function. See the module docstring.
+ """
+ set_implicit_options(role_fn)
+ _role_registry[name] = role_fn
+
+def register_local_role(name, role_fn):
+ """
+ Register an interpreted text role by its local or language-dependent name.
+
+ :Parameters:
+ - `name`: The local or language-dependent name of the interpreted role.
+ - `role_fn`: The role function. See the module docstring.
+ """
+ set_implicit_options(role_fn)
+ _roles[name] = role_fn
+
+def set_implicit_options(role_fn):
+ """
+ Add customization options to role functions, unless explicitly set or
+ disabled.
+ """
+ if not hasattr(role_fn, 'options') or role_fn.options is None:
+ role_fn.options = {'class': directives.class_option}
+ elif 'class' not in role_fn.options:
+ role_fn.options['class'] = directives.class_option
+
+def register_generic_role(canonical_name, node_class):
+ """For roles which simply wrap a given `node_class` around the text."""
+ role = GenericRole(canonical_name, node_class)
+ register_canonical_role(canonical_name, role)
+
+
+class GenericRole(object):
+
+ """
+ Generic interpreted text role, where the interpreted text is simply
+ wrapped with the provided node class.
+ """
+
+ def __init__(self, role_name, node_class):
+ self.name = role_name
+ self.node_class = node_class
+
+ def __call__(self, role, rawtext, text, lineno, inliner,
+ options={}, content=[]):
+ set_classes(options)
+ return [self.node_class(rawtext, text, **options)], []
+
+
+class CustomRole(object):
+
+ """
+ Wrapper for custom interpreted text roles.
+ """
+
+ def __init__(self, role_name, base_role, options={}, content=[]):
+ self.name = role_name
+ self.base_role = base_role
+ self.options = None
+ if hasattr(base_role, 'options'):
+ self.options = base_role.options
+ self.content = None
+ if hasattr(base_role, 'content'):
+ self.content = base_role.content
+ self.supplied_options = options
+ self.supplied_content = content
+
+ def __call__(self, role, rawtext, text, lineno, inliner,
+ options={}, content=[]):
+ opts = self.supplied_options.copy()
+ opts.update(options)
+ cont = list(self.supplied_content)
+ if cont and content:
+ cont += '\n'
+ cont.extend(content)
+ return self.base_role(role, rawtext, text, lineno, inliner,
+ options=opts, content=cont)
+
+
+def generic_custom_role(role, rawtext, text, lineno, inliner,
+ options={}, content=[]):
+ """"""
+ # Once nested inline markup is implemented, this and other methods should
+ # recursively call inliner.nested_parse().
+ set_classes(options)
+ return [nodes.inline(rawtext, text, **options)], []
+
+generic_custom_role.options = {'class': directives.class_option}
+
+
+######################################################################
+# Define and register the standard roles:
+######################################################################
+
+register_generic_role('abbreviation', nodes.abbreviation)
+register_generic_role('acronym', nodes.acronym)
+register_generic_role('emphasis', nodes.emphasis)
+register_generic_role('literal', nodes.literal)
+register_generic_role('strong', nodes.strong)
+register_generic_role('subscript', nodes.subscript)
+register_generic_role('superscript', nodes.superscript)
+register_generic_role('title-reference', nodes.title_reference)
+
+def pep_reference_role(role, rawtext, text, lineno, inliner,
+ options={}, content=[]):
+ try:
+ pepnum = int(utils.unescape(text))
+ if pepnum < 0 or pepnum > 9999:
+ raise ValueError
+ except ValueError:
+ msg = inliner.reporter.error(
+ 'PEP number must be a number from 0 to 9999; "%s" is invalid.'
+ % text, line=lineno)
+ prb = inliner.problematic(rawtext, rawtext, msg)
+ return [prb], [msg]
+ # Base URL mainly used by inliner.pep_reference; so this is correct:
+ ref = (inliner.document.settings.pep_base_url
+ + inliner.document.settings.pep_file_url_template % pepnum)
+ set_classes(options)
+ return [nodes.reference(rawtext, 'PEP ' + text, refuri=ref,
+ **options)], []
+
+register_canonical_role('pep-reference', pep_reference_role)
+
+def rfc_reference_role(role, rawtext, text, lineno, inliner,
+ options={}, content=[]):
+ try:
+ if "#" in text:
+ rfcnum, section = utils.unescape(text).split("#", 1)
+ else:
+ rfcnum, section = utils.unescape(text), None
+ rfcnum = int(rfcnum)
+ if rfcnum < 1:
+ raise ValueError
+ except ValueError:
+ msg = inliner.reporter.error(
+ 'RFC number must be a number greater than or equal to 1; '
+ '"%s" is invalid.' % text, line=lineno)
+ prb = inliner.problematic(rawtext, rawtext, msg)
+ return [prb], [msg]
+ # Base URL mainly used by inliner.rfc_reference, so this is correct:
+ ref = inliner.document.settings.rfc_base_url + inliner.rfc_url % rfcnum
+ if section is not None:
+ ref += "#"+section
+ set_classes(options)
+ node = nodes.reference(rawtext, 'RFC ' + str(rfcnum), refuri=ref,
+ **options)
+ return [node], []
+
+register_canonical_role('rfc-reference', rfc_reference_role)
+
+def raw_role(role, rawtext, text, lineno, inliner, options={}, content=[]):
+ if not inliner.document.settings.raw_enabled:
+ msg = inliner.reporter.warning('raw (and derived) roles disabled')
+ prb = inliner.problematic(rawtext, rawtext, msg)
+ return [prb], [msg]
+ if 'format' not in options:
+ msg = inliner.reporter.error(
+ 'No format (Writer name) is associated with this role: "%s".\n'
+ 'The "raw" role cannot be used directly.\n'
+ 'Instead, use the "role" directive to create a new role with '
+ 'an associated format.' % role, line=lineno)
+ prb = inliner.problematic(rawtext, rawtext, msg)
+ return [prb], [msg]
+ set_classes(options)
+ node = nodes.raw(rawtext, utils.unescape(text, True), **options)
+ node.source, node.line = inliner.reporter.get_source_and_line(lineno)
+ return [node], []
+
+raw_role.options = {'format': directives.unchanged}
+
+register_canonical_role('raw', raw_role)
+
+def code_role(role, rawtext, text, lineno, inliner, options={}, content=[]):
+ set_classes(options)
+ language = options.get('language', '')
+ classes = ['code']
+ if 'classes' in options:
+ classes.extend(options['classes'])
+ if language and language not in classes:
+ classes.append(language)
+ try:
+ tokens = Lexer(utils.unescape(text, True), language,
+ inliner.document.settings.syntax_highlight)
+ except LexerError as error:
+ msg = inliner.reporter.warning(error)
+ prb = inliner.problematic(rawtext, rawtext, msg)
+ return [prb], [msg]
+
+ node = nodes.literal(rawtext, '', classes=classes)
+
+ # analyse content and add nodes for every token
+ for classes, value in tokens:
+ if classes:
+ node += nodes.inline(value, value, classes=classes)
+ else:
+ # insert as Text to decrease the verbosity of the output
+ node += nodes.Text(value, value)
+
+ return [node], []
+
+code_role.options = {'class': directives.class_option,
+ 'language': directives.unchanged}
+
+register_canonical_role('code', code_role)
+
+def math_role(role, rawtext, text, lineno, inliner, options={}, content=[]):
+ set_classes(options)
+ i = rawtext.find('`')
+ text = rawtext.split('`')[1]
+ node = nodes.math(rawtext, text, **options)
+ return [node], []
+
+register_canonical_role('math', math_role)
+
+######################################################################
+# Register roles that are currently unimplemented.
+######################################################################
+
+def unimplemented_role(role, rawtext, text, lineno, inliner, attributes={}):
+ msg = inliner.reporter.error(
+ 'Interpreted text role "%s" not implemented.' % role, line=lineno)
+ prb = inliner.problematic(rawtext, rawtext, msg)
+ return [prb], [msg]
+
+register_canonical_role('index', unimplemented_role)
+register_canonical_role('named-reference', unimplemented_role)
+register_canonical_role('anonymous-reference', unimplemented_role)
+register_canonical_role('uri-reference', unimplemented_role)
+register_canonical_role('footnote-reference', unimplemented_role)
+register_canonical_role('citation-reference', unimplemented_role)
+register_canonical_role('substitution-reference', unimplemented_role)
+register_canonical_role('target', unimplemented_role)
+
+# This should remain unimplemented, for testing purposes:
+register_canonical_role('restructuredtext-unimplemented-role',
+ unimplemented_role)
+
+
+def set_classes(options):
+ """
+ Auxiliary function to set options['classes'] and delete
+ options['class'].
+ """
+ if 'class' in options:
+ assert 'classes' not in options
+ options['classes'] = options['class']
+ del options['class']
--- /dev/null
+# $Id: states.py 8359 2019-08-26 16:45:33Z milde $
+# Author: David Goodger <goodger@python.org>
+# Copyright: This module has been placed in the public domain.
+
+"""
+This is the ``docutils.parsers.rst.states`` module, the core of
+the reStructuredText parser. It defines the following:
+
+:Classes:
+ - `RSTStateMachine`: reStructuredText parser's entry point.
+ - `NestedStateMachine`: recursive StateMachine.
+ - `RSTState`: reStructuredText State superclass.
+ - `Inliner`: For parsing inline markup.
+ - `Body`: Generic classifier of the first line of a block.
+ - `SpecializedBody`: Superclass for compound element members.
+ - `BulletList`: Second and subsequent bullet_list list_items
+ - `DefinitionList`: Second+ definition_list_items.
+ - `EnumeratedList`: Second+ enumerated_list list_items.
+ - `FieldList`: Second+ fields.
+ - `OptionList`: Second+ option_list_items.
+ - `RFC2822List`: Second+ RFC2822-style fields.
+ - `ExtensionOptions`: Parses directive option fields.
+ - `Explicit`: Second+ explicit markup constructs.
+ - `SubstitutionDef`: For embedded directives in substitution definitions.
+ - `Text`: Classifier of second line of a text block.
+ - `SpecializedText`: Superclass for continuation lines of Text-variants.
+ - `Definition`: Second line of potential definition_list_item.
+ - `Line`: Second line of overlined section title or transition marker.
+ - `Struct`: An auxiliary collection class.
+
+:Exception classes:
+ - `MarkupError`
+ - `ParserError`
+ - `MarkupMismatch`
+
+:Functions:
+ - `escape2null()`: Return a string, escape-backslashes converted to nulls.
+ - `unescape()`: Return a string, nulls removed or restored to backslashes.
+
+:Attributes:
+ - `state_classes`: set of State classes used with `RSTStateMachine`.
+
+Parser Overview
+===============
+
+The reStructuredText parser is implemented as a recursive state machine,
+examining its input one line at a time. To understand how the parser works,
+please first become familiar with the `docutils.statemachine` module. In the
+description below, references are made to classes defined in this module;
+please see the individual classes for details.
+
+Parsing proceeds as follows:
+
+1. The state machine examines each line of input, checking each of the
+ transition patterns of the state `Body`, in order, looking for a match.
+ The implicit transitions (blank lines and indentation) are checked before
+ any others. The 'text' transition is a catch-all (matches anything).
+
+2. The method associated with the matched transition pattern is called.
+
+ A. Some transition methods are self-contained, appending elements to the
+ document tree (`Body.doctest` parses a doctest block). The parser's
+ current line index is advanced to the end of the element, and parsing
+ continues with step 1.
+
+ B. Other transition methods trigger the creation of a nested state machine,
+ whose job is to parse a compound construct ('indent' does a block quote,
+ 'bullet' does a bullet list, 'overline' does a section [first checking
+ for a valid section header], etc.).
+
+ - In the case of lists and explicit markup, a one-off state machine is
+ created and run to parse contents of the first item.
+
+ - A new state machine is created and its initial state is set to the
+ appropriate specialized state (`BulletList` in the case of the
+ 'bullet' transition; see `SpecializedBody` for more detail). This
+ state machine is run to parse the compound element (or series of
+ explicit markup elements), and returns as soon as a non-member element
+ is encountered. For example, the `BulletList` state machine ends as
+ soon as it encounters an element which is not a list item of that
+ bullet list. The optional omission of inter-element blank lines is
+ enabled by this nested state machine.
+
+ - The current line index is advanced to the end of the elements parsed,
+ and parsing continues with step 1.
+
+ C. The result of the 'text' transition depends on the next line of text.
+ The current state is changed to `Text`, under which the second line is
+ examined. If the second line is:
+
+ - Indented: The element is a definition list item, and parsing proceeds
+ similarly to step 2.B, using the `DefinitionList` state.
+
+ - A line of uniform punctuation characters: The element is a section
+ header; again, parsing proceeds as in step 2.B, and `Body` is still
+ used.
+
+ - Anything else: The element is a paragraph, which is examined for
+ inline markup and appended to the parent element. Processing
+ continues with step 1.
+"""
+
+__docformat__ = 'reStructuredText'
+
+
+import sys
+import re
+from types import FunctionType, MethodType
+
+from docutils import nodes, statemachine, utils
+from docutils import ApplicationError, DataError
+from docutils.statemachine import StateMachineWS, StateWS
+from docutils.nodes import fully_normalize_name as normalize_name
+from docutils.nodes import whitespace_normalize_name
+import docutils.parsers.rst
+from docutils.parsers.rst import directives, languages, tableparser, roles
+from docutils.parsers.rst.languages import en as _fallback_language_module
+from docutils.utils import escape2null, unescape, column_width
+from docutils.utils import punctuation_chars, roman, urischemes
+from docutils.utils import split_escaped_whitespace
+
+class MarkupError(DataError): pass
+class UnknownInterpretedRoleError(DataError): pass
+class InterpretedRoleNotImplementedError(DataError): pass
+class ParserError(ApplicationError): pass
+class MarkupMismatch(Exception): pass
+
+
+class Struct(object):
+
+ """Stores data attributes for dotted-attribute access."""
+
+ def __init__(self, **keywordargs):
+ self.__dict__.update(keywordargs)
+
+
+class RSTStateMachine(StateMachineWS):
+
+ """
+ reStructuredText's master StateMachine.
+
+ The entry point to reStructuredText parsing is the `run()` method.
+ """
+
+ def run(self, input_lines, document, input_offset=0, match_titles=True,
+ inliner=None):
+ """
+ Parse `input_lines` and modify the `document` node in place.
+
+ Extend `StateMachineWS.run()`: set up parse-global data and
+ run the StateMachine.
+ """
+ self.language = languages.get_language(
+ document.settings.language_code)
+ self.match_titles = match_titles
+ if inliner is None:
+ inliner = Inliner()
+ inliner.init_customizations(document.settings)
+ self.memo = Struct(document=document,
+ reporter=document.reporter,
+ language=self.language,
+ title_styles=[],
+ section_level=0,
+ section_bubble_up_kludge=False,
+ inliner=inliner)
+ self.document = document
+ self.attach_observer(document.note_source)
+ self.reporter = self.memo.reporter
+ self.node = document
+ results = StateMachineWS.run(self, input_lines, input_offset,
+ input_source=document['source'])
+ assert results == [], 'RSTStateMachine.run() results should be empty!'
+ self.node = self.memo = None # remove unneeded references
+
+
+class NestedStateMachine(StateMachineWS):
+
+ """
+ StateMachine run from within other StateMachine runs, to parse nested
+ document structures.
+ """
+
+ def run(self, input_lines, input_offset, memo, node, match_titles=True):
+ """
+ Parse `input_lines` and populate a `docutils.nodes.document` instance.
+
+ Extend `StateMachineWS.run()`: set up document-wide data.
+ """
+ self.match_titles = match_titles
+ self.memo = memo
+ self.document = memo.document
+ self.attach_observer(self.document.note_source)
+ self.reporter = memo.reporter
+ self.language = memo.language
+ self.node = node
+ results = StateMachineWS.run(self, input_lines, input_offset)
+ assert results == [], ('NestedStateMachine.run() results should be '
+ 'empty!')
+ return results
+
+
+class RSTState(StateWS):
+
+ """
+ reStructuredText State superclass.
+
+ Contains methods used by all State subclasses.
+ """
+
+ nested_sm = NestedStateMachine
+ nested_sm_cache = []
+
+ def __init__(self, state_machine, debug=False):
+ self.nested_sm_kwargs = {'state_classes': state_classes,
+ 'initial_state': 'Body'}
+ StateWS.__init__(self, state_machine, debug)
+
+ def runtime_init(self):
+ StateWS.runtime_init(self)
+ memo = self.state_machine.memo
+ self.memo = memo
+ self.reporter = memo.reporter
+ self.inliner = memo.inliner
+ self.document = memo.document
+ self.parent = self.state_machine.node
+ # enable the reporter to determine source and source-line
+ if not hasattr(self.reporter, 'get_source_and_line'):
+ self.reporter.get_source_and_line = self.state_machine.get_source_and_line
+
+
+ def goto_line(self, abs_line_offset):
+ """
+ Jump to input line `abs_line_offset`, ignoring jumps past the end.
+ """
+ try:
+ self.state_machine.goto_line(abs_line_offset)
+ except EOFError:
+ pass
+
+ def no_match(self, context, transitions):
+ """
+ Override `StateWS.no_match` to generate a system message.
+
+ This code should never be run.
+ """
+ self.reporter.severe(
+ 'Internal error: no transition pattern match. State: "%s"; '
+ 'transitions: %s; context: %s; current line: %r.'
+ % (self.__class__.__name__, transitions, context,
+ self.state_machine.line))
+ return context, None, []
+
+ def bof(self, context):
+ """Called at beginning of file."""
+ return [], []
+
+ def nested_parse(self, block, input_offset, node, match_titles=False,
+ state_machine_class=None, state_machine_kwargs=None):
+ """
+ Create a new StateMachine rooted at `node` and run it over the input
+ `block`.
+ """
+ use_default = 0
+ if state_machine_class is None:
+ state_machine_class = self.nested_sm
+ use_default += 1
+ if state_machine_kwargs is None:
+ state_machine_kwargs = self.nested_sm_kwargs
+ use_default += 1
+ block_length = len(block)
+
+ state_machine = None
+ if use_default == 2:
+ try:
+ state_machine = self.nested_sm_cache.pop()
+ except IndexError:
+ pass
+ if not state_machine:
+ state_machine = state_machine_class(debug=self.debug,
+ **state_machine_kwargs)
+ state_machine.run(block, input_offset, memo=self.memo,
+ node=node, match_titles=match_titles)
+ if use_default == 2:
+ self.nested_sm_cache.append(state_machine)
+ else:
+ state_machine.unlink()
+ new_offset = state_machine.abs_line_offset()
+ # No `block.parent` implies disconnected -- lines aren't in sync:
+ if block.parent and (len(block) - block_length) != 0:
+ # Adjustment for block if modified in nested parse:
+ self.state_machine.next_line(len(block) - block_length)
+ return new_offset
+
+ def nested_list_parse(self, block, input_offset, node, initial_state,
+ blank_finish,
+ blank_finish_state=None,
+ extra_settings={},
+ match_titles=False,
+ state_machine_class=None,
+ state_machine_kwargs=None):
+ """
+ Create a new StateMachine rooted at `node` and run it over the input
+ `block`. Also keep track of optional intermediate blank lines and the
+ required final one.
+ """
+ if state_machine_class is None:
+ state_machine_class = self.nested_sm
+ if state_machine_kwargs is None:
+ state_machine_kwargs = self.nested_sm_kwargs.copy()
+ state_machine_kwargs['initial_state'] = initial_state
+ state_machine = state_machine_class(debug=self.debug,
+ **state_machine_kwargs)
+ if blank_finish_state is None:
+ blank_finish_state = initial_state
+ state_machine.states[blank_finish_state].blank_finish = blank_finish
+ for key, value in extra_settings.items():
+ setattr(state_machine.states[initial_state], key, value)
+ state_machine.run(block, input_offset, memo=self.memo,
+ node=node, match_titles=match_titles)
+ blank_finish = state_machine.states[blank_finish_state].blank_finish
+ state_machine.unlink()
+ return state_machine.abs_line_offset(), blank_finish
+
+ def section(self, title, source, style, lineno, messages):
+ """Check for a valid subsection and create one if it checks out."""
+ if self.check_subsection(source, style, lineno):
+ self.new_subsection(title, lineno, messages)
+
+ def check_subsection(self, source, style, lineno):
+ """
+ Check for a valid subsection header. Return 1 (true) or None (false).
+
+ When a new section is reached that isn't a subsection of the current
+ section, back up the line count (use ``previous_line(-x)``), then
+ ``raise EOFError``. The current StateMachine will finish, then the
+ calling StateMachine can re-examine the title. This will work its way
+ back up the calling chain until the correct section level isreached.
+
+ @@@ Alternative: Evaluate the title, store the title info & level, and
+ back up the chain until that level is reached. Store in memo? Or
+ return in results?
+
+ :Exception: `EOFError` when a sibling or supersection encountered.
+ """
+ memo = self.memo
+ title_styles = memo.title_styles
+ mylevel = memo.section_level
+ try: # check for existing title style
+ level = title_styles.index(style) + 1
+ except ValueError: # new title style
+ if len(title_styles) == memo.section_level: # new subsection
+ title_styles.append(style)
+ return 1
+ else: # not at lowest level
+ self.parent += self.title_inconsistent(source, lineno)
+ return None
+ if level <= mylevel: # sibling or supersection
+ memo.section_level = level # bubble up to parent section
+ if len(style) == 2:
+ memo.section_bubble_up_kludge = True
+ # back up 2 lines for underline title, 3 for overline title
+ self.state_machine.previous_line(len(style) + 1)
+ raise EOFError # let parent section re-evaluate
+ if level == mylevel + 1: # immediate subsection
+ return 1
+ else: # invalid subsection
+ self.parent += self.title_inconsistent(source, lineno)
+ return None
+
+ def title_inconsistent(self, sourcetext, lineno):
+ error = self.reporter.severe(
+ 'Title level inconsistent:', nodes.literal_block('', sourcetext),
+ line=lineno)
+ return error
+
+ def new_subsection(self, title, lineno, messages):
+ """Append new subsection to document tree. On return, check level."""
+ memo = self.memo
+ mylevel = memo.section_level
+ memo.section_level += 1
+ section_node = nodes.section()
+ self.parent += section_node
+ textnodes, title_messages = self.inline_text(title, lineno)
+ titlenode = nodes.title(title, '', *textnodes)
+ name = normalize_name(titlenode.astext())
+ section_node['names'].append(name)
+ section_node += titlenode
+ section_node += messages
+ section_node += title_messages
+ self.document.note_implicit_target(section_node, section_node)
+ offset = self.state_machine.line_offset + 1
+ absoffset = self.state_machine.abs_line_offset() + 1
+ newabsoffset = self.nested_parse(
+ self.state_machine.input_lines[offset:], input_offset=absoffset,
+ node=section_node, match_titles=True)
+ self.goto_line(newabsoffset)
+ if memo.section_level <= mylevel: # can't handle next section?
+ raise EOFError # bubble up to supersection
+ # reset section_level; next pass will detect it properly
+ memo.section_level = mylevel
+
+ def paragraph(self, lines, lineno):
+ """
+ Return a list (paragraph & messages) & a boolean: literal_block next?
+ """
+ data = '\n'.join(lines).rstrip()
+ if re.search(r'(?<!\\)(\\\\)*::$', data):
+ if len(data) == 2:
+ return [], 1
+ elif data[-3] in ' \n':
+ text = data[:-3].rstrip()
+ else:
+ text = data[:-1]
+ literalnext = 1
+ else:
+ text = data
+ literalnext = 0
+ textnodes, messages = self.inline_text(text, lineno)
+ p = nodes.paragraph(data, '', *textnodes)
+ p.source, p.line = self.state_machine.get_source_and_line(lineno)
+ return [p] + messages, literalnext
+
+ def inline_text(self, text, lineno):
+ """
+ Return 2 lists: nodes (text and inline elements), and system_messages.
+ """
+ nodes, messages = self.inliner.parse(text, lineno,
+ self.memo, self.parent)
+ return nodes, messages
+
+ def unindent_warning(self, node_name):
+ # the actual problem is one line below the current line
+ lineno = self.state_machine.abs_line_number()+1
+ return self.reporter.warning('%s ends without a blank line; '
+ 'unexpected unindent.' % node_name,
+ line=lineno)
+
+
+def build_regexp(definition, compile=True):
+ """
+ Build, compile and return a regular expression based on `definition`.
+
+ :Parameter: `definition`: a 4-tuple (group name, prefix, suffix, parts),
+ where "parts" is a list of regular expressions and/or regular
+ expression definitions to be joined into an or-group.
+ """
+ name, prefix, suffix, parts = definition
+ part_strings = []
+ for part in parts:
+ if isinstance(part, tuple):
+ part_strings.append(build_regexp(part, None))
+ else:
+ part_strings.append(part)
+ or_group = '|'.join(part_strings)
+ regexp = '%(prefix)s(?P<%(name)s>%(or_group)s)%(suffix)s' % locals()
+ if compile:
+ return re.compile(regexp, re.UNICODE)
+ else:
+ return regexp
+
+
+class Inliner(object):
+
+ """
+ Parse inline markup; call the `parse()` method.
+ """
+
+ def __init__(self):
+ self.implicit_dispatch = []
+ """List of (pattern, bound method) tuples, used by
+ `self.implicit_inline`."""
+
+ def init_customizations(self, settings):
+ # lookahead and look-behind expressions for inline markup rules
+ if getattr(settings, 'character_level_inline_markup', False):
+ start_string_prefix = u'(^|(?<!\x00))'
+ end_string_suffix = u''
+ else:
+ start_string_prefix = (u'(^|(?<=\\s|[%s%s]))' %
+ (punctuation_chars.openers,
+ punctuation_chars.delimiters))
+ end_string_suffix = (u'($|(?=\\s|[\x00%s%s%s]))' %
+ (punctuation_chars.closing_delimiters,
+ punctuation_chars.delimiters,
+ punctuation_chars.closers))
+ args = locals().copy()
+ args.update(vars(self.__class__))
+
+ parts = ('initial_inline', start_string_prefix, '',
+ [('start', '', self.non_whitespace_after, # simple start-strings
+ [r'\*\*', # strong
+ r'\*(?!\*)', # emphasis but not strong
+ r'``', # literal
+ r'_`', # inline internal target
+ r'\|(?!\|)'] # substitution reference
+ ),
+ ('whole', '', end_string_suffix, # whole constructs
+ [# reference name & end-string
+ r'(?P<refname>%s)(?P<refend>__?)' % self.simplename,
+ ('footnotelabel', r'\[', r'(?P<fnend>\]_)',
+ [r'[0-9]+', # manually numbered
+ r'\#(%s)?' % self.simplename, # auto-numbered (w/ label?)
+ r'\*', # auto-symbol
+ r'(?P<citationlabel>%s)' % self.simplename] # citation reference
+ )
+ ]
+ ),
+ ('backquote', # interpreted text or phrase reference
+ '(?P<role>(:%s:)?)' % self.simplename, # optional role
+ self.non_whitespace_after,
+ ['`(?!`)'] # but not literal
+ )
+ ]
+ )
+ self.start_string_prefix = start_string_prefix
+ self.end_string_suffix = end_string_suffix
+ self.parts = parts
+
+ self.patterns = Struct(
+ initial=build_regexp(parts),
+ emphasis=re.compile(self.non_whitespace_escape_before
+ + r'(\*)' + end_string_suffix, re.UNICODE),
+ strong=re.compile(self.non_whitespace_escape_before
+ + r'(\*\*)' + end_string_suffix, re.UNICODE),
+ interpreted_or_phrase_ref=re.compile(
+ r"""
+ %(non_unescaped_whitespace_escape_before)s
+ (
+ `
+ (?P<suffix>
+ (?P<role>:%(simplename)s:)?
+ (?P<refend>__?)?
+ )
+ )
+ %(end_string_suffix)s
+ """ % args, re.VERBOSE | re.UNICODE),
+ embedded_link=re.compile(
+ r"""
+ (
+ (?:[ \n]+|^) # spaces or beginning of line/string
+ < # open bracket
+ %(non_whitespace_after)s
+ (([^<>]|\x00[<>])+) # anything but unescaped angle brackets
+ %(non_whitespace_escape_before)s
+ > # close bracket
+ )
+ $ # end of string
+ """ % args, re.VERBOSE | re.UNICODE),
+ literal=re.compile(self.non_whitespace_before + '(``)'
+ + end_string_suffix, re.UNICODE),
+ target=re.compile(self.non_whitespace_escape_before
+ + r'(`)' + end_string_suffix, re.UNICODE),
+ substitution_ref=re.compile(self.non_whitespace_escape_before
+ + r'(\|_{0,2})'
+ + end_string_suffix, re.UNICODE),
+ email=re.compile(self.email_pattern % args + '$',
+ re.VERBOSE | re.UNICODE),
+ uri=re.compile(
+ (r"""
+ %(start_string_prefix)s
+ (?P<whole>
+ (?P<absolute> # absolute URI
+ (?P<scheme> # scheme (http, ftp, mailto)
+ [a-zA-Z][a-zA-Z0-9.+-]*
+ )
+ :
+ (
+ ( # either:
+ (//?)? # hierarchical URI
+ %(uric)s* # URI characters
+ %(uri_end)s # final URI char
+ )
+ ( # optional query
+ \?%(uric)s*
+ %(uri_end)s
+ )?
+ ( # optional fragment
+ \#%(uric)s*
+ %(uri_end)s
+ )?
+ )
+ )
+ | # *OR*
+ (?P<email> # email address
+ """ + self.email_pattern + r"""
+ )
+ )
+ %(end_string_suffix)s
+ """) % args, re.VERBOSE | re.UNICODE),
+ pep=re.compile(
+ r"""
+ %(start_string_prefix)s
+ (
+ (pep-(?P<pepnum1>\d+)(.txt)?) # reference to source file
+ |
+ (PEP\s+(?P<pepnum2>\d+)) # reference by name
+ )
+ %(end_string_suffix)s""" % args, re.VERBOSE | re.UNICODE),
+ rfc=re.compile(
+ r"""
+ %(start_string_prefix)s
+ (RFC(-|\s+)?(?P<rfcnum>\d+))
+ %(end_string_suffix)s""" % args, re.VERBOSE | re.UNICODE))
+
+ self.implicit_dispatch.append((self.patterns.uri,
+ self.standalone_uri))
+ if settings.pep_references:
+ self.implicit_dispatch.append((self.patterns.pep,
+ self.pep_reference))
+ if settings.rfc_references:
+ self.implicit_dispatch.append((self.patterns.rfc,
+ self.rfc_reference))
+
+ def parse(self, text, lineno, memo, parent):
+ # Needs to be refactored for nested inline markup.
+ # Add nested_parse() method?
+ """
+ Return 2 lists: nodes (text and inline elements), and system_messages.
+
+ Using `self.patterns.initial`, a pattern which matches start-strings
+ (emphasis, strong, interpreted, phrase reference, literal,
+ substitution reference, and inline target) and complete constructs
+ (simple reference, footnote reference), search for a candidate. When
+ one is found, check for validity (e.g., not a quoted '*' character).
+ If valid, search for the corresponding end string if applicable, and
+ check it for validity. If not found or invalid, generate a warning
+ and ignore the start-string. Implicit inline markup (e.g. standalone
+ URIs) is found last.
+ """
+ self.reporter = memo.reporter
+ self.document = memo.document
+ self.language = memo.language
+ self.parent = parent
+ pattern_search = self.patterns.initial.search
+ dispatch = self.dispatch
+ remaining = escape2null(text)
+ processed = []
+ unprocessed = []
+ messages = []
+ while remaining:
+ match = pattern_search(remaining)
+ if match:
+ groups = match.groupdict()
+ method = dispatch[groups['start'] or groups['backquote']
+ or groups['refend'] or groups['fnend']]
+ before, inlines, remaining, sysmessages = method(self, match,
+ lineno)
+ unprocessed.append(before)
+ messages += sysmessages
+ if inlines:
+ processed += self.implicit_inline(''.join(unprocessed),
+ lineno)
+ processed += inlines
+ unprocessed = []
+ else:
+ break
+ remaining = ''.join(unprocessed) + remaining
+ if remaining:
+ processed += self.implicit_inline(remaining, lineno)
+ return processed, messages
+
+ # Inline object recognition
+ # -------------------------
+ # See also init_customizations().
+ non_whitespace_before = r'(?<!\s)'
+ non_whitespace_escape_before = r'(?<![\s\x00])'
+ non_unescaped_whitespace_escape_before = r'(?<!(?<!\x00)[\s\x00])'
+ non_whitespace_after = r'(?!\s)'
+ # Alphanumerics with isolated internal [-._+:] chars (i.e. not 2 together):
+ simplename = r'(?:(?!_)\w)+(?:[-._+:](?:(?!_)\w)+)*'
+ # Valid URI characters (see RFC 2396 & RFC 2732);
+ # final \x00 allows backslash escapes in URIs:
+ uric = r"""[-_.!~*'()[\];/:@&=+$,%a-zA-Z0-9\x00]"""
+ # Delimiter indicating the end of a URI (not part of the URI):
+ uri_end_delim = r"""[>]"""
+ # Last URI character; same as uric but no punctuation:
+ urilast = r"""[_~*/=+a-zA-Z0-9]"""
+ # End of a URI (either 'urilast' or 'uric followed by a
+ # uri_end_delim'):
+ uri_end = r"""(?:%(urilast)s|%(uric)s(?=%(uri_end_delim)s))""" % locals()
+ emailc = r"""[-_!~*'{|}/#?^`&=+$%a-zA-Z0-9\x00]"""
+ email_pattern = r"""
+ %(emailc)s+(?:\.%(emailc)s+)* # name
+ (?<!\x00)@ # at
+ %(emailc)s+(?:\.%(emailc)s*)* # host
+ %(uri_end)s # final URI char
+ """
+
+ def quoted_start(self, match):
+ """Test if inline markup start-string is 'quoted'.
+
+ 'Quoted' in this context means the start-string is enclosed in a pair
+ of matching opening/closing delimiters (not necessarily quotes)
+ or at the end of the match.
+ """
+ string = match.string
+ start = match.start()
+ if start == 0: # start-string at beginning of text
+ return False
+ prestart = string[start - 1]
+ try:
+ poststart = string[match.end()]
+ except IndexError: # start-string at end of text
+ return True # not "quoted" but no markup start-string either
+ return punctuation_chars.match_chars(prestart, poststart)
+
+ def inline_obj(self, match, lineno, end_pattern, nodeclass,
+ restore_backslashes=False):
+ string = match.string
+ matchstart = match.start('start')
+ matchend = match.end('start')
+ if self.quoted_start(match):
+ return (string[:matchend], [], string[matchend:], [], '')
+ endmatch = end_pattern.search(string[matchend:])
+ if endmatch and endmatch.start(1): # 1 or more chars
+ text = endmatch.string[:endmatch.start(1)]
+ if restore_backslashes:
+ text = unescape(text, True)
+ textend = matchend + endmatch.end(1)
+ rawsource = unescape(string[matchstart:textend], True)
+ node = nodeclass(rawsource, text)
+ return (string[:matchstart], [node],
+ string[textend:], [], endmatch.group(1))
+ msg = self.reporter.warning(
+ 'Inline %s start-string without end-string.'
+ % nodeclass.__name__, line=lineno)
+ text = unescape(string[matchstart:matchend], True)
+ prb = self.problematic(text, text, msg)
+ return string[:matchstart], [prb], string[matchend:], [msg], ''
+
+ def problematic(self, text, rawsource, message):
+ msgid = self.document.set_id(message, self.parent)
+ problematic = nodes.problematic(rawsource, text, refid=msgid)
+ prbid = self.document.set_id(problematic)
+ message.add_backref(prbid)
+ return problematic
+
+ def emphasis(self, match, lineno):
+ before, inlines, remaining, sysmessages, endstring = self.inline_obj(
+ match, lineno, self.patterns.emphasis, nodes.emphasis)
+ return before, inlines, remaining, sysmessages
+
+ def strong(self, match, lineno):
+ before, inlines, remaining, sysmessages, endstring = self.inline_obj(
+ match, lineno, self.patterns.strong, nodes.strong)
+ return before, inlines, remaining, sysmessages
+
+ def interpreted_or_phrase_ref(self, match, lineno):
+ end_pattern = self.patterns.interpreted_or_phrase_ref
+ string = match.string
+ matchstart = match.start('backquote')
+ matchend = match.end('backquote')
+ rolestart = match.start('role')
+ role = match.group('role')
+ position = ''
+ if role:
+ role = role[1:-1]
+ position = 'prefix'
+ elif self.quoted_start(match):
+ return (string[:matchend], [], string[matchend:], [])
+ endmatch = end_pattern.search(string[matchend:])
+ if endmatch and endmatch.start(1): # 1 or more chars
+ textend = matchend + endmatch.end()
+ if endmatch.group('role'):
+ if role:
+ msg = self.reporter.warning(
+ 'Multiple roles in interpreted text (both '
+ 'prefix and suffix present; only one allowed).',
+ line=lineno)
+ text = unescape(string[rolestart:textend], True)
+ prb = self.problematic(text, text, msg)
+ return string[:rolestart], [prb], string[textend:], [msg]
+ role = endmatch.group('suffix')[1:-1]
+ position = 'suffix'
+ escaped = endmatch.string[:endmatch.start(1)]
+ rawsource = unescape(string[matchstart:textend], True)
+ if rawsource[-1:] == '_':
+ if role:
+ msg = self.reporter.warning(
+ 'Mismatch: both interpreted text role %s and '
+ 'reference suffix.' % position, line=lineno)
+ text = unescape(string[rolestart:textend], True)
+ prb = self.problematic(text, text, msg)
+ return string[:rolestart], [prb], string[textend:], [msg]
+ return self.phrase_ref(string[:matchstart], string[textend:],
+ rawsource, escaped)
+ else:
+ rawsource = unescape(string[rolestart:textend], True)
+ nodelist, messages = self.interpreted(rawsource, escaped, role,
+ lineno)
+ return (string[:rolestart], nodelist,
+ string[textend:], messages)
+ msg = self.reporter.warning(
+ 'Inline interpreted text or phrase reference start-string '
+ 'without end-string.', line=lineno)
+ text = unescape(string[matchstart:matchend], True)
+ prb = self.problematic(text, text, msg)
+ return string[:matchstart], [prb], string[matchend:], [msg]
+
+ def phrase_ref(self, before, after, rawsource, escaped, text=None):
+ # `text` is ignored (since 0.16)
+ match = self.patterns.embedded_link.search(escaped)
+ if match: # embedded <URI> or <alias_>
+ text = escaped[:match.start(0)]
+ unescaped = unescape(text)
+ rawtext = unescape(text, True)
+ aliastext = match.group(2)
+ rawaliastext = unescape(aliastext, True)
+ underscore_escaped = rawaliastext.endswith(r'\_')
+ if aliastext.endswith('_') and not (underscore_escaped
+ or self.patterns.uri.match(aliastext)):
+ aliastype = 'name'
+ alias = normalize_name(unescape(aliastext[:-1]))
+ target = nodes.target(match.group(1), refname=alias)
+ target.indirect_reference_name = whitespace_normalize_name(
+ unescape(aliastext[:-1]))
+ else:
+ aliastype = 'uri'
+ # remove unescaped whitespace
+ alias_parts = split_escaped_whitespace(match.group(2))
+ alias = ' '.join(''.join(part.split())
+ for part in alias_parts)
+ alias = self.adjust_uri(unescape(alias))
+ if alias.endswith(r'\_'):
+ alias = alias[:-2] + '_'
+ target = nodes.target(match.group(1), refuri=alias)
+ target.referenced = 1
+ if not aliastext:
+ raise ApplicationError('problem with embedded link: %r'
+ % aliastext)
+ if not text:
+ text = alias
+ unescaped = unescape(text)
+ rawtext = rawaliastext
+ else:
+ text = escaped
+ unescaped = unescape(text)
+ target = None
+ rawtext = unescape(escaped, True)
+
+ refname = normalize_name(unescaped)
+ reference = nodes.reference(rawsource, text,
+ name=whitespace_normalize_name(unescaped))
+ reference[0].rawsource = rawtext
+
+ node_list = [reference]
+
+ if rawsource[-2:] == '__':
+ if target and (aliastype == 'name'):
+ reference['refname'] = alias
+ self.document.note_refname(reference)
+ # self.document.note_indirect_target(target) # required?
+ elif target and (aliastype == 'uri'):
+ reference['refuri'] = alias
+ else:
+ reference['anonymous'] = 1
+ else:
+ if target:
+ target['names'].append(refname)
+ if aliastype == 'name':
+ reference['refname'] = alias
+ self.document.note_indirect_target(target)
+ self.document.note_refname(reference)
+ else:
+ reference['refuri'] = alias
+ self.document.note_explicit_target(target, self.parent)
+ # target.note_referenced_by(name=refname)
+ node_list.append(target)
+ else:
+ reference['refname'] = refname
+ self.document.note_refname(reference)
+ return before, node_list, after, []
+
+
+ def adjust_uri(self, uri):
+ match = self.patterns.email.match(uri)
+ if match:
+ return 'mailto:' + uri
+ else:
+ return uri
+
+ def interpreted(self, rawsource, text, role, lineno):
+ role_fn, messages = roles.role(role, self.language, lineno,
+ self.reporter)
+ if role_fn:
+ nodes, messages2 = role_fn(role, rawsource, text, lineno, self)
+ return nodes, messages + messages2
+ else:
+ msg = self.reporter.error(
+ 'Unknown interpreted text role "%s".' % role,
+ line=lineno)
+ return ([self.problematic(rawsource, rawsource, msg)],
+ messages + [msg])
+
+ def literal(self, match, lineno):
+ before, inlines, remaining, sysmessages, endstring = self.inline_obj(
+ match, lineno, self.patterns.literal, nodes.literal,
+ restore_backslashes=True)
+ return before, inlines, remaining, sysmessages
+
+ def inline_internal_target(self, match, lineno):
+ before, inlines, remaining, sysmessages, endstring = self.inline_obj(
+ match, lineno, self.patterns.target, nodes.target)
+ if inlines and isinstance(inlines[0], nodes.target):
+ assert len(inlines) == 1
+ target = inlines[0]
+ name = normalize_name(target.astext())
+ target['names'].append(name)
+ self.document.note_explicit_target(target, self.parent)
+ return before, inlines, remaining, sysmessages
+
+ def substitution_reference(self, match, lineno):
+ before, inlines, remaining, sysmessages, endstring = self.inline_obj(
+ match, lineno, self.patterns.substitution_ref,
+ nodes.substitution_reference)
+ if len(inlines) == 1:
+ subref_node = inlines[0]
+ if isinstance(subref_node, nodes.substitution_reference):
+ subref_text = subref_node.astext()
+ self.document.note_substitution_ref(subref_node, subref_text)
+ if endstring[-1:] == '_':
+ reference_node = nodes.reference(
+ '|%s%s' % (subref_text, endstring), '')
+ if endstring[-2:] == '__':
+ reference_node['anonymous'] = 1
+ else:
+ reference_node['refname'] = normalize_name(subref_text)
+ self.document.note_refname(reference_node)
+ reference_node += subref_node
+ inlines = [reference_node]
+ return before, inlines, remaining, sysmessages
+
+ def footnote_reference(self, match, lineno):
+ """
+ Handles `nodes.footnote_reference` and `nodes.citation_reference`
+ elements.
+ """
+ label = match.group('footnotelabel')
+ refname = normalize_name(label)
+ string = match.string
+ before = string[:match.start('whole')]
+ remaining = string[match.end('whole'):]
+ if match.group('citationlabel'):
+ refnode = nodes.citation_reference('[%s]_' % label,
+ refname=refname)
+ refnode += nodes.Text(label)
+ self.document.note_citation_ref(refnode)
+ else:
+ refnode = nodes.footnote_reference('[%s]_' % label)
+ if refname[0] == '#':
+ refname = refname[1:]
+ refnode['auto'] = 1
+ self.document.note_autofootnote_ref(refnode)
+ elif refname == '*':
+ refname = ''
+ refnode['auto'] = '*'
+ self.document.note_symbol_footnote_ref(
+ refnode)
+ else:
+ refnode += nodes.Text(label)
+ if refname:
+ refnode['refname'] = refname
+ self.document.note_footnote_ref(refnode)
+ if utils.get_trim_footnote_ref_space(self.document.settings):
+ before = before.rstrip()
+ return (before, [refnode], remaining, [])
+
+ def reference(self, match, lineno, anonymous=False):
+ referencename = match.group('refname')
+ refname = normalize_name(referencename)
+ referencenode = nodes.reference(
+ referencename + match.group('refend'), referencename,
+ name=whitespace_normalize_name(referencename))
+ referencenode[0].rawsource = referencename
+ if anonymous:
+ referencenode['anonymous'] = 1
+ else:
+ referencenode['refname'] = refname
+ self.document.note_refname(referencenode)
+ string = match.string
+ matchstart = match.start('whole')
+ matchend = match.end('whole')
+ return (string[:matchstart], [referencenode], string[matchend:], [])
+
+ def anonymous_reference(self, match, lineno):
+ return self.reference(match, lineno, anonymous=1)
+
+ def standalone_uri(self, match, lineno):
+ if (not match.group('scheme')
+ or match.group('scheme').lower() in urischemes.schemes):
+ if match.group('email'):
+ addscheme = 'mailto:'
+ else:
+ addscheme = ''
+ text = match.group('whole')
+ refuri = addscheme + unescape(text)
+ reference = nodes.reference(unescape(text, True), text,
+ refuri=refuri)
+ return [reference]
+ else: # not a valid scheme
+ raise MarkupMismatch
+
+ def pep_reference(self, match, lineno):
+ text = match.group(0)
+ if text.startswith('pep-'):
+ pepnum = int(unescape(match.group('pepnum1')))
+ elif text.startswith('PEP'):
+ pepnum = int(unescape(match.group('pepnum2')))
+ else:
+ raise MarkupMismatch
+ ref = (self.document.settings.pep_base_url
+ + self.document.settings.pep_file_url_template % pepnum)
+ return [nodes.reference(unescape(text, True), text, refuri=ref)]
+
+ rfc_url = 'rfc%d.html'
+
+ def rfc_reference(self, match, lineno):
+ text = match.group(0)
+ if text.startswith('RFC'):
+ rfcnum = int(unescape(match.group('rfcnum')))
+ ref = self.document.settings.rfc_base_url + self.rfc_url % rfcnum
+ else:
+ raise MarkupMismatch
+ return [nodes.reference(unescape(text, True), text, refuri=ref)]
+
+ def implicit_inline(self, text, lineno):
+ """
+ Check each of the patterns in `self.implicit_dispatch` for a match,
+ and dispatch to the stored method for the pattern. Recursively check
+ the text before and after the match. Return a list of `nodes.Text`
+ and inline element nodes.
+ """
+ if not text:
+ return []
+ for pattern, method in self.implicit_dispatch:
+ match = pattern.search(text)
+ if match:
+ try:
+ # Must recurse on strings before *and* after the match;
+ # there may be multiple patterns.
+ return (self.implicit_inline(text[:match.start()], lineno)
+ + method(match, lineno) +
+ self.implicit_inline(text[match.end():], lineno))
+ except MarkupMismatch:
+ pass
+ return [nodes.Text(text, unescape(text, True))]
+
+ dispatch = {'*': emphasis,
+ '**': strong,
+ '`': interpreted_or_phrase_ref,
+ '``': literal,
+ '_`': inline_internal_target,
+ ']_': footnote_reference,
+ '|': substitution_reference,
+ '_': reference,
+ '__': anonymous_reference}
+
+
+def _loweralpha_to_int(s, _zero=(ord('a')-1)):
+ return ord(s) - _zero
+
+def _upperalpha_to_int(s, _zero=(ord('A')-1)):
+ return ord(s) - _zero
+
+def _lowerroman_to_int(s):
+ return roman.fromRoman(s.upper())
+
+
+class Body(RSTState):
+
+ """
+ Generic classifier of the first line of a block.
+ """
+
+ double_width_pad_char = tableparser.TableParser.double_width_pad_char
+ """Padding character for East Asian double-width text."""
+
+ enum = Struct()
+ """Enumerated list parsing information."""
+
+ enum.formatinfo = {
+ 'parens': Struct(prefix='(', suffix=')', start=1, end=-1),
+ 'rparen': Struct(prefix='', suffix=')', start=0, end=-1),
+ 'period': Struct(prefix='', suffix='.', start=0, end=-1)}
+ enum.formats = enum.formatinfo.keys()
+ enum.sequences = ['arabic', 'loweralpha', 'upperalpha',
+ 'lowerroman', 'upperroman'] # ORDERED!
+ enum.sequencepats = {'arabic': '[0-9]+',
+ 'loweralpha': '[a-z]',
+ 'upperalpha': '[A-Z]',
+ 'lowerroman': '[ivxlcdm]+',
+ 'upperroman': '[IVXLCDM]+',}
+ enum.converters = {'arabic': int,
+ 'loweralpha': _loweralpha_to_int,
+ 'upperalpha': _upperalpha_to_int,
+ 'lowerroman': _lowerroman_to_int,
+ 'upperroman': roman.fromRoman}
+
+ enum.sequenceregexps = {}
+ for sequence in enum.sequences:
+ enum.sequenceregexps[sequence] = re.compile(
+ enum.sequencepats[sequence] + '$', re.UNICODE)
+
+ grid_table_top_pat = re.compile(r'\+-[-+]+-\+ *$')
+ """Matches the top (& bottom) of a full table)."""
+
+ simple_table_top_pat = re.compile('=+( +=+)+ *$')
+ """Matches the top of a simple table."""
+
+ simple_table_border_pat = re.compile('=+[ =]*$')
+ """Matches the bottom & header bottom of a simple table."""
+
+ pats = {}
+ """Fragments of patterns used by transitions."""
+
+ pats['nonalphanum7bit'] = '[!-/:-@[-`{-~]'
+ pats['alpha'] = '[a-zA-Z]'
+ pats['alphanum'] = '[a-zA-Z0-9]'
+ pats['alphanumplus'] = '[a-zA-Z0-9_-]'
+ pats['enum'] = ('(%(arabic)s|%(loweralpha)s|%(upperalpha)s|%(lowerroman)s'
+ '|%(upperroman)s|#)' % enum.sequencepats)
+ pats['optname'] = '%(alphanum)s%(alphanumplus)s*' % pats
+ # @@@ Loosen up the pattern? Allow Unicode?
+ pats['optarg'] = '(%(alpha)s%(alphanumplus)s*|<[^<>]+>)' % pats
+ pats['shortopt'] = r'(-|\+)%(alphanum)s( ?%(optarg)s)?' % pats
+ pats['longopt'] = r'(--|/)%(optname)s([ =]%(optarg)s)?' % pats
+ pats['option'] = r'(%(shortopt)s|%(longopt)s)' % pats
+
+ for format in enum.formats:
+ pats[format] = '(?P<%s>%s%s%s)' % (
+ format, re.escape(enum.formatinfo[format].prefix),
+ pats['enum'], re.escape(enum.formatinfo[format].suffix))
+
+ patterns = {
+ 'bullet': u'[-+*\u2022\u2023\u2043]( +|$)',
+ 'enumerator': r'(%(parens)s|%(rparen)s|%(period)s)( +|$)' % pats,
+ 'field_marker': r':(?![: ])([^:\\]|\\.|:(?!([ `]|$)))*(?<! ):( +|$)',
+ 'option_marker': r'%(option)s(, %(option)s)*( +| ?$)' % pats,
+ 'doctest': r'>>>( +|$)',
+ 'line_block': r'\|( +|$)',
+ 'grid_table_top': grid_table_top_pat,
+ 'simple_table_top': simple_table_top_pat,
+ 'explicit_markup': r'\.\.( +|$)',
+ 'anonymous': r'__( +|$)',
+ 'line': r'(%(nonalphanum7bit)s)\1* *$' % pats,
+ 'text': r''}
+ initial_transitions = (
+ 'bullet',
+ 'enumerator',
+ 'field_marker',
+ 'option_marker',
+ 'doctest',
+ 'line_block',
+ 'grid_table_top',
+ 'simple_table_top',
+ 'explicit_markup',
+ 'anonymous',
+ 'line',
+ 'text')
+
+ def indent(self, match, context, next_state):
+ """Block quote."""
+ indented, indent, line_offset, blank_finish = \
+ self.state_machine.get_indented()
+ elements = self.block_quote(indented, line_offset)
+ self.parent += elements
+ if not blank_finish:
+ self.parent += self.unindent_warning('Block quote')
+ return context, next_state, []
+
+ def block_quote(self, indented, line_offset):
+ elements = []
+ while indented:
+ (blockquote_lines,
+ attribution_lines,
+ attribution_offset,
+ indented,
+ new_line_offset) = self.split_attribution(indented, line_offset)
+ blockquote = nodes.block_quote()
+ self.nested_parse(blockquote_lines, line_offset, blockquote)
+ elements.append(blockquote)
+ if attribution_lines:
+ attribution, messages = self.parse_attribution(
+ attribution_lines, attribution_offset)
+ blockquote += attribution
+ elements += messages
+ line_offset = new_line_offset
+ while indented and not indented[0]:
+ indented = indented[1:]
+ line_offset += 1
+ return elements
+
+ # U+2014 is an em-dash:
+ attribution_pattern = re.compile(u'(---?(?!-)|\u2014) *(?=[^ \\n])',
+ re.UNICODE)
+
+ def split_attribution(self, indented, line_offset):
+ """
+ Check for a block quote attribution and split it off:
+
+ * First line after a blank line must begin with a dash ("--", "---",
+ em-dash; matches `self.attribution_pattern`).
+ * Every line after that must have consistent indentation.
+ * Attributions must be preceded by block quote content.
+
+ Return a tuple of: (block quote content lines, content offset,
+ attribution lines, attribution offset, remaining indented lines).
+ """
+ blank = None
+ nonblank_seen = False
+ for i in range(len(indented)):
+ line = indented[i].rstrip()
+ if line:
+ if nonblank_seen and blank == i - 1: # last line blank
+ match = self.attribution_pattern.match(line)
+ if match:
+ attribution_end, indent = self.check_attribution(
+ indented, i)
+ if attribution_end:
+ a_lines = indented[i:attribution_end]
+ a_lines.trim_left(match.end(), end=1)
+ a_lines.trim_left(indent, start=1)
+ return (indented[:i], a_lines,
+ i, indented[attribution_end:],
+ line_offset + attribution_end)
+ nonblank_seen = True
+ else:
+ blank = i
+ else:
+ return (indented, None, None, None, None)
+
+ def check_attribution(self, indented, attribution_start):
+ """
+ Check attribution shape.
+ Return the index past the end of the attribution, and the indent.
+ """
+ indent = None
+ i = attribution_start + 1
+ for i in range(attribution_start + 1, len(indented)):
+ line = indented[i].rstrip()
+ if not line:
+ break
+ if indent is None:
+ indent = len(line) - len(line.lstrip())
+ elif len(line) - len(line.lstrip()) != indent:
+ return None, None # bad shape; not an attribution
+ else:
+ # return index of line after last attribution line:
+ i += 1
+ return i, (indent or 0)
+
+ def parse_attribution(self, indented, line_offset):
+ text = '\n'.join(indented).rstrip()
+ lineno = self.state_machine.abs_line_number() + line_offset
+ textnodes, messages = self.inline_text(text, lineno)
+ node = nodes.attribution(text, '', *textnodes)
+ node.source, node.line = self.state_machine.get_source_and_line(lineno)
+ return node, messages
+
+ def bullet(self, match, context, next_state):
+ """Bullet list item."""
+ bulletlist = nodes.bullet_list()
+ (bulletlist.source,
+ bulletlist.line) = self.state_machine.get_source_and_line()
+ self.parent += bulletlist
+ bulletlist['bullet'] = match.string[0]
+ i, blank_finish = self.list_item(match.end())
+ bulletlist += i
+ offset = self.state_machine.line_offset + 1 # next line
+ new_line_offset, blank_finish = self.nested_list_parse(
+ self.state_machine.input_lines[offset:],
+ input_offset=self.state_machine.abs_line_offset() + 1,
+ node=bulletlist, initial_state='BulletList',
+ blank_finish=blank_finish)
+ self.goto_line(new_line_offset)
+ if not blank_finish:
+ self.parent += self.unindent_warning('Bullet list')
+ return [], next_state, []
+
+ def list_item(self, indent):
+ if self.state_machine.line[indent:]:
+ indented, line_offset, blank_finish = (
+ self.state_machine.get_known_indented(indent))
+ else:
+ indented, indent, line_offset, blank_finish = (
+ self.state_machine.get_first_known_indented(indent))
+ listitem = nodes.list_item('\n'.join(indented))
+ if indented:
+ self.nested_parse(indented, input_offset=line_offset,
+ node=listitem)
+ return listitem, blank_finish
+
+ def enumerator(self, match, context, next_state):
+ """Enumerated List Item"""
+ format, sequence, text, ordinal = self.parse_enumerator(match)
+ if not self.is_enumerated_list_item(ordinal, sequence, format):
+ raise statemachine.TransitionCorrection('text')
+ enumlist = nodes.enumerated_list()
+ self.parent += enumlist
+ if sequence == '#':
+ enumlist['enumtype'] = 'arabic'
+ else:
+ enumlist['enumtype'] = sequence
+ enumlist['prefix'] = self.enum.formatinfo[format].prefix
+ enumlist['suffix'] = self.enum.formatinfo[format].suffix
+ if ordinal != 1:
+ enumlist['start'] = ordinal
+ msg = self.reporter.info(
+ 'Enumerated list start value not ordinal-1: "%s" (ordinal %s)'
+ % (text, ordinal))
+ self.parent += msg
+ listitem, blank_finish = self.list_item(match.end())
+ enumlist += listitem
+ offset = self.state_machine.line_offset + 1 # next line
+ newline_offset, blank_finish = self.nested_list_parse(
+ self.state_machine.input_lines[offset:],
+ input_offset=self.state_machine.abs_line_offset() + 1,
+ node=enumlist, initial_state='EnumeratedList',
+ blank_finish=blank_finish,
+ extra_settings={'lastordinal': ordinal,
+ 'format': format,
+ 'auto': sequence == '#'})
+ self.goto_line(newline_offset)
+ if not blank_finish:
+ self.parent += self.unindent_warning('Enumerated list')
+ return [], next_state, []
+
+ def parse_enumerator(self, match, expected_sequence=None):
+ """
+ Analyze an enumerator and return the results.
+
+ :Return:
+ - the enumerator format ('period', 'parens', or 'rparen'),
+ - the sequence used ('arabic', 'loweralpha', 'upperroman', etc.),
+ - the text of the enumerator, stripped of formatting, and
+ - the ordinal value of the enumerator ('a' -> 1, 'ii' -> 2, etc.;
+ ``None`` is returned for invalid enumerator text).
+
+ The enumerator format has already been determined by the regular
+ expression match. If `expected_sequence` is given, that sequence is
+ tried first. If not, we check for Roman numeral 1. This way,
+ single-character Roman numerals (which are also alphabetical) can be
+ matched. If no sequence has been matched, all sequences are checked in
+ order.
+ """
+ groupdict = match.groupdict()
+ sequence = ''
+ for format in self.enum.formats:
+ if groupdict[format]: # was this the format matched?
+ break # yes; keep `format`
+ else: # shouldn't happen
+ raise ParserError('enumerator format not matched')
+ text = groupdict[format][self.enum.formatinfo[format].start
+ :self.enum.formatinfo[format].end]
+ if text == '#':
+ sequence = '#'
+ elif expected_sequence:
+ try:
+ if self.enum.sequenceregexps[expected_sequence].match(text):
+ sequence = expected_sequence
+ except KeyError: # shouldn't happen
+ raise ParserError('unknown enumerator sequence: %s'
+ % sequence)
+ elif text == 'i':
+ sequence = 'lowerroman'
+ elif text == 'I':
+ sequence = 'upperroman'
+ if not sequence:
+ for sequence in self.enum.sequences:
+ if self.enum.sequenceregexps[sequence].match(text):
+ break
+ else: # shouldn't happen
+ raise ParserError('enumerator sequence not matched')
+ if sequence == '#':
+ ordinal = 1
+ else:
+ try:
+ ordinal = self.enum.converters[sequence](text)
+ except roman.InvalidRomanNumeralError:
+ ordinal = None
+ return format, sequence, text, ordinal
+
+ def is_enumerated_list_item(self, ordinal, sequence, format):
+ """
+ Check validity based on the ordinal value and the second line.
+
+ Return true if the ordinal is valid and the second line is blank,
+ indented, or starts with the next enumerator or an auto-enumerator.
+ """
+ if ordinal is None:
+ return None
+ try:
+ next_line = self.state_machine.next_line()
+ except EOFError: # end of input lines
+ self.state_machine.previous_line()
+ return 1
+ else:
+ self.state_machine.previous_line()
+ if not next_line[:1].strip(): # blank or indented
+ return 1
+ result = self.make_enumerator(ordinal + 1, sequence, format)
+ if result:
+ next_enumerator, auto_enumerator = result
+ try:
+ if ( next_line.startswith(next_enumerator) or
+ next_line.startswith(auto_enumerator) ):
+ return 1
+ except TypeError:
+ pass
+ return None
+
+ def make_enumerator(self, ordinal, sequence, format):
+ """
+ Construct and return the next enumerated list item marker, and an
+ auto-enumerator ("#" instead of the regular enumerator).
+
+ Return ``None`` for invalid (out of range) ordinals.
+ """ #"
+ if sequence == '#':
+ enumerator = '#'
+ elif sequence == 'arabic':
+ enumerator = str(ordinal)
+ else:
+ if sequence.endswith('alpha'):
+ if ordinal > 26:
+ return None
+ enumerator = chr(ordinal + ord('a') - 1)
+ elif sequence.endswith('roman'):
+ try:
+ enumerator = roman.toRoman(ordinal)
+ except roman.RomanError:
+ return None
+ else: # shouldn't happen
+ raise ParserError('unknown enumerator sequence: "%s"'
+ % sequence)
+ if sequence.startswith('lower'):
+ enumerator = enumerator.lower()
+ elif sequence.startswith('upper'):
+ enumerator = enumerator.upper()
+ else: # shouldn't happen
+ raise ParserError('unknown enumerator sequence: "%s"'
+ % sequence)
+ formatinfo = self.enum.formatinfo[format]
+ next_enumerator = (formatinfo.prefix + enumerator + formatinfo.suffix
+ + ' ')
+ auto_enumerator = formatinfo.prefix + '#' + formatinfo.suffix + ' '
+ return next_enumerator, auto_enumerator
+
+ def field_marker(self, match, context, next_state):
+ """Field list item."""
+ field_list = nodes.field_list()
+ self.parent += field_list
+ field, blank_finish = self.field(match)
+ field_list += field
+ offset = self.state_machine.line_offset + 1 # next line
+ newline_offset, blank_finish = self.nested_list_parse(
+ self.state_machine.input_lines[offset:],
+ input_offset=self.state_machine.abs_line_offset() + 1,
+ node=field_list, initial_state='FieldList',
+ blank_finish=blank_finish)
+ self.goto_line(newline_offset)
+ if not blank_finish:
+ self.parent += self.unindent_warning('Field list')
+ return [], next_state, []
+
+ def field(self, match):
+ name = self.parse_field_marker(match)
+ src, srcline = self.state_machine.get_source_and_line()
+ lineno = self.state_machine.abs_line_number()
+ indented, indent, line_offset, blank_finish = \
+ self.state_machine.get_first_known_indented(match.end())
+ field_node = nodes.field()
+ field_node.source = src
+ field_node.line = srcline
+ name_nodes, name_messages = self.inline_text(name, lineno)
+ field_node += nodes.field_name(name, '', *name_nodes)
+ field_body = nodes.field_body('\n'.join(indented), *name_messages)
+ field_node += field_body
+ if indented:
+ self.parse_field_body(indented, line_offset, field_body)
+ return field_node, blank_finish
+
+ def parse_field_marker(self, match):
+ """Extract & return field name from a field marker match."""
+ field = match.group()[1:] # strip off leading ':'
+ field = field[:field.rfind(':')] # strip off trailing ':' etc.
+ return field
+
+ def parse_field_body(self, indented, offset, node):
+ self.nested_parse(indented, input_offset=offset, node=node)
+
+ def option_marker(self, match, context, next_state):
+ """Option list item."""
+ optionlist = nodes.option_list()
+ (optionlist.source, optionlist.line) = self.state_machine.get_source_and_line()
+ try:
+ listitem, blank_finish = self.option_list_item(match)
+ except MarkupError as error:
+ # This shouldn't happen; pattern won't match.
+ msg = self.reporter.error(u'Invalid option list marker: %s' %
+ error)
+ self.parent += msg
+ indented, indent, line_offset, blank_finish = \
+ self.state_machine.get_first_known_indented(match.end())
+ elements = self.block_quote(indented, line_offset)
+ self.parent += elements
+ if not blank_finish:
+ self.parent += self.unindent_warning('Option list')
+ return [], next_state, []
+ self.parent += optionlist
+ optionlist += listitem
+ offset = self.state_machine.line_offset + 1 # next line
+ newline_offset, blank_finish = self.nested_list_parse(
+ self.state_machine.input_lines[offset:],
+ input_offset=self.state_machine.abs_line_offset() + 1,
+ node=optionlist, initial_state='OptionList',
+ blank_finish=blank_finish)
+ self.goto_line(newline_offset)
+ if not blank_finish:
+ self.parent += self.unindent_warning('Option list')
+ return [], next_state, []
+
+ def option_list_item(self, match):
+ offset = self.state_machine.abs_line_offset()
+ options = self.parse_option_marker(match)
+ indented, indent, line_offset, blank_finish = \
+ self.state_machine.get_first_known_indented(match.end())
+ if not indented: # not an option list item
+ self.goto_line(offset)
+ raise statemachine.TransitionCorrection('text')
+ option_group = nodes.option_group('', *options)
+ description = nodes.description('\n'.join(indented))
+ option_list_item = nodes.option_list_item('', option_group,
+ description)
+ if indented:
+ self.nested_parse(indented, input_offset=line_offset,
+ node=description)
+ return option_list_item, blank_finish
+
+ def parse_option_marker(self, match):
+ """
+ Return a list of `node.option` and `node.option_argument` objects,
+ parsed from an option marker match.
+
+ :Exception: `MarkupError` for invalid option markers.
+ """
+ optlist = []
+ optionstrings = match.group().rstrip().split(', ')
+ for optionstring in optionstrings:
+ tokens = optionstring.split()
+ delimiter = ' '
+ firstopt = tokens[0].split('=', 1)
+ if len(firstopt) > 1:
+ # "--opt=value" form
+ tokens[:1] = firstopt
+ delimiter = '='
+ elif (len(tokens[0]) > 2
+ and ((tokens[0].startswith('-')
+ and not tokens[0].startswith('--'))
+ or tokens[0].startswith('+'))):
+ # "-ovalue" form
+ tokens[:1] = [tokens[0][:2], tokens[0][2:]]
+ delimiter = ''
+ if len(tokens) > 1 and (tokens[1].startswith('<')
+ and tokens[-1].endswith('>')):
+ # "-o <value1 value2>" form; join all values into one token
+ tokens[1:] = [' '.join(tokens[1:])]
+ if 0 < len(tokens) <= 2:
+ option = nodes.option(optionstring)
+ option += nodes.option_string(tokens[0], tokens[0])
+ if len(tokens) > 1:
+ option += nodes.option_argument(tokens[1], tokens[1],
+ delimiter=delimiter)
+ optlist.append(option)
+ else:
+ raise MarkupError(
+ 'wrong number of option tokens (=%s), should be 1 or 2: '
+ '"%s"' % (len(tokens), optionstring))
+ return optlist
+
+ def doctest(self, match, context, next_state):
+ data = '\n'.join(self.state_machine.get_text_block())
+ # TODO: prepend class value ['pycon'] (Python Console)
+ # parse with `directives.body.CodeBlock` (returns literal-block
+ # with class "code" and syntax highlight markup).
+ self.parent += nodes.doctest_block(data, data)
+ return [], next_state, []
+
+ def line_block(self, match, context, next_state):
+ """First line of a line block."""
+ block = nodes.line_block()
+ self.parent += block
+ lineno = self.state_machine.abs_line_number()
+ line, messages, blank_finish = self.line_block_line(match, lineno)
+ block += line
+ self.parent += messages
+ if not blank_finish:
+ offset = self.state_machine.line_offset + 1 # next line
+ new_line_offset, blank_finish = self.nested_list_parse(
+ self.state_machine.input_lines[offset:],
+ input_offset=self.state_machine.abs_line_offset() + 1,
+ node=block, initial_state='LineBlock',
+ blank_finish=0)
+ self.goto_line(new_line_offset)
+ if not blank_finish:
+ self.parent += self.reporter.warning(
+ 'Line block ends without a blank line.',
+ line=lineno+1)
+ if len(block):
+ if block[0].indent is None:
+ block[0].indent = 0
+ self.nest_line_block_lines(block)
+ return [], next_state, []
+
+ def line_block_line(self, match, lineno):
+ """Return one line element of a line_block."""
+ indented, indent, line_offset, blank_finish = \
+ self.state_machine.get_first_known_indented(match.end(),
+ until_blank=True)
+ text = u'\n'.join(indented)
+ text_nodes, messages = self.inline_text(text, lineno)
+ line = nodes.line(text, '', *text_nodes)
+ if match.string.rstrip() != '|': # not empty
+ line.indent = len(match.group(1)) - 1
+ return line, messages, blank_finish
+
+ def nest_line_block_lines(self, block):
+ for index in range(1, len(block)):
+ if getattr(block[index], 'indent', None) is None:
+ block[index].indent = block[index - 1].indent
+ self.nest_line_block_segment(block)
+
+ def nest_line_block_segment(self, block):
+ indents = [item.indent for item in block]
+ least = min(indents)
+ new_items = []
+ new_block = nodes.line_block()
+ for item in block:
+ if item.indent > least:
+ new_block.append(item)
+ else:
+ if len(new_block):
+ self.nest_line_block_segment(new_block)
+ new_items.append(new_block)
+ new_block = nodes.line_block()
+ new_items.append(item)
+ if len(new_block):
+ self.nest_line_block_segment(new_block)
+ new_items.append(new_block)
+ block[:] = new_items
+
+ def grid_table_top(self, match, context, next_state):
+ """Top border of a full table."""
+ return self.table_top(match, context, next_state,
+ self.isolate_grid_table,
+ tableparser.GridTableParser)
+
+ def simple_table_top(self, match, context, next_state):
+ """Top border of a simple table."""
+ return self.table_top(match, context, next_state,
+ self.isolate_simple_table,
+ tableparser.SimpleTableParser)
+
+ def table_top(self, match, context, next_state,
+ isolate_function, parser_class):
+ """Top border of a generic table."""
+ nodelist, blank_finish = self.table(isolate_function, parser_class)
+ self.parent += nodelist
+ if not blank_finish:
+ msg = self.reporter.warning(
+ 'Blank line required after table.',
+ line=self.state_machine.abs_line_number()+1)
+ self.parent += msg
+ return [], next_state, []
+
+ def table(self, isolate_function, parser_class):
+ """Parse a table."""
+ block, messages, blank_finish = isolate_function()
+ if block:
+ try:
+ parser = parser_class()
+ tabledata = parser.parse(block)
+ tableline = (self.state_machine.abs_line_number() - len(block)
+ + 1)
+ table = self.build_table(tabledata, tableline)
+ nodelist = [table] + messages
+ except tableparser.TableMarkupError as err:
+ nodelist = self.malformed_table(block, ' '.join(err.args),
+ offset=err.offset) + messages
+ else:
+ nodelist = messages
+ return nodelist, blank_finish
+
+ def isolate_grid_table(self):
+ messages = []
+ blank_finish = 1
+ try:
+ block = self.state_machine.get_text_block(flush_left=True)
+ except statemachine.UnexpectedIndentationError as err:
+ block, src, srcline = err.args
+ messages.append(self.reporter.error('Unexpected indentation.',
+ source=src, line=srcline))
+ blank_finish = 0
+ block.disconnect()
+ # for East Asian chars:
+ block.pad_double_width(self.double_width_pad_char)
+ width = len(block[0].strip())
+ for i in range(len(block)):
+ block[i] = block[i].strip()
+ if block[i][0] not in '+|': # check left edge
+ blank_finish = 0
+ self.state_machine.previous_line(len(block) - i)
+ del block[i:]
+ break
+ if not self.grid_table_top_pat.match(block[-1]): # find bottom
+ blank_finish = 0
+ # from second-last to third line of table:
+ for i in range(len(block) - 2, 1, -1):
+ if self.grid_table_top_pat.match(block[i]):
+ self.state_machine.previous_line(len(block) - i + 1)
+ del block[i+1:]
+ break
+ else:
+ messages.extend(self.malformed_table(block))
+ return [], messages, blank_finish
+ for i in range(len(block)): # check right edge
+ if len(block[i]) != width or block[i][-1] not in '+|':
+ messages.extend(self.malformed_table(block))
+ return [], messages, blank_finish
+ return block, messages, blank_finish
+
+ def isolate_simple_table(self):
+ start = self.state_machine.line_offset
+ lines = self.state_machine.input_lines
+ limit = len(lines) - 1
+ toplen = len(lines[start].strip())
+ pattern_match = self.simple_table_border_pat.match
+ found = 0
+ found_at = None
+ i = start + 1
+ while i <= limit:
+ line = lines[i]
+ match = pattern_match(line)
+ if match:
+ if len(line.strip()) != toplen:
+ self.state_machine.next_line(i - start)
+ messages = self.malformed_table(
+ lines[start:i+1], 'Bottom/header table border does '
+ 'not match top border.')
+ return [], messages, i == limit or not lines[i+1].strip()
+ found += 1
+ found_at = i
+ if found == 2 or i == limit or not lines[i+1].strip():
+ end = i
+ break
+ i += 1
+ else: # reached end of input_lines
+ if found:
+ extra = ' or no blank line after table bottom'
+ self.state_machine.next_line(found_at - start)
+ block = lines[start:found_at+1]
+ else:
+ extra = ''
+ self.state_machine.next_line(i - start - 1)
+ block = lines[start:]
+ messages = self.malformed_table(
+ block, 'No bottom table border found%s.' % extra)
+ return [], messages, not extra
+ self.state_machine.next_line(end - start)
+ block = lines[start:end+1]
+ # for East Asian chars:
+ block.pad_double_width(self.double_width_pad_char)
+ return block, [], end == limit or not lines[end+1].strip()
+
+ def malformed_table(self, block, detail='', offset=0):
+ block.replace(self.double_width_pad_char, '')
+ data = '\n'.join(block)
+ message = 'Malformed table.'
+ startline = self.state_machine.abs_line_number() - len(block) + 1
+ if detail:
+ message += '\n' + detail
+ error = self.reporter.error(message, nodes.literal_block(data, data),
+ line=startline+offset)
+ return [error]
+
+ def build_table(self, tabledata, tableline, stub_columns=0, widths=None):
+ colwidths, headrows, bodyrows = tabledata
+ table = nodes.table()
+ if widths == 'auto':
+ table['classes'] += ['colwidths-auto']
+ elif widths: # "grid" or list of integers
+ table['classes'] += ['colwidths-given']
+ tgroup = nodes.tgroup(cols=len(colwidths))
+ table += tgroup
+ for colwidth in colwidths:
+ colspec = nodes.colspec(colwidth=colwidth)
+ if stub_columns:
+ colspec.attributes['stub'] = 1
+ stub_columns -= 1
+ tgroup += colspec
+ if headrows:
+ thead = nodes.thead()
+ tgroup += thead
+ for row in headrows:
+ thead += self.build_table_row(row, tableline)
+ tbody = nodes.tbody()
+ tgroup += tbody
+ for row in bodyrows:
+ tbody += self.build_table_row(row, tableline)
+ return table
+
+ def build_table_row(self, rowdata, tableline):
+ row = nodes.row()
+ for cell in rowdata:
+ if cell is None:
+ continue
+ morerows, morecols, offset, cellblock = cell
+ attributes = {}
+ if morerows:
+ attributes['morerows'] = morerows
+ if morecols:
+ attributes['morecols'] = morecols
+ entry = nodes.entry(**attributes)
+ row += entry
+ if ''.join(cellblock):
+ self.nested_parse(cellblock, input_offset=tableline+offset,
+ node=entry)
+ return row
+
+
+ explicit = Struct()
+ """Patterns and constants used for explicit markup recognition."""
+
+ explicit.patterns = Struct(
+ target=re.compile(r"""
+ (
+ _ # anonymous target
+ | # *OR*
+ (?!_) # no underscore at the beginning
+ (?P<quote>`?) # optional open quote
+ (?![ `]) # first char. not space or
+ # backquote
+ (?P<name> # reference name
+ .+?
+ )
+ %(non_whitespace_escape_before)s
+ (?P=quote) # close quote if open quote used
+ )
+ (?<!(?<!\x00):) # no unescaped colon at end
+ %(non_whitespace_escape_before)s
+ [ ]? # optional space
+ : # end of reference name
+ ([ ]+|$) # followed by whitespace
+ """ % vars(Inliner), re.VERBOSE | re.UNICODE),
+ reference=re.compile(r"""
+ (
+ (?P<simple>%(simplename)s)_
+ | # *OR*
+ ` # open backquote
+ (?![ ]) # not space
+ (?P<phrase>.+?) # hyperlink phrase
+ %(non_whitespace_escape_before)s
+ `_ # close backquote,
+ # reference mark
+ )
+ $ # end of string
+ """ % vars(Inliner), re.VERBOSE | re.UNICODE),
+ substitution=re.compile(r"""
+ (
+ (?![ ]) # first char. not space
+ (?P<name>.+?) # substitution text
+ %(non_whitespace_escape_before)s
+ \| # close delimiter
+ )
+ ([ ]+|$) # followed by whitespace
+ """ % vars(Inliner),
+ re.VERBOSE | re.UNICODE),)
+
+ def footnote(self, match):
+ src, srcline = self.state_machine.get_source_and_line()
+ indented, indent, offset, blank_finish = \
+ self.state_machine.get_first_known_indented(match.end())
+ label = match.group(1)
+ name = normalize_name(label)
+ footnote = nodes.footnote('\n'.join(indented))
+ footnote.source = src
+ footnote.line = srcline
+ if name[0] == '#': # auto-numbered
+ name = name[1:] # autonumber label
+ footnote['auto'] = 1
+ if name:
+ footnote['names'].append(name)
+ self.document.note_autofootnote(footnote)
+ elif name == '*': # auto-symbol
+ name = ''
+ footnote['auto'] = '*'
+ self.document.note_symbol_footnote(footnote)
+ else: # manually numbered
+ footnote += nodes.label('', label)
+ footnote['names'].append(name)
+ self.document.note_footnote(footnote)
+ if name:
+ self.document.note_explicit_target(footnote, footnote)
+ else:
+ self.document.set_id(footnote, footnote)
+ if indented:
+ self.nested_parse(indented, input_offset=offset, node=footnote)
+ return [footnote], blank_finish
+
+ def citation(self, match):
+ src, srcline = self.state_machine.get_source_and_line()
+ indented, indent, offset, blank_finish = \
+ self.state_machine.get_first_known_indented(match.end())
+ label = match.group(1)
+ name = normalize_name(label)
+ citation = nodes.citation('\n'.join(indented))
+ citation.source = src
+ citation.line = srcline
+ citation += nodes.label('', label)
+ citation['names'].append(name)
+ self.document.note_citation(citation)
+ self.document.note_explicit_target(citation, citation)
+ if indented:
+ self.nested_parse(indented, input_offset=offset, node=citation)
+ return [citation], blank_finish
+
+ def hyperlink_target(self, match):
+ pattern = self.explicit.patterns.target
+ lineno = self.state_machine.abs_line_number()
+ block, indent, offset, blank_finish = \
+ self.state_machine.get_first_known_indented(
+ match.end(), until_blank=True, strip_indent=False)
+ blocktext = match.string[:match.end()] + '\n'.join(block)
+ block = [escape2null(line) for line in block]
+ escaped = block[0]
+ blockindex = 0
+ while True:
+ targetmatch = pattern.match(escaped)
+ if targetmatch:
+ break
+ blockindex += 1
+ try:
+ escaped += block[blockindex]
+ except IndexError:
+ raise MarkupError('malformed hyperlink target.')
+ del block[:blockindex]
+ block[0] = (block[0] + ' ')[targetmatch.end()-len(escaped)-1:].strip()
+ target = self.make_target(block, blocktext, lineno,
+ targetmatch.group('name'))
+ return [target], blank_finish
+
+ def make_target(self, block, block_text, lineno, target_name):
+ target_type, data = self.parse_target(block, block_text, lineno)
+ if target_type == 'refname':
+ target = nodes.target(block_text, '', refname=normalize_name(data))
+ target.indirect_reference_name = data
+ self.add_target(target_name, '', target, lineno)
+ self.document.note_indirect_target(target)
+ return target
+ elif target_type == 'refuri':
+ target = nodes.target(block_text, '')
+ self.add_target(target_name, data, target, lineno)
+ return target
+ else:
+ return data
+
+ def parse_target(self, block, block_text, lineno):
+ """
+ Determine the type of reference of a target.
+
+ :Return: A 2-tuple, one of:
+
+ - 'refname' and the indirect reference name
+ - 'refuri' and the URI
+ - 'malformed' and a system_message node
+ """
+ if block and block[-1].strip()[-1:] == '_': # possible indirect target
+ reference = ' '.join([line.strip() for line in block])
+ refname = self.is_reference(reference)
+ if refname:
+ return 'refname', refname
+ ref_parts = split_escaped_whitespace(' '.join(block))
+ reference = ' '.join(''.join(unescape(part).split())
+ for part in ref_parts)
+ return 'refuri', reference
+
+ def is_reference(self, reference):
+ match = self.explicit.patterns.reference.match(
+ whitespace_normalize_name(reference))
+ if not match:
+ return None
+ return unescape(match.group('simple') or match.group('phrase'))
+
+ def add_target(self, targetname, refuri, target, lineno):
+ target.line = lineno
+ if targetname:
+ name = normalize_name(unescape(targetname))
+ target['names'].append(name)
+ if refuri:
+ uri = self.inliner.adjust_uri(refuri)
+ if uri:
+ target['refuri'] = uri
+ else:
+ raise ApplicationError('problem with URI: %r' % refuri)
+ self.document.note_explicit_target(target, self.parent)
+ else: # anonymous target
+ if refuri:
+ target['refuri'] = refuri
+ target['anonymous'] = 1
+ self.document.note_anonymous_target(target)
+
+ def substitution_def(self, match):
+ pattern = self.explicit.patterns.substitution
+ src, srcline = self.state_machine.get_source_and_line()
+ block, indent, offset, blank_finish = \
+ self.state_machine.get_first_known_indented(match.end(),
+ strip_indent=False)
+ blocktext = (match.string[:match.end()] + '\n'.join(block))
+ block.disconnect()
+ escaped = escape2null(block[0].rstrip())
+ blockindex = 0
+ while True:
+ subdefmatch = pattern.match(escaped)
+ if subdefmatch:
+ break
+ blockindex += 1
+ try:
+ escaped = escaped + ' ' + escape2null(block[blockindex].strip())
+ except IndexError:
+ raise MarkupError('malformed substitution definition.')
+ del block[:blockindex] # strip out the substitution marker
+ block[0] = (block[0].strip() + ' ')[subdefmatch.end()-len(escaped)-1:-1]
+ if not block[0]:
+ del block[0]
+ offset += 1
+ while block and not block[-1].strip():
+ block.pop()
+ subname = subdefmatch.group('name')
+ substitution_node = nodes.substitution_definition(blocktext)
+ substitution_node.source = src
+ substitution_node.line = srcline
+ if not block:
+ msg = self.reporter.warning(
+ 'Substitution definition "%s" missing contents.' % subname,
+ nodes.literal_block(blocktext, blocktext),
+ source=src, line=srcline)
+ return [msg], blank_finish
+ block[0] = block[0].strip()
+ substitution_node['names'].append(
+ nodes.whitespace_normalize_name(subname))
+ new_abs_offset, blank_finish = self.nested_list_parse(
+ block, input_offset=offset, node=substitution_node,
+ initial_state='SubstitutionDef', blank_finish=blank_finish)
+ i = 0
+ for node in substitution_node[:]:
+ if not (isinstance(node, nodes.Inline) or
+ isinstance(node, nodes.Text)):
+ self.parent += substitution_node[i]
+ del substitution_node[i]
+ else:
+ i += 1
+ for node in substitution_node.traverse(nodes.Element):
+ if self.disallowed_inside_substitution_definitions(node):
+ pformat = nodes.literal_block('', node.pformat().rstrip())
+ msg = self.reporter.error(
+ 'Substitution definition contains illegal element <%s>:'
+ % node.tagname,
+ pformat, nodes.literal_block(blocktext, blocktext),
+ source=src, line=srcline)
+ return [msg], blank_finish
+ if len(substitution_node) == 0:
+ msg = self.reporter.warning(
+ 'Substitution definition "%s" empty or invalid.' % subname,
+ nodes.literal_block(blocktext, blocktext),
+ source=src, line=srcline)
+ return [msg], blank_finish
+ self.document.note_substitution_def(
+ substitution_node, subname, self.parent)
+ return [substitution_node], blank_finish
+
+ def disallowed_inside_substitution_definitions(self, node):
+ if (node['ids'] or
+ isinstance(node, nodes.reference) and node.get('anonymous') or
+ isinstance(node, nodes.footnote_reference) and node.get('auto')):
+ return True
+ else:
+ return False
+
+ def directive(self, match, **option_presets):
+ """Returns a 2-tuple: list of nodes, and a "blank finish" boolean."""
+ type_name = match.group(1)
+ directive_class, messages = directives.directive(
+ type_name, self.memo.language, self.document)
+ self.parent += messages
+ if directive_class:
+ return self.run_directive(
+ directive_class, match, type_name, option_presets)
+ else:
+ return self.unknown_directive(type_name)
+
+ def run_directive(self, directive, match, type_name, option_presets):
+ """
+ Parse a directive then run its directive function.
+
+ Parameters:
+
+ - `directive`: The class implementing the directive. Must be
+ a subclass of `rst.Directive`.
+
+ - `match`: A regular expression match object which matched the first
+ line of the directive.
+
+ - `type_name`: The directive name, as used in the source text.
+
+ - `option_presets`: A dictionary of preset options, defaults for the
+ directive options. Currently, only an "alt" option is passed by
+ substitution definitions (value: the substitution name), which may
+ be used by an embedded image directive.
+
+ Returns a 2-tuple: list of nodes, and a "blank finish" boolean.
+ """
+ if isinstance(directive, (FunctionType, MethodType)):
+ from docutils.parsers.rst import convert_directive_function
+ directive = convert_directive_function(directive)
+ lineno = self.state_machine.abs_line_number()
+ initial_line_offset = self.state_machine.line_offset
+ indented, indent, line_offset, blank_finish \
+ = self.state_machine.get_first_known_indented(match.end(),
+ strip_top=0)
+ block_text = '\n'.join(self.state_machine.input_lines[
+ initial_line_offset : self.state_machine.line_offset + 1])
+ try:
+ arguments, options, content, content_offset = (
+ self.parse_directive_block(indented, line_offset,
+ directive, option_presets))
+ except MarkupError as detail:
+ error = self.reporter.error(
+ 'Error in "%s" directive:\n%s.' % (type_name,
+ ' '.join(detail.args)),
+ nodes.literal_block(block_text, block_text), line=lineno)
+ return [error], blank_finish
+ directive_instance = directive(
+ type_name, arguments, options, content, lineno,
+ content_offset, block_text, self, self.state_machine)
+ try:
+ result = directive_instance.run()
+ except docutils.parsers.rst.DirectiveError as error:
+ msg_node = self.reporter.system_message(error.level, error.msg,
+ line=lineno)
+ msg_node += nodes.literal_block(block_text, block_text)
+ result = [msg_node]
+ assert isinstance(result, list), \
+ 'Directive "%s" must return a list of nodes.' % type_name
+ for i in range(len(result)):
+ assert isinstance(result[i], nodes.Node), \
+ ('Directive "%s" returned non-Node object (index %s): %r'
+ % (type_name, i, result[i]))
+ return (result,
+ blank_finish or self.state_machine.is_next_line_blank())
+
+ def parse_directive_block(self, indented, line_offset, directive,
+ option_presets):
+ option_spec = directive.option_spec
+ has_content = directive.has_content
+ if indented and not indented[0].strip():
+ indented.trim_start()
+ line_offset += 1
+ while indented and not indented[-1].strip():
+ indented.trim_end()
+ if indented and (directive.required_arguments
+ or directive.optional_arguments
+ or option_spec):
+ for i, line in enumerate(indented):
+ if not line.strip():
+ break
+ else:
+ i += 1
+ arg_block = indented[:i]
+ content = indented[i+1:]
+ content_offset = line_offset + i + 1
+ else:
+ content = indented
+ content_offset = line_offset
+ arg_block = []
+ if option_spec:
+ options, arg_block = self.parse_directive_options(
+ option_presets, option_spec, arg_block)
+ else:
+ options = {}
+ if arg_block and not (directive.required_arguments
+ or directive.optional_arguments):
+ content = arg_block + indented[i:]
+ content_offset = line_offset
+ arg_block = []
+ while content and not content[0].strip():
+ content.trim_start()
+ content_offset += 1
+ if directive.required_arguments or directive.optional_arguments:
+ arguments = self.parse_directive_arguments(
+ directive, arg_block)
+ else:
+ arguments = []
+ if content and not has_content:
+ raise MarkupError('no content permitted')
+ return (arguments, options, content, content_offset)
+
+ def parse_directive_options(self, option_presets, option_spec, arg_block):
+ options = option_presets.copy()
+ for i, line in enumerate(arg_block):
+ if re.match(Body.patterns['field_marker'], line):
+ opt_block = arg_block[i:]
+ arg_block = arg_block[:i]
+ break
+ else:
+ opt_block = []
+ if opt_block:
+ success, data = self.parse_extension_options(option_spec,
+ opt_block)
+ if success: # data is a dict of options
+ options.update(data)
+ else: # data is an error string
+ raise MarkupError(data)
+ return options, arg_block
+
+ def parse_directive_arguments(self, directive, arg_block):
+ required = directive.required_arguments
+ optional = directive.optional_arguments
+ arg_text = '\n'.join(arg_block)
+ arguments = arg_text.split()
+ if len(arguments) < required:
+ raise MarkupError('%s argument(s) required, %s supplied'
+ % (required, len(arguments)))
+ elif len(arguments) > required + optional:
+ if directive.final_argument_whitespace:
+ arguments = arg_text.split(None, required + optional - 1)
+ else:
+ raise MarkupError(
+ 'maximum %s argument(s) allowed, %s supplied'
+ % (required + optional, len(arguments)))
+ return arguments
+
+ def parse_extension_options(self, option_spec, datalines):
+ """
+ Parse `datalines` for a field list containing extension options
+ matching `option_spec`.
+
+ :Parameters:
+ - `option_spec`: a mapping of option name to conversion
+ function, which should raise an exception on bad input.
+ - `datalines`: a list of input strings.
+
+ :Return:
+ - Success value, 1 or 0.
+ - An option dictionary on success, an error string on failure.
+ """
+ node = nodes.field_list()
+ newline_offset, blank_finish = self.nested_list_parse(
+ datalines, 0, node, initial_state='ExtensionOptions',
+ blank_finish=True)
+ if newline_offset != len(datalines): # incomplete parse of block
+ return 0, 'invalid option block'
+ try:
+ options = utils.extract_extension_options(node, option_spec)
+ except KeyError as detail:
+ return 0, ('unknown option: "%s"' % detail.args[0])
+ except (ValueError, TypeError) as detail:
+ return 0, ('invalid option value: %s' % ' '.join(detail.args))
+ except utils.ExtensionOptionError as detail:
+ return 0, ('invalid option data: %s' % ' '.join(detail.args))
+ if blank_finish:
+ return 1, options
+ else:
+ return 0, 'option data incompletely parsed'
+
+ def unknown_directive(self, type_name):
+ lineno = self.state_machine.abs_line_number()
+ indented, indent, offset, blank_finish = \
+ self.state_machine.get_first_known_indented(0, strip_indent=False)
+ text = '\n'.join(indented)
+ error = self.reporter.error(
+ 'Unknown directive type "%s".' % type_name,
+ nodes.literal_block(text, text), line=lineno)
+ return [error], blank_finish
+
+ def comment(self, match):
+ if not match.string[match.end():].strip() \
+ and self.state_machine.is_next_line_blank(): # an empty comment?
+ return [nodes.comment()], 1 # "A tiny but practical wart."
+ indented, indent, offset, blank_finish = \
+ self.state_machine.get_first_known_indented(match.end())
+ while indented and not indented[-1].strip():
+ indented.trim_end()
+ text = '\n'.join(indented)
+ return [nodes.comment(text, text)], blank_finish
+
+ explicit.constructs = [
+ (footnote,
+ re.compile(r"""
+ \.\.[ ]+ # explicit markup start
+ \[
+ ( # footnote label:
+ [0-9]+ # manually numbered footnote
+ | # *OR*
+ \# # anonymous auto-numbered footnote
+ | # *OR*
+ \#%s # auto-number ed?) footnote label
+ | # *OR*
+ \* # auto-symbol footnote
+ )
+ \]
+ ([ ]+|$) # whitespace or end of line
+ """ % Inliner.simplename, re.VERBOSE | re.UNICODE)),
+ (citation,
+ re.compile(r"""
+ \.\.[ ]+ # explicit markup start
+ \[(%s)\] # citation label
+ ([ ]+|$) # whitespace or end of line
+ """ % Inliner.simplename, re.VERBOSE | re.UNICODE)),
+ (hyperlink_target,
+ re.compile(r"""
+ \.\.[ ]+ # explicit markup start
+ _ # target indicator
+ (?![ ]|$) # first char. not space or EOL
+ """, re.VERBOSE | re.UNICODE)),
+ (substitution_def,
+ re.compile(r"""
+ \.\.[ ]+ # explicit markup start
+ \| # substitution indicator
+ (?![ ]|$) # first char. not space or EOL
+ """, re.VERBOSE | re.UNICODE)),
+ (directive,
+ re.compile(r"""
+ \.\.[ ]+ # explicit markup start
+ (%s) # directive name
+ [ ]? # optional space
+ :: # directive delimiter
+ ([ ]+|$) # whitespace or end of line
+ """ % Inliner.simplename, re.VERBOSE | re.UNICODE))]
+
+ def explicit_markup(self, match, context, next_state):
+ """Footnotes, hyperlink targets, directives, comments."""
+ nodelist, blank_finish = self.explicit_construct(match)
+ self.parent += nodelist
+ self.explicit_list(blank_finish)
+ return [], next_state, []
+
+ def explicit_construct(self, match):
+ """Determine which explicit construct this is, parse & return it."""
+ errors = []
+ for method, pattern in self.explicit.constructs:
+ expmatch = pattern.match(match.string)
+ if expmatch:
+ try:
+ return method(self, expmatch)
+ except MarkupError as error:
+ lineno = self.state_machine.abs_line_number()
+ message = ' '.join(error.args)
+ errors.append(self.reporter.warning(message, line=lineno))
+ break
+ nodelist, blank_finish = self.comment(match)
+ return nodelist + errors, blank_finish
+
+ def explicit_list(self, blank_finish):
+ """
+ Create a nested state machine for a series of explicit markup
+ constructs (including anonymous hyperlink targets).
+ """
+ offset = self.state_machine.line_offset + 1 # next line
+ newline_offset, blank_finish = self.nested_list_parse(
+ self.state_machine.input_lines[offset:],
+ input_offset=self.state_machine.abs_line_offset() + 1,
+ node=self.parent, initial_state='Explicit',
+ blank_finish=blank_finish,
+ match_titles=self.state_machine.match_titles)
+ self.goto_line(newline_offset)
+ if not blank_finish:
+ self.parent += self.unindent_warning('Explicit markup')
+
+ def anonymous(self, match, context, next_state):
+ """Anonymous hyperlink targets."""
+ nodelist, blank_finish = self.anonymous_target(match)
+ self.parent += nodelist
+ self.explicit_list(blank_finish)
+ return [], next_state, []
+
+ def anonymous_target(self, match):
+ lineno = self.state_machine.abs_line_number()
+ block, indent, offset, blank_finish \
+ = self.state_machine.get_first_known_indented(match.end(),
+ until_blank=True)
+ blocktext = match.string[:match.end()] + '\n'.join(block)
+ block = [escape2null(line) for line in block]
+ target = self.make_target(block, blocktext, lineno, '')
+ return [target], blank_finish
+
+ def line(self, match, context, next_state):
+ """Section title overline or transition marker."""
+ if self.state_machine.match_titles:
+ return [match.string], 'Line', []
+ elif match.string.strip() == '::':
+ raise statemachine.TransitionCorrection('text')
+ elif len(match.string.strip()) < 4:
+ msg = self.reporter.info(
+ 'Unexpected possible title overline or transition.\n'
+ "Treating it as ordinary text because it's so short.",
+ line=self.state_machine.abs_line_number())
+ self.parent += msg
+ raise statemachine.TransitionCorrection('text')
+ else:
+ blocktext = self.state_machine.line
+ msg = self.reporter.severe(
+ 'Unexpected section title or transition.',
+ nodes.literal_block(blocktext, blocktext),
+ line=self.state_machine.abs_line_number())
+ self.parent += msg
+ return [], next_state, []
+
+ def text(self, match, context, next_state):
+ """Titles, definition lists, paragraphs."""
+ return [match.string], 'Text', []
+
+
+class RFC2822Body(Body):
+
+ """
+ RFC2822 headers are only valid as the first constructs in documents. As
+ soon as anything else appears, the `Body` state should take over.
+ """
+
+ patterns = Body.patterns.copy() # can't modify the original
+ patterns['rfc2822'] = r'[!-9;-~]+:( +|$)'
+ initial_transitions = [(name, 'Body')
+ for name in Body.initial_transitions]
+ initial_transitions.insert(-1, ('rfc2822', 'Body')) # just before 'text'
+
+ def rfc2822(self, match, context, next_state):
+ """RFC2822-style field list item."""
+ fieldlist = nodes.field_list(classes=['rfc2822'])
+ self.parent += fieldlist
+ field, blank_finish = self.rfc2822_field(match)
+ fieldlist += field
+ offset = self.state_machine.line_offset + 1 # next line
+ newline_offset, blank_finish = self.nested_list_parse(
+ self.state_machine.input_lines[offset:],
+ input_offset=self.state_machine.abs_line_offset() + 1,
+ node=fieldlist, initial_state='RFC2822List',
+ blank_finish=blank_finish)
+ self.goto_line(newline_offset)
+ if not blank_finish:
+ self.parent += self.unindent_warning(
+ 'RFC2822-style field list')
+ return [], next_state, []
+
+ def rfc2822_field(self, match):
+ name = match.string[:match.string.find(':')]
+ indented, indent, line_offset, blank_finish = \
+ self.state_machine.get_first_known_indented(match.end(),
+ until_blank=True)
+ fieldnode = nodes.field()
+ fieldnode += nodes.field_name(name, name)
+ fieldbody = nodes.field_body('\n'.join(indented))
+ fieldnode += fieldbody
+ if indented:
+ self.nested_parse(indented, input_offset=line_offset,
+ node=fieldbody)
+ return fieldnode, blank_finish
+
+
+class SpecializedBody(Body):
+
+ """
+ Superclass for second and subsequent compound element members. Compound
+ elements are lists and list-like constructs.
+
+ All transition methods are disabled (redefined as `invalid_input`).
+ Override individual methods in subclasses to re-enable.
+
+ For example, once an initial bullet list item, say, is recognized, the
+ `BulletList` subclass takes over, with a "bullet_list" node as its
+ container. Upon encountering the initial bullet list item, `Body.bullet`
+ calls its ``self.nested_list_parse`` (`RSTState.nested_list_parse`), which
+ starts up a nested parsing session with `BulletList` as the initial state.
+ Only the ``bullet`` transition method is enabled in `BulletList`; as long
+ as only bullet list items are encountered, they are parsed and inserted
+ into the container. The first construct which is *not* a bullet list item
+ triggers the `invalid_input` method, which ends the nested parse and
+ closes the container. `BulletList` needs to recognize input that is
+ invalid in the context of a bullet list, which means everything *other
+ than* bullet list items, so it inherits the transition list created in
+ `Body`.
+ """
+
+ def invalid_input(self, match=None, context=None, next_state=None):
+ """Not a compound element member. Abort this state machine."""
+ self.state_machine.previous_line() # back up so parent SM can reassess
+ raise EOFError
+
+ indent = invalid_input
+ bullet = invalid_input
+ enumerator = invalid_input
+ field_marker = invalid_input
+ option_marker = invalid_input
+ doctest = invalid_input
+ line_block = invalid_input
+ grid_table_top = invalid_input
+ simple_table_top = invalid_input
+ explicit_markup = invalid_input
+ anonymous = invalid_input
+ line = invalid_input
+ text = invalid_input
+
+
+class BulletList(SpecializedBody):
+
+ """Second and subsequent bullet_list list_items."""
+
+ def bullet(self, match, context, next_state):
+ """Bullet list item."""
+ if match.string[0] != self.parent['bullet']:
+ # different bullet: new list
+ self.invalid_input()
+ listitem, blank_finish = self.list_item(match.end())
+ self.parent += listitem
+ self.blank_finish = blank_finish
+ return [], next_state, []
+
+
+class DefinitionList(SpecializedBody):
+
+ """Second and subsequent definition_list_items."""
+
+ def text(self, match, context, next_state):
+ """Definition lists."""
+ return [match.string], 'Definition', []
+
+
+class EnumeratedList(SpecializedBody):
+
+ """Second and subsequent enumerated_list list_items."""
+
+ def enumerator(self, match, context, next_state):
+ """Enumerated list item."""
+ format, sequence, text, ordinal = self.parse_enumerator(
+ match, self.parent['enumtype'])
+ if ( format != self.format
+ or (sequence != '#' and (sequence != self.parent['enumtype']
+ or self.auto
+ or ordinal != (self.lastordinal + 1)))
+ or not self.is_enumerated_list_item(ordinal, sequence, format)):
+ # different enumeration: new list
+ self.invalid_input()
+ if sequence == '#':
+ self.auto = 1
+ listitem, blank_finish = self.list_item(match.end())
+ self.parent += listitem
+ self.blank_finish = blank_finish
+ self.lastordinal = ordinal
+ return [], next_state, []
+
+
+class FieldList(SpecializedBody):
+
+ """Second and subsequent field_list fields."""
+
+ def field_marker(self, match, context, next_state):
+ """Field list field."""
+ field, blank_finish = self.field(match)
+ self.parent += field
+ self.blank_finish = blank_finish
+ return [], next_state, []
+
+
+class OptionList(SpecializedBody):
+
+ """Second and subsequent option_list option_list_items."""
+
+ def option_marker(self, match, context, next_state):
+ """Option list item."""
+ try:
+ option_list_item, blank_finish = self.option_list_item(match)
+ except MarkupError:
+ self.invalid_input()
+ self.parent += option_list_item
+ self.blank_finish = blank_finish
+ return [], next_state, []
+
+
+class RFC2822List(SpecializedBody, RFC2822Body):
+
+ """Second and subsequent RFC2822-style field_list fields."""
+
+ patterns = RFC2822Body.patterns
+ initial_transitions = RFC2822Body.initial_transitions
+
+ def rfc2822(self, match, context, next_state):
+ """RFC2822-style field list item."""
+ field, blank_finish = self.rfc2822_field(match)
+ self.parent += field
+ self.blank_finish = blank_finish
+ return [], 'RFC2822List', []
+
+ blank = SpecializedBody.invalid_input
+
+
+class ExtensionOptions(FieldList):
+
+ """
+ Parse field_list fields for extension options.
+
+ No nested parsing is done (including inline markup parsing).
+ """
+
+ def parse_field_body(self, indented, offset, node):
+ """Override `Body.parse_field_body` for simpler parsing."""
+ lines = []
+ for line in list(indented) + ['']:
+ if line.strip():
+ lines.append(line)
+ elif lines:
+ text = '\n'.join(lines)
+ node += nodes.paragraph(text, text)
+ lines = []
+
+
+class LineBlock(SpecializedBody):
+
+ """Second and subsequent lines of a line_block."""
+
+ blank = SpecializedBody.invalid_input
+
+ def line_block(self, match, context, next_state):
+ """New line of line block."""
+ lineno = self.state_machine.abs_line_number()
+ line, messages, blank_finish = self.line_block_line(match, lineno)
+ self.parent += line
+ self.parent.parent += messages
+ self.blank_finish = blank_finish
+ return [], next_state, []
+
+
+class Explicit(SpecializedBody):
+
+ """Second and subsequent explicit markup construct."""
+
+ def explicit_markup(self, match, context, next_state):
+ """Footnotes, hyperlink targets, directives, comments."""
+ nodelist, blank_finish = self.explicit_construct(match)
+ self.parent += nodelist
+ self.blank_finish = blank_finish
+ return [], next_state, []
+
+ def anonymous(self, match, context, next_state):
+ """Anonymous hyperlink targets."""
+ nodelist, blank_finish = self.anonymous_target(match)
+ self.parent += nodelist
+ self.blank_finish = blank_finish
+ return [], next_state, []
+
+ blank = SpecializedBody.invalid_input
+
+
+class SubstitutionDef(Body):
+
+ """
+ Parser for the contents of a substitution_definition element.
+ """
+
+ patterns = {
+ 'embedded_directive': re.compile(r'(%s)::( +|$)'
+ % Inliner.simplename, re.UNICODE),
+ 'text': r''}
+ initial_transitions = ['embedded_directive', 'text']
+
+ def embedded_directive(self, match, context, next_state):
+ nodelist, blank_finish = self.directive(match,
+ alt=self.parent['names'][0])
+ self.parent += nodelist
+ if not self.state_machine.at_eof():
+ self.blank_finish = blank_finish
+ raise EOFError
+
+ def text(self, match, context, next_state):
+ if not self.state_machine.at_eof():
+ self.blank_finish = self.state_machine.is_next_line_blank()
+ raise EOFError
+
+
+class Text(RSTState):
+
+ """
+ Classifier of second line of a text block.
+
+ Could be a paragraph, a definition list item, or a title.
+ """
+
+ patterns = {'underline': Body.patterns['line'],
+ 'text': r''}
+ initial_transitions = [('underline', 'Body'), ('text', 'Body')]
+
+ def blank(self, match, context, next_state):
+ """End of paragraph."""
+ # NOTE: self.paragraph returns [ node, system_message(s) ], literalnext
+ paragraph, literalnext = self.paragraph(
+ context, self.state_machine.abs_line_number() - 1)
+ self.parent += paragraph
+ if literalnext:
+ self.parent += self.literal_block()
+ return [], 'Body', []
+
+ def eof(self, context):
+ if context:
+ self.blank(None, context, None)
+ return []
+
+ def indent(self, match, context, next_state):
+ """Definition list item."""
+ definitionlist = nodes.definition_list()
+ definitionlistitem, blank_finish = self.definition_list_item(context)
+ definitionlist += definitionlistitem
+ self.parent += definitionlist
+ offset = self.state_machine.line_offset + 1 # next line
+ newline_offset, blank_finish = self.nested_list_parse(
+ self.state_machine.input_lines[offset:],
+ input_offset=self.state_machine.abs_line_offset() + 1,
+ node=definitionlist, initial_state='DefinitionList',
+ blank_finish=blank_finish, blank_finish_state='Definition')
+ self.goto_line(newline_offset)
+ if not blank_finish:
+ self.parent += self.unindent_warning('Definition list')
+ return [], 'Body', []
+
+ def underline(self, match, context, next_state):
+ """Section title."""
+ lineno = self.state_machine.abs_line_number()
+ title = context[0].rstrip()
+ underline = match.string.rstrip()
+ source = title + '\n' + underline
+ messages = []
+ if column_width(title) > len(underline):
+ if len(underline) < 4:
+ if self.state_machine.match_titles:
+ msg = self.reporter.info(
+ 'Possible title underline, too short for the title.\n'
+ "Treating it as ordinary text because it's so short.",
+ line=lineno)
+ self.parent += msg
+ raise statemachine.TransitionCorrection('text')
+ else:
+ blocktext = context[0] + '\n' + self.state_machine.line
+ msg = self.reporter.warning('Title underline too short.',
+ nodes.literal_block(blocktext, blocktext), line=lineno)
+ messages.append(msg)
+ if not self.state_machine.match_titles:
+ blocktext = context[0] + '\n' + self.state_machine.line
+ # We need get_source_and_line() here to report correctly
+ src, srcline = self.state_machine.get_source_and_line()
+ # TODO: why is abs_line_number() == srcline+1
+ # if the error is in a table (try with test_tables.py)?
+ # print("get_source_and_line", srcline)
+ # print("abs_line_number", self.state_machine.abs_line_number())
+ msg = self.reporter.severe('Unexpected section title.',
+ nodes.literal_block(blocktext, blocktext),
+ source=src, line=srcline)
+ self.parent += messages
+ self.parent += msg
+ return [], next_state, []
+ style = underline[0]
+ context[:] = []
+ self.section(title, source, style, lineno - 1, messages)
+ return [], next_state, []
+
+ def text(self, match, context, next_state):
+ """Paragraph."""
+ startline = self.state_machine.abs_line_number() - 1
+ msg = None
+ try:
+ block = self.state_machine.get_text_block(flush_left=True)
+ except statemachine.UnexpectedIndentationError as err:
+ block, src, srcline = err.args
+ msg = self.reporter.error('Unexpected indentation.',
+ source=src, line=srcline)
+ lines = context + list(block)
+ paragraph, literalnext = self.paragraph(lines, startline)
+ self.parent += paragraph
+ self.parent += msg
+ if literalnext:
+ try:
+ self.state_machine.next_line()
+ except EOFError:
+ pass
+ self.parent += self.literal_block()
+ return [], next_state, []
+
+ def literal_block(self):
+ """Return a list of nodes."""
+ indented, indent, offset, blank_finish = \
+ self.state_machine.get_indented()
+ while indented and not indented[-1].strip():
+ indented.trim_end()
+ if not indented:
+ return self.quoted_literal_block()
+ data = '\n'.join(indented)
+ literal_block = nodes.literal_block(data, data)
+ (literal_block.source,
+ literal_block.line) = self.state_machine.get_source_and_line(offset+1)
+ nodelist = [literal_block]
+ if not blank_finish:
+ nodelist.append(self.unindent_warning('Literal block'))
+ return nodelist
+
+ def quoted_literal_block(self):
+ abs_line_offset = self.state_machine.abs_line_offset()
+ offset = self.state_machine.line_offset
+ parent_node = nodes.Element()
+ new_abs_offset = self.nested_parse(
+ self.state_machine.input_lines[offset:],
+ input_offset=abs_line_offset, node=parent_node, match_titles=False,
+ state_machine_kwargs={'state_classes': (QuotedLiteralBlock,),
+ 'initial_state': 'QuotedLiteralBlock'})
+ self.goto_line(new_abs_offset)
+ return parent_node.children
+
+ def definition_list_item(self, termline):
+ indented, indent, line_offset, blank_finish = \
+ self.state_machine.get_indented()
+ itemnode = nodes.definition_list_item(
+ '\n'.join(termline + list(indented)))
+ lineno = self.state_machine.abs_line_number() - 1
+ (itemnode.source,
+ itemnode.line) = self.state_machine.get_source_and_line(lineno)
+ termlist, messages = self.term(termline, lineno)
+ itemnode += termlist
+ definition = nodes.definition('', *messages)
+ itemnode += definition
+ if termline[0][-2:] == '::':
+ definition += self.reporter.info(
+ 'Blank line missing before literal block (after the "::")? '
+ 'Interpreted as a definition list item.',
+ line=lineno+1)
+ self.nested_parse(indented, input_offset=line_offset, node=definition)
+ return itemnode, blank_finish
+
+ classifier_delimiter = re.compile(' +: +')
+
+ def term(self, lines, lineno):
+ """Return a definition_list's term and optional classifiers."""
+ assert len(lines) == 1
+ text_nodes, messages = self.inline_text(lines[0], lineno)
+ term_node = nodes.term(lines[0])
+ (term_node.source,
+ term_node.line) = self.state_machine.get_source_and_line(lineno)
+ node_list = [term_node]
+ for i in range(len(text_nodes)):
+ node = text_nodes[i]
+ if isinstance(node, nodes.Text):
+ parts = self.classifier_delimiter.split(node)
+ if len(parts) == 1:
+ node_list[-1] += node
+ else:
+ text = parts[0].rstrip()
+ textnode = nodes.Text(text)
+ node_list[-1] += textnode
+ for part in parts[1:]:
+ node_list.append(
+ nodes.classifier(unescape(part, True), part))
+ else:
+ node_list[-1] += node
+ return node_list, messages
+
+
+class SpecializedText(Text):
+
+ """
+ Superclass for second and subsequent lines of Text-variants.
+
+ All transition methods are disabled. Override individual methods in
+ subclasses to re-enable.
+ """
+
+ def eof(self, context):
+ """Incomplete construct."""
+ return []
+
+ def invalid_input(self, match=None, context=None, next_state=None):
+ """Not a compound element member. Abort this state machine."""
+ raise EOFError
+
+ blank = invalid_input
+ indent = invalid_input
+ underline = invalid_input
+ text = invalid_input
+
+
+class Definition(SpecializedText):
+
+ """Second line of potential definition_list_item."""
+
+ def eof(self, context):
+ """Not a definition."""
+ self.state_machine.previous_line(2) # so parent SM can reassess
+ return []
+
+ def indent(self, match, context, next_state):
+ """Definition list item."""
+ itemnode, blank_finish = self.definition_list_item(context)
+ self.parent += itemnode
+ self.blank_finish = blank_finish
+ return [], 'DefinitionList', []
+
+
+class Line(SpecializedText):
+
+ """
+ Second line of over- & underlined section title or transition marker.
+ """
+
+ eofcheck = 1 # @@@ ???
+ """Set to 0 while parsing sections, so that we don't catch the EOF."""
+
+ def eof(self, context):
+ """Transition marker at end of section or document."""
+ marker = context[0].strip()
+ if self.memo.section_bubble_up_kludge:
+ self.memo.section_bubble_up_kludge = False
+ elif len(marker) < 4:
+ self.state_correction(context)
+ if self.eofcheck: # ignore EOFError with sections
+ lineno = self.state_machine.abs_line_number() - 1
+ transition = nodes.transition(rawsource=context[0])
+ transition.line = lineno
+ self.parent += transition
+ self.eofcheck = 1
+ return []
+
+ def blank(self, match, context, next_state):
+ """Transition marker."""
+ src, srcline = self.state_machine.get_source_and_line()
+ marker = context[0].strip()
+ if len(marker) < 4:
+ self.state_correction(context)
+ transition = nodes.transition(rawsource=marker)
+ transition.source = src
+ transition.line = srcline - 1
+ self.parent += transition
+ return [], 'Body', []
+
+ def text(self, match, context, next_state):
+ """Potential over- & underlined title."""
+ lineno = self.state_machine.abs_line_number() - 1
+ overline = context[0]
+ title = match.string
+ underline = ''
+ try:
+ underline = self.state_machine.next_line()
+ except EOFError:
+ blocktext = overline + '\n' + title
+ if len(overline.rstrip()) < 4:
+ self.short_overline(context, blocktext, lineno, 2)
+ else:
+ msg = self.reporter.severe(
+ 'Incomplete section title.',
+ nodes.literal_block(blocktext, blocktext),
+ line=lineno)
+ self.parent += msg
+ return [], 'Body', []
+ source = '%s\n%s\n%s' % (overline, title, underline)
+ overline = overline.rstrip()
+ underline = underline.rstrip()
+ if not self.transitions['underline'][0].match(underline):
+ blocktext = overline + '\n' + title + '\n' + underline
+ if len(overline.rstrip()) < 4:
+ self.short_overline(context, blocktext, lineno, 2)
+ else:
+ msg = self.reporter.severe(
+ 'Missing matching underline for section title overline.',
+ nodes.literal_block(source, source),
+ line=lineno)
+ self.parent += msg
+ return [], 'Body', []
+ elif overline != underline:
+ blocktext = overline + '\n' + title + '\n' + underline
+ if len(overline.rstrip()) < 4:
+ self.short_overline(context, blocktext, lineno, 2)
+ else:
+ msg = self.reporter.severe(
+ 'Title overline & underline mismatch.',
+ nodes.literal_block(source, source),
+ line=lineno)
+ self.parent += msg
+ return [], 'Body', []
+ title = title.rstrip()
+ messages = []
+ if column_width(title) > len(overline):
+ blocktext = overline + '\n' + title + '\n' + underline
+ if len(overline.rstrip()) < 4:
+ self.short_overline(context, blocktext, lineno, 2)
+ else:
+ msg = self.reporter.warning(
+ 'Title overline too short.',
+ nodes.literal_block(source, source),
+ line=lineno)
+ messages.append(msg)
+ style = (overline[0], underline[0])
+ self.eofcheck = 0 # @@@ not sure this is correct
+ self.section(title.lstrip(), source, style, lineno + 1, messages)
+ self.eofcheck = 1
+ return [], 'Body', []
+
+ indent = text # indented title
+
+ def underline(self, match, context, next_state):
+ overline = context[0]
+ blocktext = overline + '\n' + self.state_machine.line
+ lineno = self.state_machine.abs_line_number() - 1
+ if len(overline.rstrip()) < 4:
+ self.short_overline(context, blocktext, lineno, 1)
+ msg = self.reporter.error(
+ 'Invalid section title or transition marker.',
+ nodes.literal_block(blocktext, blocktext),
+ line=lineno)
+ self.parent += msg
+ return [], 'Body', []
+
+ def short_overline(self, context, blocktext, lineno, lines=1):
+ msg = self.reporter.info(
+ 'Possible incomplete section title.\nTreating the overline as '
+ "ordinary text because it's so short.",
+ line=lineno)
+ self.parent += msg
+ self.state_correction(context, lines)
+
+ def state_correction(self, context, lines=1):
+ self.state_machine.previous_line(lines)
+ context[:] = []
+ raise statemachine.StateCorrection('Body', 'text')
+
+
+class QuotedLiteralBlock(RSTState):
+
+ """
+ Nested parse handler for quoted (unindented) literal blocks.
+
+ Special-purpose. Not for inclusion in `state_classes`.
+ """
+
+ patterns = {'initial_quoted': r'(%(nonalphanum7bit)s)' % Body.pats,
+ 'text': r''}
+ initial_transitions = ('initial_quoted', 'text')
+
+ def __init__(self, state_machine, debug=False):
+ RSTState.__init__(self, state_machine, debug)
+ self.messages = []
+ self.initial_lineno = None
+
+ def blank(self, match, context, next_state):
+ if context:
+ raise EOFError
+ else:
+ return context, next_state, []
+
+ def eof(self, context):
+ if context:
+ src, srcline = self.state_machine.get_source_and_line(
+ self.initial_lineno)
+ text = '\n'.join(context)
+ literal_block = nodes.literal_block(text, text)
+ literal_block.source = src
+ literal_block.line = srcline
+ self.parent += literal_block
+ else:
+ self.parent += self.reporter.warning(
+ 'Literal block expected; none found.',
+ line=self.state_machine.abs_line_number())
+ # src not available, because statemachine.input_lines is empty
+ self.state_machine.previous_line()
+ self.parent += self.messages
+ return []
+
+ def indent(self, match, context, next_state):
+ assert context, ('QuotedLiteralBlock.indent: context should not '
+ 'be empty!')
+ self.messages.append(
+ self.reporter.error('Unexpected indentation.',
+ line=self.state_machine.abs_line_number()))
+ self.state_machine.previous_line()
+ raise EOFError
+
+ def initial_quoted(self, match, context, next_state):
+ """Match arbitrary quote character on the first line only."""
+ self.remove_transition('initial_quoted')
+ quote = match.string[0]
+ pattern = re.compile(re.escape(quote), re.UNICODE)
+ # New transition matches consistent quotes only:
+ self.add_transition('quoted',
+ (pattern, self.quoted, self.__class__.__name__))
+ self.initial_lineno = self.state_machine.abs_line_number()
+ return [match.string], next_state, []
+
+ def quoted(self, match, context, next_state):
+ """Match consistent quotes on subsequent lines."""
+ context.append(match.string)
+ return context, next_state, []
+
+ def text(self, match, context, next_state):
+ if context:
+ self.messages.append(
+ self.reporter.error('Inconsistent literal block quoting.',
+ line=self.state_machine.abs_line_number()))
+ self.state_machine.previous_line()
+ raise EOFError
+
+
+state_classes = (Body, BulletList, DefinitionList, EnumeratedList, FieldList,
+ OptionList, LineBlock, ExtensionOptions, Explicit, Text,
+ Definition, Line, SubstitutionDef, RFC2822Body, RFC2822List)
+"""Standard set of State classes used to start `RSTStateMachine`."""
--- /dev/null
+# $Id: tableparser.py 8373 2019-08-27 12:11:30Z milde $
+# Author: David Goodger <goodger@python.org>
+# Copyright: This module has been placed in the public domain.
+
+"""
+This module defines table parser classes,which parse plaintext-graphic tables
+and produce a well-formed data structure suitable for building a CALS table.
+
+:Classes:
+ - `GridTableParser`: Parse fully-formed tables represented with a grid.
+ - `SimpleTableParser`: Parse simple tables, delimited by top & bottom
+ borders.
+
+:Exception class: `TableMarkupError`
+
+:Function:
+ `update_dict_of_lists()`: Merge two dictionaries containing list values.
+"""
+
+__docformat__ = 'reStructuredText'
+
+
+import re
+import sys
+from docutils import DataError
+from docutils.utils import strip_combining_chars
+
+
+class TableMarkupError(DataError):
+
+ """
+ Raise if there is any problem with table markup.
+
+ The keyword argument `offset` denotes the offset of the problem
+ from the table's start line.
+ """
+
+ def __init__(self, *args, **kwargs):
+ self.offset = kwargs.pop('offset', 0)
+ DataError.__init__(self, *args)
+
+
+class TableParser(object):
+
+ """
+ Abstract superclass for the common parts of the syntax-specific parsers.
+ """
+
+ head_body_separator_pat = None
+ """Matches the row separator between head rows and body rows."""
+
+ double_width_pad_char = '\x00'
+ """Padding character for East Asian double-width text."""
+
+ def parse(self, block):
+ """
+ Analyze the text `block` and return a table data structure.
+
+ Given a plaintext-graphic table in `block` (list of lines of text; no
+ whitespace padding), parse the table, construct and return the data
+ necessary to construct a CALS table or equivalent.
+
+ Raise `TableMarkupError` if there is any problem with the markup.
+ """
+ self.setup(block)
+ self.find_head_body_sep()
+ self.parse_table()
+ structure = self.structure_from_cells()
+ return structure
+
+ def find_head_body_sep(self):
+ """Look for a head/body row separator line; store the line index."""
+ for i in range(len(self.block)):
+ line = self.block[i]
+ if self.head_body_separator_pat.match(line):
+ if self.head_body_sep:
+ raise TableMarkupError(
+ 'Multiple head/body row separators '
+ '(table lines %s and %s); only one allowed.'
+ % (self.head_body_sep+1, i+1), offset=i)
+ else:
+ self.head_body_sep = i
+ self.block[i] = line.replace('=', '-')
+ if self.head_body_sep == 0 or self.head_body_sep == (len(self.block)
+ - 1):
+ raise TableMarkupError('The head/body row separator may not be '
+ 'the first or last line of the table.',
+ offset=i)
+
+
+class GridTableParser(TableParser):
+
+ """
+ Parse a grid table using `parse()`.
+
+ Here's an example of a grid table::
+
+ +------------------------+------------+----------+----------+
+ | Header row, column 1 | Header 2 | Header 3 | Header 4 |
+ +========================+============+==========+==========+
+ | body row 1, column 1 | column 2 | column 3 | column 4 |
+ +------------------------+------------+----------+----------+
+ | body row 2 | Cells may span columns. |
+ +------------------------+------------+---------------------+
+ | body row 3 | Cells may | - Table cells |
+ +------------------------+ span rows. | - contain |
+ | body row 4 | | - body elements. |
+ +------------------------+------------+---------------------+
+
+ Intersections use '+', row separators use '-' (except for one optional
+ head/body row separator, which uses '='), and column separators use '|'.
+
+ Passing the above table to the `parse()` method will result in the
+ following data structure::
+
+ ([24, 12, 10, 10],
+ [[(0, 0, 1, ['Header row, column 1']),
+ (0, 0, 1, ['Header 2']),
+ (0, 0, 1, ['Header 3']),
+ (0, 0, 1, ['Header 4'])]],
+ [[(0, 0, 3, ['body row 1, column 1']),
+ (0, 0, 3, ['column 2']),
+ (0, 0, 3, ['column 3']),
+ (0, 0, 3, ['column 4'])],
+ [(0, 0, 5, ['body row 2']),
+ (0, 2, 5, ['Cells may span columns.']),
+ None,
+ None],
+ [(0, 0, 7, ['body row 3']),
+ (1, 0, 7, ['Cells may', 'span rows.', '']),
+ (1, 1, 7, ['- Table cells', '- contain', '- body elements.']),
+ None],
+ [(0, 0, 9, ['body row 4']), None, None, None]])
+
+ The first item is a list containing column widths (colspecs). The second
+ item is a list of head rows, and the third is a list of body rows. Each
+ row contains a list of cells. Each cell is either None (for a cell unused
+ because of another cell's span), or a tuple. A cell tuple contains four
+ items: the number of extra rows used by the cell in a vertical span
+ (morerows); the number of extra columns used by the cell in a horizontal
+ span (morecols); the line offset of the first line of the cell contents;
+ and the cell contents, a list of lines of text.
+ """
+
+ head_body_separator_pat = re.compile(r'\+=[=+]+=\+ *$')
+
+ def setup(self, block):
+ self.block = block[:] # make a copy; it may be modified
+ self.block.disconnect() # don't propagate changes to parent
+ self.bottom = len(block) - 1
+ self.right = len(block[0]) - 1
+ self.head_body_sep = None
+ self.done = [-1] * len(block[0])
+ self.cells = []
+ self.rowseps = {0: [0]}
+ self.colseps = {0: [0]}
+
+ def parse_table(self):
+ """
+ Start with a queue of upper-left corners, containing the upper-left
+ corner of the table itself. Trace out one rectangular cell, remember
+ it, and add its upper-right and lower-left corners to the queue of
+ potential upper-left corners of further cells. Process the queue in
+ top-to-bottom order, keeping track of how much of each text column has
+ been seen.
+
+ We'll end up knowing all the row and column boundaries, cell positions
+ and their dimensions.
+ """
+ corners = [(0, 0)]
+ while corners:
+ top, left = corners.pop(0)
+ if top == self.bottom or left == self.right \
+ or top <= self.done[left]:
+ continue
+ result = self.scan_cell(top, left)
+ if not result:
+ continue
+ bottom, right, rowseps, colseps = result
+ update_dict_of_lists(self.rowseps, rowseps)
+ update_dict_of_lists(self.colseps, colseps)
+ self.mark_done(top, left, bottom, right)
+ cellblock = self.block.get_2D_block(top + 1, left + 1,
+ bottom, right)
+ cellblock.disconnect() # lines in cell can't sync with parent
+ cellblock.replace(self.double_width_pad_char, '')
+ self.cells.append((top, left, bottom, right, cellblock))
+ corners.extend([(top, right), (bottom, left)])
+ corners.sort()
+ if not self.check_parse_complete():
+ raise TableMarkupError('Malformed table; parse incomplete.')
+
+ def mark_done(self, top, left, bottom, right):
+ """For keeping track of how much of each text column has been seen."""
+ before = top - 1
+ after = bottom - 1
+ for col in range(left, right):
+ assert self.done[col] == before
+ self.done[col] = after
+
+ def check_parse_complete(self):
+ """Each text column should have been completely seen."""
+ last = self.bottom - 1
+ for col in range(self.right):
+ if self.done[col] != last:
+ return False
+ return True
+
+ def scan_cell(self, top, left):
+ """Starting at the top-left corner, start tracing out a cell."""
+ assert self.block[top][left] == '+'
+ result = self.scan_right(top, left)
+ return result
+
+ def scan_right(self, top, left):
+ """
+ Look for the top-right corner of the cell, and make note of all column
+ boundaries ('+').
+ """
+ colseps = {}
+ line = self.block[top]
+ for i in range(left + 1, self.right + 1):
+ if line[i] == '+':
+ colseps[i] = [top]
+ result = self.scan_down(top, left, i)
+ if result:
+ bottom, rowseps, newcolseps = result
+ update_dict_of_lists(colseps, newcolseps)
+ return bottom, i, rowseps, colseps
+ elif line[i] != '-':
+ return None
+ return None
+
+ def scan_down(self, top, left, right):
+ """
+ Look for the bottom-right corner of the cell, making note of all row
+ boundaries.
+ """
+ rowseps = {}
+ for i in range(top + 1, self.bottom + 1):
+ if self.block[i][right] == '+':
+ rowseps[i] = [right]
+ result = self.scan_left(top, left, i, right)
+ if result:
+ newrowseps, colseps = result
+ update_dict_of_lists(rowseps, newrowseps)
+ return i, rowseps, colseps
+ elif self.block[i][right] != '|':
+ return None
+ return None
+
+ def scan_left(self, top, left, bottom, right):
+ """
+ Noting column boundaries, look for the bottom-left corner of the cell.
+ It must line up with the starting point.
+ """
+ colseps = {}
+ line = self.block[bottom]
+ for i in range(right - 1, left, -1):
+ if line[i] == '+':
+ colseps[i] = [bottom]
+ elif line[i] != '-':
+ return None
+ if line[left] != '+':
+ return None
+ result = self.scan_up(top, left, bottom, right)
+ if result is not None:
+ rowseps = result
+ return rowseps, colseps
+ return None
+
+ def scan_up(self, top, left, bottom, right):
+ """
+ Noting row boundaries, see if we can return to the starting point.
+ """
+ rowseps = {}
+ for i in range(bottom - 1, top, -1):
+ if self.block[i][left] == '+':
+ rowseps[i] = [left]
+ elif self.block[i][left] != '|':
+ return None
+ return rowseps
+
+ def structure_from_cells(self):
+ """
+ From the data collected by `scan_cell()`, convert to the final data
+ structure.
+ """
+ rowseps = sorted(self.rowseps.keys()) # list of row boundaries
+ rowindex = {}
+ for i in range(len(rowseps)):
+ rowindex[rowseps[i]] = i # row boundary -> row number mapping
+ colseps = sorted(self.colseps.keys()) # list of column boundaries
+ colindex = {}
+ for i in range(len(colseps)):
+ colindex[colseps[i]] = i # column boundary -> col number map
+ colspecs = [(colseps[i] - colseps[i - 1] - 1)
+ for i in range(1, len(colseps))] # list of column widths
+ # prepare an empty table with the correct number of rows & columns
+ onerow = [None for i in range(len(colseps) - 1)]
+ rows = [onerow[:] for i in range(len(rowseps) - 1)]
+ # keep track of # of cells remaining; should reduce to zero
+ remaining = (len(rowseps) - 1) * (len(colseps) - 1)
+ for top, left, bottom, right, block in self.cells:
+ rownum = rowindex[top]
+ colnum = colindex[left]
+ assert rows[rownum][colnum] is None, (
+ 'Cell (row %s, column %s) already used.'
+ % (rownum + 1, colnum + 1))
+ morerows = rowindex[bottom] - rownum - 1
+ morecols = colindex[right] - colnum - 1
+ remaining -= (morerows + 1) * (morecols + 1)
+ # write the cell into the table
+ rows[rownum][colnum] = (morerows, morecols, top + 1, block)
+ assert remaining == 0, 'Unused cells remaining.'
+ if self.head_body_sep: # separate head rows from body rows
+ numheadrows = rowindex[self.head_body_sep]
+ headrows = rows[:numheadrows]
+ bodyrows = rows[numheadrows:]
+ else:
+ headrows = []
+ bodyrows = rows
+ return (colspecs, headrows, bodyrows)
+
+
+class SimpleTableParser(TableParser):
+
+ """
+ Parse a simple table using `parse()`.
+
+ Here's an example of a simple table::
+
+ ===== =====
+ col 1 col 2
+ ===== =====
+ 1 Second column of row 1.
+ 2 Second column of row 2.
+ Second line of paragraph.
+ 3 - Second column of row 3.
+
+ - Second item in bullet
+ list (row 3, column 2).
+ 4 is a span
+ ------------
+ 5
+ ===== =====
+
+ Top and bottom borders use '=', column span underlines use '-', column
+ separation is indicated with spaces.
+
+ Passing the above table to the `parse()` method will result in the
+ following data structure, whose interpretation is the same as for
+ `GridTableParser`::
+
+ ([5, 25],
+ [[(0, 0, 1, ['col 1']),
+ (0, 0, 1, ['col 2'])]],
+ [[(0, 0, 3, ['1']),
+ (0, 0, 3, ['Second column of row 1.'])],
+ [(0, 0, 4, ['2']),
+ (0, 0, 4, ['Second column of row 2.',
+ 'Second line of paragraph.'])],
+ [(0, 0, 6, ['3']),
+ (0, 0, 6, ['- Second column of row 3.',
+ '',
+ '- Second item in bullet',
+ ' list (row 3, column 2).'])],
+ [(0, 1, 10, ['4 is a span'])],
+ [(0, 0, 12, ['5']),
+ (0, 0, 12, [''])]])
+ """
+
+ head_body_separator_pat = re.compile('=[ =]*$')
+ span_pat = re.compile('-[ -]*$')
+
+ def setup(self, block):
+ self.block = block[:] # make a copy; it will be modified
+ self.block.disconnect() # don't propagate changes to parent
+ # Convert top & bottom borders to column span underlines:
+ self.block[0] = self.block[0].replace('=', '-')
+ self.block[-1] = self.block[-1].replace('=', '-')
+ self.head_body_sep = None
+ self.columns = []
+ self.border_end = None
+ self.table = []
+ self.done = [-1] * len(block[0])
+ self.rowseps = {0: [0]}
+ self.colseps = {0: [0]}
+
+ def parse_table(self):
+ """
+ First determine the column boundaries from the top border, then
+ process rows. Each row may consist of multiple lines; accumulate
+ lines until a row is complete. Call `self.parse_row` to finish the
+ job.
+ """
+ # Top border must fully describe all table columns.
+ self.columns = self.parse_columns(self.block[0], 0)
+ self.border_end = self.columns[-1][1]
+ firststart, firstend = self.columns[0]
+ offset = 1 # skip top border
+ start = 1
+ text_found = None
+ while offset < len(self.block):
+ line = self.block[offset]
+ if self.span_pat.match(line):
+ # Column span underline or border; row is complete.
+ self.parse_row(self.block[start:offset], start,
+ (line.rstrip(), offset))
+ start = offset + 1
+ text_found = None
+ elif line[firststart:firstend].strip():
+ # First column not blank, therefore it's a new row.
+ if text_found and offset != start:
+ self.parse_row(self.block[start:offset], start)
+ start = offset
+ text_found = 1
+ elif not text_found:
+ start = offset + 1
+ offset += 1
+
+ def parse_columns(self, line, offset):
+ """
+ Given a column span underline, return a list of (begin, end) pairs.
+ """
+ cols = []
+ end = 0
+ while True:
+ begin = line.find('-', end)
+ end = line.find(' ', begin)
+ if begin < 0:
+ break
+ if end < 0:
+ end = len(line)
+ cols.append((begin, end))
+ if self.columns:
+ if cols[-1][1] != self.border_end:
+ raise TableMarkupError('Column span incomplete in table '
+ 'line %s.' % (offset+1),
+ offset=offset)
+ # Allow for an unbounded rightmost column:
+ cols[-1] = (cols[-1][0], self.columns[-1][1])
+ return cols
+
+ def init_row(self, colspec, offset):
+ i = 0
+ cells = []
+ for start, end in colspec:
+ morecols = 0
+ try:
+ assert start == self.columns[i][0]
+ while end != self.columns[i][1]:
+ i += 1
+ morecols += 1
+ except (AssertionError, IndexError):
+ raise TableMarkupError('Column span alignment problem '
+ 'in table line %s.' % (offset+2),
+ offset=offset+1)
+ cells.append([0, morecols, offset, []])
+ i += 1
+ return cells
+
+ def parse_row(self, lines, start, spanline=None):
+ """
+ Given the text `lines` of a row, parse it and append to `self.table`.
+
+ The row is parsed according to the current column spec (either
+ `spanline` if provided or `self.columns`). For each column, extract
+ text from each line, and check for text in column margins. Finally,
+ adjust for insignificant whitespace.
+ """
+ if not (lines or spanline):
+ # No new row, just blank lines.
+ return
+ if spanline:
+ columns = self.parse_columns(*spanline)
+ span_offset = spanline[1]
+ else:
+ columns = self.columns[:]
+ span_offset = start
+ self.check_columns(lines, start, columns)
+ row = self.init_row(columns, start)
+ for i in range(len(columns)):
+ start, end = columns[i]
+ cellblock = lines.get_2D_block(0, start, len(lines), end)
+ cellblock.disconnect() # lines in cell can't sync with parent
+ cellblock.replace(self.double_width_pad_char, '')
+ row[i][3] = cellblock
+ self.table.append(row)
+
+ def check_columns(self, lines, first_line, columns):
+ """
+ Check for text in column margins and text overflow in the last column.
+ Raise TableMarkupError if anything but whitespace is in column margins.
+ Adjust the end value for the last column if there is text overflow.
+ """
+ # "Infinite" value for a dummy last column's beginning, used to
+ # check for text overflow:
+ columns.append((sys.maxsize, None))
+ lastcol = len(columns) - 2
+ # combining characters do not contribute to the column width
+ lines = [strip_combining_chars(line) for line in lines]
+
+ for i in range(len(columns) - 1):
+ start, end = columns[i]
+ nextstart = columns[i+1][0]
+ offset = 0
+ for line in lines:
+ if i == lastcol and line[end:].strip():
+ text = line[start:].rstrip()
+ new_end = start + len(text)
+ main_start, main_end = self.columns[-1]
+ columns[i] = (start, max(main_end, new_end))
+ if new_end > main_end:
+ self.columns[-1] = (main_start, new_end)
+ elif line[end:nextstart].strip():
+ raise TableMarkupError('Text in column margin '
+ 'in table line %s.' % (first_line+offset+1),
+ offset=first_line+offset)
+ offset += 1
+ columns.pop()
+
+ def structure_from_cells(self):
+ colspecs = [end - start for start, end in self.columns]
+ first_body_row = 0
+ if self.head_body_sep:
+ for i in range(len(self.table)):
+ if self.table[i][0][2] > self.head_body_sep:
+ first_body_row = i
+ break
+ return (colspecs, self.table[:first_body_row],
+ self.table[first_body_row:])
+
+
+def update_dict_of_lists(master, newdata):
+ """
+ Extend the list values of `master` with those from `newdata`.
+
+ Both parameters must be dictionaries containing list values.
+ """
+ for key, values in newdata.items():
+ master.setdefault(key, []).extend(values)
--- /dev/null
+# $Id: __init__.py 8239 2018-11-21 21:46:00Z milde $
+# Authors: David Goodger <goodger@python.org>; Ueli Schlaepfer
+# Copyright: This module has been placed in the public domain.
+
+"""
+This package contains Docutils Reader modules.
+"""
+
+__docformat__ = 'reStructuredText'
+
+import sys
+
+from docutils import utils, parsers, Component
+from docutils.transforms import universal
+
+
+class Reader(Component):
+
+ """
+ Abstract base class for docutils Readers.
+
+ Each reader module or package must export a subclass also called 'Reader'.
+
+ The two steps of a Reader's responsibility are to read data from the
+ source Input object and parse the data with the Parser object.
+ Call `read()` to process a document.
+ """
+
+ component_type = 'reader'
+ config_section = 'readers'
+
+ def get_transforms(self):
+ return Component.get_transforms(self) + [
+ universal.Decorations,
+ universal.ExposeInternals,
+ universal.StripComments,]
+
+ def __init__(self, parser=None, parser_name=None):
+ """
+ Initialize the Reader instance.
+
+ Several instance attributes are defined with dummy initial values.
+ Subclasses may use these attributes as they wish.
+ """
+
+ self.parser = parser
+ """A `parsers.Parser` instance shared by all doctrees. May be left
+ unspecified if the document source determines the parser."""
+
+ if parser is None and parser_name:
+ self.set_parser(parser_name)
+
+ self.source = None
+ """`docutils.io` IO object, source of input data."""
+
+ self.input = None
+ """Raw text input; either a single string or, for more complex cases,
+ a collection of strings."""
+
+ def set_parser(self, parser_name):
+ """Set `self.parser` by name."""
+ parser_class = parsers.get_parser_class(parser_name)
+ self.parser = parser_class()
+
+ def read(self, source, parser, settings):
+ self.source = source
+ if not self.parser:
+ self.parser = parser
+ self.settings = settings
+ self.input = self.source.read()
+ self.parse()
+ return self.document
+
+ def parse(self):
+ """Parse `self.input` into a document tree."""
+ self.document = document = self.new_document()
+ self.parser.parse(self.input, document)
+ document.current_source = document.current_line = None
+
+ def new_document(self):
+ """Create and return a new empty document tree (root node)."""
+ document = utils.new_document(self.source.source_path, self.settings)
+ return document
+
+
+class ReReader(Reader):
+
+ """
+ A reader which rereads an existing document tree (e.g. a
+ deserializer).
+
+ Often used in conjunction with `writers.UnfilteredWriter`.
+ """
+
+ def get_transforms(self):
+ # Do not add any transforms. They have already been applied
+ # by the reader which originally created the document.
+ return Component.get_transforms(self)
+
+
+_reader_aliases = {}
+
+def get_reader_class(reader_name):
+ """Return the Reader class from the `reader_name` module."""
+ reader_name = reader_name.lower()
+ if reader_name in _reader_aliases:
+ reader_name = _reader_aliases[reader_name]
+ try:
+ module = __import__(reader_name, globals(), locals(), level=1)
+ except ImportError:
+ module = __import__(reader_name, globals(), locals(), level=0)
+ return module.Reader
--- /dev/null
+# $Id: doctree.py 4564 2006-05-21 20:44:42Z wiemann $
+# Author: Martin Blais <blais@furius.ca>
+# Copyright: This module has been placed in the public domain.
+
+"""Reader for existing document trees."""
+
+from docutils import readers, utils, transforms
+
+
+class Reader(readers.ReReader):
+
+ """
+ Adapt the Reader API for an existing document tree.
+
+ The existing document tree must be passed as the ``source`` parameter to
+ the `docutils.core.Publisher` initializer, wrapped in a
+ `docutils.io.DocTreeInput` object::
+
+ pub = docutils.core.Publisher(
+ ..., source=docutils.io.DocTreeInput(document), ...)
+
+ The original document settings are overridden; if you want to use the
+ settings of the original document, pass ``settings=document.settings`` to
+ the Publisher call above.
+ """
+
+ supported = ('doctree',)
+
+ config_section = 'doctree reader'
+ config_section_dependencies = ('readers',)
+
+ def parse(self):
+ """
+ No parsing to do; refurbish the document tree instead.
+ Overrides the inherited method.
+ """
+ self.document = self.input
+ # Create fresh Transformer object, to be populated from Writer
+ # component.
+ self.document.transformer = transforms.Transformer(self.document)
+ # Replace existing settings object with new one.
+ self.document.settings = self.settings
+ # Create fresh Reporter object because it is dependent on
+ # (new) settings.
+ self.document.reporter = utils.new_reporter(
+ self.document.get('source', ''), self.document.settings)
--- /dev/null
+# $Id: pep.py 7320 2012-01-19 22:33:02Z milde $
+# Author: David Goodger <goodger@python.org>
+# Copyright: This module has been placed in the public domain.
+
+"""
+Python Enhancement Proposal (PEP) Reader.
+"""
+
+__docformat__ = 'reStructuredText'
+
+
+from docutils.readers import standalone
+from docutils.transforms import peps, references, misc, frontmatter
+from docutils.parsers import rst
+
+
+class Reader(standalone.Reader):
+
+ supported = ('pep',)
+ """Contexts this reader supports."""
+
+ settings_spec = (
+ 'PEP Reader Option Defaults',
+ 'The --pep-references and --rfc-references options (for the '
+ 'reStructuredText parser) are on by default.',
+ ())
+
+ config_section = 'pep reader'
+ config_section_dependencies = ('readers', 'standalone reader')
+
+ def get_transforms(self):
+ transforms = standalone.Reader.get_transforms(self)
+ # We have PEP-specific frontmatter handling.
+ transforms.remove(frontmatter.DocTitle)
+ transforms.remove(frontmatter.SectionSubTitle)
+ transforms.remove(frontmatter.DocInfo)
+ transforms.extend([peps.Headers, peps.Contents, peps.TargetNotes])
+ return transforms
+
+ settings_default_overrides = {'pep_references': 1, 'rfc_references': 1}
+
+ inliner_class = rst.states.Inliner
+
+ def __init__(self, parser=None, parser_name=None):
+ """`parser` should be ``None``."""
+ if parser is None:
+ parser = rst.Parser(rfc2822=True, inliner=self.inliner_class())
+ standalone.Reader.__init__(self, parser, '')
--- /dev/null
+# $Id: standalone.py 4802 2006-11-12 18:02:17Z goodger $
+# Author: David Goodger <goodger@python.org>
+# Copyright: This module has been placed in the public domain.
+
+"""
+Standalone file Reader for the reStructuredText markup syntax.
+"""
+
+__docformat__ = 'reStructuredText'
+
+
+import sys
+from docutils import frontend, readers
+from docutils.transforms import frontmatter, references, misc
+
+
+class Reader(readers.Reader):
+
+ supported = ('standalone',)
+ """Contexts this reader supports."""
+
+ document = None
+ """A single document tree."""
+
+ settings_spec = (
+ 'Standalone Reader',
+ None,
+ (('Disable the promotion of a lone top-level section title to '
+ 'document title (and subsequent section title to document '
+ 'subtitle promotion; enabled by default).',
+ ['--no-doc-title'],
+ {'dest': 'doctitle_xform', 'action': 'store_false', 'default': 1,
+ 'validator': frontend.validate_boolean}),
+ ('Disable the bibliographic field list transform (enabled by '
+ 'default).',
+ ['--no-doc-info'],
+ {'dest': 'docinfo_xform', 'action': 'store_false', 'default': 1,
+ 'validator': frontend.validate_boolean}),
+ ('Activate the promotion of lone subsection titles to '
+ 'section subtitles (disabled by default).',
+ ['--section-subtitles'],
+ {'dest': 'sectsubtitle_xform', 'action': 'store_true', 'default': 0,
+ 'validator': frontend.validate_boolean}),
+ ('Deactivate the promotion of lone subsection titles.',
+ ['--no-section-subtitles'],
+ {'dest': 'sectsubtitle_xform', 'action': 'store_false'}),
+ ))
+
+ config_section = 'standalone reader'
+ config_section_dependencies = ('readers',)
+
+ def get_transforms(self):
+ return readers.Reader.get_transforms(self) + [
+ references.Substitutions,
+ references.PropagateTargets,
+ frontmatter.DocTitle,
+ frontmatter.SectionSubTitle,
+ frontmatter.DocInfo,
+ references.AnonymousHyperlinks,
+ references.IndirectHyperlinks,
+ references.Footnotes,
+ references.ExternalTargets,
+ references.InternalTargets,
+ references.DanglingReferences,
+ misc.Transitions,
+ ]
--- /dev/null
+ # $Id: statemachine.py 8435 2019-12-12 13:04:57Z milde $
+# Author: David Goodger <goodger@python.org>
+# Copyright: This module has been placed in the public domain.
+
+"""
+A finite state machine specialized for regular-expression-based text filters,
+this module defines the following classes:
+
+- `StateMachine`, a state machine
+- `State`, a state superclass
+- `StateMachineWS`, a whitespace-sensitive version of `StateMachine`
+- `StateWS`, a state superclass for use with `StateMachineWS`
+- `SearchStateMachine`, uses `re.search()` instead of `re.match()`
+- `SearchStateMachineWS`, uses `re.search()` instead of `re.match()`
+- `ViewList`, extends standard Python lists.
+- `StringList`, string-specific ViewList.
+
+Exception classes:
+
+- `StateMachineError`
+- `UnknownStateError`
+- `DuplicateStateError`
+- `UnknownTransitionError`
+- `DuplicateTransitionError`
+- `TransitionPatternNotFound`
+- `TransitionMethodNotFound`
+- `UnexpectedIndentationError`
+- `TransitionCorrection`: Raised to switch to another transition.
+- `StateCorrection`: Raised to switch to another state & transition.
+
+Functions:
+
+- `string2lines()`: split a multi-line string into a list of one-line strings
+
+
+How To Use This Module
+======================
+(See the individual classes, methods, and attributes for details.)
+
+1. Import it: ``import statemachine`` or ``from statemachine import ...``.
+ You will also need to ``import re``.
+
+2. Derive a subclass of `State` (or `StateWS`) for each state in your state
+ machine::
+
+ class MyState(statemachine.State):
+
+ Within the state's class definition:
+
+ a) Include a pattern for each transition, in `State.patterns`::
+
+ patterns = {'atransition': r'pattern', ...}
+
+ b) Include a list of initial transitions to be set up automatically, in
+ `State.initial_transitions`::
+
+ initial_transitions = ['atransition', ...]
+
+ c) Define a method for each transition, with the same name as the
+ transition pattern::
+
+ def atransition(self, match, context, next_state):
+ # do something
+ result = [...] # a list
+ return context, next_state, result
+ # context, next_state may be altered
+
+ Transition methods may raise an `EOFError` to cut processing short.
+
+ d) You may wish to override the `State.bof()` and/or `State.eof()` implicit
+ transition methods, which handle the beginning- and end-of-file.
+
+ e) In order to handle nested processing, you may wish to override the
+ attributes `State.nested_sm` and/or `State.nested_sm_kwargs`.
+
+ If you are using `StateWS` as a base class, in order to handle nested
+ indented blocks, you may wish to:
+
+ - override the attributes `StateWS.indent_sm`,
+ `StateWS.indent_sm_kwargs`, `StateWS.known_indent_sm`, and/or
+ `StateWS.known_indent_sm_kwargs`;
+ - override the `StateWS.blank()` method; and/or
+ - override or extend the `StateWS.indent()`, `StateWS.known_indent()`,
+ and/or `StateWS.firstknown_indent()` methods.
+
+3. Create a state machine object::
+
+ sm = StateMachine(state_classes=[MyState, ...],
+ initial_state='MyState')
+
+4. Obtain the input text, which needs to be converted into a tab-free list of
+ one-line strings. For example, to read text from a file called
+ 'inputfile'::
+
+ input_string = open('inputfile').read()
+ input_lines = statemachine.string2lines(input_string)
+
+5. Run the state machine on the input text and collect the results, a list::
+
+ results = sm.run(input_lines)
+
+6. Remove any lingering circular references::
+
+ sm.unlink()
+"""
+from __future__ import print_function
+
+__docformat__ = 'restructuredtext'
+
+import sys
+import re
+import unicodedata
+from docutils import utils
+from docutils.utils.error_reporting import ErrorOutput
+
+if sys.version_info >= (3, 0):
+ unicode = str # noqa
+
+
+class StateMachine(object):
+
+ """
+ A finite state machine for text filters using regular expressions.
+
+ The input is provided in the form of a list of one-line strings (no
+ newlines). States are subclasses of the `State` class. Transitions consist
+ of regular expression patterns and transition methods, and are defined in
+ each state.
+
+ The state machine is started with the `run()` method, which returns the
+ results of processing in a list.
+ """
+
+ def __init__(self, state_classes, initial_state, debug=False):
+ """
+ Initialize a `StateMachine` object; add state objects.
+
+ Parameters:
+
+ - `state_classes`: a list of `State` (sub)classes.
+ - `initial_state`: a string, the class name of the initial state.
+ - `debug`: a boolean; produce verbose output if true (nonzero).
+ """
+
+ self.input_lines = None
+ """`StringList` of input lines (without newlines).
+ Filled by `self.run()`."""
+
+ self.input_offset = 0
+ """Offset of `self.input_lines` from the beginning of the file."""
+
+ self.line = None
+ """Current input line."""
+
+ self.line_offset = -1
+ """Current input line offset from beginning of `self.input_lines`."""
+
+ self.debug = debug
+ """Debugging mode on/off."""
+
+ self.initial_state = initial_state
+ """The name of the initial state (key to `self.states`)."""
+
+ self.current_state = initial_state
+ """The name of the current state (key to `self.states`)."""
+
+ self.states = {}
+ """Mapping of {state_name: State_object}."""
+
+ self.add_states(state_classes)
+
+ self.observers = []
+ """List of bound methods or functions to call whenever the current
+ line changes. Observers are called with one argument, ``self``.
+ Cleared at the end of `run()`."""
+
+ self._stderr = ErrorOutput()
+ """Wrapper around sys.stderr catching en-/decoding errors"""
+
+
+ def unlink(self):
+ """Remove circular references to objects no longer required."""
+ for state in self.states.values():
+ state.unlink()
+ self.states = None
+
+ def run(self, input_lines, input_offset=0, context=None,
+ input_source=None, initial_state=None):
+ """
+ Run the state machine on `input_lines`. Return results (a list).
+
+ Reset `self.line_offset` and `self.current_state`. Run the
+ beginning-of-file transition. Input one line at a time and check for a
+ matching transition. If a match is found, call the transition method
+ and possibly change the state. Store the context returned by the
+ transition method to be passed on to the next transition matched.
+ Accumulate the results returned by the transition methods in a list.
+ Run the end-of-file transition. Finally, return the accumulated
+ results.
+
+ Parameters:
+
+ - `input_lines`: a list of strings without newlines, or `StringList`.
+ - `input_offset`: the line offset of `input_lines` from the beginning
+ of the file.
+ - `context`: application-specific storage.
+ - `input_source`: name or path of source of `input_lines`.
+ - `initial_state`: name of initial state.
+ """
+ self.runtime_init()
+ if isinstance(input_lines, StringList):
+ self.input_lines = input_lines
+ else:
+ self.input_lines = StringList(input_lines, source=input_source)
+ self.input_offset = input_offset
+ self.line_offset = -1
+ self.current_state = initial_state or self.initial_state
+ if self.debug:
+ print((
+ u'\nStateMachine.run: input_lines (line_offset=%s):\n| %s'
+ % (self.line_offset, u'\n| '.join(self.input_lines))), file=self._stderr)
+ transitions = None
+ results = []
+ state = self.get_state()
+ try:
+ if self.debug:
+ print('\nStateMachine.run: bof transition', file=self._stderr)
+ context, result = state.bof(context)
+ results.extend(result)
+ while True:
+ try:
+ try:
+ self.next_line()
+ if self.debug:
+ source, offset = self.input_lines.info(
+ self.line_offset)
+ print((
+ u'\nStateMachine.run: line (source=%r, '
+ u'offset=%r):\n| %s'
+ % (source, offset, self.line)), file=self._stderr)
+ context, next_state, result = self.check_line(
+ context, state, transitions)
+ except EOFError:
+ if self.debug:
+ print((
+ '\nStateMachine.run: %s.eof transition'
+ % state.__class__.__name__), file=self._stderr)
+ result = state.eof(context)
+ results.extend(result)
+ break
+ else:
+ results.extend(result)
+ except TransitionCorrection as exception:
+ self.previous_line() # back up for another try
+ transitions = (exception.args[0],)
+ if self.debug:
+ print((
+ '\nStateMachine.run: TransitionCorrection to '
+ 'state "%s", transition %s.'
+ % (state.__class__.__name__, transitions[0])), file=self._stderr)
+ continue
+ except StateCorrection as exception:
+ self.previous_line() # back up for another try
+ next_state = exception.args[0]
+ if len(exception.args) == 1:
+ transitions = None
+ else:
+ transitions = (exception.args[1],)
+ if self.debug:
+ print((
+ '\nStateMachine.run: StateCorrection to state '
+ '"%s", transition %s.'
+ % (next_state, transitions[0])), file=self._stderr)
+ else:
+ transitions = None
+ state = self.get_state(next_state)
+ except:
+ if self.debug:
+ self.error()
+ raise
+ self.observers = []
+ return results
+
+ def get_state(self, next_state=None):
+ """
+ Return current state object; set it first if `next_state` given.
+
+ Parameter `next_state`: a string, the name of the next state.
+
+ Exception: `UnknownStateError` raised if `next_state` unknown.
+ """
+ if next_state:
+ if self.debug and next_state != self.current_state:
+ print((
+ '\nStateMachine.get_state: Changing state from '
+ '"%s" to "%s" (input line %s).'
+ % (self.current_state, next_state,
+ self.abs_line_number())), file=self._stderr)
+ self.current_state = next_state
+ try:
+ return self.states[self.current_state]
+ except KeyError:
+ raise UnknownStateError(self.current_state)
+
+ def next_line(self, n=1):
+ """Load `self.line` with the `n`'th next line and return it."""
+ try:
+ try:
+ self.line_offset += n
+ self.line = self.input_lines[self.line_offset]
+ except IndexError:
+ self.line = None
+ raise EOFError
+ return self.line
+ finally:
+ self.notify_observers()
+
+ def is_next_line_blank(self):
+ """Return 1 if the next line is blank or non-existant."""
+ try:
+ return not self.input_lines[self.line_offset + 1].strip()
+ except IndexError:
+ return 1
+
+ def at_eof(self):
+ """Return 1 if the input is at or past end-of-file."""
+ return self.line_offset >= len(self.input_lines) - 1
+
+ def at_bof(self):
+ """Return 1 if the input is at or before beginning-of-file."""
+ return self.line_offset <= 0
+
+ def previous_line(self, n=1):
+ """Load `self.line` with the `n`'th previous line and return it."""
+ self.line_offset -= n
+ if self.line_offset < 0:
+ self.line = None
+ else:
+ self.line = self.input_lines[self.line_offset]
+ self.notify_observers()
+ return self.line
+
+ def goto_line(self, line_offset):
+ """Jump to absolute line offset `line_offset`, load and return it."""
+ try:
+ try:
+ self.line_offset = line_offset - self.input_offset
+ self.line = self.input_lines[self.line_offset]
+ except IndexError:
+ self.line = None
+ raise EOFError
+ return self.line
+ finally:
+ self.notify_observers()
+
+ def get_source(self, line_offset):
+ """Return source of line at absolute line offset `line_offset`."""
+ return self.input_lines.source(line_offset - self.input_offset)
+
+ def abs_line_offset(self):
+ """Return line offset of current line, from beginning of file."""
+ return self.line_offset + self.input_offset
+
+ def abs_line_number(self):
+ """Return line number of current line (counting from 1)."""
+ return self.line_offset + self.input_offset + 1
+
+ def get_source_and_line(self, lineno=None):
+ """Return (source, line) tuple for current or given line number.
+
+ Looks up the source and line number in the `self.input_lines`
+ StringList instance to count for included source files.
+
+ If the optional argument `lineno` is given, convert it from an
+ absolute line number to the corresponding (source, line) pair.
+ """
+ if lineno is None:
+ offset = self.line_offset
+ else:
+ offset = lineno - self.input_offset - 1
+ try:
+ src, srcoffset = self.input_lines.info(offset)
+ srcline = srcoffset + 1
+ except (TypeError):
+ # line is None if index is "Just past the end"
+ src, srcline = self.get_source_and_line(offset + self.input_offset)
+ return src, srcline + 1
+ except (IndexError): # `offset` is off the list
+ src, srcline = None, None
+ # raise AssertionError('cannot find line %d in %s lines' %
+ # (offset, len(self.input_lines)))
+ # # list(self.input_lines.lines())))
+ return (src, srcline)
+
+ def insert_input(self, input_lines, source):
+ self.input_lines.insert(self.line_offset + 1, '',
+ source='internal padding after '+source,
+ offset=len(input_lines))
+ self.input_lines.insert(self.line_offset + 1, '',
+ source='internal padding before '+source,
+ offset=-1)
+ self.input_lines.insert(self.line_offset + 2,
+ StringList(input_lines, source))
+
+ def get_text_block(self, flush_left=False):
+ """
+ Return a contiguous block of text.
+
+ If `flush_left` is true, raise `UnexpectedIndentationError` if an
+ indented line is encountered before the text block ends (with a blank
+ line).
+ """
+ try:
+ block = self.input_lines.get_text_block(self.line_offset,
+ flush_left)
+ self.next_line(len(block) - 1)
+ return block
+ except UnexpectedIndentationError as err:
+ block = err.args[0]
+ self.next_line(len(block) - 1) # advance to last line of block
+ raise
+
+ def check_line(self, context, state, transitions=None):
+ """
+ Examine one line of input for a transition match & execute its method.
+
+ Parameters:
+
+ - `context`: application-dependent storage.
+ - `state`: a `State` object, the current state.
+ - `transitions`: an optional ordered list of transition names to try,
+ instead of ``state.transition_order``.
+
+ Return the values returned by the transition method:
+
+ - context: possibly modified from the parameter `context`;
+ - next state name (`State` subclass name);
+ - the result output of the transition, a list.
+
+ When there is no match, ``state.no_match()`` is called and its return
+ value is returned.
+ """
+ if transitions is None:
+ transitions = state.transition_order
+ state_correction = None
+ if self.debug:
+ print((
+ '\nStateMachine.check_line: state="%s", transitions=%r.'
+ % (state.__class__.__name__, transitions)), file=self._stderr)
+ for name in transitions:
+ pattern, method, next_state = state.transitions[name]
+ match = pattern.match(self.line)
+ if match:
+ if self.debug:
+ print((
+ '\nStateMachine.check_line: Matched transition '
+ '"%s" in state "%s".'
+ % (name, state.__class__.__name__)), file=self._stderr)
+ return method(match, context, next_state)
+ else:
+ if self.debug:
+ print((
+ '\nStateMachine.check_line: No match in state "%s".'
+ % state.__class__.__name__), file=self._stderr)
+ return state.no_match(context, transitions)
+
+ def add_state(self, state_class):
+ """
+ Initialize & add a `state_class` (`State` subclass) object.
+
+ Exception: `DuplicateStateError` raised if `state_class` was already
+ added.
+ """
+ statename = state_class.__name__
+ if statename in self.states:
+ raise DuplicateStateError(statename)
+ self.states[statename] = state_class(self, self.debug)
+
+ def add_states(self, state_classes):
+ """
+ Add `state_classes` (a list of `State` subclasses).
+ """
+ for state_class in state_classes:
+ self.add_state(state_class)
+
+ def runtime_init(self):
+ """
+ Initialize `self.states`.
+ """
+ for state in self.states.values():
+ state.runtime_init()
+
+ def error(self):
+ """Report error details."""
+ type, value, module, line, function = _exception_data()
+ print(u'%s: %s' % (type, value), file=self._stderr)
+ print('input line %s' % (self.abs_line_number()), file=self._stderr)
+ print((u'module %s, line %s, function %s' %
+ (module, line, function)), file=self._stderr)
+
+ def attach_observer(self, observer):
+ """
+ The `observer` parameter is a function or bound method which takes two
+ arguments, the source and offset of the current line.
+ """
+ self.observers.append(observer)
+
+ def detach_observer(self, observer):
+ self.observers.remove(observer)
+
+ def notify_observers(self):
+ for observer in self.observers:
+ try:
+ info = self.input_lines.info(self.line_offset)
+ except IndexError:
+ info = (None, None)
+ observer(*info)
+
+
+class State(object):
+
+ """
+ State superclass. Contains a list of transitions, and transition methods.
+
+ Transition methods all have the same signature. They take 3 parameters:
+
+ - An `re` match object. ``match.string`` contains the matched input line,
+ ``match.start()`` gives the start index of the match, and
+ ``match.end()`` gives the end index.
+ - A context object, whose meaning is application-defined (initial value
+ ``None``). It can be used to store any information required by the state
+ machine, and the retured context is passed on to the next transition
+ method unchanged.
+ - The name of the next state, a string, taken from the transitions list;
+ normally it is returned unchanged, but it may be altered by the
+ transition method if necessary.
+
+ Transition methods all return a 3-tuple:
+
+ - A context object, as (potentially) modified by the transition method.
+ - The next state name (a return value of ``None`` means no state change).
+ - The processing result, a list, which is accumulated by the state
+ machine.
+
+ Transition methods may raise an `EOFError` to cut processing short.
+
+ There are two implicit transitions, and corresponding transition methods
+ are defined: `bof()` handles the beginning-of-file, and `eof()` handles
+ the end-of-file. These methods have non-standard signatures and return
+ values. `bof()` returns the initial context and results, and may be used
+ to return a header string, or do any other processing needed. `eof()`
+ should handle any remaining context and wrap things up; it returns the
+ final processing result.
+
+ Typical applications need only subclass `State` (or a subclass), set the
+ `patterns` and `initial_transitions` class attributes, and provide
+ corresponding transition methods. The default object initialization will
+ take care of constructing the list of transitions.
+ """
+
+ patterns = None
+ """
+ {Name: pattern} mapping, used by `make_transition()`. Each pattern may
+ be a string or a compiled `re` pattern. Override in subclasses.
+ """
+
+ initial_transitions = None
+ """
+ A list of transitions to initialize when a `State` is instantiated.
+ Each entry is either a transition name string, or a (transition name, next
+ state name) pair. See `make_transitions()`. Override in subclasses.
+ """
+
+ nested_sm = None
+ """
+ The `StateMachine` class for handling nested processing.
+
+ If left as ``None``, `nested_sm` defaults to the class of the state's
+ controlling state machine. Override it in subclasses to avoid the default.
+ """
+
+ nested_sm_kwargs = None
+ """
+ Keyword arguments dictionary, passed to the `nested_sm` constructor.
+
+ Two keys must have entries in the dictionary:
+
+ - Key 'state_classes' must be set to a list of `State` classes.
+ - Key 'initial_state' must be set to the name of the initial state class.
+
+ If `nested_sm_kwargs` is left as ``None``, 'state_classes' defaults to the
+ class of the current state, and 'initial_state' defaults to the name of
+ the class of the current state. Override in subclasses to avoid the
+ defaults.
+ """
+
+ def __init__(self, state_machine, debug=False):
+ """
+ Initialize a `State` object; make & add initial transitions.
+
+ Parameters:
+
+ - `statemachine`: the controlling `StateMachine` object.
+ - `debug`: a boolean; produce verbose output if true.
+ """
+
+ self.transition_order = []
+ """A list of transition names in search order."""
+
+ self.transitions = {}
+ """
+ A mapping of transition names to 3-tuples containing
+ (compiled_pattern, transition_method, next_state_name). Initialized as
+ an instance attribute dynamically (instead of as a class attribute)
+ because it may make forward references to patterns and methods in this
+ or other classes.
+ """
+
+ self.add_initial_transitions()
+
+ self.state_machine = state_machine
+ """A reference to the controlling `StateMachine` object."""
+
+ self.debug = debug
+ """Debugging mode on/off."""
+
+ if self.nested_sm is None:
+ self.nested_sm = self.state_machine.__class__
+ if self.nested_sm_kwargs is None:
+ self.nested_sm_kwargs = {'state_classes': [self.__class__],
+ 'initial_state': self.__class__.__name__}
+
+ def runtime_init(self):
+ """
+ Initialize this `State` before running the state machine; called from
+ `self.state_machine.run()`.
+ """
+ pass
+
+ def unlink(self):
+ """Remove circular references to objects no longer required."""
+ self.state_machine = None
+
+ def add_initial_transitions(self):
+ """Make and add transitions listed in `self.initial_transitions`."""
+ if self.initial_transitions:
+ names, transitions = self.make_transitions(
+ self.initial_transitions)
+ self.add_transitions(names, transitions)
+
+ def add_transitions(self, names, transitions):
+ """
+ Add a list of transitions to the start of the transition list.
+
+ Parameters:
+
+ - `names`: a list of transition names.
+ - `transitions`: a mapping of names to transition tuples.
+
+ Exceptions: `DuplicateTransitionError`, `UnknownTransitionError`.
+ """
+ for name in names:
+ if name in self.transitions:
+ raise DuplicateTransitionError(name)
+ if name not in transitions:
+ raise UnknownTransitionError(name)
+ self.transition_order[:0] = names
+ self.transitions.update(transitions)
+
+ def add_transition(self, name, transition):
+ """
+ Add a transition to the start of the transition list.
+
+ Parameter `transition`: a ready-made transition 3-tuple.
+
+ Exception: `DuplicateTransitionError`.
+ """
+ if name in self.transitions:
+ raise DuplicateTransitionError(name)
+ self.transition_order[:0] = [name]
+ self.transitions[name] = transition
+
+ def remove_transition(self, name):
+ """
+ Remove a transition by `name`.
+
+ Exception: `UnknownTransitionError`.
+ """
+ try:
+ del self.transitions[name]
+ self.transition_order.remove(name)
+ except:
+ raise UnknownTransitionError(name)
+
+ def make_transition(self, name, next_state=None):
+ """
+ Make & return a transition tuple based on `name`.
+
+ This is a convenience function to simplify transition creation.
+
+ Parameters:
+
+ - `name`: a string, the name of the transition pattern & method. This
+ `State` object must have a method called '`name`', and a dictionary
+ `self.patterns` containing a key '`name`'.
+ - `next_state`: a string, the name of the next `State` object for this
+ transition. A value of ``None`` (or absent) implies no state change
+ (i.e., continue with the same state).
+
+ Exceptions: `TransitionPatternNotFound`, `TransitionMethodNotFound`.
+ """
+ if next_state is None:
+ next_state = self.__class__.__name__
+ try:
+ pattern = self.patterns[name]
+ if not hasattr(pattern, 'match'):
+ pattern = self.patterns[name] = re.compile(pattern)
+ except KeyError:
+ raise TransitionPatternNotFound(
+ '%s.patterns[%r]' % (self.__class__.__name__, name))
+ try:
+ method = getattr(self, name)
+ except AttributeError:
+ raise TransitionMethodNotFound(
+ '%s.%s' % (self.__class__.__name__, name))
+ return (pattern, method, next_state)
+
+ def make_transitions(self, name_list):
+ """
+ Return a list of transition names and a transition mapping.
+
+ Parameter `name_list`: a list, where each entry is either a transition
+ name string, or a 1- or 2-tuple (transition name, optional next state
+ name).
+ """
+ stringtype = type('')
+ names = []
+ transitions = {}
+ for namestate in name_list:
+ if isinstance(namestate, stringtype):
+ transitions[namestate] = self.make_transition(namestate)
+ names.append(namestate)
+ else:
+ transitions[namestate[0]] = self.make_transition(*namestate)
+ names.append(namestate[0])
+ return names, transitions
+
+ def no_match(self, context, transitions):
+ """
+ Called when there is no match from `StateMachine.check_line()`.
+
+ Return the same values returned by transition methods:
+
+ - context: unchanged;
+ - next state name: ``None``;
+ - empty result list.
+
+ Override in subclasses to catch this event.
+ """
+ return context, None, []
+
+ def bof(self, context):
+ """
+ Handle beginning-of-file. Return unchanged `context`, empty result.
+
+ Override in subclasses.
+
+ Parameter `context`: application-defined storage.
+ """
+ return context, []
+
+ def eof(self, context):
+ """
+ Handle end-of-file. Return empty result.
+
+ Override in subclasses.
+
+ Parameter `context`: application-defined storage.
+ """
+ return []
+
+ def nop(self, match, context, next_state):
+ """
+ A "do nothing" transition method.
+
+ Return unchanged `context` & `next_state`, empty result. Useful for
+ simple state changes (actionless transitions).
+ """
+ return context, next_state, []
+
+
+class StateMachineWS(StateMachine):
+
+ """
+ `StateMachine` subclass specialized for whitespace recognition.
+
+ There are three methods provided for extracting indented text blocks:
+
+ - `get_indented()`: use when the indent is unknown.
+ - `get_known_indented()`: use when the indent is known for all lines.
+ - `get_first_known_indented()`: use when only the first line's indent is
+ known.
+ """
+
+ def get_indented(self, until_blank=False, strip_indent=True):
+ """
+ Return a block of indented lines of text, and info.
+
+ Extract an indented block where the indent is unknown for all lines.
+
+ :Parameters:
+ - `until_blank`: Stop collecting at the first blank line if true.
+ - `strip_indent`: Strip common leading indent if true (default).
+
+ :Return:
+ - the indented block (a list of lines of text),
+ - its indent,
+ - its first line offset from BOF, and
+ - whether or not it finished with a blank line.
+ """
+ offset = self.abs_line_offset()
+ indented, indent, blank_finish = self.input_lines.get_indented(
+ self.line_offset, until_blank, strip_indent)
+ if indented:
+ self.next_line(len(indented) - 1) # advance to last indented line
+ while indented and not indented[0].strip():
+ indented.trim_start()
+ offset += 1
+ return indented, indent, offset, blank_finish
+
+ def get_known_indented(self, indent, until_blank=False, strip_indent=True):
+ """
+ Return an indented block and info.
+
+ Extract an indented block where the indent is known for all lines.
+ Starting with the current line, extract the entire text block with at
+ least `indent` indentation (which must be whitespace, except for the
+ first line).
+
+ :Parameters:
+ - `indent`: The number of indent columns/characters.
+ - `until_blank`: Stop collecting at the first blank line if true.
+ - `strip_indent`: Strip `indent` characters of indentation if true
+ (default).
+
+ :Return:
+ - the indented block,
+ - its first line offset from BOF, and
+ - whether or not it finished with a blank line.
+ """
+ offset = self.abs_line_offset()
+ indented, indent, blank_finish = self.input_lines.get_indented(
+ self.line_offset, until_blank, strip_indent,
+ block_indent=indent)
+ self.next_line(len(indented) - 1) # advance to last indented line
+ while indented and not indented[0].strip():
+ indented.trim_start()
+ offset += 1
+ return indented, offset, blank_finish
+
+ def get_first_known_indented(self, indent, until_blank=False,
+ strip_indent=True, strip_top=True):
+ """
+ Return an indented block and info.
+
+ Extract an indented block where the indent is known for the first line
+ and unknown for all other lines.
+
+ :Parameters:
+ - `indent`: The first line's indent (# of columns/characters).
+ - `until_blank`: Stop collecting at the first blank line if true
+ (1).
+ - `strip_indent`: Strip `indent` characters of indentation if true
+ (1, default).
+ - `strip_top`: Strip blank lines from the beginning of the block.
+
+ :Return:
+ - the indented block,
+ - its indent,
+ - its first line offset from BOF, and
+ - whether or not it finished with a blank line.
+ """
+ offset = self.abs_line_offset()
+ indented, indent, blank_finish = self.input_lines.get_indented(
+ self.line_offset, until_blank, strip_indent,
+ first_indent=indent)
+ self.next_line(len(indented) - 1) # advance to last indented line
+ if strip_top:
+ while indented and not indented[0].strip():
+ indented.trim_start()
+ offset += 1
+ return indented, indent, offset, blank_finish
+
+
+class StateWS(State):
+
+ """
+ State superclass specialized for whitespace (blank lines & indents).
+
+ Use this class with `StateMachineWS`. The transitions 'blank' (for blank
+ lines) and 'indent' (for indented text blocks) are added automatically,
+ before any other transitions. The transition method `blank()` handles
+ blank lines and `indent()` handles nested indented blocks. Indented
+ blocks trigger a new state machine to be created by `indent()` and run.
+ The class of the state machine to be created is in `indent_sm`, and the
+ constructor keyword arguments are in the dictionary `indent_sm_kwargs`.
+
+ The methods `known_indent()` and `firstknown_indent()` are provided for
+ indented blocks where the indent (all lines' and first line's only,
+ respectively) is known to the transition method, along with the attributes
+ `known_indent_sm` and `known_indent_sm_kwargs`. Neither transition method
+ is triggered automatically.
+ """
+
+ indent_sm = None
+ """
+ The `StateMachine` class handling indented text blocks.
+
+ If left as ``None``, `indent_sm` defaults to the value of
+ `State.nested_sm`. Override it in subclasses to avoid the default.
+ """
+
+ indent_sm_kwargs = None
+ """
+ Keyword arguments dictionary, passed to the `indent_sm` constructor.
+
+ If left as ``None``, `indent_sm_kwargs` defaults to the value of
+ `State.nested_sm_kwargs`. Override it in subclasses to avoid the default.
+ """
+
+ known_indent_sm = None
+ """
+ The `StateMachine` class handling known-indented text blocks.
+
+ If left as ``None``, `known_indent_sm` defaults to the value of
+ `indent_sm`. Override it in subclasses to avoid the default.
+ """
+
+ known_indent_sm_kwargs = None
+ """
+ Keyword arguments dictionary, passed to the `known_indent_sm` constructor.
+
+ If left as ``None``, `known_indent_sm_kwargs` defaults to the value of
+ `indent_sm_kwargs`. Override it in subclasses to avoid the default.
+ """
+
+ ws_patterns = {'blank': re.compile(' *$'),
+ 'indent': re.compile(' +')}
+ """Patterns for default whitespace transitions. May be overridden in
+ subclasses."""
+
+ ws_initial_transitions = ('blank', 'indent')
+ """Default initial whitespace transitions, added before those listed in
+ `State.initial_transitions`. May be overridden in subclasses."""
+
+ def __init__(self, state_machine, debug=False):
+ """
+ Initialize a `StateSM` object; extends `State.__init__()`.
+
+ Check for indent state machine attributes, set defaults if not set.
+ """
+ State.__init__(self, state_machine, debug)
+ if self.indent_sm is None:
+ self.indent_sm = self.nested_sm
+ if self.indent_sm_kwargs is None:
+ self.indent_sm_kwargs = self.nested_sm_kwargs
+ if self.known_indent_sm is None:
+ self.known_indent_sm = self.indent_sm
+ if self.known_indent_sm_kwargs is None:
+ self.known_indent_sm_kwargs = self.indent_sm_kwargs
+
+ def add_initial_transitions(self):
+ """
+ Add whitespace-specific transitions before those defined in subclass.
+
+ Extends `State.add_initial_transitions()`.
+ """
+ State.add_initial_transitions(self)
+ if self.patterns is None:
+ self.patterns = {}
+ self.patterns.update(self.ws_patterns)
+ names, transitions = self.make_transitions(
+ self.ws_initial_transitions)
+ self.add_transitions(names, transitions)
+
+ def blank(self, match, context, next_state):
+ """Handle blank lines. Does nothing. Override in subclasses."""
+ return self.nop(match, context, next_state)
+
+ def indent(self, match, context, next_state):
+ """
+ Handle an indented text block. Extend or override in subclasses.
+
+ Recursively run the registered state machine for indented blocks
+ (`self.indent_sm`).
+ """
+ indented, indent, line_offset, blank_finish = \
+ self.state_machine.get_indented()
+ sm = self.indent_sm(debug=self.debug, **self.indent_sm_kwargs)
+ results = sm.run(indented, input_offset=line_offset)
+ return context, next_state, results
+
+ def known_indent(self, match, context, next_state):
+ """
+ Handle a known-indent text block. Extend or override in subclasses.
+
+ Recursively run the registered state machine for known-indent indented
+ blocks (`self.known_indent_sm`). The indent is the length of the
+ match, ``match.end()``.
+ """
+ indented, line_offset, blank_finish = \
+ self.state_machine.get_known_indented(match.end())
+ sm = self.known_indent_sm(debug=self.debug,
+ **self.known_indent_sm_kwargs)
+ results = sm.run(indented, input_offset=line_offset)
+ return context, next_state, results
+
+ def first_known_indent(self, match, context, next_state):
+ """
+ Handle an indented text block (first line's indent known).
+
+ Extend or override in subclasses.
+
+ Recursively run the registered state machine for known-indent indented
+ blocks (`self.known_indent_sm`). The indent is the length of the
+ match, ``match.end()``.
+ """
+ indented, line_offset, blank_finish = \
+ self.state_machine.get_first_known_indented(match.end())
+ sm = self.known_indent_sm(debug=self.debug,
+ **self.known_indent_sm_kwargs)
+ results = sm.run(indented, input_offset=line_offset)
+ return context, next_state, results
+
+
+class _SearchOverride(object):
+
+ """
+ Mix-in class to override `StateMachine` regular expression behavior.
+
+ Changes regular expression matching, from the default `re.match()`
+ (succeeds only if the pattern matches at the start of `self.line`) to
+ `re.search()` (succeeds if the pattern matches anywhere in `self.line`).
+ When subclassing a `StateMachine`, list this class **first** in the
+ inheritance list of the class definition.
+ """
+
+ def match(self, pattern):
+ """
+ Return the result of a regular expression search.
+
+ Overrides `StateMachine.match()`.
+
+ Parameter `pattern`: `re` compiled regular expression.
+ """
+ return pattern.search(self.line)
+
+
+class SearchStateMachine(_SearchOverride, StateMachine):
+ """`StateMachine` which uses `re.search()` instead of `re.match()`."""
+ pass
+
+
+class SearchStateMachineWS(_SearchOverride, StateMachineWS):
+ """`StateMachineWS` which uses `re.search()` instead of `re.match()`."""
+ pass
+
+
+class ViewList(object):
+
+ """
+ List with extended functionality: slices of ViewList objects are child
+ lists, linked to their parents. Changes made to a child list also affect
+ the parent list. A child list is effectively a "view" (in the SQL sense)
+ of the parent list. Changes to parent lists, however, do *not* affect
+ active child lists. If a parent list is changed, any active child lists
+ should be recreated.
+
+ The start and end of the slice can be trimmed using the `trim_start()` and
+ `trim_end()` methods, without affecting the parent list. The link between
+ child and parent lists can be broken by calling `disconnect()` on the
+ child list.
+
+ Also, ViewList objects keep track of the source & offset of each item.
+ This information is accessible via the `source()`, `offset()`, and
+ `info()` methods.
+ """
+
+ def __init__(self, initlist=None, source=None, items=None,
+ parent=None, parent_offset=None):
+ self.data = []
+ """The actual list of data, flattened from various sources."""
+
+ self.items = []
+ """A list of (source, offset) pairs, same length as `self.data`: the
+ source of each line and the offset of each line from the beginning of
+ its source."""
+
+ self.parent = parent
+ """The parent list."""
+
+ self.parent_offset = parent_offset
+ """Offset of this list from the beginning of the parent list."""
+
+ if isinstance(initlist, ViewList):
+ self.data = initlist.data[:]
+ self.items = initlist.items[:]
+ elif initlist is not None:
+ self.data = list(initlist)
+ if items:
+ self.items = items
+ else:
+ self.items = [(source, i) for i in range(len(initlist))]
+ assert len(self.data) == len(self.items), 'data mismatch'
+
+ def __str__(self):
+ return str(self.data)
+
+ def __repr__(self):
+ return '%s(%s, items=%s)' % (self.__class__.__name__,
+ self.data, self.items)
+
+ def __lt__(self, other): return self.data < self.__cast(other)
+ def __le__(self, other): return self.data <= self.__cast(other)
+ def __eq__(self, other): return self.data == self.__cast(other)
+ def __ne__(self, other): return self.data != self.__cast(other)
+ def __gt__(self, other): return self.data > self.__cast(other)
+ def __ge__(self, other): return self.data >= self.__cast(other)
+
+ def __cmp__(self, other):
+ # from https://docs.python.org/3.0/whatsnew/3.0.html
+ mine = self.data
+ yours = self.__cast(other)
+ return (mine > yours) - (yours < mine)
+
+ def __cast(self, other):
+ if isinstance(other, ViewList):
+ return other.data
+ else:
+ return other
+
+ def __contains__(self, item): return item in self.data
+ def __len__(self): return len(self.data)
+
+ # The __getitem__()/__setitem__() methods check whether the index
+ # is a slice first, since indexing a native list with a slice object
+ # just works.
+
+ def __getitem__(self, i):
+ if isinstance(i, slice):
+ assert i.step in (None, 1), 'cannot handle slice with stride'
+ return self.__class__(self.data[i.start:i.stop],
+ items=self.items[i.start:i.stop],
+ parent=self, parent_offset=i.start or 0)
+ else:
+ return self.data[i]
+
+ def __setitem__(self, i, item):
+ if isinstance(i, slice):
+ assert i.step in (None, 1), 'cannot handle slice with stride'
+ if not isinstance(item, ViewList):
+ raise TypeError('assigning non-ViewList to ViewList slice')
+ self.data[i.start:i.stop] = item.data
+ self.items[i.start:i.stop] = item.items
+ assert len(self.data) == len(self.items), 'data mismatch'
+ if self.parent:
+ self.parent[(i.start or 0) + self.parent_offset
+ : (i.stop or len(self)) + self.parent_offset] = item
+ else:
+ self.data[i] = item
+ if self.parent:
+ self.parent[i + self.parent_offset] = item
+
+ def __delitem__(self, i):
+ try:
+ del self.data[i]
+ del self.items[i]
+ if self.parent:
+ del self.parent[i + self.parent_offset]
+ except TypeError:
+ assert i.step is None, 'cannot handle slice with stride'
+ del self.data[i.start:i.stop]
+ del self.items[i.start:i.stop]
+ if self.parent:
+ del self.parent[(i.start or 0) + self.parent_offset
+ : (i.stop or len(self)) + self.parent_offset]
+
+ def __add__(self, other):
+ if isinstance(other, ViewList):
+ return self.__class__(self.data + other.data,
+ items=(self.items + other.items))
+ else:
+ raise TypeError('adding non-ViewList to a ViewList')
+
+ def __radd__(self, other):
+ if isinstance(other, ViewList):
+ return self.__class__(other.data + self.data,
+ items=(other.items + self.items))
+ else:
+ raise TypeError('adding ViewList to a non-ViewList')
+
+ def __iadd__(self, other):
+ if isinstance(other, ViewList):
+ self.data += other.data
+ else:
+ raise TypeError('argument to += must be a ViewList')
+ return self
+
+ def __mul__(self, n):
+ return self.__class__(self.data * n, items=(self.items * n))
+
+ __rmul__ = __mul__
+
+ def __imul__(self, n):
+ self.data *= n
+ self.items *= n
+ return self
+
+ def extend(self, other):
+ if not isinstance(other, ViewList):
+ raise TypeError('extending a ViewList with a non-ViewList')
+ if self.parent:
+ self.parent.insert(len(self.data) + self.parent_offset, other)
+ self.data.extend(other.data)
+ self.items.extend(other.items)
+
+ def append(self, item, source=None, offset=0):
+ if source is None:
+ self.extend(item)
+ else:
+ if self.parent:
+ self.parent.insert(len(self.data) + self.parent_offset, item,
+ source, offset)
+ self.data.append(item)
+ self.items.append((source, offset))
+
+ def insert(self, i, item, source=None, offset=0):
+ if source is None:
+ if not isinstance(item, ViewList):
+ raise TypeError('inserting non-ViewList with no source given')
+ self.data[i:i] = item.data
+ self.items[i:i] = item.items
+ if self.parent:
+ index = (len(self.data) + i) % len(self.data)
+ self.parent.insert(index + self.parent_offset, item)
+ else:
+ self.data.insert(i, item)
+ self.items.insert(i, (source, offset))
+ if self.parent:
+ index = (len(self.data) + i) % len(self.data)
+ self.parent.insert(index + self.parent_offset, item,
+ source, offset)
+
+ def pop(self, i=-1):
+ if self.parent:
+ index = (len(self.data) + i) % len(self.data)
+ self.parent.pop(index + self.parent_offset)
+ self.items.pop(i)
+ return self.data.pop(i)
+
+ def trim_start(self, n=1):
+ """
+ Remove items from the start of the list, without touching the parent.
+ """
+ if n > len(self.data):
+ raise IndexError("Size of trim too large; can't trim %s items "
+ "from a list of size %s." % (n, len(self.data)))
+ elif n < 0:
+ raise IndexError('Trim size must be >= 0.')
+ del self.data[:n]
+ del self.items[:n]
+ if self.parent:
+ self.parent_offset += n
+
+ def trim_end(self, n=1):
+ """
+ Remove items from the end of the list, without touching the parent.
+ """
+ if n > len(self.data):
+ raise IndexError("Size of trim too large; can't trim %s items "
+ "from a list of size %s." % (n, len(self.data)))
+ elif n < 0:
+ raise IndexError('Trim size must be >= 0.')
+ del self.data[-n:]
+ del self.items[-n:]
+
+ def remove(self, item):
+ index = self.index(item)
+ del self[index]
+
+ def count(self, item): return self.data.count(item)
+ def index(self, item): return self.data.index(item)
+
+ def reverse(self):
+ self.data.reverse()
+ self.items.reverse()
+ self.parent = None
+
+ def sort(self, *args):
+ tmp = sorted(zip(self.data, self.items), *args)
+ self.data = [entry[0] for entry in tmp]
+ self.items = [entry[1] for entry in tmp]
+ self.parent = None
+
+ def info(self, i):
+ """Return source & offset for index `i`."""
+ try:
+ return self.items[i]
+ except IndexError:
+ if i == len(self.data): # Just past the end
+ return self.items[i - 1][0], None
+ else:
+ raise
+
+ def source(self, i):
+ """Return source for index `i`."""
+ return self.info(i)[0]
+
+ def offset(self, i):
+ """Return offset for index `i`."""
+ return self.info(i)[1]
+
+ def disconnect(self):
+ """Break link between this list and parent list."""
+ self.parent = None
+
+ def xitems(self):
+ """Return iterator yielding (source, offset, value) tuples."""
+ for (value, (source, offset)) in zip(self.data, self.items):
+ yield (source, offset, value)
+
+ def pprint(self):
+ """Print the list in `grep` format (`source:offset:value` lines)"""
+ for line in self.xitems():
+ print("%s:%d:%s" % line)
+
+
+class StringList(ViewList):
+
+ """A `ViewList` with string-specific methods."""
+
+ def trim_left(self, length, start=0, end=sys.maxsize):
+ """
+ Trim `length` characters off the beginning of each item, in-place,
+ from index `start` to `end`. No whitespace-checking is done on the
+ trimmed text. Does not affect slice parent.
+ """
+ self.data[start:end] = [line[length:]
+ for line in self.data[start:end]]
+
+ def get_text_block(self, start, flush_left=False):
+ """
+ Return a contiguous block of text.
+
+ If `flush_left` is true, raise `UnexpectedIndentationError` if an
+ indented line is encountered before the text block ends (with a blank
+ line).
+ """
+ end = start
+ last = len(self.data)
+ while end < last:
+ line = self.data[end]
+ if not line.strip():
+ break
+ if flush_left and (line[0] == ' '):
+ source, offset = self.info(end)
+ raise UnexpectedIndentationError(self[start:end], source,
+ offset + 1)
+ end += 1
+ return self[start:end]
+
+ def get_indented(self, start=0, until_blank=False, strip_indent=True,
+ block_indent=None, first_indent=None):
+ """
+ Extract and return a StringList of indented lines of text.
+
+ Collect all lines with indentation, determine the minimum indentation,
+ remove the minimum indentation from all indented lines (unless
+ `strip_indent` is false), and return them. All lines up to but not
+ including the first unindented line will be returned.
+
+ :Parameters:
+ - `start`: The index of the first line to examine.
+ - `until_blank`: Stop collecting at the first blank line if true.
+ - `strip_indent`: Strip common leading indent if true (default).
+ - `block_indent`: The indent of the entire block, if known.
+ - `first_indent`: The indent of the first line, if known.
+
+ :Return:
+ - a StringList of indented lines with mininum indent removed;
+ - the amount of the indent;
+ - a boolean: did the indented block finish with a blank line or EOF?
+ """
+ indent = block_indent # start with None if unknown
+ end = start
+ if block_indent is not None and first_indent is None:
+ first_indent = block_indent
+ if first_indent is not None:
+ end += 1
+ last = len(self.data)
+ while end < last:
+ line = self.data[end]
+ if line and (line[0] != ' '
+ or (block_indent is not None
+ and line[:block_indent].strip())):
+ # Line not indented or insufficiently indented.
+ # Block finished properly iff the last indented line blank:
+ blank_finish = ((end > start)
+ and not self.data[end - 1].strip())
+ break
+ stripped = line.lstrip()
+ if not stripped: # blank line
+ if until_blank:
+ blank_finish = 1
+ break
+ elif block_indent is None:
+ line_indent = len(line) - len(stripped)
+ if indent is None:
+ indent = line_indent
+ else:
+ indent = min(indent, line_indent)
+ end += 1
+ else:
+ blank_finish = 1 # block ends at end of lines
+ block = self[start:end]
+ if first_indent is not None and block:
+ block.data[0] = block.data[0][first_indent:]
+ if indent and strip_indent:
+ block.trim_left(indent, start=(first_indent is not None))
+ return block, indent or 0, blank_finish
+
+ def get_2D_block(self, top, left, bottom, right, strip_indent=True):
+ block = self[top:bottom]
+ indent = right
+ for i in range(len(block.data)):
+ # get slice from line, care for combining characters
+ ci = utils.column_indices(block.data[i])
+ try:
+ left = ci[left]
+ except IndexError:
+ left += len(block.data[i]) - len(ci)
+ try:
+ right = ci[right]
+ except IndexError:
+ right += len(block.data[i]) - len(ci)
+ block.data[i] = line = block.data[i][left:right].rstrip()
+ if line:
+ indent = min(indent, len(line) - len(line.lstrip()))
+ if strip_indent and 0 < indent < right:
+ block.data = [line[indent:] for line in block.data]
+ return block
+
+ def pad_double_width(self, pad_char):
+ """
+ Pad all double-width characters in self by appending `pad_char` to each.
+ For East Asian language support.
+ """
+ east_asian_width = unicodedata.east_asian_width
+ for i in range(len(self.data)):
+ line = self.data[i]
+ if isinstance(line, unicode):
+ new = []
+ for char in line:
+ new.append(char)
+ if east_asian_width(char) in 'WF': # 'W'ide & 'F'ull-width
+ new.append(pad_char)
+ self.data[i] = ''.join(new)
+
+ def replace(self, old, new):
+ """Replace all occurrences of substring `old` with `new`."""
+ for i in range(len(self.data)):
+ self.data[i] = self.data[i].replace(old, new)
+
+
+class StateMachineError(Exception): pass
+class UnknownStateError(StateMachineError): pass
+class DuplicateStateError(StateMachineError): pass
+class UnknownTransitionError(StateMachineError): pass
+class DuplicateTransitionError(StateMachineError): pass
+class TransitionPatternNotFound(StateMachineError): pass
+class TransitionMethodNotFound(StateMachineError): pass
+class UnexpectedIndentationError(StateMachineError): pass
+
+
+class TransitionCorrection(Exception):
+
+ """
+ Raise from within a transition method to switch to another transition.
+
+ Raise with one argument, the new transition name.
+ """
+
+
+class StateCorrection(Exception):
+
+ """
+ Raise from within a transition method to switch to another state.
+
+ Raise with one or two arguments: new state name, and an optional new
+ transition name.
+ """
+
+def string2lines(astring, tab_width=8, convert_whitespace=False,
+ whitespace=re.compile('[\v\f]')):
+ """
+ Return a list of one-line strings with tabs expanded, no newlines, and
+ trailing whitespace stripped.
+
+ Each tab is expanded with between 1 and `tab_width` spaces, so that the
+ next character's index becomes a multiple of `tab_width` (8 by default).
+
+ Parameters:
+
+ - `astring`: a multi-line string.
+ - `tab_width`: the number of columns between tab stops.
+ - `convert_whitespace`: convert form feeds and vertical tabs to spaces?
+ """
+ if convert_whitespace:
+ astring = whitespace.sub(' ', astring)
+ # TODO: add a test for too long lines (max_line_lenght = 1000, say)?
+ # See bug #381.
+ return [s.expandtabs(tab_width).rstrip() for s in astring.splitlines()]
+
+def _exception_data():
+ """
+ Return exception information:
+
+ - the exception's class name;
+ - the exception object;
+ - the name of the file containing the offending code;
+ - the line number of the offending code;
+ - the function name of the offending code.
+ """
+ type, value, traceback = sys.exc_info()
+ while traceback.tb_next:
+ traceback = traceback.tb_next
+ code = traceback.tb_frame.f_code
+ return (type.__name__, value, code.co_filename, traceback.tb_lineno,
+ code.co_name)
--- /dev/null
+# $Id: __init__.py 8358 2019-08-26 16:45:09Z milde $
+# Authors: David Goodger <goodger@python.org>; Ueli Schlaepfer
+# Copyright: This module has been placed in the public domain.
+
+"""
+This package contains modules for standard tree transforms available
+to Docutils components. Tree transforms serve a variety of purposes:
+
+- To tie up certain syntax-specific "loose ends" that remain after the
+ initial parsing of the input plaintext. These transforms are used to
+ supplement a limited syntax.
+
+- To automate the internal linking of the document tree (hyperlink
+ references, footnote references, etc.).
+
+- To extract useful information from the document tree. These
+ transforms may be used to construct (for example) indexes and tables
+ of contents.
+
+Each transform is an optional step that a Docutils component may
+choose to perform on the parsed document.
+"""
+
+__docformat__ = 'reStructuredText'
+
+
+from docutils import languages, ApplicationError, TransformSpec
+
+
+class TransformError(ApplicationError): pass
+
+
+class Transform(object):
+
+ """
+ Docutils transform component abstract base class.
+ """
+
+ default_priority = None
+ """Numerical priority of this transform, 0 through 999 (override)."""
+
+ def __init__(self, document, startnode=None):
+ """
+ Initial setup for in-place document transforms.
+ """
+
+ self.document = document
+ """The document tree to transform."""
+
+ self.startnode = startnode
+ """Node from which to begin the transform. For many transforms which
+ apply to the document as a whole, `startnode` is not set (i.e. its
+ value is `None`)."""
+
+ self.language = languages.get_language(
+ document.settings.language_code, document.reporter)
+ """Language module local to this document."""
+
+ def apply(self, **kwargs):
+ """Override to apply the transform to the document tree."""
+ raise NotImplementedError('subclass must override this method')
+
+
+class Transformer(TransformSpec):
+
+ """
+ Stores transforms (`Transform` classes) and applies them to document
+ trees. Also keeps track of components by component type name.
+ """
+
+ def __init__(self, document):
+ self.transforms = []
+ """List of transforms to apply. Each item is a 4-tuple:
+ ``(priority string, transform class, pending node or None, kwargs)``.
+ """
+
+ self.unknown_reference_resolvers = []
+ """List of hook functions which assist in resolving references"""
+
+ self.document = document
+ """The `nodes.document` object this Transformer is attached to."""
+
+ self.applied = []
+ """Transforms already applied, in order."""
+
+ self.sorted = 0
+ """Boolean: is `self.tranforms` sorted?"""
+
+ self.components = {}
+ """Mapping of component type name to component object. Set by
+ `self.populate_from_components()`."""
+
+ self.serialno = 0
+ """Internal serial number to keep track of the add order of
+ transforms."""
+
+ def add_transform(self, transform_class, priority=None, **kwargs):
+ """
+ Store a single transform. Use `priority` to override the default.
+ `kwargs` is a dictionary whose contents are passed as keyword
+ arguments to the `apply` method of the transform. This can be used to
+ pass application-specific data to the transform instance.
+ """
+ if priority is None:
+ priority = transform_class.default_priority
+ priority_string = self.get_priority_string(priority)
+ self.transforms.append(
+ (priority_string, transform_class, None, kwargs))
+ self.sorted = 0
+
+ def add_transforms(self, transform_list):
+ """Store multiple transforms, with default priorities."""
+ for transform_class in transform_list:
+ priority_string = self.get_priority_string(
+ transform_class.default_priority)
+ self.transforms.append(
+ (priority_string, transform_class, None, {}))
+ self.sorted = 0
+
+ def add_pending(self, pending, priority=None):
+ """Store a transform with an associated `pending` node."""
+ transform_class = pending.transform
+ if priority is None:
+ priority = transform_class.default_priority
+ priority_string = self.get_priority_string(priority)
+ self.transforms.append(
+ (priority_string, transform_class, pending, {}))
+ self.sorted = 0
+
+ def get_priority_string(self, priority):
+ """
+ Return a string, `priority` combined with `self.serialno`.
+
+ This ensures FIFO order on transforms with identical priority.
+ """
+ self.serialno += 1
+ return '%03d-%03d' % (priority, self.serialno)
+
+ def populate_from_components(self, components):
+ """
+ Store each component's default transforms, with default priorities.
+ Also, store components by type name in a mapping for later lookup.
+ """
+ for component in components:
+ if component is None:
+ continue
+ self.add_transforms(component.get_transforms())
+ self.components[component.component_type] = component
+ self.sorted = 0
+ # Set up all of the reference resolvers for this transformer. Each
+ # component of this transformer is able to register its own helper
+ # functions to help resolve references.
+ unknown_reference_resolvers = []
+ for i in components:
+ unknown_reference_resolvers.extend(i.unknown_reference_resolvers)
+ decorated_list = sorted((f.priority, f) for f in unknown_reference_resolvers)
+ self.unknown_reference_resolvers.extend(f[1] for f in decorated_list)
+
+ def apply_transforms(self):
+ """Apply all of the stored transforms, in priority order."""
+ self.document.reporter.attach_observer(
+ self.document.note_transform_message)
+ while self.transforms:
+ if not self.sorted:
+ # Unsorted initially, and whenever a transform is added.
+ self.transforms.sort()
+ self.transforms.reverse()
+ self.sorted = 1
+ priority, transform_class, pending, kwargs = self.transforms.pop()
+ transform = transform_class(self.document, startnode=pending)
+ transform.apply(**kwargs)
+ self.applied.append((priority, transform_class, pending, kwargs))
--- /dev/null
+# $Id: components.py 4564 2006-05-21 20:44:42Z wiemann $
+# Author: David Goodger <goodger@python.org>
+# Copyright: This module has been placed in the public domain.
+
+"""
+Docutils component-related transforms.
+"""
+
+__docformat__ = 'reStructuredText'
+
+import sys
+import os
+import re
+import time
+from docutils import nodes, utils
+from docutils import ApplicationError, DataError
+from docutils.transforms import Transform, TransformError
+
+
+class Filter(Transform):
+
+ """
+ Include or exclude elements which depend on a specific Docutils component.
+
+ For use with `nodes.pending` elements. A "pending" element's dictionary
+ attribute ``details`` must contain the keys "component" and "format". The
+ value of ``details['component']`` must match the type name of the
+ component the elements depend on (e.g. "writer"). The value of
+ ``details['format']`` is the name of a specific format or context of that
+ component (e.g. "html"). If the matching Docutils component supports that
+ format or context, the "pending" element is replaced by the contents of
+ ``details['nodes']`` (a list of nodes); otherwise, the "pending" element
+ is removed.
+
+ For example, the reStructuredText "meta" directive creates a "pending"
+ element containing a "meta" element (in ``pending.details['nodes']``).
+ Only writers (``pending.details['component'] == 'writer'``) supporting the
+ "html" format (``pending.details['format'] == 'html'``) will include the
+ "meta" element; it will be deleted from the output of all other writers.
+ """
+
+ default_priority = 780
+
+ def apply(self):
+ pending = self.startnode
+ component_type = pending.details['component'] # 'reader' or 'writer'
+ format = pending.details['format']
+ component = self.document.transformer.components[component_type]
+ if component.supports(format):
+ pending.replace_self(pending.details['nodes'])
+ else:
+ pending.parent.remove(pending)
--- /dev/null
+# $Id: frontmatter.py 8389 2019-09-11 11:39:13Z milde $
+# Author: David Goodger, Ueli Schlaepfer <goodger@python.org>
+# Copyright: This module has been placed in the public domain.
+
+"""
+Transforms related to the front matter of a document or a section
+(information found before the main text):
+
+- `DocTitle`: Used to transform a lone top level section's title to
+ the document title, promote a remaining lone top-level section's
+ title to the document subtitle, and determine the document's title
+ metadata (document['title']) based on the document title and/or the
+ "title" setting.
+
+- `SectionSubTitle`: Used to transform a lone subsection into a
+ subtitle.
+
+- `DocInfo`: Used to transform a bibliographic field list into docinfo
+ elements.
+"""
+
+__docformat__ = 'reStructuredText'
+
+import re
+import sys
+
+from docutils import nodes, utils
+from docutils.transforms import TransformError, Transform
+
+
+if sys.version_info >= (3, 0):
+ unicode = str # noqa
+
+
+class TitlePromoter(Transform):
+
+ """
+ Abstract base class for DocTitle and SectionSubTitle transforms.
+ """
+
+ def promote_title(self, node):
+ """
+ Transform the following tree::
+
+ <node>
+ <section>
+ <title>
+ ...
+
+ into ::
+
+ <node>
+ <title>
+ ...
+
+ `node` is normally a document.
+ """
+ # Type check
+ if not isinstance(node, nodes.Element):
+ raise TypeError('node must be of Element-derived type.')
+
+ # `node` must not have a title yet.
+ assert not (len(node) and isinstance(node[0], nodes.title))
+ section, index = self.candidate_index(node)
+ if index is None:
+ return False
+
+ # Transfer the section's attributes to the node:
+ # NOTE: Change `replace` to False to NOT replace attributes that
+ # already exist in node with those in section.
+ # NOTE: Remove `and_source` to NOT copy the 'source'
+ # attribute from section
+ node.update_all_atts_concatenating(section, replace=True, and_source=True)
+
+ # setup_child is called automatically for all nodes.
+ node[:] = (section[:1] # section title
+ + node[:index] # everything that was in the
+ # node before the section
+ + section[1:]) # everything that was in the section
+ assert isinstance(node[0], nodes.title)
+ return True
+
+ def promote_subtitle(self, node):
+ """
+ Transform the following node tree::
+
+ <node>
+ <title>
+ <section>
+ <title>
+ ...
+
+ into ::
+
+ <node>
+ <title>
+ <subtitle>
+ ...
+ """
+ # Type check
+ if not isinstance(node, nodes.Element):
+ raise TypeError('node must be of Element-derived type.')
+
+ subsection, index = self.candidate_index(node)
+ if index is None:
+ return False
+ subtitle = nodes.subtitle()
+
+ # Transfer the subsection's attributes to the new subtitle
+ # NOTE: Change `replace` to False to NOT replace attributes
+ # that already exist in node with those in section.
+ # NOTE: Remove `and_source` to NOT copy the 'source'
+ # attribute from section.
+ subtitle.update_all_atts_concatenating(subsection, replace=True, and_source=True)
+
+ # Transfer the contents of the subsection's title to the
+ # subtitle:
+ subtitle[:] = subsection[0][:]
+ node[:] = (node[:1] # title
+ + [subtitle]
+ # everything that was before the section:
+ + node[1:index]
+ # everything that was in the subsection:
+ + subsection[1:])
+ return True
+
+ def candidate_index(self, node):
+ """
+ Find and return the promotion candidate and its index.
+
+ Return (None, None) if no valid candidate was found.
+ """
+ index = node.first_child_not_matching_class(
+ nodes.PreBibliographic)
+ if (index is None or len(node) > (index + 1)
+ or not isinstance(node[index], nodes.section)):
+ return None, None
+ else:
+ return node[index], index
+
+
+class DocTitle(TitlePromoter):
+
+ """
+ In reStructuredText_, there is no way to specify a document title
+ and subtitle explicitly. Instead, we can supply the document title
+ (and possibly the subtitle as well) implicitly, and use this
+ two-step transform to "raise" or "promote" the title(s) (and their
+ corresponding section contents) to the document level.
+
+ 1. If the document contains a single top-level section as its
+ first non-comment element, the top-level section's title
+ becomes the document's title, and the top-level section's
+ contents become the document's immediate contents. The lone
+ top-level section header must be the first non-comment element
+ in the document.
+
+ For example, take this input text::
+
+ =================
+ Top-Level Title
+ =================
+
+ A paragraph.
+
+ Once parsed, it looks like this::
+
+ <document>
+ <section names="top-level title">
+ <title>
+ Top-Level Title
+ <paragraph>
+ A paragraph.
+
+ After running the DocTitle transform, we have::
+
+ <document names="top-level title">
+ <title>
+ Top-Level Title
+ <paragraph>
+ A paragraph.
+
+ 2. If step 1 successfully determines the document title, we
+ continue by checking for a subtitle.
+
+ If the lone top-level section itself contains a single
+ second-level section as its first non-comment element, that
+ section's title is promoted to the document's subtitle, and
+ that section's contents become the document's immediate
+ contents. Given this input text::
+
+ =================
+ Top-Level Title
+ =================
+
+ Second-Level Title
+ ~~~~~~~~~~~~~~~~~~
+
+ A paragraph.
+
+ After parsing and running the Section Promotion transform, the
+ result is::
+
+ <document names="top-level title">
+ <title>
+ Top-Level Title
+ <subtitle names="second-level title">
+ Second-Level Title
+ <paragraph>
+ A paragraph.
+
+ (Note that the implicit hyperlink target generated by the
+ "Second-Level Title" is preserved on the "subtitle" element
+ itself.)
+
+ Any comment elements occurring before the document title or
+ subtitle are accumulated and inserted as the first body elements
+ after the title(s).
+
+ This transform also sets the document's metadata title
+ (document['title']).
+
+ .. _reStructuredText: http://docutils.sf.net/rst.html
+ """
+
+ default_priority = 320
+
+ def set_metadata(self):
+ """
+ Set document['title'] metadata title from the following
+ sources, listed in order of priority:
+
+ * Existing document['title'] attribute.
+ * "title" setting.
+ * Document title node (as promoted by promote_title).
+ """
+ if not self.document.hasattr('title'):
+ if self.document.settings.title is not None:
+ self.document['title'] = self.document.settings.title
+ elif len(self.document) and isinstance(self.document[0], nodes.title):
+ self.document['title'] = self.document[0].astext()
+
+ def apply(self):
+ if getattr(self.document.settings, 'doctitle_xform', 1):
+ # promote_(sub)title defined in TitlePromoter base class.
+ if self.promote_title(self.document):
+ # If a title has been promoted, also try to promote a
+ # subtitle.
+ self.promote_subtitle(self.document)
+ # Set document['title'].
+ self.set_metadata()
+
+
+class SectionSubTitle(TitlePromoter):
+
+ """
+ This works like document subtitles, but for sections. For example, ::
+
+ <section>
+ <title>
+ Title
+ <section>
+ <title>
+ Subtitle
+ ...
+
+ is transformed into ::
+
+ <section>
+ <title>
+ Title
+ <subtitle>
+ Subtitle
+ ...
+
+ For details refer to the docstring of DocTitle.
+ """
+
+ default_priority = 350
+
+ def apply(self):
+ if not getattr(self.document.settings, 'sectsubtitle_xform', 1):
+ return
+ for section in self.document._traverse(nodes.section):
+ # On our way through the node tree, we are modifying it
+ # but only the not-yet-visited part, so that the iterator
+ # returned by _traverse() is not corrupted.
+ self.promote_subtitle(section)
+
+
+class DocInfo(Transform):
+
+ """
+ This transform is specific to the reStructuredText_ markup syntax;
+ see "Bibliographic Fields" in the `reStructuredText Markup
+ Specification`_ for a high-level description. This transform
+ should be run *after* the `DocTitle` transform.
+
+ Given a field list as the first non-comment element after the
+ document title and subtitle (if present), registered bibliographic
+ field names are transformed to the corresponding DTD elements,
+ becoming child elements of the "docinfo" element (except for a
+ dedication and/or an abstract, which become "topic" elements after
+ "docinfo").
+
+ For example, given this document fragment after parsing::
+
+ <document>
+ <title>
+ Document Title
+ <field_list>
+ <field>
+ <field_name>
+ Author
+ <field_body>
+ <paragraph>
+ A. Name
+ <field>
+ <field_name>
+ Status
+ <field_body>
+ <paragraph>
+ $RCSfile$
+ ...
+
+ After running the bibliographic field list transform, the
+ resulting document tree would look like this::
+
+ <document>
+ <title>
+ Document Title
+ <docinfo>
+ <author>
+ A. Name
+ <status>
+ frontmatter.py
+ ...
+
+ The "Status" field contained an expanded RCS keyword, which is
+ normally (but optionally) cleaned up by the transform. The sole
+ contents of the field body must be a paragraph containing an
+ expanded RCS keyword of the form "$keyword: expansion text $". Any
+ RCS keyword can be processed in any bibliographic field. The
+ dollar signs and leading RCS keyword name are removed. Extra
+ processing is done for the following RCS keywords:
+
+ - "RCSfile" expands to the name of the file in the RCS or CVS
+ repository, which is the name of the source file with a ",v"
+ suffix appended. The transform will remove the ",v" suffix.
+
+ - "Date" expands to the format "YYYY/MM/DD hh:mm:ss" (in the UTC
+ time zone). The RCS Keywords transform will extract just the
+ date itself and transform it to an ISO 8601 format date, as in
+ "2000-12-31".
+
+ (Since the source file for this text is itself stored under CVS,
+ we can't show an example of the "Date" RCS keyword because we
+ can't prevent any RCS keywords used in this explanation from
+ being expanded. Only the "RCSfile" keyword is stable; its
+ expansion text changes only if the file name changes.)
+
+ .. _reStructuredText: http://docutils.sf.net/rst.html
+ .. _reStructuredText Markup Specification:
+ http://docutils.sf.net/docs/ref/rst/restructuredtext.html
+ """
+
+ default_priority = 340
+
+ biblio_nodes = {
+ 'author': nodes.author,
+ 'authors': nodes.authors,
+ 'organization': nodes.organization,
+ 'address': nodes.address,
+ 'contact': nodes.contact,
+ 'version': nodes.version,
+ 'revision': nodes.revision,
+ 'status': nodes.status,
+ 'date': nodes.date,
+ 'copyright': nodes.copyright,
+ 'dedication': nodes.topic,
+ 'abstract': nodes.topic}
+ """Canonical field name (lowcased) to node class name mapping for
+ bibliographic fields (field_list)."""
+
+ def apply(self):
+ if not getattr(self.document.settings, 'docinfo_xform', 1):
+ return
+ document = self.document
+ index = document.first_child_not_matching_class(
+ nodes.PreBibliographic)
+ if index is None:
+ return
+ candidate = document[index]
+ if isinstance(candidate, nodes.field_list):
+ biblioindex = document.first_child_not_matching_class(
+ (nodes.Titular, nodes.Decorative))
+ nodelist = self.extract_bibliographic(candidate)
+ del document[index] # untransformed field list (candidate)
+ document[biblioindex:biblioindex] = nodelist
+
+ def extract_bibliographic(self, field_list):
+ docinfo = nodes.docinfo()
+ bibliofields = self.language.bibliographic_fields
+ labels = self.language.labels
+ topics = {'dedication': None, 'abstract': None}
+ for field in field_list:
+ try:
+ name = field[0][0].astext()
+ normedname = nodes.fully_normalize_name(name)
+ if not (len(field) == 2 and normedname in bibliofields
+ and self.check_empty_biblio_field(field, name)):
+ raise TransformError
+ canonical = bibliofields[normedname]
+ biblioclass = self.biblio_nodes[canonical]
+ if issubclass(biblioclass, nodes.TextElement):
+ if not self.check_compound_biblio_field(field, name):
+ raise TransformError
+ utils.clean_rcs_keywords(
+ field[1][0], self.rcs_keyword_substitutions)
+ docinfo.append(biblioclass('', '', *field[1][0]))
+ elif issubclass(biblioclass, nodes.authors):
+ self.extract_authors(field, name, docinfo)
+ elif issubclass(biblioclass, nodes.topic):
+ if topics[canonical]:
+ field[-1] += self.document.reporter.warning(
+ 'There can only be one "%s" field.' % name,
+ base_node=field)
+ raise TransformError
+ title = nodes.title(name, labels[canonical])
+ title[0].rawsource = labels[canonical]
+ topics[canonical] = biblioclass(
+ '', title, classes=[canonical], *field[1].children)
+ else:
+ docinfo.append(biblioclass('', *field[1].children))
+ except TransformError:
+ if len(field[-1]) == 1 \
+ and isinstance(field[-1][0], nodes.paragraph):
+ utils.clean_rcs_keywords(
+ field[-1][0], self.rcs_keyword_substitutions)
+ # if normedname not in bibliofields:
+ classvalue = nodes.make_id(normedname)
+ if classvalue:
+ field['classes'].append(classvalue)
+ docinfo.append(field)
+ nodelist = []
+ if len(docinfo) != 0:
+ nodelist.append(docinfo)
+ for name in ('dedication', 'abstract'):
+ if topics[name]:
+ nodelist.append(topics[name])
+ return nodelist
+
+ def check_empty_biblio_field(self, field, name):
+ if len(field[-1]) < 1:
+ field[-1] += self.document.reporter.warning(
+ 'Cannot extract empty bibliographic field "%s".' % name,
+ base_node=field)
+ return None
+ return 1
+
+ def check_compound_biblio_field(self, field, name):
+ if len(field[-1]) > 1:
+ field[-1] += self.document.reporter.warning(
+ 'Cannot extract compound bibliographic field "%s".' % name,
+ base_node=field)
+ return None
+ if not isinstance(field[-1][0], nodes.paragraph):
+ field[-1] += self.document.reporter.warning(
+ 'Cannot extract bibliographic field "%s" containing '
+ 'anything other than a single paragraph.' % name,
+ base_node=field)
+ return None
+ return 1
+
+ rcs_keyword_substitutions = [
+ (re.compile(r'\$' r'Date: (\d\d\d\d)[-/](\d\d)[-/](\d\d)[ T][\d:]+'
+ r'[^$]* \$', re.IGNORECASE), r'\1-\2-\3'),
+ (re.compile(r'\$' r'RCSfile: (.+),v \$', re.IGNORECASE), r'\1'),
+ (re.compile(r'\$[a-zA-Z]+: (.+) \$'), r'\1'),]
+
+ def extract_authors(self, field, name, docinfo):
+ try:
+ if len(field[1]) == 1:
+ if isinstance(field[1][0], nodes.paragraph):
+ authors = self.authors_from_one_paragraph(field)
+ elif isinstance(field[1][0], nodes.bullet_list):
+ authors = self.authors_from_bullet_list(field)
+ else:
+ raise TransformError
+ else:
+ authors = self.authors_from_paragraphs(field)
+ authornodes = [nodes.author('', '', *author)
+ for author in authors if author]
+ if len(authornodes) >= 1:
+ docinfo.append(nodes.authors('', *authornodes))
+ else:
+ raise TransformError
+ except TransformError:
+ field[-1] += self.document.reporter.warning(
+ 'Bibliographic field "%s" incompatible with extraction: '
+ 'it must contain either a single paragraph (with authors '
+ 'separated by one of "%s"), multiple paragraphs (one per '
+ 'author), or a bullet list with one paragraph (one author) '
+ 'per item.'
+ % (name, ''.join(self.language.author_separators)),
+ base_node=field)
+ raise
+
+ def authors_from_one_paragraph(self, field):
+ """Return list of Text nodes for authornames.
+
+ The set of separators is locale dependent (default: ";"- or ",").
+ """
+ # @@ keep original formatting? (e.g. ``:authors: A. Test, *et-al*``)
+ text = ''.join(unicode(node)
+ for node in field[1].traverse(nodes.Text))
+ if not text:
+ raise TransformError
+ for authorsep in self.language.author_separators:
+ # don't split at escaped `authorsep`:
+ pattern = '(?<!\x00)%s' % authorsep
+ authornames = re.split(pattern, text)
+ if len(authornames) > 1:
+ break
+ authornames = (name.strip() for name in authornames)
+ authors = [[nodes.Text(name, utils.unescape(name, True))]
+ for name in authornames if name]
+ return authors
+
+ def authors_from_bullet_list(self, field):
+ authors = []
+ for item in field[1][0]:
+ if isinstance(item, nodes.comment):
+ continue
+ if len(item) != 1 or not isinstance(item[0], nodes.paragraph):
+ raise TransformError
+ authors.append(item[0].children)
+ if not authors:
+ raise TransformError
+ return authors
+
+ def authors_from_paragraphs(self, field):
+ for item in field[1]:
+ if not isinstance(item, (nodes.paragraph, nodes.comment)):
+ raise TransformError
+ authors = [item.children for item in field[1]
+ if not isinstance(item, nodes.comment)]
+ return authors
--- /dev/null
+# $Id: misc.py 6314 2010-04-26 10:04:17Z milde $
+# Author: David Goodger <goodger@python.org>
+# Copyright: This module has been placed in the public domain.
+
+"""
+Miscellaneous transforms.
+"""
+
+__docformat__ = 'reStructuredText'
+
+from docutils import nodes
+from docutils.transforms import Transform, TransformError
+
+
+class CallBack(Transform):
+
+ """
+ Inserts a callback into a document. The callback is called when the
+ transform is applied, which is determined by its priority.
+
+ For use with `nodes.pending` elements. Requires a ``details['callback']``
+ entry, a bound method or function which takes one parameter: the pending
+ node. Other data can be stored in the ``details`` attribute or in the
+ object hosting the callback method.
+ """
+
+ default_priority = 990
+
+ def apply(self):
+ pending = self.startnode
+ pending.details['callback'](pending)
+ pending.parent.remove(pending)
+
+
+class ClassAttribute(Transform):
+
+ """
+ Move the "class" attribute specified in the "pending" node into the
+ immediately following non-comment element.
+ """
+
+ default_priority = 210
+
+ def apply(self):
+ pending = self.startnode
+ parent = pending.parent
+ child = pending
+ while parent:
+ # Check for appropriate following siblings:
+ for index in range(parent.index(child) + 1, len(parent)):
+ element = parent[index]
+ if (isinstance(element, nodes.Invisible) or
+ isinstance(element, nodes.system_message)):
+ continue
+ element['classes'] += pending.details['class']
+ pending.parent.remove(pending)
+ return
+ else:
+ # At end of section or container; apply to sibling
+ child = parent
+ parent = parent.parent
+ error = self.document.reporter.error(
+ 'No suitable element following "%s" directive'
+ % pending.details['directive'],
+ nodes.literal_block(pending.rawsource, pending.rawsource),
+ line=pending.line)
+ pending.replace_self(error)
+
+
+class Transitions(Transform):
+
+ """
+ Move transitions at the end of sections up the tree. Complain
+ on transitions after a title, at the beginning or end of the
+ document, and after another transition.
+
+ For example, transform this::
+
+ <section>
+ ...
+ <transition>
+ <section>
+ ...
+
+ into this::
+
+ <section>
+ ...
+ <transition>
+ <section>
+ ...
+ """
+
+ default_priority = 830
+
+ def apply(self):
+ for node in self.document.traverse(nodes.transition):
+ self.visit_transition(node)
+
+ def visit_transition(self, node):
+ index = node.parent.index(node)
+ error = None
+ if (index == 0 or
+ isinstance(node.parent[0], nodes.title) and
+ (index == 1 or
+ isinstance(node.parent[1], nodes.subtitle) and
+ index == 2)):
+ assert (isinstance(node.parent, nodes.document) or
+ isinstance(node.parent, nodes.section))
+ error = self.document.reporter.error(
+ 'Document or section may not begin with a transition.',
+ source=node.source, line=node.line)
+ elif isinstance(node.parent[index - 1], nodes.transition):
+ error = self.document.reporter.error(
+ 'At least one body element must separate transitions; '
+ 'adjacent transitions are not allowed.',
+ source=node.source, line=node.line)
+ if error:
+ # Insert before node and update index.
+ node.parent.insert(index, error)
+ index += 1
+ assert index < len(node.parent)
+ if index != len(node.parent) - 1:
+ # No need to move the node.
+ return
+ # Node behind which the transition is to be moved.
+ sibling = node
+ # While sibling is the last node of its parent.
+ while index == len(sibling.parent) - 1:
+ sibling = sibling.parent
+ # If sibling is the whole document (i.e. it has no parent).
+ if sibling.parent is None:
+ # Transition at the end of document. Do not move the
+ # transition up, and place an error behind.
+ error = self.document.reporter.error(
+ 'Document may not end with a transition.',
+ line=node.line)
+ node.parent.insert(node.parent.index(node) + 1, error)
+ return
+ index = sibling.parent.index(sibling)
+ # Remove the original transition node.
+ node.parent.remove(node)
+ # Insert the transition after the sibling.
+ sibling.parent.insert(index + 1, node)
--- /dev/null
+# $Id: parts.py 8403 2019-10-11 10:09:53Z milde $
+# Authors: David Goodger <goodger@python.org>; Ueli Schlaepfer; Dmitry Jemerov
+# Copyright: This module has been placed in the public domain.
+
+"""
+Transforms related to document parts.
+"""
+
+__docformat__ = 'reStructuredText'
+
+
+import re
+import sys
+from docutils import nodes, utils
+from docutils.transforms import TransformError, Transform
+
+
+class SectNum(Transform):
+
+ """
+ Automatically assigns numbers to the titles of document sections.
+
+ It is possible to limit the maximum section level for which the numbers
+ are added. For those sections that are auto-numbered, the "autonum"
+ attribute is set, informing the contents table generator that a different
+ form of the TOC should be used.
+ """
+
+ default_priority = 710
+ """Should be applied before `Contents`."""
+
+ def apply(self):
+ self.maxdepth = self.startnode.details.get('depth', None)
+ self.startvalue = self.startnode.details.get('start', 1)
+ self.prefix = self.startnode.details.get('prefix', '')
+ self.suffix = self.startnode.details.get('suffix', '')
+ self.startnode.parent.remove(self.startnode)
+ if self.document.settings.sectnum_xform:
+ if self.maxdepth is None:
+ self.maxdepth = sys.maxsize
+ self.update_section_numbers(self.document)
+ else: # store details for eventual section numbering by the writer
+ self.document.settings.sectnum_depth = self.maxdepth
+ self.document.settings.sectnum_start = self.startvalue
+ self.document.settings.sectnum_prefix = self.prefix
+ self.document.settings.sectnum_suffix = self.suffix
+
+ def update_section_numbers(self, node, prefix=(), depth=0):
+ depth += 1
+ if prefix:
+ sectnum = 1
+ else:
+ sectnum = self.startvalue
+ for child in node:
+ if isinstance(child, nodes.section):
+ numbers = prefix + (str(sectnum),)
+ title = child[0]
+ # Use for spacing:
+ generated = nodes.generated(
+ '', (self.prefix + '.'.join(numbers) + self.suffix
+ + u'\u00a0' * 3),
+ classes=['sectnum'])
+ title.insert(0, generated)
+ title['auto'] = 1
+ if depth < self.maxdepth:
+ self.update_section_numbers(child, numbers, depth)
+ sectnum += 1
+
+
+class Contents(Transform):
+
+ """
+ This transform generates a table of contents from the entire document tree
+ or from a single branch. It locates "section" elements and builds them
+ into a nested bullet list, which is placed within a "topic" created by the
+ contents directive. A title is either explicitly specified, taken from
+ the appropriate language module, or omitted (local table of contents).
+ The depth may be specified. Two-way references between the table of
+ contents and section titles are generated (requires Writer support).
+
+ This transform requires a startnode, which contains generation
+ options and provides the location for the generated table of contents (the
+ startnode is replaced by the table of contents "topic").
+ """
+
+ default_priority = 720
+
+ def apply(self):
+ try: # let the writer (or output software) build the contents list?
+ toc_by_writer = self.document.settings.use_latex_toc
+ except AttributeError:
+ toc_by_writer = False
+ details = self.startnode.details
+ if 'local' in details:
+ startnode = self.startnode.parent.parent
+ while not (isinstance(startnode, nodes.section)
+ or isinstance(startnode, nodes.document)):
+ # find the ToC root: a direct ancestor of startnode
+ startnode = startnode.parent
+ else:
+ startnode = self.document
+ self.toc_id = self.startnode.parent['ids'][0]
+ if 'backlinks' in details:
+ self.backlinks = details['backlinks']
+ else:
+ self.backlinks = self.document.settings.toc_backlinks
+ if toc_by_writer:
+ # move customization settings to the parent node
+ self.startnode.parent.attributes.update(details)
+ self.startnode.parent.remove(self.startnode)
+ else:
+ contents = self.build_contents(startnode)
+ if len(contents):
+ self.startnode.replace_self(contents)
+ else:
+ self.startnode.parent.parent.remove(self.startnode.parent)
+
+ def build_contents(self, node, level=0):
+ level += 1
+ sections = [sect for sect in node if isinstance(sect, nodes.section)]
+ entries = []
+ autonum = 0
+ depth = self.startnode.details.get('depth', sys.maxsize)
+ for section in sections:
+ title = section[0]
+ auto = title.get('auto') # May be set by SectNum.
+ entrytext = self.copy_and_filter(title)
+ reference = nodes.reference('', '', refid=section['ids'][0],
+ *entrytext)
+ ref_id = self.document.set_id(reference,
+ suggested_prefix='toc-entry')
+ entry = nodes.paragraph('', '', reference)
+ item = nodes.list_item('', entry)
+ if ( self.backlinks in ('entry', 'top')
+ and title.next_node(nodes.reference) is None):
+ if self.backlinks == 'entry':
+ title['refid'] = ref_id
+ elif self.backlinks == 'top':
+ title['refid'] = self.toc_id
+ if level < depth:
+ subsects = self.build_contents(section, level)
+ item += subsects
+ entries.append(item)
+ if entries:
+ contents = nodes.bullet_list('', *entries)
+ if auto:
+ contents['classes'].append('auto-toc')
+ return contents
+ else:
+ return []
+
+ def copy_and_filter(self, node):
+ """Return a copy of a title, with references, images, etc. removed."""
+ visitor = ContentsFilter(self.document)
+ node.walkabout(visitor)
+ return visitor.get_entry_text()
+
+
+class ContentsFilter(nodes.TreeCopyVisitor):
+
+ def get_entry_text(self):
+ return self.get_tree_copy().children
+
+ def visit_citation_reference(self, node):
+ raise nodes.SkipNode
+
+ def visit_footnote_reference(self, node):
+ raise nodes.SkipNode
+
+ def visit_image(self, node):
+ if node.hasattr('alt'):
+ self.parent.append(nodes.Text(node['alt']))
+ raise nodes.SkipNode
+
+ def ignore_node_but_process_children(self, node):
+ raise nodes.SkipDeparture
+
+ visit_problematic = ignore_node_but_process_children
+ visit_reference = ignore_node_but_process_children
+ visit_target = ignore_node_but_process_children
--- /dev/null
+# $Id: peps.py 7995 2016-12-10 17:50:59Z milde $
+# Author: David Goodger <goodger@python.org>
+# Copyright: This module has been placed in the public domain.
+
+"""
+Transforms for PEP processing.
+
+- `Headers`: Used to transform a PEP's initial RFC-2822 header. It remains a
+ field list, but some entries get processed.
+- `Contents`: Auto-inserts a table of contents.
+- `PEPZero`: Special processing for PEP 0.
+"""
+
+__docformat__ = 'reStructuredText'
+
+import sys
+import os
+import re
+import time
+from docutils import nodes, utils, languages
+from docutils import ApplicationError, DataError
+from docutils.transforms import Transform, TransformError
+from docutils.transforms import parts, references, misc
+
+
+class Headers(Transform):
+
+ """
+ Process fields in a PEP's initial RFC-2822 header.
+ """
+
+ default_priority = 360
+
+ pep_url = 'pep-%04d'
+ pep_cvs_url = ('http://hg.python.org'
+ '/peps/file/default/pep-%04d.txt')
+ rcs_keyword_substitutions = (
+ (re.compile(r'\$' r'RCSfile: (.+),v \$$', re.IGNORECASE), r'\1'),
+ (re.compile(r'\$[a-zA-Z]+: (.+) \$$'), r'\1'),)
+
+ def apply(self):
+ if not len(self.document):
+ # @@@ replace these DataErrors with proper system messages
+ raise DataError('Document tree is empty.')
+ header = self.document[0]
+ if not isinstance(header, nodes.field_list) or \
+ 'rfc2822' not in header['classes']:
+ raise DataError('Document does not begin with an RFC-2822 '
+ 'header; it is not a PEP.')
+ pep = None
+ for field in header:
+ if field[0].astext().lower() == 'pep': # should be the first field
+ value = field[1].astext()
+ try:
+ pep = int(value)
+ cvs_url = self.pep_cvs_url % pep
+ except ValueError:
+ pep = value
+ cvs_url = None
+ msg = self.document.reporter.warning(
+ '"PEP" header must contain an integer; "%s" is an '
+ 'invalid value.' % pep, base_node=field)
+ msgid = self.document.set_id(msg)
+ prb = nodes.problematic(value, value or '(none)',
+ refid=msgid)
+ prbid = self.document.set_id(prb)
+ msg.add_backref(prbid)
+ if len(field[1]):
+ field[1][0][:] = [prb]
+ else:
+ field[1] += nodes.paragraph('', '', prb)
+ break
+ if pep is None:
+ raise DataError('Document does not contain an RFC-2822 "PEP" '
+ 'header.')
+ if pep == 0:
+ # Special processing for PEP 0.
+ pending = nodes.pending(PEPZero)
+ self.document.insert(1, pending)
+ self.document.note_pending(pending)
+ if len(header) < 2 or header[1][0].astext().lower() != 'title':
+ raise DataError('No title!')
+ for field in header:
+ name = field[0].astext().lower()
+ body = field[1]
+ if len(body) > 1:
+ raise DataError('PEP header field body contains multiple '
+ 'elements:\n%s' % field.pformat(level=1))
+ elif len(body) == 1:
+ if not isinstance(body[0], nodes.paragraph):
+ raise DataError('PEP header field body may only contain '
+ 'a single paragraph:\n%s'
+ % field.pformat(level=1))
+ elif name == 'last-modified':
+ date = time.strftime(
+ '%d-%b-%Y',
+ time.localtime(os.stat(self.document['source'])[8]))
+ if cvs_url:
+ body += nodes.paragraph(
+ '', '', nodes.reference('', date, refuri=cvs_url))
+ else:
+ # empty
+ continue
+ para = body[0]
+ if name == 'author':
+ for node in para:
+ if isinstance(node, nodes.reference):
+ node.replace_self(mask_email(node))
+ elif name == 'discussions-to':
+ for node in para:
+ if isinstance(node, nodes.reference):
+ node.replace_self(mask_email(node, pep))
+ elif name in ('replaces', 'replaced-by', 'requires'):
+ newbody = []
+ space = nodes.Text(' ')
+ for refpep in re.split(r',?\s+', body.astext()):
+ pepno = int(refpep)
+ newbody.append(nodes.reference(
+ refpep, refpep,
+ refuri=(self.document.settings.pep_base_url
+ + self.pep_url % pepno)))
+ newbody.append(space)
+ para[:] = newbody[:-1] # drop trailing space
+ elif name == 'last-modified':
+ utils.clean_rcs_keywords(para, self.rcs_keyword_substitutions)
+ if cvs_url:
+ date = para.astext()
+ para[:] = [nodes.reference('', date, refuri=cvs_url)]
+ elif name == 'content-type':
+ pep_type = para.astext()
+ uri = self.document.settings.pep_base_url + self.pep_url % 12
+ para[:] = [nodes.reference('', pep_type, refuri=uri)]
+ elif name == 'version' and len(body):
+ utils.clean_rcs_keywords(para, self.rcs_keyword_substitutions)
+
+
+class Contents(Transform):
+
+ """
+ Insert an empty table of contents topic and a transform placeholder into
+ the document after the RFC 2822 header.
+ """
+
+ default_priority = 380
+
+ def apply(self):
+ language = languages.get_language(self.document.settings.language_code,
+ self.document.reporter)
+ name = language.labels['contents']
+ title = nodes.title('', name)
+ topic = nodes.topic('', title, classes=['contents'])
+ name = nodes.fully_normalize_name(name)
+ if not self.document.has_name(name):
+ topic['names'].append(name)
+ self.document.note_implicit_target(topic)
+ pending = nodes.pending(parts.Contents)
+ topic += pending
+ self.document.insert(1, topic)
+ self.document.note_pending(pending)
+
+
+class TargetNotes(Transform):
+
+ """
+ Locate the "References" section, insert a placeholder for an external
+ target footnote insertion transform at the end, and schedule the
+ transform to run immediately.
+ """
+
+ default_priority = 520
+
+ def apply(self):
+ doc = self.document
+ i = len(doc) - 1
+ refsect = copyright = None
+ while i >= 0 and isinstance(doc[i], nodes.section):
+ title_words = doc[i][0].astext().lower().split()
+ if 'references' in title_words:
+ refsect = doc[i]
+ break
+ elif 'copyright' in title_words:
+ copyright = i
+ i -= 1
+ if not refsect:
+ refsect = nodes.section()
+ refsect += nodes.title('', 'References')
+ doc.set_id(refsect)
+ if copyright:
+ # Put the new "References" section before "Copyright":
+ doc.insert(copyright, refsect)
+ else:
+ # Put the new "References" section at end of doc:
+ doc.append(refsect)
+ pending = nodes.pending(references.TargetNotes)
+ refsect.append(pending)
+ self.document.note_pending(pending, 0)
+ pending = nodes.pending(misc.CallBack,
+ details={'callback': self.cleanup_callback})
+ refsect.append(pending)
+ self.document.note_pending(pending, 1)
+
+ def cleanup_callback(self, pending):
+ """
+ Remove an empty "References" section.
+
+ Called after the `references.TargetNotes` transform is complete.
+ """
+ if len(pending.parent) == 2: # <title> and <pending>
+ pending.parent.parent.remove(pending.parent)
+
+
+class PEPZero(Transform):
+
+ """
+ Special processing for PEP 0.
+ """
+
+ default_priority =760
+
+ def apply(self):
+ visitor = PEPZeroSpecial(self.document)
+ self.document.walk(visitor)
+ self.startnode.parent.remove(self.startnode)
+
+
+class PEPZeroSpecial(nodes.SparseNodeVisitor):
+
+ """
+ Perform the special processing needed by PEP 0:
+
+ - Mask email addresses.
+
+ - Link PEP numbers in the second column of 4-column tables to the PEPs
+ themselves.
+ """
+
+ pep_url = Headers.pep_url
+
+ def unknown_visit(self, node):
+ pass
+
+ def visit_reference(self, node):
+ node.replace_self(mask_email(node))
+
+ def visit_field_list(self, node):
+ if 'rfc2822' in node['classes']:
+ raise nodes.SkipNode
+
+ def visit_tgroup(self, node):
+ self.pep_table = node['cols'] == 4
+ self.entry = 0
+
+ def visit_colspec(self, node):
+ self.entry += 1
+ if self.pep_table and self.entry == 2:
+ node['classes'].append('num')
+
+ def visit_row(self, node):
+ self.entry = 0
+
+ def visit_entry(self, node):
+ self.entry += 1
+ if self.pep_table and self.entry == 2 and len(node) == 1:
+ node['classes'].append('num')
+ p = node[0]
+ if isinstance(p, nodes.paragraph) and len(p) == 1:
+ text = p.astext()
+ try:
+ pep = int(text)
+ ref = (self.document.settings.pep_base_url
+ + self.pep_url % pep)
+ p[0] = nodes.reference(text, text, refuri=ref)
+ except ValueError:
+ pass
+
+
+non_masked_addresses = ('peps@python.org',
+ 'python-list@python.org',
+ 'python-dev@python.org')
+
+def mask_email(ref, pepno=None):
+ """
+ Mask the email address in `ref` and return a replacement node.
+
+ `ref` is returned unchanged if it contains no email address.
+
+ For email addresses such as "user@host", mask the address as "user at
+ host" (text) to thwart simple email address harvesters (except for those
+ listed in `non_masked_addresses`). If a PEP number (`pepno`) is given,
+ return a reference including a default email subject.
+ """
+ if ref.hasattr('refuri') and ref['refuri'].startswith('mailto:'):
+ if ref['refuri'][8:] in non_masked_addresses:
+ replacement = ref[0]
+ else:
+ replacement_text = ref.astext().replace('@', ' at ')
+ replacement = nodes.raw('', replacement_text, format='html')
+ if pepno is None:
+ return replacement
+ else:
+ ref['refuri'] += '?subject=PEP%%20%s' % pepno
+ ref[:] = [replacement]
+ return ref
+ else:
+ return ref
--- /dev/null
+# $Id: references.py 8387 2019-09-06 13:16:34Z milde $
+# Author: David Goodger <goodger@python.org>
+# Copyright: This module has been placed in the public domain.
+
+"""
+Transforms for resolving references.
+"""
+
+__docformat__ = 'reStructuredText'
+
+import sys
+import re
+from docutils import nodes, utils
+from docutils.transforms import TransformError, Transform
+
+
+class PropagateTargets(Transform):
+
+ """
+ Propagate empty internal targets to the next element.
+
+ Given the following nodes::
+
+ <target ids="internal1" names="internal1">
+ <target anonymous="1" ids="id1">
+ <target ids="internal2" names="internal2">
+ <paragraph>
+ This is a test.
+
+ PropagateTargets propagates the ids and names of the internal
+ targets preceding the paragraph to the paragraph itself::
+
+ <target refid="internal1">
+ <target anonymous="1" refid="id1">
+ <target refid="internal2">
+ <paragraph ids="internal2 id1 internal1" names="internal2 internal1">
+ This is a test.
+ """
+
+ default_priority = 260
+
+ def apply(self):
+ for target in self.document.traverse(nodes.target):
+ # Only block-level targets without reference (like ".. target:"):
+ if (isinstance(target.parent, nodes.TextElement) or
+ (target.hasattr('refid') or target.hasattr('refuri') or
+ target.hasattr('refname'))):
+ continue
+ assert len(target) == 0, 'error: block-level target has children'
+ next_node = target.next_node(ascend=True)
+ # Do not move names and ids into Invisibles (we'd lose the
+ # attributes) or different Targetables (e.g. footnotes).
+ if (next_node is not None and
+ ((not isinstance(next_node, nodes.Invisible) and
+ not isinstance(next_node, nodes.Targetable)) or
+ isinstance(next_node, nodes.target))):
+ next_node['ids'].extend(target['ids'])
+ next_node['names'].extend(target['names'])
+ # Set defaults for next_node.expect_referenced_by_name/id.
+ if not hasattr(next_node, 'expect_referenced_by_name'):
+ next_node.expect_referenced_by_name = {}
+ if not hasattr(next_node, 'expect_referenced_by_id'):
+ next_node.expect_referenced_by_id = {}
+ for id in target['ids']:
+ # Update IDs to node mapping.
+ self.document.ids[id] = next_node
+ # If next_node is referenced by id ``id``, this
+ # target shall be marked as referenced.
+ next_node.expect_referenced_by_id[id] = target
+ for name in target['names']:
+ next_node.expect_referenced_by_name[name] = target
+ # If there are any expect_referenced_by_... attributes
+ # in target set, copy them to next_node.
+ next_node.expect_referenced_by_name.update(
+ getattr(target, 'expect_referenced_by_name', {}))
+ next_node.expect_referenced_by_id.update(
+ getattr(target, 'expect_referenced_by_id', {}))
+ # Set refid to point to the first former ID of target
+ # which is now an ID of next_node.
+ target['refid'] = target['ids'][0]
+ # Clear ids and names; they have been moved to
+ # next_node.
+ target['ids'] = []
+ target['names'] = []
+ self.document.note_refid(target)
+
+
+class AnonymousHyperlinks(Transform):
+
+ """
+ Link anonymous references to targets. Given::
+
+ <paragraph>
+ <reference anonymous="1">
+ internal
+ <reference anonymous="1">
+ external
+ <target anonymous="1" ids="id1">
+ <target anonymous="1" ids="id2" refuri="http://external">
+
+ Corresponding references are linked via "refid" or resolved via "refuri"::
+
+ <paragraph>
+ <reference anonymous="1" refid="id1">
+ text
+ <reference anonymous="1" refuri="http://external">
+ external
+ <target anonymous="1" ids="id1">
+ <target anonymous="1" ids="id2" refuri="http://external">
+ """
+
+ default_priority = 440
+
+ def apply(self):
+ anonymous_refs = []
+ anonymous_targets = []
+ for node in self.document.traverse(nodes.reference):
+ if node.get('anonymous'):
+ anonymous_refs.append(node)
+ for node in self.document.traverse(nodes.target):
+ if node.get('anonymous'):
+ anonymous_targets.append(node)
+ if len(anonymous_refs) \
+ != len(anonymous_targets):
+ msg = self.document.reporter.error(
+ 'Anonymous hyperlink mismatch: %s references but %s '
+ 'targets.\nSee "backrefs" attribute for IDs.'
+ % (len(anonymous_refs), len(anonymous_targets)))
+ msgid = self.document.set_id(msg)
+ for ref in anonymous_refs:
+ prb = nodes.problematic(
+ ref.rawsource, ref.rawsource, refid=msgid)
+ prbid = self.document.set_id(prb)
+ msg.add_backref(prbid)
+ ref.replace_self(prb)
+ return
+ for ref, target in zip(anonymous_refs, anonymous_targets):
+ target.referenced = 1
+ while True:
+ if target.hasattr('refuri'):
+ ref['refuri'] = target['refuri']
+ ref.resolved = 1
+ break
+ else:
+ if not target['ids']:
+ # Propagated target.
+ target = self.document.ids[target['refid']]
+ continue
+ ref['refid'] = target['ids'][0]
+ self.document.note_refid(ref)
+ break
+
+
+class IndirectHyperlinks(Transform):
+
+ """
+ a) Indirect external references::
+
+ <paragraph>
+ <reference refname="indirect external">
+ indirect external
+ <target id="id1" name="direct external"
+ refuri="http://indirect">
+ <target id="id2" name="indirect external"
+ refname="direct external">
+
+ The "refuri" attribute is migrated back to all indirect targets
+ from the final direct target (i.e. a target not referring to
+ another indirect target)::
+
+ <paragraph>
+ <reference refname="indirect external">
+ indirect external
+ <target id="id1" name="direct external"
+ refuri="http://indirect">
+ <target id="id2" name="indirect external"
+ refuri="http://indirect">
+
+ Once the attribute is migrated, the preexisting "refname" attribute
+ is dropped.
+
+ b) Indirect internal references::
+
+ <target id="id1" name="final target">
+ <paragraph>
+ <reference refname="indirect internal">
+ indirect internal
+ <target id="id2" name="indirect internal 2"
+ refname="final target">
+ <target id="id3" name="indirect internal"
+ refname="indirect internal 2">
+
+ Targets which indirectly refer to an internal target become one-hop
+ indirect (their "refid" attributes are directly set to the internal
+ target's "id"). References which indirectly refer to an internal
+ target become direct internal references::
+
+ <target id="id1" name="final target">
+ <paragraph>
+ <reference refid="id1">
+ indirect internal
+ <target id="id2" name="indirect internal 2" refid="id1">
+ <target id="id3" name="indirect internal" refid="id1">
+ """
+
+ default_priority = 460
+
+ def apply(self):
+ for target in self.document.indirect_targets:
+ if not target.resolved:
+ self.resolve_indirect_target(target)
+ self.resolve_indirect_references(target)
+
+ def resolve_indirect_target(self, target):
+ refname = target.get('refname')
+ if refname is None:
+ reftarget_id = target['refid']
+ else:
+ reftarget_id = self.document.nameids.get(refname)
+ if not reftarget_id:
+ # Check the unknown_reference_resolvers
+ for resolver_function in \
+ self.document.transformer.unknown_reference_resolvers:
+ if resolver_function(target):
+ break
+ else:
+ self.nonexistent_indirect_target(target)
+ return
+ reftarget = self.document.ids[reftarget_id]
+ reftarget.note_referenced_by(id=reftarget_id)
+ if isinstance(reftarget, nodes.target) \
+ and not reftarget.resolved and reftarget.hasattr('refname'):
+ if hasattr(target, 'multiply_indirect'):
+ #and target.multiply_indirect):
+ #del target.multiply_indirect
+ self.circular_indirect_reference(target)
+ return
+ target.multiply_indirect = 1
+ self.resolve_indirect_target(reftarget) # multiply indirect
+ del target.multiply_indirect
+ if reftarget.hasattr('refuri'):
+ target['refuri'] = reftarget['refuri']
+ if 'refid' in target:
+ del target['refid']
+ elif reftarget.hasattr('refid'):
+ target['refid'] = reftarget['refid']
+ self.document.note_refid(target)
+ else:
+ if reftarget['ids']:
+ target['refid'] = reftarget_id
+ self.document.note_refid(target)
+ else:
+ self.nonexistent_indirect_target(target)
+ return
+ if refname is not None:
+ del target['refname']
+ target.resolved = 1
+
+ def nonexistent_indirect_target(self, target):
+ if target['refname'] in self.document.nameids:
+ self.indirect_target_error(target, 'which is a duplicate, and '
+ 'cannot be used as a unique reference')
+ else:
+ self.indirect_target_error(target, 'which does not exist')
+
+ def circular_indirect_reference(self, target):
+ self.indirect_target_error(target, 'forming a circular reference')
+
+ def indirect_target_error(self, target, explanation):
+ naming = ''
+ reflist = []
+ if target['names']:
+ naming = '"%s" ' % target['names'][0]
+ for name in target['names']:
+ reflist.extend(self.document.refnames.get(name, []))
+ for id in target['ids']:
+ reflist.extend(self.document.refids.get(id, []))
+ if target['ids']:
+ naming += '(id="%s")' % target['ids'][0]
+ msg = self.document.reporter.error(
+ 'Indirect hyperlink target %s refers to target "%s", %s.'
+ % (naming, target['refname'], explanation), base_node=target)
+ msgid = self.document.set_id(msg)
+ for ref in utils.uniq(reflist):
+ prb = nodes.problematic(
+ ref.rawsource, ref.rawsource, refid=msgid)
+ prbid = self.document.set_id(prb)
+ msg.add_backref(prbid)
+ ref.replace_self(prb)
+ target.resolved = 1
+
+ def resolve_indirect_references(self, target):
+ if target.hasattr('refid'):
+ attname = 'refid'
+ call_method = self.document.note_refid
+ elif target.hasattr('refuri'):
+ attname = 'refuri'
+ call_method = None
+ else:
+ return
+ attval = target[attname]
+ for name in target['names']:
+ reflist = self.document.refnames.get(name, [])
+ if reflist:
+ target.note_referenced_by(name=name)
+ for ref in reflist:
+ if ref.resolved:
+ continue
+ del ref['refname']
+ ref[attname] = attval
+ if call_method:
+ call_method(ref)
+ ref.resolved = 1
+ if isinstance(ref, nodes.target):
+ self.resolve_indirect_references(ref)
+ for id in target['ids']:
+ reflist = self.document.refids.get(id, [])
+ if reflist:
+ target.note_referenced_by(id=id)
+ for ref in reflist:
+ if ref.resolved:
+ continue
+ del ref['refid']
+ ref[attname] = attval
+ if call_method:
+ call_method(ref)
+ ref.resolved = 1
+ if isinstance(ref, nodes.target):
+ self.resolve_indirect_references(ref)
+
+
+class ExternalTargets(Transform):
+
+ """
+ Given::
+
+ <paragraph>
+ <reference refname="direct external">
+ direct external
+ <target id="id1" name="direct external" refuri="http://direct">
+
+ The "refname" attribute is replaced by the direct "refuri" attribute::
+
+ <paragraph>
+ <reference refuri="http://direct">
+ direct external
+ <target id="id1" name="direct external" refuri="http://direct">
+ """
+
+ default_priority = 640
+
+ def apply(self):
+ for target in self.document.traverse(nodes.target):
+ if target.hasattr('refuri'):
+ refuri = target['refuri']
+ for name in target['names']:
+ reflist = self.document.refnames.get(name, [])
+ if reflist:
+ target.note_referenced_by(name=name)
+ for ref in reflist:
+ if ref.resolved:
+ continue
+ del ref['refname']
+ ref['refuri'] = refuri
+ ref.resolved = 1
+
+
+class InternalTargets(Transform):
+
+ default_priority = 660
+
+ def apply(self):
+ for target in self.document.traverse(nodes.target):
+ if not target.hasattr('refuri') and not target.hasattr('refid'):
+ self.resolve_reference_ids(target)
+
+ def resolve_reference_ids(self, target):
+ """
+ Given::
+
+ <paragraph>
+ <reference refname="direct internal">
+ direct internal
+ <target id="id1" name="direct internal">
+
+ The "refname" attribute is replaced by "refid" linking to the target's
+ "id"::
+
+ <paragraph>
+ <reference refid="id1">
+ direct internal
+ <target id="id1" name="direct internal">
+ """
+ for name in target['names']:
+ refid = self.document.nameids.get(name)
+ reflist = self.document.refnames.get(name, [])
+ if reflist:
+ target.note_referenced_by(name=name)
+ for ref in reflist:
+ if ref.resolved:
+ continue
+ if refid:
+ del ref['refname']
+ ref['refid'] = refid
+ ref.resolved = 1
+
+
+class Footnotes(Transform):
+
+ """
+ Assign numbers to autonumbered footnotes, and resolve links to footnotes,
+ citations, and their references.
+
+ Given the following ``document`` as input::
+
+ <document>
+ <paragraph>
+ A labeled autonumbered footnote referece:
+ <footnote_reference auto="1" id="id1" refname="footnote">
+ <paragraph>
+ An unlabeled autonumbered footnote referece:
+ <footnote_reference auto="1" id="id2">
+ <footnote auto="1" id="id3">
+ <paragraph>
+ Unlabeled autonumbered footnote.
+ <footnote auto="1" id="footnote" name="footnote">
+ <paragraph>
+ Labeled autonumbered footnote.
+
+ Auto-numbered footnotes have attribute ``auto="1"`` and no label.
+ Auto-numbered footnote_references have no reference text (they're
+ empty elements). When resolving the numbering, a ``label`` element
+ is added to the beginning of the ``footnote``, and reference text
+ to the ``footnote_reference``.
+
+ The transformed result will be::
+
+ <document>
+ <paragraph>
+ A labeled autonumbered footnote referece:
+ <footnote_reference auto="1" id="id1" refid="footnote">
+ 2
+ <paragraph>
+ An unlabeled autonumbered footnote referece:
+ <footnote_reference auto="1" id="id2" refid="id3">
+ 1
+ <footnote auto="1" id="id3" backrefs="id2">
+ <label>
+ 1
+ <paragraph>
+ Unlabeled autonumbered footnote.
+ <footnote auto="1" id="footnote" name="footnote" backrefs="id1">
+ <label>
+ 2
+ <paragraph>
+ Labeled autonumbered footnote.
+
+ Note that the footnotes are not in the same order as the references.
+
+ The labels and reference text are added to the auto-numbered ``footnote``
+ and ``footnote_reference`` elements. Footnote elements are backlinked to
+ their references via "refids" attributes. References are assigned "id"
+ and "refid" attributes.
+
+ After adding labels and reference text, the "auto" attributes can be
+ ignored.
+ """
+
+ default_priority = 620
+
+ autofootnote_labels = None
+ """Keep track of unlabeled autonumbered footnotes."""
+
+ symbols = [
+ # Entries 1-4 and 6 below are from section 12.51 of
+ # The Chicago Manual of Style, 14th edition.
+ '*', # asterisk/star
+ u'\u2020', # dagger †
+ u'\u2021', # double dagger ‡
+ u'\u00A7', # section mark §
+ u'\u00B6', # paragraph mark (pilcrow) ¶
+ # (parallels ['||'] in CMoS)
+ '#', # number sign
+ # The entries below were chosen arbitrarily.
+ u'\u2660', # spade suit ♠
+ u'\u2665', # heart suit ♥
+ u'\u2666', # diamond suit ♦
+ u'\u2663', # club suit ♣
+ ]
+
+ def apply(self):
+ self.autofootnote_labels = []
+ startnum = self.document.autofootnote_start
+ self.document.autofootnote_start = self.number_footnotes(startnum)
+ self.number_footnote_references(startnum)
+ self.symbolize_footnotes()
+ self.resolve_footnotes_and_citations()
+
+ def number_footnotes(self, startnum):
+ """
+ Assign numbers to autonumbered footnotes.
+
+ For labeled autonumbered footnotes, copy the number over to
+ corresponding footnote references.
+ """
+ for footnote in self.document.autofootnotes:
+ while True:
+ label = str(startnum)
+ startnum += 1
+ if label not in self.document.nameids:
+ break
+ footnote.insert(0, nodes.label('', label))
+ for name in footnote['names']:
+ for ref in self.document.footnote_refs.get(name, []):
+ ref += nodes.Text(label)
+ ref.delattr('refname')
+ assert len(footnote['ids']) == len(ref['ids']) == 1
+ ref['refid'] = footnote['ids'][0]
+ footnote.add_backref(ref['ids'][0])
+ self.document.note_refid(ref)
+ ref.resolved = 1
+ if not footnote['names'] and not footnote['dupnames']:
+ footnote['names'].append(label)
+ self.document.note_explicit_target(footnote, footnote)
+ self.autofootnote_labels.append(label)
+ return startnum
+
+ def number_footnote_references(self, startnum):
+ """Assign numbers to autonumbered footnote references."""
+ i = 0
+ for ref in self.document.autofootnote_refs:
+ if ref.resolved or ref.hasattr('refid'):
+ continue
+ try:
+ label = self.autofootnote_labels[i]
+ except IndexError:
+ msg = self.document.reporter.error(
+ 'Too many autonumbered footnote references: only %s '
+ 'corresponding footnotes available.'
+ % len(self.autofootnote_labels), base_node=ref)
+ msgid = self.document.set_id(msg)
+ for ref in self.document.autofootnote_refs[i:]:
+ if ref.resolved or ref.hasattr('refname'):
+ continue
+ prb = nodes.problematic(
+ ref.rawsource, ref.rawsource, refid=msgid)
+ prbid = self.document.set_id(prb)
+ msg.add_backref(prbid)
+ ref.replace_self(prb)
+ break
+ ref += nodes.Text(label)
+ id = self.document.nameids[label]
+ footnote = self.document.ids[id]
+ ref['refid'] = id
+ self.document.note_refid(ref)
+ assert len(ref['ids']) == 1
+ footnote.add_backref(ref['ids'][0])
+ ref.resolved = 1
+ i += 1
+
+ def symbolize_footnotes(self):
+ """Add symbols indexes to "[*]"-style footnotes and references."""
+ labels = []
+ for footnote in self.document.symbol_footnotes:
+ reps, index = divmod(self.document.symbol_footnote_start,
+ len(self.symbols))
+ labeltext = self.symbols[index] * (reps + 1)
+ labels.append(labeltext)
+ footnote.insert(0, nodes.label('', labeltext))
+ self.document.symbol_footnote_start += 1
+ self.document.set_id(footnote)
+ i = 0
+ for ref in self.document.symbol_footnote_refs:
+ try:
+ ref += nodes.Text(labels[i])
+ except IndexError:
+ msg = self.document.reporter.error(
+ 'Too many symbol footnote references: only %s '
+ 'corresponding footnotes available.' % len(labels),
+ base_node=ref)
+ msgid = self.document.set_id(msg)
+ for ref in self.document.symbol_footnote_refs[i:]:
+ if ref.resolved or ref.hasattr('refid'):
+ continue
+ prb = nodes.problematic(
+ ref.rawsource, ref.rawsource, refid=msgid)
+ prbid = self.document.set_id(prb)
+ msg.add_backref(prbid)
+ ref.replace_self(prb)
+ break
+ footnote = self.document.symbol_footnotes[i]
+ assert len(footnote['ids']) == 1
+ ref['refid'] = footnote['ids'][0]
+ self.document.note_refid(ref)
+ footnote.add_backref(ref['ids'][0])
+ i += 1
+
+ def resolve_footnotes_and_citations(self):
+ """
+ Link manually-labeled footnotes and citations to/from their
+ references.
+ """
+ for footnote in self.document.footnotes:
+ for label in footnote['names']:
+ if label in self.document.footnote_refs:
+ reflist = self.document.footnote_refs[label]
+ self.resolve_references(footnote, reflist)
+ for citation in self.document.citations:
+ for label in citation['names']:
+ if label in self.document.citation_refs:
+ reflist = self.document.citation_refs[label]
+ self.resolve_references(citation, reflist)
+
+ def resolve_references(self, note, reflist):
+ assert len(note['ids']) == 1
+ id = note['ids'][0]
+ for ref in reflist:
+ if ref.resolved:
+ continue
+ ref.delattr('refname')
+ ref['refid'] = id
+ assert len(ref['ids']) == 1
+ note.add_backref(ref['ids'][0])
+ ref.resolved = 1
+ note.resolved = 1
+
+
+class CircularSubstitutionDefinitionError(Exception): pass
+
+
+class Substitutions(Transform):
+
+ """
+ Given the following ``document`` as input::
+
+ <document>
+ <paragraph>
+ The
+ <substitution_reference refname="biohazard">
+ biohazard
+ symbol is deservedly scary-looking.
+ <substitution_definition name="biohazard">
+ <image alt="biohazard" uri="biohazard.png">
+
+ The ``substitution_reference`` will simply be replaced by the
+ contents of the corresponding ``substitution_definition``.
+
+ The transformed result will be::
+
+ <document>
+ <paragraph>
+ The
+ <image alt="biohazard" uri="biohazard.png">
+ symbol is deservedly scary-looking.
+ <substitution_definition name="biohazard">
+ <image alt="biohazard" uri="biohazard.png">
+ """
+
+ default_priority = 220
+ """The Substitutions transform has to be applied very early, before
+ `docutils.tranforms.frontmatter.DocTitle` and others."""
+
+ def apply(self):
+ defs = self.document.substitution_defs
+ normed = self.document.substitution_names
+ subreflist = list(self.document.traverse(nodes.substitution_reference))
+ nested = {}
+ for ref in subreflist:
+ refname = ref['refname']
+ key = None
+ if refname in defs:
+ key = refname
+ else:
+ normed_name = refname.lower()
+ if normed_name in normed:
+ key = normed[normed_name]
+ if key is None:
+ msg = self.document.reporter.error(
+ 'Undefined substitution referenced: "%s".'
+ % refname, base_node=ref)
+ msgid = self.document.set_id(msg)
+ prb = nodes.problematic(
+ ref.rawsource, ref.rawsource, refid=msgid)
+ prbid = self.document.set_id(prb)
+ msg.add_backref(prbid)
+ ref.replace_self(prb)
+ else:
+ subdef = defs[key]
+ parent = ref.parent
+ index = parent.index(ref)
+ if ('ltrim' in subdef.attributes
+ or 'trim' in subdef.attributes):
+ if index > 0 and isinstance(parent[index - 1],
+ nodes.Text):
+ parent[index - 1] = parent[index - 1].rstrip()
+ if ('rtrim' in subdef.attributes
+ or 'trim' in subdef.attributes):
+ if (len(parent) > index + 1
+ and isinstance(parent[index + 1], nodes.Text)):
+ parent[index + 1] = parent[index + 1].lstrip()
+ subdef_copy = subdef.deepcopy()
+ try:
+ # Take care of nested substitution references:
+ for nested_ref in subdef_copy.traverse(
+ nodes.substitution_reference):
+ nested_name = normed[nested_ref['refname'].lower()]
+ if nested_name in nested.setdefault(nested_name, []):
+ raise CircularSubstitutionDefinitionError
+ else:
+ nested[nested_name].append(key)
+ nested_ref['ref-origin'] = ref
+ subreflist.append(nested_ref)
+ except CircularSubstitutionDefinitionError:
+ parent = ref.parent
+ if isinstance(parent, nodes.substitution_definition):
+ msg = self.document.reporter.error(
+ 'Circular substitution definition detected:',
+ nodes.literal_block(parent.rawsource,
+ parent.rawsource),
+ line=parent.line, base_node=parent)
+ parent.replace_self(msg)
+ else:
+ # find original ref substitution which cased this error
+ ref_origin = ref
+ while ref_origin.hasattr('ref-origin'):
+ ref_origin = ref_origin['ref-origin']
+ msg = self.document.reporter.error(
+ 'Circular substitution definition referenced: '
+ '"%s".' % refname, base_node=ref_origin)
+ msgid = self.document.set_id(msg)
+ prb = nodes.problematic(
+ ref.rawsource, ref.rawsource, refid=msgid)
+ prbid = self.document.set_id(prb)
+ msg.add_backref(prbid)
+ ref.replace_self(prb)
+ else:
+ ref.replace_self(subdef_copy.children)
+ # register refname of the replacment node(s)
+ # (needed for resolution of references)
+ for node in subdef_copy.children:
+ if isinstance(node, nodes.Referential):
+ # HACK: verify refname attribute exists.
+ # Test with docs/dev/todo.txt, see. |donate|
+ if 'refname' in node:
+ self.document.note_refname(node)
+
+
+class TargetNotes(Transform):
+
+ """
+ Creates a footnote for each external target in the text, and corresponding
+ footnote references after each reference.
+ """
+
+ default_priority = 540
+ """The TargetNotes transform has to be applied after `IndirectHyperlinks`
+ but before `Footnotes`."""
+
+
+ def __init__(self, document, startnode):
+ Transform.__init__(self, document, startnode=startnode)
+
+ self.classes = startnode.details.get('class', [])
+
+ def apply(self):
+ notes = {}
+ nodelist = []
+ for target in self.document.traverse(nodes.target):
+ # Only external targets.
+ if not target.hasattr('refuri'):
+ continue
+ names = target['names']
+ refs = []
+ for name in names:
+ refs.extend(self.document.refnames.get(name, []))
+ if not refs:
+ continue
+ footnote = self.make_target_footnote(target['refuri'], refs,
+ notes)
+ if target['refuri'] not in notes:
+ notes[target['refuri']] = footnote
+ nodelist.append(footnote)
+ # Take care of anonymous references.
+ for ref in self.document.traverse(nodes.reference):
+ if not ref.get('anonymous'):
+ continue
+ if ref.hasattr('refuri'):
+ footnote = self.make_target_footnote(ref['refuri'], [ref],
+ notes)
+ if ref['refuri'] not in notes:
+ notes[ref['refuri']] = footnote
+ nodelist.append(footnote)
+ self.startnode.replace_self(nodelist)
+
+ def make_target_footnote(self, refuri, refs, notes):
+ if refuri in notes: # duplicate?
+ footnote = notes[refuri]
+ assert len(footnote['names']) == 1
+ footnote_name = footnote['names'][0]
+ else: # original
+ footnote = nodes.footnote()
+ footnote_id = self.document.set_id(footnote)
+ # Use uppercase letters and a colon; they can't be
+ # produced inside names by the parser.
+ footnote_name = 'TARGET_NOTE: ' + footnote_id
+ footnote['auto'] = 1
+ footnote['names'] = [footnote_name]
+ footnote_paragraph = nodes.paragraph()
+ footnote_paragraph += nodes.reference('', refuri, refuri=refuri)
+ footnote += footnote_paragraph
+ self.document.note_autofootnote(footnote)
+ self.document.note_explicit_target(footnote, footnote)
+ for ref in refs:
+ if isinstance(ref, nodes.target):
+ continue
+ refnode = nodes.footnote_reference(refname=footnote_name, auto=1)
+ refnode['classes'] += self.classes
+ self.document.note_autofootnote_ref(refnode)
+ self.document.note_footnote_ref(refnode)
+ index = ref.parent.index(ref) + 1
+ reflist = [refnode]
+ if not utils.get_trim_footnote_ref_space(self.document.settings):
+ if self.classes:
+ reflist.insert(0, nodes.inline(text=' ', Classes=self.classes))
+ else:
+ reflist.insert(0, nodes.Text(' '))
+ ref.parent.insert(index, reflist)
+ return footnote
+
+
+class DanglingReferences(Transform):
+
+ """
+ Check for dangling references (incl. footnote & citation) and for
+ unreferenced targets.
+ """
+
+ default_priority = 850
+
+ def apply(self):
+ visitor = DanglingReferencesVisitor(
+ self.document,
+ self.document.transformer.unknown_reference_resolvers)
+ self.document.walk(visitor)
+ # *After* resolving all references, check for unreferenced
+ # targets:
+ for target in self.document.traverse(nodes.target):
+ if not target.referenced:
+ if target.get('anonymous'):
+ # If we have unreferenced anonymous targets, there
+ # is already an error message about anonymous
+ # hyperlink mismatch; no need to generate another
+ # message.
+ continue
+ if target['names']:
+ naming = target['names'][0]
+ elif target['ids']:
+ naming = target['ids'][0]
+ else:
+ # Hack: Propagated targets always have their refid
+ # attribute set.
+ naming = target['refid']
+ self.document.reporter.info(
+ 'Hyperlink target "%s" is not referenced.'
+ % naming, base_node=target)
+
+
+class DanglingReferencesVisitor(nodes.SparseNodeVisitor):
+
+ def __init__(self, document, unknown_reference_resolvers):
+ nodes.SparseNodeVisitor.__init__(self, document)
+ self.document = document
+ self.unknown_reference_resolvers = unknown_reference_resolvers
+
+ def unknown_visit(self, node):
+ pass
+
+ def visit_reference(self, node):
+ if node.resolved or not node.hasattr('refname'):
+ return
+ refname = node['refname']
+ id = self.document.nameids.get(refname)
+ if id is None:
+ for resolver_function in self.unknown_reference_resolvers:
+ if resolver_function(node):
+ break
+ else:
+ if refname in self.document.nameids:
+ msg = self.document.reporter.error(
+ 'Duplicate target name, cannot be used as a unique '
+ 'reference: "%s".' % (node['refname']), base_node=node)
+ else:
+ msg = self.document.reporter.error(
+ 'Unknown target name: "%s".' % (node['refname']),
+ base_node=node)
+ msgid = self.document.set_id(msg)
+ prb = nodes.problematic(
+ node.rawsource, node.rawsource, refid=msgid)
+ try:
+ prbid = node['ids'][0]
+ except IndexError:
+ prbid = self.document.set_id(prb)
+ msg.add_backref(prbid)
+ node.replace_self(prb)
+ else:
+ del node['refname']
+ node['refid'] = id
+ self.document.ids[id].note_referenced_by(id=id)
+ node.resolved = 1
+
+ visit_footnote_reference = visit_citation_reference = visit_reference
--- /dev/null
+# $Id: universal.py 8393 2019-09-18 10:13:00Z milde $
+# -*- coding: utf-8 -*-
+# Authors: David Goodger <goodger@python.org>; Ueli Schlaepfer; Günter Milde
+# Maintainer: docutils-develop@lists.sourceforge.net
+# Copyright: This module has been placed in the public domain.
+
+"""
+Transforms needed by most or all documents:
+
+- `Decorations`: Generate a document's header & footer.
+- `Messages`: Placement of system messages stored in
+ `nodes.document.transform_messages`.
+- `TestMessages`: Like `Messages`, used on test runs.
+- `FinalReferences`: Resolve remaining references.
+"""
+
+__docformat__ = 'reStructuredText'
+
+import re
+import sys
+import time
+from docutils import nodes, utils
+from docutils.transforms import TransformError, Transform
+from docutils.utils import smartquotes
+
+
+if sys.version_info >= (3, 0):
+ unicode = str # noqa
+
+
+class Decorations(Transform):
+
+ """
+ Populate a document's decoration element (header, footer).
+ """
+
+ default_priority = 820
+
+ def apply(self):
+ header_nodes = self.generate_header()
+ if header_nodes:
+ decoration = self.document.get_decoration()
+ header = decoration.get_header()
+ header.extend(header_nodes)
+ footer_nodes = self.generate_footer()
+ if footer_nodes:
+ decoration = self.document.get_decoration()
+ footer = decoration.get_footer()
+ footer.extend(footer_nodes)
+
+ def generate_header(self):
+ return None
+
+ def generate_footer(self):
+ # @@@ Text is hard-coded for now.
+ # Should be made dynamic (language-dependent).
+ # @@@ Use timestamp from the `SOURCE_DATE_EPOCH`_ environment variable
+ # for the datestamp?
+ # See https://sourceforge.net/p/docutils/patches/132/
+ # and https://reproducible-builds.org/specs/source-date-epoch/
+ settings = self.document.settings
+ if settings.generator or settings.datestamp or settings.source_link \
+ or settings.source_url:
+ text = []
+ if settings.source_link and settings._source \
+ or settings.source_url:
+ if settings.source_url:
+ source = settings.source_url
+ else:
+ source = utils.relative_path(settings._destination,
+ settings._source)
+ text.extend([
+ nodes.reference('', 'View document source',
+ refuri=source),
+ nodes.Text('.\n')])
+ if settings.datestamp:
+ datestamp = time.strftime(settings.datestamp, time.gmtime())
+ text.append(nodes.Text('Generated on: ' + datestamp + '.\n'))
+ if settings.generator:
+ text.extend([
+ nodes.Text('Generated by '),
+ nodes.reference('', 'Docutils', refuri=
+ 'http://docutils.sourceforge.net/'),
+ nodes.Text(' from '),
+ nodes.reference('', 'reStructuredText', refuri='http://'
+ 'docutils.sourceforge.net/rst.html'),
+ nodes.Text(' source.\n')])
+ return [nodes.paragraph('', '', *text)]
+ else:
+ return None
+
+
+class ExposeInternals(Transform):
+
+ """
+ Expose internal attributes if ``expose_internals`` setting is set.
+ """
+
+ default_priority = 840
+
+ def not_Text(self, node):
+ return not isinstance(node, nodes.Text)
+
+ def apply(self):
+ if self.document.settings.expose_internals:
+ for node in self.document.traverse(self.not_Text):
+ for att in self.document.settings.expose_internals:
+ value = getattr(node, att, None)
+ if value is not None:
+ node['internal:' + att] = value
+
+
+class Messages(Transform):
+
+ """
+ Place any system messages generated after parsing into a dedicated section
+ of the document.
+ """
+
+ default_priority = 860
+
+ def apply(self):
+ unfiltered = self.document.transform_messages
+ threshold = self.document.reporter.report_level
+ messages = []
+ for msg in unfiltered:
+ if msg['level'] >= threshold and not msg.parent:
+ messages.append(msg)
+ if messages:
+ section = nodes.section(classes=['system-messages'])
+ # @@@ get this from the language module?
+ section += nodes.title('', 'Docutils System Messages')
+ section += messages
+ self.document.transform_messages[:] = []
+ self.document += section
+
+
+class FilterMessages(Transform):
+
+ """
+ Remove system messages below verbosity threshold.
+ """
+
+ default_priority = 870
+
+ def apply(self):
+ for node in tuple(self.document.traverse(nodes.system_message)):
+ if node['level'] < self.document.reporter.report_level:
+ node.parent.remove(node)
+
+
+class TestMessages(Transform):
+
+ """
+ Append all post-parse system messages to the end of the document.
+
+ Used for testing purposes.
+ """
+
+ default_priority = 880
+
+ def apply(self):
+ for msg in self.document.transform_messages:
+ if not msg.parent:
+ self.document += msg
+
+
+class StripComments(Transform):
+
+ """
+ Remove comment elements from the document tree (only if the
+ ``strip_comments`` setting is enabled).
+ """
+
+ default_priority = 740
+
+ def apply(self):
+ if self.document.settings.strip_comments:
+ for node in tuple(self.document.traverse(nodes.comment)):
+ node.parent.remove(node)
+
+
+class StripClassesAndElements(Transform):
+
+ """
+ Remove from the document tree all elements with classes in
+ `self.document.settings.strip_elements_with_classes` and all "classes"
+ attribute values in `self.document.settings.strip_classes`.
+ """
+
+ default_priority = 420
+
+ def apply(self):
+ if self.document.settings.strip_elements_with_classes:
+ self.strip_elements = set(
+ self.document.settings.strip_elements_with_classes)
+ # Iterate over a tuple as removing the current node
+ # corrupts the iterator returned by `traverse`:
+ for node in tuple(self.document.traverse(self.check_classes)):
+ node.parent.remove(node)
+
+ if not self.document.settings.strip_classes:
+ return
+ strip_classes = self.document.settings.strip_classes
+ for node in self.document.traverse(nodes.Element):
+ for class_value in strip_classes:
+ try:
+ node['classes'].remove(class_value)
+ except ValueError:
+ pass
+
+ def check_classes(self, node):
+ if not isinstance(node, nodes.Element):
+ return False
+ for class_value in node['classes'][:]:
+ if class_value in self.strip_elements:
+ return True
+ return False
+
+
+class SmartQuotes(Transform):
+
+ """
+ Replace ASCII quotation marks with typographic form.
+
+ Also replace multiple dashes with em-dash/en-dash characters.
+ """
+
+ default_priority = 850
+
+ nodes_to_skip = (nodes.FixedTextElement, nodes.Special)
+ """Do not apply "smartquotes" to instances of these block-level nodes."""
+
+ literal_nodes = (nodes.FixedTextElement, nodes.Special,
+ nodes.image, nodes.literal, nodes.math,
+ nodes.raw, nodes.problematic)
+ """Do apply smartquotes to instances of these inline nodes."""
+
+ smartquotes_action = 'qDe'
+ """Setting to select smartquote transformations.
+
+ The default 'qDe' educates normal quote characters: (", '),
+ em- and en-dashes (---, --) and ellipses (...).
+ """
+
+ def __init__(self, document, startnode):
+ Transform.__init__(self, document, startnode=startnode)
+ self.unsupported_languages = set()
+
+ def get_tokens(self, txtnodes):
+ # A generator that yields ``(texttype, nodetext)`` tuples for a list
+ # of "Text" nodes (interface to ``smartquotes.educate_tokens()``).
+ for node in txtnodes:
+ if (isinstance(node.parent, self.literal_nodes)
+ or isinstance(node.parent.parent, self.literal_nodes)):
+ yield ('literal', unicode(node))
+ else:
+ # SmartQuotes uses backslash escapes instead of null-escapes
+ txt = re.sub('(?<=\x00)([-\\\'".`])', r'\\\1', unicode(node))
+ yield ('plain', txt)
+
+ def apply(self):
+ smart_quotes = self.document.settings.smart_quotes
+ if not smart_quotes:
+ return
+ try:
+ alternative = smart_quotes.startswith('alt')
+ except AttributeError:
+ alternative = False
+
+ document_language = self.document.settings.language_code
+ lc_smartquotes = self.document.settings.smartquotes_locales
+ if lc_smartquotes:
+ smartquotes.smartchars.quotes.update(dict(lc_smartquotes))
+
+ # "Educate" quotes in normal text. Handle each block of text
+ # (TextElement node) as a unit to keep context around inline nodes:
+ for node in self.document.traverse(nodes.TextElement):
+ # skip preformatted text blocks and special elements:
+ if isinstance(node, self.nodes_to_skip):
+ continue
+ # nested TextElements are not "block-level" elements:
+ if isinstance(node.parent, nodes.TextElement):
+ continue
+
+ # list of text nodes in the "text block":
+ txtnodes = [txtnode for txtnode in node.traverse(nodes.Text)
+ if not isinstance(txtnode.parent,
+ nodes.option_string)]
+
+ # language: use typographical quotes for language "lang"
+ lang = node.get_language_code(document_language)
+ # use alternative form if `smart-quotes` setting starts with "alt":
+ if alternative:
+ if '-x-altquot' in lang:
+ lang = lang.replace('-x-altquot', '')
+ else:
+ lang += '-x-altquot'
+ # drop unsupported subtags:
+ for tag in utils.normalize_language_tag(lang):
+ if tag in smartquotes.smartchars.quotes:
+ lang = tag
+ break
+ else: # language not supported: (keep ASCII quotes)
+ if lang not in self.unsupported_languages:
+ self.document.reporter.warning('No smart quotes '
+ 'defined for language "%s".'%lang, base_node=node)
+ self.unsupported_languages.add(lang)
+ lang = ''
+
+ # Iterator educating quotes in plain text:
+ # (see "utils/smartquotes.py" for the attribute setting)
+ teacher = smartquotes.educate_tokens(self.get_tokens(txtnodes),
+ attr=self.smartquotes_action, language=lang)
+
+ for txtnode, newtext in zip(txtnodes, teacher):
+ txtnode.parent.replace(txtnode, nodes.Text(newtext,
+ rawsource=txtnode.rawsource))
+
+ self.unsupported_languages = set() # reset
--- /dev/null
+# $Id: writer_aux.py 7808 2015-02-27 17:03:32Z milde $
+# Author: Lea Wiemann <LeWiemann@gmail.com>
+# Copyright: This module has been placed in the public domain.
+
+"""
+Auxiliary transforms mainly to be used by Writer components.
+
+This module is called "writer_aux" because otherwise there would be
+conflicting imports like this one::
+
+ from docutils import writers
+ from docutils.transforms import writers
+"""
+
+__docformat__ = 'reStructuredText'
+
+from docutils import nodes, utils, languages
+from docutils.transforms import Transform
+
+
+class Compound(Transform):
+
+ """
+ Flatten all compound paragraphs. For example, transform ::
+
+ <compound>
+ <paragraph>
+ <literal_block>
+ <paragraph>
+
+ into ::
+
+ <paragraph>
+ <literal_block classes="continued">
+ <paragraph classes="continued">
+ """
+
+ default_priority = 910
+
+ def apply(self):
+ for compound in self.document.traverse(nodes.compound):
+ first_child = True
+ for child in compound:
+ if first_child:
+ if not isinstance(child, nodes.Invisible):
+ first_child = False
+ else:
+ child['classes'].append('continued')
+ # Substitute children for compound.
+ compound.replace_self(compound[:])
+
+
+class Admonitions(Transform):
+
+ """
+ Transform specific admonitions, like this:
+
+ <note>
+ <paragraph>
+ Note contents ...
+
+ into generic admonitions, like this::
+
+ <admonition classes="note">
+ <title>
+ Note
+ <paragraph>
+ Note contents ...
+
+ The admonition title is localized.
+ """
+
+ default_priority = 920
+
+ def apply(self):
+ language = languages.get_language(self.document.settings.language_code,
+ self.document.reporter)
+ for node in self.document.traverse(nodes.Admonition):
+ node_name = node.__class__.__name__
+ # Set class, so that we know what node this admonition came from.
+ node['classes'].append(node_name)
+ if not isinstance(node, nodes.admonition):
+ # Specific admonition. Transform into a generic admonition.
+ admonition = nodes.admonition(node.rawsource, *node.children,
+ **node.attributes)
+ title = nodes.title('', language.labels[node_name])
+ admonition.insert(0, title)
+ node.replace_self(admonition)
--- /dev/null
+# coding: utf-8
+# $Id: __init__.py 8376 2019-08-27 19:49:29Z milde $
+# Author: David Goodger <goodger@python.org>
+# Copyright: This module has been placed in the public domain.
+
+"""
+Miscellaneous utilities for the documentation utilities.
+"""
+
+__docformat__ = 'reStructuredText'
+
+import sys
+import os
+import os.path
+import re
+import itertools
+import warnings
+import unicodedata
+from docutils import ApplicationError, DataError, __version_info__
+from docutils import nodes
+from docutils.nodes import unescape
+import docutils.io
+from docutils.utils.error_reporting import ErrorOutput, SafeString
+
+if sys.version_info >= (3, 0):
+ unicode = str
+
+
+class SystemMessage(ApplicationError):
+
+ def __init__(self, system_message, level):
+ Exception.__init__(self, system_message.astext())
+ self.level = level
+
+
+class SystemMessagePropagation(ApplicationError): pass
+
+
+class Reporter(object):
+
+ """
+ Info/warning/error reporter and ``system_message`` element generator.
+
+ Five levels of system messages are defined, along with corresponding
+ methods: `debug()`, `info()`, `warning()`, `error()`, and `severe()`.
+
+ There is typically one Reporter object per process. A Reporter object is
+ instantiated with thresholds for reporting (generating warnings) and
+ halting processing (raising exceptions), a switch to turn debug output on
+ or off, and an I/O stream for warnings. These are stored as instance
+ attributes.
+
+ When a system message is generated, its level is compared to the stored
+ thresholds, and a warning or error is generated as appropriate. Debug
+ messages are produced if the stored debug switch is on, independently of
+ other thresholds. Message output is sent to the stored warning stream if
+ not set to ''.
+
+ The Reporter class also employs a modified form of the "Observer" pattern
+ [GoF95]_ to track system messages generated. The `attach_observer` method
+ should be called before parsing, with a bound method or function which
+ accepts system messages. The observer can be removed with
+ `detach_observer`, and another added in its place.
+
+ .. [GoF95] Gamma, Helm, Johnson, Vlissides. *Design Patterns: Elements of
+ Reusable Object-Oriented Software*. Addison-Wesley, Reading, MA, USA,
+ 1995.
+ """
+
+ levels = 'DEBUG INFO WARNING ERROR SEVERE'.split()
+ """List of names for system message levels, indexed by level."""
+
+ # system message level constants:
+ (DEBUG_LEVEL,
+ INFO_LEVEL,
+ WARNING_LEVEL,
+ ERROR_LEVEL,
+ SEVERE_LEVEL) = range(5)
+
+ def __init__(self, source, report_level, halt_level, stream=None,
+ debug=False, encoding=None, error_handler='backslashreplace'):
+ """
+ :Parameters:
+ - `source`: The path to or description of the source data.
+ - `report_level`: The level at or above which warning output will
+ be sent to `stream`.
+ - `halt_level`: The level at or above which `SystemMessage`
+ exceptions will be raised, halting execution.
+ - `debug`: Show debug (level=0) system messages?
+ - `stream`: Where warning output is sent. Can be file-like (has a
+ ``.write`` method), a string (file name, opened for writing),
+ '' (empty string) or `False` (for discarding all stream messages)
+ or `None` (implies `sys.stderr`; default).
+ - `encoding`: The output encoding.
+ - `error_handler`: The error handler for stderr output encoding.
+ """
+
+ self.source = source
+ """The path to or description of the source data."""
+
+ self.error_handler = error_handler
+ """The character encoding error handler."""
+
+ self.debug_flag = debug
+ """Show debug (level=0) system messages?"""
+
+ self.report_level = report_level
+ """The level at or above which warning output will be sent
+ to `self.stream`."""
+
+ self.halt_level = halt_level
+ """The level at or above which `SystemMessage` exceptions
+ will be raised, halting execution."""
+
+ if not isinstance(stream, ErrorOutput):
+ stream = ErrorOutput(stream, encoding, error_handler)
+
+ self.stream = stream
+ """Where warning output is sent."""
+
+ self.encoding = encoding or getattr(stream, 'encoding', 'ascii')
+ """The output character encoding."""
+
+ self.observers = []
+ """List of bound methods or functions to call with each system_message
+ created."""
+
+ self.max_level = -1
+ """The highest level system message generated so far."""
+
+ def set_conditions(self, category, report_level, halt_level,
+ stream=None, debug=False):
+ warnings.warn('docutils.utils.Reporter.set_conditions deprecated; '
+ 'set attributes via configuration settings or directly',
+ DeprecationWarning, stacklevel=2)
+ self.report_level = report_level
+ self.halt_level = halt_level
+ if not isinstance(stream, ErrorOutput):
+ stream = ErrorOutput(stream, self.encoding, self.error_handler)
+ self.stream = stream
+ self.debug_flag = debug
+
+ def attach_observer(self, observer):
+ """
+ The `observer` parameter is a function or bound method which takes one
+ argument, a `nodes.system_message` instance.
+ """
+ self.observers.append(observer)
+
+ def detach_observer(self, observer):
+ self.observers.remove(observer)
+
+ def notify_observers(self, message):
+ for observer in self.observers:
+ observer(message)
+
+ def system_message(self, level, message, *children, **kwargs):
+ """
+ Return a system_message object.
+
+ Raise an exception or generate a warning if appropriate.
+ """
+ # `message` can be a `string`, `unicode`, or `Exception` instance.
+ if isinstance(message, Exception):
+ message = SafeString(message)
+
+ attributes = kwargs.copy()
+ if 'base_node' in kwargs:
+ source, line = get_source_line(kwargs['base_node'])
+ del attributes['base_node']
+ if source is not None:
+ attributes.setdefault('source', source)
+ if line is not None:
+ attributes.setdefault('line', line)
+ # assert source is not None, "node has line- but no source-argument"
+ if not 'source' in attributes: # 'line' is absolute line number
+ try: # look up (source, line-in-source)
+ source, line = self.get_source_and_line(attributes.get('line'))
+ except AttributeError:
+ source, line = None, None
+ if source is not None:
+ attributes['source'] = source
+ if line is not None:
+ attributes['line'] = line
+ # assert attributes['line'] is not None, (message, kwargs)
+ # assert attributes['source'] is not None, (message, kwargs)
+ attributes.setdefault('source', self.source)
+
+ msg = nodes.system_message(message, level=level,
+ type=self.levels[level],
+ *children, **attributes)
+ if self.stream and (level >= self.report_level
+ or self.debug_flag and level == self.DEBUG_LEVEL
+ or level >= self.halt_level):
+ self.stream.write(msg.astext() + '\n')
+ if level >= self.halt_level:
+ raise SystemMessage(msg, level)
+ if level > self.DEBUG_LEVEL or self.debug_flag:
+ self.notify_observers(msg)
+ self.max_level = max(level, self.max_level)
+ return msg
+
+ def debug(self, *args, **kwargs):
+ """
+ Level-0, "DEBUG": an internal reporting issue. Typically, there is no
+ effect on the processing. Level-0 system messages are handled
+ separately from the others.
+ """
+ if self.debug_flag:
+ return self.system_message(self.DEBUG_LEVEL, *args, **kwargs)
+
+ def info(self, *args, **kwargs):
+ """
+ Level-1, "INFO": a minor issue that can be ignored. Typically there is
+ no effect on processing, and level-1 system messages are not reported.
+ """
+ return self.system_message(self.INFO_LEVEL, *args, **kwargs)
+
+ def warning(self, *args, **kwargs):
+ """
+ Level-2, "WARNING": an issue that should be addressed. If ignored,
+ there may be unpredictable problems with the output.
+ """
+ return self.system_message(self.WARNING_LEVEL, *args, **kwargs)
+
+ def error(self, *args, **kwargs):
+ """
+ Level-3, "ERROR": an error that should be addressed. If ignored, the
+ output will contain errors.
+ """
+ return self.system_message(self.ERROR_LEVEL, *args, **kwargs)
+
+ def severe(self, *args, **kwargs):
+ """
+ Level-4, "SEVERE": a severe error that must be addressed. If ignored,
+ the output will contain severe errors. Typically level-4 system
+ messages are turned into exceptions which halt processing.
+ """
+ return self.system_message(self.SEVERE_LEVEL, *args, **kwargs)
+
+
+class ExtensionOptionError(DataError): pass
+class BadOptionError(ExtensionOptionError): pass
+class BadOptionDataError(ExtensionOptionError): pass
+class DuplicateOptionError(ExtensionOptionError): pass
+
+
+def extract_extension_options(field_list, options_spec):
+ """
+ Return a dictionary mapping extension option names to converted values.
+
+ :Parameters:
+ - `field_list`: A flat field list without field arguments, where each
+ field body consists of a single paragraph only.
+ - `options_spec`: Dictionary mapping known option names to a
+ conversion function such as `int` or `float`.
+
+ :Exceptions:
+ - `KeyError` for unknown option names.
+ - `ValueError` for invalid option values (raised by the conversion
+ function).
+ - `TypeError` for invalid option value types (raised by conversion
+ function).
+ - `DuplicateOptionError` for duplicate options.
+ - `BadOptionError` for invalid fields.
+ - `BadOptionDataError` for invalid option data (missing name,
+ missing data, bad quotes, etc.).
+ """
+ option_list = extract_options(field_list)
+ option_dict = assemble_option_dict(option_list, options_spec)
+ return option_dict
+
+def extract_options(field_list):
+ """
+ Return a list of option (name, value) pairs from field names & bodies.
+
+ :Parameter:
+ `field_list`: A flat field list, where each field name is a single
+ word and each field body consists of a single paragraph only.
+
+ :Exceptions:
+ - `BadOptionError` for invalid fields.
+ - `BadOptionDataError` for invalid option data (missing name,
+ missing data, bad quotes, etc.).
+ """
+ option_list = []
+ for field in field_list:
+ if len(field[0].astext().split()) != 1:
+ raise BadOptionError(
+ 'extension option field name may not contain multiple words')
+ name = str(field[0].astext().lower())
+ body = field[1]
+ if len(body) == 0:
+ data = None
+ elif len(body) > 1 or not isinstance(body[0], nodes.paragraph) \
+ or len(body[0]) != 1 or not isinstance(body[0][0], nodes.Text):
+ raise BadOptionDataError(
+ 'extension option field body may contain\n'
+ 'a single paragraph only (option "%s")' % name)
+ else:
+ data = body[0][0].astext()
+ option_list.append((name, data))
+ return option_list
+
+def assemble_option_dict(option_list, options_spec):
+ """
+ Return a mapping of option names to values.
+
+ :Parameters:
+ - `option_list`: A list of (name, value) pairs (the output of
+ `extract_options()`).
+ - `options_spec`: Dictionary mapping known option names to a
+ conversion function such as `int` or `float`.
+
+ :Exceptions:
+ - `KeyError` for unknown option names.
+ - `DuplicateOptionError` for duplicate options.
+ - `ValueError` for invalid option values (raised by conversion
+ function).
+ - `TypeError` for invalid option value types (raised by conversion
+ function).
+ """
+ options = {}
+ for name, value in option_list:
+ convertor = options_spec[name] # raises KeyError if unknown
+ if convertor is None:
+ raise KeyError(name) # or if explicitly disabled
+ if name in options:
+ raise DuplicateOptionError('duplicate option "%s"' % name)
+ try:
+ options[name] = convertor(value)
+ except (ValueError, TypeError) as detail:
+ raise detail.__class__('(option: "%s"; value: %r)\n%s'
+ % (name, value, ' '.join(detail.args)))
+ return options
+
+
+class NameValueError(DataError): pass
+
+
+def decode_path(path):
+ """
+ Ensure `path` is Unicode. Return `nodes.reprunicode` object.
+
+ Decode file/path string in a failsave manner if not already done.
+ """
+ # see also http://article.gmane.org/gmane.text.docutils.user/2905
+ if isinstance(path, unicode):
+ return path
+ try:
+ path = path.decode(sys.getfilesystemencoding(), 'strict')
+ except AttributeError: # default value None has no decode method
+ return nodes.reprunicode(path)
+ except UnicodeDecodeError:
+ try:
+ path = path.decode('utf-8', 'strict')
+ except UnicodeDecodeError:
+ path = path.decode('ascii', 'replace')
+ return nodes.reprunicode(path)
+
+
+def extract_name_value(line):
+ """
+ Return a list of (name, value) from a line of the form "name=value ...".
+
+ :Exception:
+ `NameValueError` for invalid input (missing name, missing data, bad
+ quotes, etc.).
+ """
+ attlist = []
+ while line:
+ equals = line.find('=')
+ if equals == -1:
+ raise NameValueError('missing "="')
+ attname = line[:equals].strip()
+ if equals == 0 or not attname:
+ raise NameValueError(
+ 'missing attribute name before "="')
+ line = line[equals+1:].lstrip()
+ if not line:
+ raise NameValueError(
+ 'missing value after "%s="' % attname)
+ if line[0] in '\'"':
+ endquote = line.find(line[0], 1)
+ if endquote == -1:
+ raise NameValueError(
+ 'attribute "%s" missing end quote (%s)'
+ % (attname, line[0]))
+ if len(line) > endquote + 1 and line[endquote + 1].strip():
+ raise NameValueError(
+ 'attribute "%s" end quote (%s) not followed by '
+ 'whitespace' % (attname, line[0]))
+ data = line[1:endquote]
+ line = line[endquote+1:].lstrip()
+ else:
+ space = line.find(' ')
+ if space == -1:
+ data = line
+ line = ''
+ else:
+ data = line[:space]
+ line = line[space+1:].lstrip()
+ attlist.append((attname.lower(), data))
+ return attlist
+
+def new_reporter(source_path, settings):
+ """
+ Return a new Reporter object.
+
+ :Parameters:
+ `source` : string
+ The path to or description of the source text of the document.
+ `settings` : optparse.Values object
+ Runtime settings.
+ """
+ reporter = Reporter(
+ source_path, settings.report_level, settings.halt_level,
+ stream=settings.warning_stream, debug=settings.debug,
+ encoding=settings.error_encoding,
+ error_handler=settings.error_encoding_error_handler)
+ return reporter
+
+def new_document(source_path, settings=None):
+ """
+ Return a new empty document object.
+
+ :Parameters:
+ `source_path` : string
+ The path to or description of the source text of the document.
+ `settings` : optparse.Values object
+ Runtime settings. If none are provided, a default core set will
+ be used. If you will use the document object with any Docutils
+ components, you must provide their default settings as well. For
+ example, if parsing, at least provide the parser settings,
+ obtainable as follows::
+
+ settings = docutils.frontend.OptionParser(
+ components=(docutils.parsers.rst.Parser,)
+ ).get_default_values()
+ """
+ from docutils import frontend
+ if settings is None:
+ settings = frontend.OptionParser().get_default_values()
+ source_path = decode_path(source_path)
+ reporter = new_reporter(source_path, settings)
+ document = nodes.document(settings, reporter, source=source_path)
+ document.note_source(source_path, -1)
+ return document
+
+def clean_rcs_keywords(paragraph, keyword_substitutions):
+ if len(paragraph) == 1 and isinstance(paragraph[0], nodes.Text):
+ textnode = paragraph[0]
+ for pattern, substitution in keyword_substitutions:
+ match = pattern.search(textnode)
+ if match:
+ paragraph[0] = nodes.Text(pattern.sub(substitution, textnode))
+ return
+
+def relative_path(source, target):
+ """
+ Build and return a path to `target`, relative to `source` (both files).
+
+ If there is no common prefix, return the absolute path to `target`.
+ """
+ source_parts = os.path.abspath(source or type(target)('dummy_file')
+ ).split(os.sep)
+ target_parts = os.path.abspath(target).split(os.sep)
+ # Check first 2 parts because '/dir'.split('/') == ['', 'dir']:
+ if source_parts[:2] != target_parts[:2]:
+ # Nothing in common between paths.
+ # Return absolute path, using '/' for URLs:
+ return '/'.join(target_parts)
+ source_parts.reverse()
+ target_parts.reverse()
+ while (source_parts and target_parts
+ and source_parts[-1] == target_parts[-1]):
+ # Remove path components in common:
+ source_parts.pop()
+ target_parts.pop()
+ target_parts.reverse()
+ parts = ['..'] * (len(source_parts) - 1) + target_parts
+ return '/'.join(parts)
+
+def get_stylesheet_reference(settings, relative_to=None):
+ """
+ Retrieve a stylesheet reference from the settings object.
+
+ Deprecated. Use get_stylesheet_list() instead to
+ enable specification of multiple stylesheets as a comma-separated
+ list.
+ """
+ if settings.stylesheet_path:
+ assert not settings.stylesheet, (
+ 'stylesheet and stylesheet_path are mutually exclusive.')
+ if relative_to == None:
+ relative_to = settings._destination
+ return relative_path(relative_to, settings.stylesheet_path)
+ else:
+ return settings.stylesheet
+
+# Return 'stylesheet' or 'stylesheet_path' arguments as list.
+#
+# The original settings arguments are kept unchanged: you can test
+# with e.g. ``if settings.stylesheet_path:``
+#
+# Differences to ``get_stylesheet_reference``:
+# * return value is a list
+# * no re-writing of the path (and therefore no optional argument)
+# (if required, use ``utils.relative_path(source, target)``
+# in the calling script)
+def get_stylesheet_list(settings):
+ """
+ Retrieve list of stylesheet references from the settings object.
+ """
+ assert not (settings.stylesheet and settings.stylesheet_path), (
+ 'stylesheet and stylesheet_path are mutually exclusive.')
+ stylesheets = settings.stylesheet_path or settings.stylesheet or []
+ # programmatically set default can be string or unicode:
+ if not isinstance(stylesheets, list):
+ stylesheets = [path.strip() for path in stylesheets.split(',')]
+ # expand relative paths if found in stylesheet-dirs:
+ return [find_file_in_dirs(path, settings.stylesheet_dirs)
+ for path in stylesheets]
+
+def find_file_in_dirs(path, dirs):
+ """
+ Search for `path` in the list of directories `dirs`.
+
+ Return the first expansion that matches an existing file.
+ """
+ if os.path.isabs(path):
+ return path
+ for d in dirs:
+ if d == '.':
+ f = path
+ else:
+ d = os.path.expanduser(d)
+ f = os.path.join(d, path)
+ if os.path.exists(f):
+ return f
+ return path
+
+def get_trim_footnote_ref_space(settings):
+ """
+ Return whether or not to trim footnote space.
+
+ If trim_footnote_reference_space is not None, return it.
+
+ If trim_footnote_reference_space is None, return False unless the
+ footnote reference style is 'superscript'.
+ """
+ if settings.trim_footnote_reference_space is None:
+ return hasattr(settings, 'footnote_references') and \
+ settings.footnote_references == 'superscript'
+ else:
+ return settings.trim_footnote_reference_space
+
+def get_source_line(node):
+ """
+ Return the "source" and "line" attributes from the `node` given or from
+ its closest ancestor.
+ """
+ while node:
+ if node.source or node.line:
+ return node.source, node.line
+ node = node.parent
+ return None, None
+
+def escape2null(text):
+ """Return a string with escape-backslashes converted to nulls."""
+ parts = []
+ start = 0
+ while True:
+ found = text.find('\\', start)
+ if found == -1:
+ parts.append(text[start:])
+ return ''.join(parts)
+ parts.append(text[start:found])
+ parts.append('\x00' + text[found+1:found+2])
+ start = found + 2 # skip character after escape
+
+# `unescape` definition moved to `nodes` to avoid circular import dependency.
+
+def split_escaped_whitespace(text):
+ """
+ Split `text` on escaped whitespace (null+space or null+newline).
+ Return a list of strings.
+ """
+ strings = text.split('\x00 ')
+ strings = [string.split('\x00\n') for string in strings]
+ # flatten list of lists of strings to list of strings:
+ return list(itertools.chain(*strings))
+
+def strip_combining_chars(text):
+ if isinstance(text, str) and sys.version_info < (3, 0):
+ return text
+ return u''.join([c for c in text if not unicodedata.combining(c)])
+
+def find_combining_chars(text):
+ """Return indices of all combining chars in Unicode string `text`.
+
+ >>> from docutils.utils import find_combining_chars
+ >>> find_combining_chars(u'A t̆ab̆lĕ')
+ [3, 6, 9]
+
+ """
+ if isinstance(text, str) and sys.version_info < (3, 0):
+ return []
+ return [i for i,c in enumerate(text) if unicodedata.combining(c)]
+
+def column_indices(text):
+ """Indices of Unicode string `text` when skipping combining characters.
+
+ >>> from docutils.utils import column_indices
+ >>> column_indices(u'A t̆ab̆lĕ')
+ [0, 1, 2, 4, 5, 7, 8]
+
+ """
+ # TODO: account for asian wide chars here instead of using dummy
+ # replacements in the tableparser?
+ string_indices = list(range(len(text)))
+ for index in find_combining_chars(text):
+ string_indices[index] = None
+ return [i for i in string_indices if i is not None]
+
+east_asian_widths = {'W': 2, # Wide
+ 'F': 2, # Full-width (wide)
+ 'Na': 1, # Narrow
+ 'H': 1, # Half-width (narrow)
+ 'N': 1, # Neutral (not East Asian, treated as narrow)
+ 'A': 1} # Ambiguous (s/b wide in East Asian context,
+ # narrow otherwise, but that doesn't work)
+"""Mapping of result codes from `unicodedata.east_asian_widt()` to character
+column widths."""
+
+def column_width(text):
+ """Return the column width of text.
+
+ Correct ``len(text)`` for wide East Asian and combining Unicode chars.
+ """
+ if isinstance(text, str) and sys.version_info < (3, 0):
+ return len(text)
+ width = sum([east_asian_widths[unicodedata.east_asian_width(c)]
+ for c in text])
+ # correction for combining chars:
+ width -= len(find_combining_chars(text))
+ return width
+
+def uniq(L):
+ r = []
+ for item in L:
+ if not item in r:
+ r.append(item)
+ return r
+
+def unique_combinations(items, n):
+ """Return `itertools.combinations`."""
+ warnings.warn('docutils.utils.unique_combinations is deprecated; '
+ 'use itertools.combinations directly.',
+ DeprecationWarning, stacklevel=2)
+ return itertools.combinations(items, n)
+
+def normalize_language_tag(tag):
+ """Return a list of normalized combinations for a `BCP 47` language tag.
+
+ Example:
+
+ >>> from docutils.utils import normalize_language_tag
+ >>> normalize_language_tag('de_AT-1901')
+ ['de-at-1901', 'de-at', 'de-1901', 'de']
+ >>> normalize_language_tag('de-CH-x_altquot')
+ ['de-ch-x-altquot', 'de-ch', 'de-x-altquot', 'de']
+
+ """
+ # normalize:
+ tag = tag.lower().replace('-', '_')
+ # split (except singletons, which mark the following tag as non-standard):
+ tag = re.sub(r'_([a-zA-Z0-9])_', r'_\1-', tag)
+ subtags = [subtag for subtag in tag.split('_')]
+ base_tag = (subtags.pop(0),)
+ # find all combinations of subtags
+ taglist = []
+ for n in range(len(subtags), 0, -1):
+ # for tags in unique_combinations(subtags, n):
+ for tags in itertools.combinations(subtags, n):
+ taglist.append('-'.join(base_tag+tags))
+ taglist += base_tag
+ return taglist
+
+
+class DependencyList(object):
+
+ """
+ List of dependencies, with file recording support.
+
+ Note that the output file is not automatically closed. You have
+ to explicitly call the close() method.
+ """
+
+ def __init__(self, output_file=None, dependencies=[]):
+ """
+ Initialize the dependency list, automatically setting the
+ output file to `output_file` (see `set_output()`) and adding
+ all supplied dependencies.
+ """
+ self.set_output(output_file)
+ for i in dependencies:
+ self.add(i)
+
+ def set_output(self, output_file):
+ """
+ Set the output file and clear the list of already added
+ dependencies.
+
+ `output_file` must be a string. The specified file is
+ immediately overwritten.
+
+ If output_file is '-', the output will be written to stdout.
+ If it is None, no file output is done when calling add().
+ """
+ self.list = []
+ if output_file:
+ if output_file == '-':
+ of = None
+ else:
+ of = output_file
+ self.file = docutils.io.FileOutput(destination_path=of,
+ encoding='utf8', autoclose=False)
+ else:
+ self.file = None
+
+ def add(self, *filenames):
+ """
+ If the dependency `filename` has not already been added,
+ append it to self.list and print it to self.file if self.file
+ is not None.
+ """
+ for filename in filenames:
+ if not filename in self.list:
+ self.list.append(filename)
+ if self.file is not None:
+ self.file.write(filename+'\n')
+
+ def close(self):
+ """
+ Close the output file.
+ """
+ self.file.close()
+ self.file = None
+
+ def __repr__(self):
+ try:
+ output_file = self.file.name
+ except AttributeError:
+ output_file = None
+ return '%s(%r, %s)' % (self.__class__.__name__, output_file, self.list)
+
+
+release_level_abbreviations = {
+ 'alpha': 'a',
+ 'beta': 'b',
+ 'candidate': 'rc',
+ 'final': '',}
+
+def version_identifier(version_info=None):
+ """
+ Return a version identifier string built from `version_info`, a
+ `docutils.VersionInfo` namedtuple instance or compatible tuple. If
+ `version_info` is not provided, by default return a version identifier
+ string based on `docutils.__version_info__` (i.e. the current Docutils
+ version).
+ """
+ if version_info is None:
+ version_info = __version_info__
+ if version_info.micro:
+ micro = '.%s' % version_info.micro
+ else:
+ # 0 is omitted:
+ micro = ''
+ releaselevel = release_level_abbreviations[version_info.releaselevel]
+ if version_info.serial:
+ serial = version_info.serial
+ else:
+ # 0 is omitted:
+ serial = ''
+ if version_info.release:
+ dev = ''
+ else:
+ dev = '.dev'
+ version = '%s.%s%s%s%s%s' % (
+ version_info.major,
+ version_info.minor,
+ micro,
+ releaselevel,
+ serial,
+ dev)
+ return version
--- /dev/null
+#!/usr/bin/python
+# coding: utf-8
+
+"""Lexical analysis of formal languages (i.e. code) using Pygments."""
+
+# :Author: Georg Brandl; Felix Wiemann; Günter Milde
+# :Date: $Date: 2019-08-26 18:46:50 +0200 (Mo, 26. Aug 2019) $
+# :Copyright: This module has been placed in the public domain.
+
+from docutils import ApplicationError
+try:
+ from pkg_resources import DistributionNotFound as ResourceError
+except (ImportError, RuntimeError):
+ class ResourceError(ApplicationError):
+ pass # stub
+try:
+ import pygments
+ from pygments.lexers import get_lexer_by_name
+ from pygments.formatters.html import _get_ttype_class
+ with_pygments = True
+except ImportError:
+ with_pygments = False
+
+# Filter the following token types from the list of class arguments:
+unstyled_tokens = ['token', # Token (base token type)
+ 'text', # Token.Text
+ ''] # short name for Token and Text
+# (Add, e.g., Token.Punctuation with ``unstyled_tokens += 'punctuation'``.)
+
+class LexerError(ApplicationError):
+ pass
+
+class Lexer(object):
+ """Parse `code` lines and yield "classified" tokens.
+
+ Arguments
+
+ code -- string of source code to parse,
+ language -- formal language the code is written in,
+ tokennames -- either 'long', 'short', or '' (see below).
+
+ Merge subsequent tokens of the same token-type.
+
+ Iterating over an instance yields the tokens as ``(tokentype, value)``
+ tuples. The value of `tokennames` configures the naming of the tokentype:
+
+ 'long': downcased full token type name,
+ 'short': short name defined by pygments.token.STANDARD_TYPES
+ (= class argument used in pygments html output),
+ 'none': skip lexical analysis.
+ """
+
+ def __init__(self, code, language, tokennames='short'):
+ """
+ Set up a lexical analyzer for `code` in `language`.
+ """
+ self.code = code
+ self.language = language
+ self.tokennames = tokennames
+ self.lexer = None
+ # get lexical analyzer for `language`:
+ if language in ('', 'text') or tokennames == 'none':
+ return
+ if not with_pygments:
+ raise LexerError('Cannot analyze code. '
+ 'Pygments package not found.')
+ try:
+ self.lexer = get_lexer_by_name(self.language)
+ except (pygments.util.ClassNotFound, ResourceError):
+ raise LexerError('Cannot analyze code. '
+ 'No Pygments lexer found for "%s".' % language)
+ # self.lexer.add_filter('tokenmerge')
+ # Since version 1.2. (released Jan 01, 2010) Pygments has a
+ # TokenMergeFilter. # ``self.merge(tokens)`` in __iter__ could
+ # be replaced by ``self.lexer.add_filter('tokenmerge')`` in __init__.
+ # However, `merge` below also strips a final newline added by pygments.
+ #
+ # self.lexer.add_filter('tokenmerge')
+
+ def merge(self, tokens):
+ """Merge subsequent tokens of same token-type.
+
+ Also strip the final newline (added by pygments).
+ """
+ tokens = iter(tokens)
+ (lasttype, lastval) = next(tokens)
+ for ttype, value in tokens:
+ if ttype is lasttype:
+ lastval += value
+ else:
+ yield(lasttype, lastval)
+ (lasttype, lastval) = (ttype, value)
+ if lastval.endswith('\n'):
+ lastval = lastval[:-1]
+ if lastval:
+ yield(lasttype, lastval)
+
+ def __iter__(self):
+ """Parse self.code and yield "classified" tokens.
+ """
+ if self.lexer is None:
+ yield ([], self.code)
+ return
+ tokens = pygments.lex(self.code, self.lexer)
+ for tokentype, value in self.merge(tokens):
+ if self.tokennames == 'long': # long CSS class args
+ classes = str(tokentype).lower().split('.')
+ else: # short CSS class args
+ classes = [_get_ttype_class(tokentype)]
+ classes = [cls for cls in classes if cls not in unstyled_tokens]
+ yield (classes, value)
+
+
+class NumberLines(object):
+ """Insert linenumber-tokens at the start of every code line.
+
+ Arguments
+
+ tokens -- iterable of ``(classes, value)`` tuples
+ startline -- first line number
+ endline -- last line number
+
+ Iterating over an instance yields the tokens with a
+ ``(['ln'], '<the line number>')`` token added for every code line.
+ Multi-line tokens are splitted."""
+
+ def __init__(self, tokens, startline, endline):
+ self.tokens = tokens
+ self.startline = startline
+ # pad linenumbers, e.g. endline == 100 -> fmt_str = '%3d '
+ self.fmt_str = '%%%dd ' % len(str(endline))
+
+ def __iter__(self):
+ lineno = self.startline
+ yield (['ln'], self.fmt_str % lineno)
+ for ttype, value in self.tokens:
+ lines = value.split('\n')
+ for line in lines[:-1]:
+ yield (ttype, line + '\n')
+ lineno += 1
+ yield (['ln'], self.fmt_str % lineno)
+ yield (ttype, lines[-1])
--- /dev/null
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+# :Id: $Id: error_reporting.py 8367 2019-08-27 12:09:56Z milde $
+# :Copyright: © 2011 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
+
+"""
+Error reporting should be safe from encoding/decoding errors.
+However, implicit conversions of strings and exceptions like
+
+>>> u'%s world: %s' % ('H\xe4llo', Exception(u'H\xe4llo')
+
+fail in some Python versions:
+
+* In Python <= 2.6, ``unicode(<exception instance>)`` uses
+ `__str__` and fails with non-ASCII chars in`unicode` arguments.
+ (work around http://bugs.python.org/issue2517):
+
+* In Python 2, unicode(<exception instance>) fails, with non-ASCII
+ chars in arguments. (Use case: in some locales, the errstr
+ argument of IOError contains non-ASCII chars.)
+
+* In Python 2, str(<exception instance>) fails, with non-ASCII chars
+ in `unicode` arguments.
+
+The `SafeString`, `ErrorString` and `ErrorOutput` classes handle
+common exceptions.
+"""
+
+import codecs
+import sys
+
+# Guess the locale's encoding.
+# If no valid guess can be made, locale_encoding is set to `None`:
+try:
+ import locale # module missing in Jython
+except ImportError:
+ locale_encoding = None
+else:
+ try:
+ locale_encoding = locale.getlocale()[1] or locale.getdefaultlocale()[1]
+ # locale.getpreferredencoding([do_setlocale=True|False])
+ # has side-effects | might return a wrong guess.
+ # (cf. Update 1 in http://stackoverflow.com/questions/4082645/using-python-2-xs-locale-module-to-format-numbers-and-currency)
+ except ValueError as error: # OS X may set UTF-8 without language code
+ # see http://bugs.python.org/issue18378
+ # and https://sourceforge.net/p/docutils/bugs/298/
+ if "unknown locale: UTF-8" in error.args:
+ locale_encoding = "UTF-8"
+ else:
+ locale_encoding = None
+ except: # any other problems determining the locale -> use None
+ locale_encoding = None
+ try:
+ codecs.lookup(locale_encoding or '') # None -> ''
+ except LookupError:
+ locale_encoding = None
+
+
+if sys.version_info >= (3, 0):
+ unicode = str # noqa
+
+
+class SafeString(object):
+ """
+ A wrapper providing robust conversion to `str` and `unicode`.
+ """
+
+ def __init__(self, data, encoding=None, encoding_errors='backslashreplace',
+ decoding_errors='replace'):
+ self.data = data
+ self.encoding = (encoding or getattr(data, 'encoding', None) or
+ locale_encoding or 'ascii')
+ self.encoding_errors = encoding_errors
+ self.decoding_errors = decoding_errors
+
+
+ def __str__(self):
+ try:
+ return str(self.data)
+ except UnicodeEncodeError:
+ if isinstance(self.data, Exception):
+ args = [str(SafeString(arg, self.encoding,
+ self.encoding_errors))
+ for arg in self.data.args]
+ return ', '.join(args)
+ if isinstance(self.data, unicode):
+ if sys.version_info > (3, 0):
+ return self.data
+ else:
+ return self.data.encode(self.encoding,
+ self.encoding_errors)
+ raise
+
+ def __unicode__(self):
+ """
+ Return unicode representation of `self.data`.
+
+ Try ``unicode(self.data)``, catch `UnicodeError` and
+
+ * if `self.data` is an Exception instance, work around
+ http://bugs.python.org/issue2517 with an emulation of
+ Exception.__unicode__,
+
+ * else decode with `self.encoding` and `self.decoding_errors`.
+ """
+ try:
+ u = unicode(self.data)
+ if isinstance(self.data, EnvironmentError):
+ u = u.replace(": u'", ": '") # normalize filename quoting
+ return u
+ except UnicodeError as error: # catch ..Encode.. and ..Decode.. errors
+ if isinstance(self.data, EnvironmentError):
+ return u"[Errno %s] %s: '%s'" % (self.data.errno,
+ SafeString(self.data.strerror, self.encoding,
+ self.decoding_errors),
+ SafeString(self.data.filename, self.encoding,
+ self.decoding_errors))
+ if isinstance(self.data, Exception):
+ args = [unicode(SafeString(arg, self.encoding,
+ decoding_errors=self.decoding_errors))
+ for arg in self.data.args]
+ return u', '.join(args)
+ if isinstance(error, UnicodeDecodeError):
+ return unicode(self.data, self.encoding, self.decoding_errors)
+ raise
+
+class ErrorString(SafeString):
+ """
+ Safely report exception type and message.
+ """
+ def __str__(self):
+ return '%s: %s' % (self.data.__class__.__name__,
+ super(ErrorString, self).__str__())
+
+ def __unicode__(self):
+ return u'%s: %s' % (self.data.__class__.__name__,
+ super(ErrorString, self).__unicode__())
+
+
+class ErrorOutput(object):
+ """
+ Wrapper class for file-like error streams with
+ failsave de- and encoding of `str`, `bytes`, `unicode` and
+ `Exception` instances.
+ """
+
+ def __init__(self, stream=None, encoding=None,
+ encoding_errors='backslashreplace',
+ decoding_errors='replace'):
+ """
+ :Parameters:
+ - `stream`: a file-like object,
+ a string (path to a file),
+ `None` (write to `sys.stderr`, default), or
+ evaluating to `False` (write() requests are ignored).
+ - `encoding`: `stream` text encoding. Guessed if None.
+ - `encoding_errors`: how to treat encoding errors.
+ """
+ if stream is None:
+ stream = sys.stderr
+ elif not(stream):
+ stream = False
+ # if `stream` is a file name, open it
+ elif isinstance(stream, str):
+ stream = open(stream, 'w')
+ elif isinstance(stream, unicode):
+ stream = open(stream.encode(sys.getfilesystemencoding()), 'w')
+
+ self.stream = stream
+ """Where warning output is sent."""
+
+ self.encoding = (encoding or getattr(stream, 'encoding', None) or
+ locale_encoding or 'ascii')
+ """The output character encoding."""
+
+ self.encoding_errors = encoding_errors
+ """Encoding error handler."""
+
+ self.decoding_errors = decoding_errors
+ """Decoding error handler."""
+
+ def write(self, data):
+ """
+ Write `data` to self.stream. Ignore, if self.stream is False.
+
+ `data` can be a `string`, `unicode`, or `Exception` instance.
+ """
+ if self.stream is False:
+ return
+ if isinstance(data, Exception):
+ data = unicode(SafeString(data, self.encoding,
+ self.encoding_errors, self.decoding_errors))
+ try:
+ self.stream.write(data)
+ except UnicodeEncodeError:
+ self.stream.write(data.encode(self.encoding, self.encoding_errors))
+ except TypeError:
+ if isinstance(data, unicode): # passed stream may expect bytes
+ self.stream.write(data.encode(self.encoding,
+ self.encoding_errors))
+ return
+ if self.stream in (sys.stderr, sys.stdout):
+ self.stream.buffer.write(data) # write bytes to raw stream
+ else:
+ self.stream.write(unicode(data, self.encoding,
+ self.decoding_errors))
+
+ def close(self):
+ """
+ Close the error-output stream.
+
+ Ignored if the stream is` sys.stderr` or `sys.stdout` or has no
+ close() method.
+ """
+ if self.stream in (sys.stdout, sys.stderr):
+ return
+ try:
+ self.stream.close()
+ except AttributeError:
+ pass
--- /dev/null
+# :Id: $Id: __init__.py 7865 2015-04-12 10:06:43Z milde $
+# :Author: Guenter 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 is the Docutils (Python Documentation Utilities) "math" sub-package.
+
+It contains various modules for conversion between different math formats
+(LaTeX, MathML, HTML).
+
+:math2html: LaTeX math -> HTML conversion from eLyXer
+:latex2mathml: LaTeX math -> presentational MathML
+:unichar2tex: Unicode character to LaTeX math translation table
+:tex2unichar: LaTeX math to Unicode character translation dictionaries
+:tex2mathml_extern: Wrapper for TeX -> MathML command line converters
+"""
+
+# helpers for Docutils math support
+# =================================
+
+def pick_math_environment(code, numbered=False):
+ """Return the right math environment to display `code`.
+
+ The test simply looks for line-breaks (``\\``) outside environments.
+ Multi-line formulae are set with ``align``, one-liners with
+ ``equation``.
+
+ If `numbered` evaluates to ``False``, the "starred" versions are used
+ to suppress numbering.
+ """
+ # cut out environment content:
+ chunks = code.split(r'\begin{')
+ toplevel_code = ''.join([chunk.split(r'\end{')[-1]
+ for chunk in chunks])
+ if toplevel_code.find(r'\\') >= 0:
+ env = 'align'
+ else:
+ env = 'equation'
+ if not numbered:
+ env += '*'
+ return env
--- /dev/null
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+# :Id: $Id: latex2mathml.py 8366 2019-08-27 12:09:19Z milde $
+# :Copyright: © 2010 Günter Milde.
+# Based on rst2mathml.py from the latex_math sandbox project
+# © 2005 Jens Jørgen Mortensen
+# :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
+
+
+"""Convert LaTex math code into presentational MathML"""
+
+# Based on the `latex_math` sandbox project by Jens Jørgen Mortensen
+
+import docutils.utils.math.tex2unichar as tex2unichar
+
+# TeX spacing combining
+over = {'acute': u'\u00B4', # u'\u0301',
+ 'bar': u'\u00AF', # u'\u0304',
+ 'breve': u'\u02D8', # u'\u0306',
+ 'check': u'\u02C7', # u'\u030C',
+ 'dot': u'\u02D9', # u'\u0307',
+ 'ddot': u'\u00A8', # u'\u0308',
+ 'dddot': u'\u20DB',
+ 'grave': u'`', # u'\u0300',
+ 'hat': u'^', # u'\u0302',
+ 'mathring': u'\u02DA', # u'\u030A',
+ 'overleftrightarrow': u'\u20e1',
+ # 'overline': # u'\u0305',
+ 'tilde': u'\u02DC', # u'\u0303',
+ 'vec': u'\u20D7'}
+
+Greek = { # Capital Greek letters: (upright in TeX style)
+ 'Phi':u'\u03a6', 'Xi':u'\u039e', 'Sigma':u'\u03a3',
+ 'Psi':u'\u03a8', 'Delta':u'\u0394', 'Theta':u'\u0398',
+ 'Upsilon':u'\u03d2', 'Pi':u'\u03a0', 'Omega':u'\u03a9',
+ 'Gamma':u'\u0393', 'Lambda':u'\u039b'}
+
+letters = tex2unichar.mathalpha
+
+special = tex2unichar.mathbin # Binary symbols
+special.update(tex2unichar.mathrel) # Relation symbols, arrow symbols
+special.update(tex2unichar.mathord) # Miscellaneous symbols
+special.update(tex2unichar.mathop) # Variable-sized symbols
+special.update(tex2unichar.mathopen) # Braces
+special.update(tex2unichar.mathclose) # Braces
+special.update(tex2unichar.mathfence)
+
+sumintprod = ''.join([special[symbol] for symbol in
+ ['sum', 'int', 'oint', 'prod']])
+
+functions = ['arccos', 'arcsin', 'arctan', 'arg', 'cos', 'cosh',
+ 'cot', 'coth', 'csc', 'deg', 'det', 'dim',
+ 'exp', 'gcd', 'hom', 'inf', 'ker', 'lg',
+ 'lim', 'liminf', 'limsup', 'ln', 'log', 'max',
+ 'min', 'Pr', 'sec', 'sin', 'sinh', 'sup',
+ 'tan', 'tanh',
+ 'injlim', 'varinjlim', 'varlimsup',
+ 'projlim', 'varliminf', 'varprojlim']
+
+
+mathbb = {
+ 'A': u'\U0001D538',
+ 'B': u'\U0001D539',
+ 'C': u'\u2102',
+ 'D': u'\U0001D53B',
+ 'E': u'\U0001D53C',
+ 'F': u'\U0001D53D',
+ 'G': u'\U0001D53E',
+ 'H': u'\u210D',
+ 'I': u'\U0001D540',
+ 'J': u'\U0001D541',
+ 'K': u'\U0001D542',
+ 'L': u'\U0001D543',
+ 'M': u'\U0001D544',
+ 'N': u'\u2115',
+ 'O': u'\U0001D546',
+ 'P': u'\u2119',
+ 'Q': u'\u211A',
+ 'R': u'\u211D',
+ 'S': u'\U0001D54A',
+ 'T': u'\U0001D54B',
+ 'U': u'\U0001D54C',
+ 'V': u'\U0001D54D',
+ 'W': u'\U0001D54E',
+ 'X': u'\U0001D54F',
+ 'Y': u'\U0001D550',
+ 'Z': u'\u2124',
+ }
+
+mathscr = {
+ 'A': u'\U0001D49C',
+ 'B': u'\u212C', # bernoulli function
+ 'C': u'\U0001D49E',
+ 'D': u'\U0001D49F',
+ 'E': u'\u2130',
+ 'F': u'\u2131',
+ 'G': u'\U0001D4A2',
+ 'H': u'\u210B', # hamiltonian
+ 'I': u'\u2110',
+ 'J': u'\U0001D4A5',
+ 'K': u'\U0001D4A6',
+ 'L': u'\u2112', # lagrangian
+ 'M': u'\u2133', # physics m-matrix
+ 'N': u'\U0001D4A9',
+ 'O': u'\U0001D4AA',
+ 'P': u'\U0001D4AB',
+ 'Q': u'\U0001D4AC',
+ 'R': u'\u211B',
+ 'S': u'\U0001D4AE',
+ 'T': u'\U0001D4AF',
+ 'U': u'\U0001D4B0',
+ 'V': u'\U0001D4B1',
+ 'W': u'\U0001D4B2',
+ 'X': u'\U0001D4B3',
+ 'Y': u'\U0001D4B4',
+ 'Z': u'\U0001D4B5',
+ 'a': u'\U0001D4B6',
+ 'b': u'\U0001D4B7',
+ 'c': u'\U0001D4B8',
+ 'd': u'\U0001D4B9',
+ 'e': u'\u212F',
+ 'f': u'\U0001D4BB',
+ 'g': u'\u210A',
+ 'h': u'\U0001D4BD',
+ 'i': u'\U0001D4BE',
+ 'j': u'\U0001D4BF',
+ 'k': u'\U0001D4C0',
+ 'l': u'\U0001D4C1',
+ 'm': u'\U0001D4C2',
+ 'n': u'\U0001D4C3',
+ 'o': u'\u2134', # order of
+ 'p': u'\U0001D4C5',
+ 'q': u'\U0001D4C6',
+ 'r': u'\U0001D4C7',
+ 's': u'\U0001D4C8',
+ 't': u'\U0001D4C9',
+ 'u': u'\U0001D4CA',
+ 'v': u'\U0001D4CB',
+ 'w': u'\U0001D4CC',
+ 'x': u'\U0001D4CD',
+ 'y': u'\U0001D4CE',
+ 'z': u'\U0001D4CF',
+ }
+
+negatables = {'=': u'\u2260',
+ r'\in': u'\u2209',
+ r'\equiv': u'\u2262'}
+
+# LaTeX to MathML translation stuff:
+class math(object):
+ """Base class for MathML elements."""
+
+ nchildren = 1000000
+ """Required number of children"""
+
+ def __init__(self, children=None, inline=None):
+ """math([children]) -> MathML element
+
+ children can be one child or a list of children."""
+
+ self.children = []
+ if children is not None:
+ if isinstance(children, list):
+ for child in children:
+ self.append(child)
+ else:
+ # Only one child:
+ self.append(children)
+
+ if inline is not None:
+ self.inline = inline
+
+ def __repr__(self):
+ if hasattr(self, 'children'):
+ return self.__class__.__name__ + '(%s)' % \
+ ','.join([repr(child) for child in self.children])
+ else:
+ return self.__class__.__name__
+
+ def full(self):
+ """Room for more children?"""
+
+ return len(self.children) >= self.nchildren
+
+ def append(self, child):
+ """append(child) -> element
+
+ Appends child and returns self if self is not full or first
+ non-full parent."""
+
+ assert not self.full()
+ self.children.append(child)
+ child.parent = self
+ node = self
+ while node.full():
+ node = node.parent
+ return node
+
+ def delete_child(self):
+ """delete_child() -> child
+
+ Delete last child and return it."""
+
+ child = self.children[-1]
+ del self.children[-1]
+ return child
+
+ def close(self):
+ """close() -> parent
+
+ Close element and return first non-full element."""
+
+ parent = self.parent
+ while parent.full():
+ parent = parent.parent
+ return parent
+
+ def xml(self):
+ """xml() -> xml-string"""
+
+ return self.xml_start() + self.xml_body() + self.xml_end()
+
+ def xml_start(self):
+ if not hasattr(self, 'inline'):
+ return ['<%s>' % self.__class__.__name__]
+ xmlns = 'http://www.w3.org/1998/Math/MathML'
+ if self.inline:
+ return ['<math xmlns="%s">' % xmlns]
+ else:
+ return ['<math xmlns="%s" mode="display">' % xmlns]
+
+ def xml_end(self):
+ return ['</%s>' % self.__class__.__name__]
+
+ def xml_body(self):
+ xml = []
+ for child in self.children:
+ xml.extend(child.xml())
+ return xml
+
+class mrow(math):
+ def xml_start(self):
+ return ['\n<%s>' % self.__class__.__name__]
+
+class mtable(math):
+ def xml_start(self):
+ return ['\n<%s>' % self.__class__.__name__]
+
+class mtr(mrow): pass
+class mtd(mrow): pass
+
+class mx(math):
+ """Base class for mo, mi, and mn"""
+
+ nchildren = 0
+ def __init__(self, data):
+ self.data = data
+
+ def xml_body(self):
+ return [self.data]
+
+class mo(mx):
+ translation = {'<': '<', '>': '>'}
+ def xml_body(self):
+ return [self.translation.get(self.data, self.data)]
+
+class mi(mx): pass
+class mn(mx): pass
+
+class msub(math):
+ nchildren = 2
+
+class msup(math):
+ nchildren = 2
+
+class msqrt(math):
+ nchildren = 1
+
+class mroot(math):
+ nchildren = 2
+
+class mfrac(math):
+ nchildren = 2
+
+class msubsup(math):
+ nchildren = 3
+ def __init__(self, children=None, reversed=False):
+ self.reversed = reversed
+ math.__init__(self, children)
+
+ def xml(self):
+ if self.reversed:
+## self.children[1:3] = self.children[2:0:-1]
+ self.children[1:3] = [self.children[2], self.children[1]]
+ self.reversed = False
+ return math.xml(self)
+
+class mfenced(math):
+ translation = {'\\{': '{', '\\langle': u'\u2329',
+ '\\}': '}', '\\rangle': u'\u232A',
+ '.': ''}
+ def __init__(self, par):
+ self.openpar = par
+ math.__init__(self)
+
+ def xml_start(self):
+ open = self.translation.get(self.openpar, self.openpar)
+ close = self.translation.get(self.closepar, self.closepar)
+ return ['<mfenced open="%s" close="%s">' % (open, close)]
+
+class mspace(math):
+ nchildren = 0
+
+class mstyle(math):
+ def __init__(self, children=None, nchildren=None, **kwargs):
+ if nchildren is not None:
+ self.nchildren = nchildren
+ math.__init__(self, children)
+ self.attrs = kwargs
+
+ def xml_start(self):
+ return ['<mstyle '] + ['%s="%s"' % item
+ for item in self.attrs.items()] + ['>']
+
+class mover(math):
+ nchildren = 2
+ def __init__(self, children=None, reversed=False):
+ self.reversed = reversed
+ math.__init__(self, children)
+
+ def xml(self):
+ if self.reversed:
+ self.children.reverse()
+ self.reversed = False
+ return math.xml(self)
+
+class munder(math):
+ nchildren = 2
+
+class munderover(math):
+ nchildren = 3
+ def __init__(self, children=None):
+ math.__init__(self, children)
+
+class mtext(math):
+ nchildren = 0
+ def __init__(self, text):
+ self.text = text
+
+ def xml_body(self):
+ return [self.text]
+
+def parse_latex_math(string, inline=True):
+ """parse_latex_math(string [,inline]) -> MathML-tree
+
+ Returns a MathML-tree parsed from string. inline=True is for
+ inline math and inline=False is for displayed math.
+
+ tree is the whole tree and node is the current element."""
+
+ # Normalize white-space:
+ string = ' '.join(string.split())
+
+ if inline:
+ node = mrow()
+ tree = math(node, inline=True)
+ else:
+ node = mtd()
+ tree = math(mtable(mtr(node)), inline=False)
+
+ while len(string) > 0:
+ n = len(string)
+ c = string[0]
+ skip = 1 # number of characters consumed
+ if n > 1:
+ c2 = string[1]
+ else:
+ c2 = ''
+ if c == ' ':
+ pass
+ elif c == '\\':
+ if c2 in '{}':
+ node = node.append(mo(c2))
+ skip = 2
+ elif c2 == ' ':
+ node = node.append(mspace())
+ skip = 2
+ elif c2 == ',': # TODO: small space
+ node = node.append(mspace())
+ skip = 2
+ elif c2.isalpha():
+ # We have a LaTeX-name:
+ i = 2
+ while i < n and string[i].isalpha():
+ i += 1
+ name = string[1:i]
+ node, skip = handle_keyword(name, node, string[i:])
+ skip += i
+ elif c2 == '\\':
+ # End of a row:
+ entry = mtd()
+ row = mtr(entry)
+ node.close().close().append(row)
+ node = entry
+ skip = 2
+ else:
+ raise SyntaxError(u'Syntax error: "%s%s"' % (c, c2))
+ elif c.isalpha():
+ node = node.append(mi(c))
+ elif c.isdigit():
+ node = node.append(mn(c))
+ elif c in "+-*/=()[]|<>,.!?':;@":
+ node = node.append(mo(c))
+ elif c == '_':
+ child = node.delete_child()
+ if isinstance(child, msup):
+ sub = msubsup(child.children, reversed=True)
+ elif isinstance(child, mo) and child.data in sumintprod:
+ sub = munder(child)
+ else:
+ sub = msub(child)
+ node.append(sub)
+ node = sub
+ elif c == '^':
+ child = node.delete_child()
+ if isinstance(child, msub):
+ sup = msubsup(child.children)
+ elif isinstance(child, mo) and child.data in sumintprod:
+ sup = mover(child)
+ elif (isinstance(child, munder) and
+ child.children[0].data in sumintprod):
+ sup = munderover(child.children)
+ else:
+ sup = msup(child)
+ node.append(sup)
+ node = sup
+ elif c == '{':
+ row = mrow()
+ node.append(row)
+ node = row
+ elif c == '}':
+ node = node.close()
+ elif c == '&':
+ entry = mtd()
+ node.close().append(entry)
+ node = entry
+ else:
+ raise SyntaxError(u'Illegal character: "%s"' % c)
+ string = string[skip:]
+ return tree
+
+
+def handle_keyword(name, node, string):
+ skip = 0
+ if len(string) > 0 and string[0] == ' ':
+ string = string[1:]
+ skip = 1
+ if name == 'begin':
+ if not string.startswith('{matrix}'):
+ raise SyntaxError(u'Environment not supported! '
+ u'Supported environment: "matrix".')
+ skip += 8
+ entry = mtd()
+ table = mtable(mtr(entry))
+ node.append(table)
+ node = entry
+ elif name == 'end':
+ if not string.startswith('{matrix}'):
+ raise SyntaxError(u'Expected "\\end{matrix}"!')
+ skip += 8
+ node = node.close().close().close()
+ elif name in ('text', 'mathrm'):
+ if string[0] != '{':
+ raise SyntaxError(u'Expected "\\text{...}"!')
+ i = string.find('}')
+ if i == -1:
+ raise SyntaxError(u'Expected "\\text{...}"!')
+ node = node.append(mtext(string[1:i]))
+ skip += i + 1
+ elif name == 'sqrt':
+ sqrt = msqrt()
+ node.append(sqrt)
+ node = sqrt
+ elif name == 'frac':
+ frac = mfrac()
+ node.append(frac)
+ node = frac
+ elif name == 'left':
+ for par in ['(', '[', '|', '\\{', '\\langle', '.']:
+ if string.startswith(par):
+ break
+ else:
+ raise SyntaxError(u'Missing left-brace!')
+ fenced = mfenced(par)
+ node.append(fenced)
+ row = mrow()
+ fenced.append(row)
+ node = row
+ skip += len(par)
+ elif name == 'right':
+ for par in [')', ']', '|', '\\}', '\\rangle', '.']:
+ if string.startswith(par):
+ break
+ else:
+ raise SyntaxError(u'Missing right-brace!')
+ node = node.close()
+ node.closepar = par
+ node = node.close()
+ skip += len(par)
+ elif name == 'not':
+ for operator in negatables:
+ if string.startswith(operator):
+ break
+ else:
+ raise SyntaxError(u'Expected something to negate: "\\not ..."!')
+ node = node.append(mo(negatables[operator]))
+ skip += len(operator)
+ elif name == 'mathbf':
+ style = mstyle(nchildren=1, fontweight='bold')
+ node.append(style)
+ node = style
+ elif name == 'mathbb':
+ if string[0] != '{' or not string[1].isupper() or string[2] != '}':
+ raise SyntaxError(u'Expected something like "\\mathbb{A}"!')
+ node = node.append(mi(mathbb[string[1]]))
+ skip += 3
+ elif name in ('mathscr', 'mathcal'):
+ if string[0] != '{' or string[2] != '}':
+ raise SyntaxError(u'Expected something like "\\mathscr{A}"!')
+ node = node.append(mi(mathscr[string[1]]))
+ skip += 3
+ elif name == 'colon': # "normal" colon, not binary operator
+ node = node.append(mo(':')) # TODO: add ``lspace="0pt"``
+ elif name in Greek: # Greek capitals (upright in "TeX style")
+ node = node.append(mo(Greek[name]))
+ # TODO: "ISO style" sets them italic. Could we use a class argument
+ # to enable styling via CSS?
+ elif name in letters:
+ node = node.append(mi(letters[name]))
+ elif name in special:
+ node = node.append(mo(special[name]))
+ elif name in functions:
+ node = node.append(mo(name))
+ elif name in over:
+ ovr = mover(mo(over[name]), reversed=True)
+ node.append(ovr)
+ node = ovr
+ else:
+ raise SyntaxError(u'Unknown LaTeX command: ' + name)
+
+ return node, skip
+
+def tex2mathml(tex_math, inline=True):
+ """Return string with MathML code corresponding to `tex_math`.
+
+ `inline`=True is for inline math and `inline`=False for displayed math.
+ """
+
+ mathml_tree = parse_latex_math(tex_math, inline=inline)
+ return ''.join(mathml_tree.xml())
--- /dev/null
+#! /usr/bin/env python
+# -*- coding: utf-8 -*-
+
+# math2html: convert LaTeX equations to HTML output.
+#
+# Copyright (C) 2009-2011 Alex Fernández
+#
+# 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://alexfernandez.github.io/elyxer/
+
+# --end--
+# Alex 20101110
+# eLyXer standalone formula conversion to HTML.
+
+import codecs
+import datetime
+import gettext
+import io
+import os.path
+import sys
+import unicodedata
+
+if sys.version_info >= (3, 0):
+ from urllib.parse import quote_plus
+else:
+ from urllib import quote_plus
+
+
+if sys.version_info >= (3, 0):
+ unicode = str #noqa
+ basestring = str # noqa
+ file = io.IOBase # noqa
+
+
+class Trace(object):
+ "A tracing class"
+
+ debugmode = False
+ quietmode = False
+ showlinesmode = False
+
+ prefix = None
+
+ def debug(cls, message):
+ "Show a debug message"
+ if not Trace.debugmode or Trace.quietmode:
+ return
+ Trace.show(message, sys.stdout)
+
+ def message(cls, message):
+ "Show a trace message"
+ if Trace.quietmode:
+ return
+ if Trace.prefix and Trace.showlinesmode:
+ message = Trace.prefix + message
+ Trace.show(message, sys.stdout)
+
+ def error(cls, message):
+ "Show an error message"
+ message = '* ' + message
+ if Trace.prefix and Trace.showlinesmode:
+ message = Trace.prefix + message
+ Trace.show(message, sys.stderr)
+
+ def fatal(cls, message):
+ "Show an error message and terminate"
+ Trace.error('FATAL: ' + message)
+ exit(-1)
+
+ def show(cls, message, channel):
+ "Show a message out of a channel"
+ if sys.version_info < (3, 0):
+ message = message.encode('utf-8')
+ channel.write(message + '\n')
+
+ debug = classmethod(debug)
+ message = classmethod(message)
+ error = classmethod(error)
+ fatal = classmethod(fatal)
+ show = classmethod(show)
+
+
+class BibStylesConfig(object):
+ "Configuration class from elyxer.config file"
+
+ abbrvnat = {
+ u'@article': u'$authors. $title. <i>$journal</i>,{ {$volume:}$pages,} $month $year.{ doi: $doi.}{ URL <a href="$url">$url</a>.}{ $note.}',
+ u'cite': u'$surname($year)',
+ u'default': u'$authors. <i>$title</i>. $publisher, $year.{ URL <a href="$url">$url</a>.}{ $note.}',
+ }
+
+ alpha = {
+ u'@article': u'$authors. $title.{ <i>$journal</i>{, {$volume}{($number)}}{: $pages}{, $year}.}{ <a href="$url">$url</a>.}{ <a href="$filename">$filename</a>.}{ $note.}',
+ u'cite': u'$Sur$YY',
+ u'default': u'$authors. $title.{ <i>$journal</i>,} $year.{ <a href="$url">$url</a>.}{ <a href="$filename">$filename</a>.}{ $note.}',
+ }
+
+ authordate2 = {
+ u'@article': u'$authors. $year. $title. <i>$journal</i>, <b>$volume</b>($number), $pages.{ URL <a href="$url">$url</a>.}{ $note.}',
+ u'@book': u'$authors. $year. <i>$title</i>. $publisher.{ URL <a href="$url">$url</a>.}{ $note.}',
+ u'cite': u'$surname, $year',
+ u'default': u'$authors. $year. <i>$title</i>. $publisher.{ URL <a href="$url">$url</a>.}{ $note.}',
+ }
+
+ default = {
+ u'@article': u'$authors: “$title”, <i>$journal</i>,{ pp. $pages,} $year.{ URL <a href="$url">$url</a>.}{ $note.}',
+ u'@book': u'{$authors: }<i>$title</i>{ ($editor, ed.)}.{{ $publisher,} $year.}{ URL <a href="$url">$url</a>.}{ $note.}',
+ u'@booklet': u'$authors: <i>$title</i>.{{ $publisher,} $year.}{ URL <a href="$url">$url</a>.}{ $note.}',
+ u'@conference': u'$authors: “$title”, <i>$journal</i>,{ pp. $pages,} $year.{ URL <a href="$url">$url</a>.}{ $note.}',
+ u'@inbook': u'$authors: <i>$title</i>.{{ $publisher,} $year.}{ URL <a href="$url">$url</a>.}{ $note.}',
+ u'@incollection': u'$authors: <i>$title</i>{ in <i>$booktitle</i>{ ($editor, ed.)}}.{{ $publisher,} $year.}{ URL <a href="$url">$url</a>.}{ $note.}',
+ u'@inproceedings': u'$authors: “$title”, <i>$booktitle</i>,{ pp. $pages,} $year.{ URL <a href="$url">$url</a>.}{ $note.}',
+ u'@manual': u'$authors: <i>$title</i>.{{ $publisher,} $year.}{ URL <a href="$url">$url</a>.}{ $note.}',
+ u'@mastersthesis': u'$authors: <i>$title</i>.{{ $publisher,} $year.}{ URL <a href="$url">$url</a>.}{ $note.}',
+ u'@misc': u'$authors: <i>$title</i>.{{ $publisher,}{ $howpublished,} $year.}{ URL <a href="$url">$url</a>.}{ $note.}',
+ u'@phdthesis': u'$authors: <i>$title</i>.{{ $publisher,} $year.}{ URL <a href="$url">$url</a>.}{ $note.}',
+ u'@proceedings': u'$authors: “$title”, <i>$journal</i>,{ pp. $pages,} $year.{ URL <a href="$url">$url</a>.}{ $note.}',
+ u'@techreport': u'$authors: <i>$title</i>, $year.{ URL <a href="$url">$url</a>.}{ $note.}',
+ u'@unpublished': u'$authors: “$title”, <i>$journal</i>, $year.{ URL <a href="$url">$url</a>.}{ $note.}',
+ u'cite': u'$index',
+ u'default': u'$authors: <i>$title</i>.{{ $publisher,} $year.}{ URL <a href="$url">$url</a>.}{ $note.}',
+ }
+
+ defaulttags = {
+ u'YY': u'??', u'authors': u'', u'surname': u'',
+ }
+
+ ieeetr = {
+ u'@article': u'$authors, “$title”, <i>$journal</i>, vol. $volume, no. $number, pp. $pages, $year.{ URL <a href="$url">$url</a>.}{ $note.}',
+ u'@book': u'$authors, <i>$title</i>. $publisher, $year.{ URL <a href="$url">$url</a>.}{ $note.}',
+ u'cite': u'$index',
+ u'default': u'$authors, “$title”. $year.{ URL <a href="$url">$url</a>.}{ $note.}',
+ }
+
+ plain = {
+ u'@article': u'$authors. $title.{ <i>$journal</i>{, {$volume}{($number)}}{:$pages}{, $year}.}{ URL <a href="$url">$url</a>.}{ $note.}',
+ u'@book': u'$authors. <i>$title</i>. $publisher,{ $month} $year.{ URL <a href="$url">$url</a>.}{ $note.}',
+ u'@incollection': u'$authors. $title.{ In <i>$booktitle</i> {($editor, ed.)}.} $publisher,{ $month} $year.{ URL <a href="$url">$url</a>.}{ $note.}',
+ u'@inproceedings': u'$authors. $title. { <i>$booktitle</i>{, {$volume}{($number)}}{:$pages}{, $year}.}{ URL <a href="$url">$url</a>.}{ $note.}',
+ u'cite': u'$index',
+ u'default': u'{$authors. }$title.{{ $publisher,} $year.}{ URL <a href="$url">$url</a>.}{ $note.}',
+ }
+
+ vancouver = {
+ u'@article': u'$authors. $title. <i>$journal</i>, $year{;{<b>$volume</b>}{($number)}{:$pages}}.{ URL: <a href="$url">$url</a>.}{ $note.}',
+ u'@book': u'$authors. $title. {$publisher, }$year.{ URL: <a href="$url">$url</a>.}{ $note.}',
+ u'cite': u'$index',
+ u'default': u'$authors. $title; {$publisher, }$year.{ $howpublished.}{ URL: <a href="$url">$url</a>.}{ $note.}',
+ }
+
+class BibTeXConfig(object):
+ "Configuration class from elyxer.config file"
+
+ replaced = {
+ u'--': u'—', u'..': u'.',
+ }
+
+class ContainerConfig(object):
+ "Configuration class from elyxer.config file"
+
+ endings = {
+ u'Align': u'\\end_layout', u'BarredText': u'\\bar',
+ u'BoldText': u'\\series', u'Cell': u'</cell',
+ u'ChangeDeleted': u'\\change_unchanged',
+ u'ChangeInserted': u'\\change_unchanged', u'ColorText': u'\\color',
+ u'EmphaticText': u'\\emph', u'Hfill': u'\\hfill', u'Inset': u'\\end_inset',
+ u'Layout': u'\\end_layout', u'LyXFooter': u'\\end_document',
+ u'LyXHeader': u'\\end_header', u'Row': u'</row', u'ShapedText': u'\\shape',
+ u'SizeText': u'\\size', u'StrikeOut': u'\\strikeout',
+ u'TextFamily': u'\\family', u'VersalitasText': u'\\noun',
+ }
+
+ extracttext = {
+ u'allowed': [u'StringContainer', u'Constant', u'FormulaConstant',],
+ u'cloned': [u'',],
+ u'extracted': [u'PlainLayout', u'TaggedText', u'Align', u'Caption', u'TextFamily', u'EmphaticText', u'VersalitasText', u'BarredText', u'SizeText', u'ColorText', u'LangLine', u'Formula', u'Bracket', u'RawText', u'BibTag', u'FormulaNumber', u'AlphaCommand', u'EmptyCommand', u'OneParamFunction', u'SymbolFunction', u'TextFunction', u'FontFunction', u'CombiningFunction', u'DecoratingFunction', u'FormulaSymbol', u'BracketCommand', u'TeXCode',],
+ }
+
+ startendings = {
+ u'\\begin_deeper': u'\\end_deeper', u'\\begin_inset': u'\\end_inset',
+ u'\\begin_layout': u'\\end_layout',
+ }
+
+ starts = {
+ u'': u'StringContainer', u'#LyX': u'BlackBox', u'</lyxtabular': u'BlackBox',
+ u'<cell': u'Cell', u'<column': u'Column', u'<row': u'Row',
+ u'\\align': u'Align', u'\\bar': u'BarredText',
+ u'\\bar default': u'BlackBox', u'\\bar no': u'BlackBox',
+ u'\\begin_body': u'BlackBox', u'\\begin_deeper': u'DeeperList',
+ u'\\begin_document': u'BlackBox', u'\\begin_header': u'LyXHeader',
+ u'\\begin_inset Argument': u'ShortTitle',
+ u'\\begin_inset Box': u'BoxInset', u'\\begin_inset Branch': u'Branch',
+ u'\\begin_inset Caption': u'Caption',
+ u'\\begin_inset CommandInset bibitem': u'BiblioEntry',
+ u'\\begin_inset CommandInset bibtex': u'BibTeX',
+ u'\\begin_inset CommandInset citation': u'BiblioCitation',
+ u'\\begin_inset CommandInset href': u'URL',
+ u'\\begin_inset CommandInset include': u'IncludeInset',
+ u'\\begin_inset CommandInset index_print': u'PrintIndex',
+ u'\\begin_inset CommandInset label': u'Label',
+ u'\\begin_inset CommandInset line': u'LineInset',
+ u'\\begin_inset CommandInset nomencl_print': u'PrintNomenclature',
+ u'\\begin_inset CommandInset nomenclature': u'NomenclatureEntry',
+ u'\\begin_inset CommandInset ref': u'Reference',
+ u'\\begin_inset CommandInset toc': u'TableOfContents',
+ u'\\begin_inset ERT': u'ERT', u'\\begin_inset Flex': u'FlexInset',
+ u'\\begin_inset Flex Chunkref': u'NewfangledChunkRef',
+ u'\\begin_inset Flex Marginnote': u'SideNote',
+ u'\\begin_inset Flex Sidenote': u'SideNote',
+ u'\\begin_inset Flex URL': u'FlexURL', u'\\begin_inset Float': u'Float',
+ u'\\begin_inset FloatList': u'ListOf', u'\\begin_inset Foot': u'Footnote',
+ u'\\begin_inset Formula': u'Formula',
+ u'\\begin_inset FormulaMacro': u'FormulaMacro',
+ u'\\begin_inset Graphics': u'Image',
+ u'\\begin_inset Index': u'IndexReference',
+ u'\\begin_inset Info': u'InfoInset',
+ u'\\begin_inset LatexCommand bibitem': u'BiblioEntry',
+ u'\\begin_inset LatexCommand bibtex': u'BibTeX',
+ u'\\begin_inset LatexCommand cite': u'BiblioCitation',
+ u'\\begin_inset LatexCommand citealt': u'BiblioCitation',
+ u'\\begin_inset LatexCommand citep': u'BiblioCitation',
+ u'\\begin_inset LatexCommand citet': u'BiblioCitation',
+ u'\\begin_inset LatexCommand htmlurl': u'URL',
+ u'\\begin_inset LatexCommand index': u'IndexReference',
+ u'\\begin_inset LatexCommand label': u'Label',
+ u'\\begin_inset LatexCommand nomenclature': u'NomenclatureEntry',
+ u'\\begin_inset LatexCommand prettyref': u'Reference',
+ u'\\begin_inset LatexCommand printindex': u'PrintIndex',
+ u'\\begin_inset LatexCommand printnomenclature': u'PrintNomenclature',
+ u'\\begin_inset LatexCommand ref': u'Reference',
+ u'\\begin_inset LatexCommand tableofcontents': u'TableOfContents',
+ u'\\begin_inset LatexCommand url': u'URL',
+ u'\\begin_inset LatexCommand vref': u'Reference',
+ u'\\begin_inset Marginal': u'SideNote',
+ u'\\begin_inset Newline': u'NewlineInset',
+ u'\\begin_inset Newpage': u'NewPageInset', u'\\begin_inset Note': u'Note',
+ u'\\begin_inset OptArg': u'ShortTitle',
+ u'\\begin_inset Phantom': u'PhantomText',
+ u'\\begin_inset Quotes': u'QuoteContainer',
+ u'\\begin_inset Tabular': u'Table', u'\\begin_inset Text': u'InsetText',
+ u'\\begin_inset VSpace': u'VerticalSpace', u'\\begin_inset Wrap': u'Wrap',
+ u'\\begin_inset listings': u'Listing',
+ u'\\begin_inset script': u'ScriptInset', u'\\begin_inset space': u'Space',
+ u'\\begin_layout': u'Layout', u'\\begin_layout Abstract': u'Abstract',
+ u'\\begin_layout Author': u'Author',
+ u'\\begin_layout Bibliography': u'Bibliography',
+ u'\\begin_layout Chunk': u'NewfangledChunk',
+ u'\\begin_layout Description': u'Description',
+ u'\\begin_layout Enumerate': u'ListItem',
+ u'\\begin_layout Itemize': u'ListItem', u'\\begin_layout List': u'List',
+ u'\\begin_layout LyX-Code': u'LyXCode',
+ u'\\begin_layout Plain': u'PlainLayout',
+ u'\\begin_layout Standard': u'StandardLayout',
+ u'\\begin_layout Title': u'Title', u'\\begin_preamble': u'LyXPreamble',
+ u'\\change_deleted': u'ChangeDeleted',
+ u'\\change_inserted': u'ChangeInserted',
+ u'\\change_unchanged': u'BlackBox', u'\\color': u'ColorText',
+ u'\\color inherit': u'BlackBox', u'\\color none': u'BlackBox',
+ u'\\emph default': u'BlackBox', u'\\emph off': u'BlackBox',
+ u'\\emph on': u'EmphaticText', u'\\emph toggle': u'EmphaticText',
+ u'\\end_body': u'LyXFooter', u'\\family': u'TextFamily',
+ u'\\family default': u'BlackBox', u'\\family roman': u'BlackBox',
+ u'\\hfill': u'Hfill', u'\\labelwidthstring': u'BlackBox',
+ u'\\lang': u'LangLine', u'\\length': u'InsetLength',
+ u'\\lyxformat': u'LyXFormat', u'\\lyxline': u'LyXLine',
+ u'\\newline': u'Newline', u'\\newpage': u'NewPage',
+ u'\\noindent': u'BlackBox', u'\\noun default': u'BlackBox',
+ u'\\noun off': u'BlackBox', u'\\noun on': u'VersalitasText',
+ u'\\paragraph_spacing': u'BlackBox', u'\\series bold': u'BoldText',
+ u'\\series default': u'BlackBox', u'\\series medium': u'BlackBox',
+ u'\\shape': u'ShapedText', u'\\shape default': u'BlackBox',
+ u'\\shape up': u'BlackBox', u'\\size': u'SizeText',
+ u'\\size normal': u'BlackBox', u'\\start_of_appendix': u'StartAppendix',
+ u'\\strikeout default': u'BlackBox', u'\\strikeout on': u'StrikeOut',
+ }
+
+ string = {
+ u'startcommand': u'\\',
+ }
+
+ table = {
+ u'headers': [u'<lyxtabular', u'<features',],
+ }
+
+class EscapeConfig(object):
+ "Configuration class from elyxer.config file"
+
+ chars = {
+ u'\n': u'', u' -- ': u' — ', u' --- ': u' — ', u'\'': u'’', u'`': u'‘',
+ }
+
+ commands = {
+ u'\\InsetSpace \\space{}': u' ', u'\\InsetSpace \\thinspace{}': u' ',
+ u'\\InsetSpace ~': u' ', u'\\SpecialChar \\-': u'',
+ u'\\SpecialChar \\@.': u'.', u'\\SpecialChar \\ldots{}': u'…',
+ u'\\SpecialChar \\menuseparator': u' ▷ ',
+ u'\\SpecialChar \\nobreakdash-': u'-', u'\\SpecialChar \\slash{}': u'/',
+ u'\\SpecialChar \\textcompwordmark{}': u'', u'\\backslash': u'\\',
+ }
+
+ entities = {
+ u'&': u'&', u'<': u'<', u'>': u'>',
+ }
+
+ html = {
+ u'/>': u'>',
+ }
+
+ iso885915 = {
+ u' ': u' ', u' ': u' ', u' ': u' ',
+ }
+
+ nonunicode = {
+ u' ': u' ',
+ }
+
+class FormulaConfig(object):
+ "Configuration class from elyxer.config file"
+
+ alphacommands = {
+ u'\\AA': u'Å', u'\\AE': u'Æ',
+ u'\\AmS': u'<span class="versalitas">AmS</span>', u'\\Angstroem': u'Å',
+ u'\\DH': u'Ð', u'\\Koppa': u'Ϟ', u'\\L': u'Ł', u'\\Micro': u'µ', u'\\O': u'Ø',
+ u'\\OE': u'Œ', u'\\Sampi': u'Ϡ', u'\\Stigma': u'Ϛ', u'\\TH': u'Þ',
+ u'\\aa': u'å', u'\\ae': u'æ', u'\\alpha': u'α', u'\\beta': u'β',
+ u'\\delta': u'δ', u'\\dh': u'ð', u'\\digamma': u'ϝ', u'\\epsilon': u'ϵ',
+ u'\\eta': u'η', u'\\eth': u'ð', u'\\gamma': u'γ', u'\\i': u'ı',
+ u'\\imath': u'ı', u'\\iota': u'ι', u'\\j': u'ȷ', u'\\jmath': u'ȷ',
+ u'\\kappa': u'κ', u'\\koppa': u'ϟ', u'\\l': u'ł', u'\\lambda': u'λ',
+ u'\\mu': u'μ', u'\\nu': u'ν', u'\\o': u'ø', u'\\oe': u'œ', u'\\omega': u'ω',
+ u'\\phi': u'φ', u'\\pi': u'π', u'\\psi': u'ψ', u'\\rho': u'ρ',
+ u'\\sampi': u'ϡ', u'\\sigma': u'σ', u'\\ss': u'ß', u'\\stigma': u'ϛ',
+ u'\\tau': u'τ', u'\\tcohm': u'Ω', u'\\textcrh': u'ħ', u'\\th': u'þ',
+ u'\\theta': u'θ', u'\\upsilon': u'υ', u'\\varDelta': u'∆',
+ u'\\varGamma': u'Γ', u'\\varLambda': u'Λ', u'\\varOmega': u'Ω',
+ u'\\varPhi': u'Φ', u'\\varPi': u'Π', u'\\varPsi': u'Ψ', u'\\varSigma': u'Σ',
+ u'\\varTheta': u'Θ', u'\\varUpsilon': u'Υ', u'\\varXi': u'Ξ',
+ u'\\varbeta': u'ϐ', u'\\varepsilon': u'ε', u'\\varkappa': u'ϰ',
+ u'\\varphi': u'φ', u'\\varpi': u'ϖ', u'\\varrho': u'ϱ', u'\\varsigma': u'ς',
+ u'\\vartheta': u'ϑ', u'\\xi': u'ξ', u'\\zeta': u'ζ',
+ }
+
+ array = {
+ u'begin': u'\\begin', u'cellseparator': u'&', u'end': u'\\end',
+ u'rowseparator': u'\\\\',
+ }
+
+ bigbrackets = {
+ u'(': [u'⎛', u'⎜', u'⎝',], u')': [u'⎞', u'⎟', u'⎠',], u'[': [u'⎡', u'⎢', u'⎣',],
+ u']': [u'⎤', u'⎥', u'⎦',], u'{': [u'⎧', u'⎪', u'⎨', u'⎩',], u'|': [u'|',],
+ u'}': [u'⎫', u'⎪', u'⎬', u'⎭',], u'∥': [u'∥',],
+ }
+
+ bigsymbols = {
+ u'∑': [u'⎲', u'⎳',], u'∫': [u'⌠', u'⌡',],
+ }
+
+ bracketcommands = {
+ u'\\left': u'span class="symbol"',
+ u'\\left.': u'<span class="leftdot"></span>',
+ u'\\middle': u'span class="symbol"', u'\\right': u'span class="symbol"',
+ u'\\right.': u'<span class="rightdot"></span>',
+ }
+
+ combiningfunctions = {
+ u'\\"': u'̈', u'\\\'': u'́', u'\\^': u'̂', u'\\`': u'̀', u'\\acute': u'́',
+ u'\\bar': u'̄', u'\\breve': u'̆', u'\\c': u'̧', u'\\check': u'̌',
+ u'\\dddot': u'⃛', u'\\ddot': u'̈', u'\\dot': u'̇', u'\\grave': u'̀',
+ u'\\hat': u'̂', u'\\mathring': u'̊', u'\\overleftarrow': u'⃖',
+ u'\\overrightarrow': u'⃗', u'\\r': u'̊', u'\\s': u'̩',
+ u'\\textcircled': u'⃝', u'\\textsubring': u'̥', u'\\tilde': u'̃',
+ u'\\v': u'̌', u'\\vec': u'⃗', u'\\~': u'̃',
+ }
+
+ commands = {
+ u'\\ ': u' ', u'\\!': u'', u'\\#': u'#', u'\\$': u'$', u'\\%': u'%',
+ u'\\&': u'&', u'\\,': u' ', u'\\:': u' ', u'\\;': u' ', u'\\AC': u'∿',
+ u'\\APLcomment': u'⍝', u'\\APLdownarrowbox': u'⍗', u'\\APLinput': u'⍞',
+ u'\\APLinv': u'⌹', u'\\APLleftarrowbox': u'⍇', u'\\APLlog': u'⍟',
+ u'\\APLrightarrowbox': u'⍈', u'\\APLuparrowbox': u'⍐', u'\\Box': u'□',
+ u'\\Bumpeq': u'≎', u'\\CIRCLE': u'●', u'\\Cap': u'⋒',
+ u'\\CapitalDifferentialD': u'ⅅ', u'\\CheckedBox': u'☑', u'\\Circle': u'○',
+ u'\\Coloneqq': u'⩴', u'\\ComplexI': u'ⅈ', u'\\ComplexJ': u'ⅉ',
+ u'\\Corresponds': u'≙', u'\\Cup': u'⋓', u'\\Delta': u'Δ', u'\\Diamond': u'◇',
+ u'\\Diamondblack': u'◆', u'\\Diamonddot': u'⟐', u'\\DifferentialD': u'ⅆ',
+ u'\\Downarrow': u'⇓', u'\\EUR': u'€', u'\\Euler': u'ℇ',
+ u'\\ExponetialE': u'ⅇ', u'\\Finv': u'Ⅎ', u'\\Game': u'⅁', u'\\Gamma': u'Γ',
+ u'\\Im': u'ℑ', u'\\Join': u'⨝', u'\\LEFTCIRCLE': u'◖', u'\\LEFTcircle': u'◐',
+ u'\\LHD': u'◀', u'\\Lambda': u'Λ', u'\\Lbag': u'⟅', u'\\Leftarrow': u'⇐',
+ u'\\Lleftarrow': u'⇚', u'\\Longleftarrow': u'⟸',
+ u'\\Longleftrightarrow': u'⟺', u'\\Longrightarrow': u'⟹', u'\\Lparen': u'⦅',
+ u'\\Lsh': u'↰', u'\\Mapsfrom': u'⇐|', u'\\Mapsto': u'|⇒', u'\\Omega': u'Ω',
+ u'\\P': u'¶', u'\\Phi': u'Φ', u'\\Pi': u'Π', u'\\Pr': u'Pr', u'\\Psi': u'Ψ',
+ u'\\Qoppa': u'Ϙ', u'\\RHD': u'▶', u'\\RIGHTCIRCLE': u'◗',
+ u'\\RIGHTcircle': u'◑', u'\\Rbag': u'⟆', u'\\Re': u'ℜ', u'\\Rparen': u'⦆',
+ u'\\Rrightarrow': u'⇛', u'\\Rsh': u'↱', u'\\S': u'§', u'\\Sigma': u'Σ',
+ u'\\Square': u'☐', u'\\Subset': u'⋐', u'\\Sun': u'☉', u'\\Supset': u'⋑',
+ u'\\Theta': u'Θ', u'\\Uparrow': u'⇑', u'\\Updownarrow': u'⇕',
+ u'\\Upsilon': u'Υ', u'\\Vdash': u'⊩', u'\\Vert': u'∥', u'\\Vvdash': u'⊪',
+ u'\\XBox': u'☒', u'\\Xi': u'Ξ', u'\\Yup': u'⅄', u'\\\\': u'<br/>',
+ u'\\_': u'_', u'\\aleph': u'ℵ', u'\\amalg': u'∐', u'\\anchor': u'⚓',
+ u'\\angle': u'∠', u'\\aquarius': u'♒', u'\\arccos': u'arccos',
+ u'\\arcsin': u'arcsin', u'\\arctan': u'arctan', u'\\arg': u'arg',
+ u'\\aries': u'♈', u'\\arrowbullet': u'➢', u'\\ast': u'∗', u'\\asymp': u'≍',
+ u'\\backepsilon': u'∍', u'\\backprime': u'‵', u'\\backsimeq': u'⋍',
+ u'\\backslash': u'\\', u'\\ballotx': u'✗', u'\\barwedge': u'⊼',
+ u'\\because': u'∵', u'\\beth': u'ℶ', u'\\between': u'≬', u'\\bigcap': u'∩',
+ u'\\bigcirc': u'○', u'\\bigcup': u'∪', u'\\bigodot': u'⊙',
+ u'\\bigoplus': u'⊕', u'\\bigotimes': u'⊗', u'\\bigsqcup': u'⊔',
+ u'\\bigstar': u'★', u'\\bigtriangledown': u'▽', u'\\bigtriangleup': u'△',
+ u'\\biguplus': u'⊎', u'\\bigvee': u'∨', u'\\bigwedge': u'∧',
+ u'\\biohazard': u'☣', u'\\blacklozenge': u'⧫', u'\\blacksmiley': u'☻',
+ u'\\blacksquare': u'■', u'\\blacktriangle': u'▲',
+ u'\\blacktriangledown': u'▼', u'\\blacktriangleleft': u'◂',
+ u'\\blacktriangleright': u'▶', u'\\blacktriangleup': u'▴', u'\\bot': u'⊥',
+ u'\\bowtie': u'⋈', u'\\box': u'▫', u'\\boxast': u'⧆', u'\\boxbar': u'◫',
+ u'\\boxbox': u'⧈', u'\\boxbslash': u'⧅', u'\\boxcircle': u'⧇',
+ u'\\boxdot': u'⊡', u'\\boxminus': u'⊟', u'\\boxplus': u'⊞',
+ u'\\boxslash': u'⧄', u'\\boxtimes': u'⊠', u'\\bullet': u'•',
+ u'\\bumpeq': u'≏', u'\\cancer': u'♋', u'\\cap': u'∩', u'\\capricornus': u'♑',
+ u'\\cat': u'⁀', u'\\cdot': u'⋅', u'\\cdots': u'⋯', u'\\cent': u'¢',
+ u'\\centerdot': u'∙', u'\\checkmark': u'✓', u'\\chi': u'χ', u'\\circ': u'∘',
+ u'\\circeq': u'≗', u'\\circlearrowleft': u'↺', u'\\circlearrowright': u'↻',
+ u'\\circledR': u'®', u'\\circledast': u'⊛', u'\\circledbslash': u'⦸',
+ u'\\circledcirc': u'⊚', u'\\circleddash': u'⊝', u'\\circledgtr': u'⧁',
+ u'\\circledless': u'⧀', u'\\clubsuit': u'♣', u'\\colon': u': ', u'\\coloneqq': u'≔',
+ u'\\complement': u'∁', u'\\cong': u'≅', u'\\coprod': u'∐',
+ u'\\copyright': u'©', u'\\cos': u'cos', u'\\cosh': u'cosh', u'\\cot': u'cot',
+ u'\\coth': u'coth', u'\\csc': u'csc', u'\\cup': u'∪', u'\\curlyvee': u'⋎',
+ u'\\curlywedge': u'⋏', u'\\curvearrowleft': u'↶',
+ u'\\curvearrowright': u'↷', u'\\dag': u'†', u'\\dagger': u'†',
+ u'\\daleth': u'ℸ', u'\\dashleftarrow': u'⇠', u'\\dashv': u'⊣',
+ u'\\ddag': u'‡', u'\\ddagger': u'‡', u'\\ddots': u'⋱', u'\\deg': u'deg',
+ u'\\det': u'det', u'\\diagdown': u'╲', u'\\diagup': u'╱',
+ u'\\diameter': u'⌀', u'\\diamond': u'◇', u'\\diamondsuit': u'♦',
+ u'\\dim': u'dim', u'\\div': u'÷', u'\\divideontimes': u'⋇',
+ u'\\dotdiv': u'∸', u'\\doteq': u'≐', u'\\doteqdot': u'≑', u'\\dotplus': u'∔',
+ u'\\dots': u'…', u'\\doublebarwedge': u'⌆', u'\\downarrow': u'↓',
+ u'\\downdownarrows': u'⇊', u'\\downharpoonleft': u'⇃',
+ u'\\downharpoonright': u'⇂', u'\\dsub': u'⩤', u'\\earth': u'♁',
+ u'\\eighthnote': u'♪', u'\\ell': u'ℓ', u'\\emptyset': u'∅',
+ u'\\eqcirc': u'≖', u'\\eqcolon': u'≕', u'\\eqsim': u'≂', u'\\euro': u'€',
+ u'\\exists': u'∃', u'\\exp': u'exp', u'\\fallingdotseq': u'≒',
+ u'\\fcmp': u'⨾', u'\\female': u'♀', u'\\flat': u'♭', u'\\forall': u'∀',
+ u'\\fourth': u'⁗', u'\\frown': u'⌢', u'\\frownie': u'☹', u'\\gcd': u'gcd',
+ u'\\gemini': u'♊', u'\\geq)': u'≥', u'\\geqq': u'≧', u'\\geqslant': u'≥',
+ u'\\gets': u'←', u'\\gg': u'≫', u'\\ggg': u'⋙', u'\\gimel': u'ℷ',
+ u'\\gneqq': u'≩', u'\\gnsim': u'⋧', u'\\gtrdot': u'⋗', u'\\gtreqless': u'⋚',
+ u'\\gtreqqless': u'⪌', u'\\gtrless': u'≷', u'\\gtrsim': u'≳',
+ u'\\guillemotleft': u'«', u'\\guillemotright': u'»', u'\\hbar': u'ℏ',
+ u'\\heartsuit': u'♥', u'\\hfill': u'<span class="hfill"> </span>',
+ u'\\hom': u'hom', u'\\hookleftarrow': u'↩', u'\\hookrightarrow': u'↪',
+ u'\\hslash': u'ℏ', u'\\idotsint': u'<span class="bigsymbol">∫⋯∫</span>',
+ u'\\iiint': u'<span class="bigsymbol">∭</span>',
+ u'\\iint': u'<span class="bigsymbol">∬</span>', u'\\imath': u'ı',
+ u'\\inf': u'inf', u'\\infty': u'∞', u'\\intercal': u'⊺',
+ u'\\interleave': u'⫴', u'\\invamp': u'⅋', u'\\invneg': u'⌐',
+ u'\\jmath': u'ȷ', u'\\jupiter': u'♃', u'\\ker': u'ker', u'\\land': u'∧',
+ u'\\landupint': u'<span class="bigsymbol">∱</span>', u'\\lang': u'⟪',
+ u'\\langle': u'⟨', u'\\lblot': u'⦉', u'\\lbrace': u'{', u'\\lbrace)': u'{',
+ u'\\lbrack': u'[', u'\\lceil': u'⌈', u'\\ldots': u'…', u'\\leadsto': u'⇝',
+ u'\\leftarrow)': u'←', u'\\leftarrowtail': u'↢', u'\\leftarrowtobar': u'⇤',
+ u'\\leftharpoondown': u'↽', u'\\leftharpoonup': u'↼',
+ u'\\leftleftarrows': u'⇇', u'\\leftleftharpoons': u'⥢', u'\\leftmoon': u'☾',
+ u'\\leftrightarrow': u'↔', u'\\leftrightarrows': u'⇆',
+ u'\\leftrightharpoons': u'⇋', u'\\leftthreetimes': u'⋋', u'\\leo': u'♌',
+ u'\\leq)': u'≤', u'\\leqq': u'≦', u'\\leqslant': u'≤', u'\\lessdot': u'⋖',
+ u'\\lesseqgtr': u'⋛', u'\\lesseqqgtr': u'⪋', u'\\lessgtr': u'≶',
+ u'\\lesssim': u'≲', u'\\lfloor': u'⌊', u'\\lg': u'lg', u'\\lgroup': u'⟮',
+ u'\\lhd': u'⊲', u'\\libra': u'♎', u'\\lightning': u'↯', u'\\limg': u'⦇',
+ u'\\liminf': u'liminf', u'\\limsup': u'limsup', u'\\ll': u'≪',
+ u'\\llbracket': u'⟦', u'\\llcorner': u'⌞', u'\\lll': u'⋘', u'\\ln': u'ln',
+ u'\\lneqq': u'≨', u'\\lnot': u'¬', u'\\lnsim': u'⋦', u'\\log': u'log',
+ u'\\longleftarrow': u'⟵', u'\\longleftrightarrow': u'⟷',
+ u'\\longmapsto': u'⟼', u'\\longrightarrow': u'⟶', u'\\looparrowleft': u'↫',
+ u'\\looparrowright': u'↬', u'\\lor': u'∨', u'\\lozenge': u'◊',
+ u'\\lrcorner': u'⌟', u'\\ltimes': u'⋉', u'\\lyxlock': u'', u'\\male': u'♂',
+ u'\\maltese': u'✠', u'\\mapsfrom': u'↤', u'\\mapsto': u'↦',
+ u'\\mathcircumflex': u'^', u'\\max': u'max', u'\\measuredangle': u'∡',
+ u'\\medbullet': u'⚫', u'\\medcirc': u'⚪', u'\\mercury': u'☿', u'\\mho': u'℧',
+ u'\\mid': u'∣', u'\\min': u'min', u'\\models': u'⊨', u'\\mp': u'∓',
+ u'\\multimap': u'⊸', u'\\nLeftarrow': u'⇍', u'\\nLeftrightarrow': u'⇎',
+ u'\\nRightarrow': u'⇏', u'\\nVDash': u'⊯', u'\\nabla': u'∇',
+ u'\\napprox': u'≉', u'\\natural': u'♮', u'\\ncong': u'≇', u'\\nearrow': u'↗',
+ u'\\neg': u'¬', u'\\neg)': u'¬', u'\\neptune': u'♆', u'\\nequiv': u'≢',
+ u'\\newline': u'<br/>', u'\\nexists': u'∄', u'\\ngeqslant': u'≱',
+ u'\\ngtr': u'≯', u'\\ngtrless': u'≹', u'\\ni': u'∋', u'\\ni)': u'∋',
+ u'\\nleftarrow': u'↚', u'\\nleftrightarrow': u'↮', u'\\nleqslant': u'≰',
+ u'\\nless': u'≮', u'\\nlessgtr': u'≸', u'\\nmid': u'∤', u'\\nolimits': u'',
+ u'\\nonumber': u'', u'\\not': u'¬', u'\\not<': u'≮', u'\\not=': u'≠',
+ u'\\not>': u'≯', u'\\notbackslash': u'⍀', u'\\notin': u'∉', u'\\notni': u'∌',
+ u'\\notslash': u'⌿', u'\\nparallel': u'∦', u'\\nprec': u'⊀',
+ u'\\nrightarrow': u'↛', u'\\nsim': u'≁', u'\\nsimeq': u'≄',
+ u'\\nsqsubset': u'⊏̸', u'\\nsubseteq': u'⊈', u'\\nsucc': u'⊁',
+ u'\\nsucccurlyeq': u'⋡', u'\\nsupset': u'⊅', u'\\nsupseteq': u'⊉',
+ u'\\ntriangleleft': u'⋪', u'\\ntrianglelefteq': u'⋬',
+ u'\\ntriangleright': u'⋫', u'\\ntrianglerighteq': u'⋭', u'\\nvDash': u'⊭',
+ u'\\nvdash': u'⊬', u'\\nwarrow': u'↖', u'\\odot': u'⊙',
+ u'\\officialeuro': u'€', u'\\oiiint': u'<span class="bigsymbol">∰</span>',
+ u'\\oiint': u'<span class="bigsymbol">∯</span>',
+ u'\\oint': u'<span class="bigsymbol">∮</span>',
+ u'\\ointclockwise': u'<span class="bigsymbol">∲</span>',
+ u'\\ointctrclockwise': u'<span class="bigsymbol">∳</span>',
+ u'\\ominus': u'⊖', u'\\oplus': u'⊕', u'\\oslash': u'⊘', u'\\otimes': u'⊗',
+ u'\\owns': u'∋', u'\\parallel': u'∥', u'\\partial': u'∂', u'\\pencil': u'✎',
+ u'\\perp': u'⊥', u'\\pisces': u'♓', u'\\pitchfork': u'⋔', u'\\pluto': u'♇',
+ u'\\pm': u'±', u'\\pointer': u'➪', u'\\pointright': u'☞', u'\\pounds': u'£',
+ u'\\prec': u'≺', u'\\preccurlyeq': u'≼', u'\\preceq': u'≼',
+ u'\\precsim': u'≾', u'\\prime': u'′', u'\\prompto': u'∝', u'\\qoppa': u'ϙ',
+ u'\\qquad': u' ', u'\\quad': u' ', u'\\quarternote': u'♩',
+ u'\\radiation': u'☢', u'\\rang': u'⟫', u'\\rangle': u'⟩', u'\\rblot': u'⦊',
+ u'\\rbrace': u'}', u'\\rbrace)': u'}', u'\\rbrack': u']', u'\\rceil': u'⌉',
+ u'\\recycle': u'♻', u'\\rfloor': u'⌋', u'\\rgroup': u'⟯', u'\\rhd': u'⊳',
+ u'\\rightangle': u'∟', u'\\rightarrow)': u'→', u'\\rightarrowtail': u'↣',
+ u'\\rightarrowtobar': u'⇥', u'\\rightharpoondown': u'⇁',
+ u'\\rightharpoonup': u'⇀', u'\\rightharpooondown': u'⇁',
+ u'\\rightharpooonup': u'⇀', u'\\rightleftarrows': u'⇄',
+ u'\\rightleftharpoons': u'⇌', u'\\rightmoon': u'☽',
+ u'\\rightrightarrows': u'⇉', u'\\rightrightharpoons': u'⥤',
+ u'\\rightthreetimes': u'⋌', u'\\rimg': u'⦈', u'\\risingdotseq': u'≓',
+ u'\\rrbracket': u'⟧', u'\\rsub': u'⩥', u'\\rtimes': u'⋊',
+ u'\\sagittarius': u'♐', u'\\saturn': u'♄', u'\\scorpio': u'♏',
+ u'\\searrow': u'↘', u'\\sec': u'sec', u'\\second': u'″', u'\\setminus': u'∖',
+ u'\\sharp': u'♯', u'\\simeq': u'≃', u'\\sin': u'sin', u'\\sinh': u'sinh',
+ u'\\sixteenthnote': u'♬', u'\\skull': u'☠', u'\\slash': u'∕',
+ u'\\smallsetminus': u'∖', u'\\smalltriangledown': u'▿',
+ u'\\smalltriangleleft': u'◃', u'\\smalltriangleright': u'▹',
+ u'\\smalltriangleup': u'▵', u'\\smile': u'⌣', u'\\smiley': u'☺',
+ u'\\spadesuit': u'♠', u'\\spddot': u'¨', u'\\sphat': u'',
+ u'\\sphericalangle': u'∢', u'\\spot': u'⦁', u'\\sptilde': u'~',
+ u'\\sqcap': u'⊓', u'\\sqcup': u'⊔', u'\\sqsubset': u'⊏',
+ u'\\sqsubseteq': u'⊑', u'\\sqsupset': u'⊐', u'\\sqsupseteq': u'⊒',
+ u'\\square': u'□', u'\\sslash': u'⫽', u'\\star': u'⋆', u'\\steaming': u'☕',
+ u'\\subseteqq': u'⫅', u'\\subsetneqq': u'⫋', u'\\succ': u'≻',
+ u'\\succcurlyeq': u'≽', u'\\succeq': u'≽', u'\\succnsim': u'⋩',
+ u'\\succsim': u'≿', u'\\sun': u'☼', u'\\sup': u'sup', u'\\supseteqq': u'⫆',
+ u'\\supsetneqq': u'⫌', u'\\surd': u'√', u'\\swarrow': u'↙',
+ u'\\swords': u'⚔', u'\\talloblong': u'⫾', u'\\tan': u'tan',
+ u'\\tanh': u'tanh', u'\\taurus': u'♉', u'\\textasciicircum': u'^',
+ u'\\textasciitilde': u'~', u'\\textbackslash': u'\\',
+ u'\\textcopyright': u'©\'', u'\\textdegree': u'°', u'\\textellipsis': u'…',
+ u'\\textemdash': u'—', u'\\textendash': u'—', u'\\texteuro': u'€',
+ u'\\textgreater': u'>', u'\\textless': u'<', u'\\textordfeminine': u'ª',
+ u'\\textordmasculine': u'º', u'\\textquotedblleft': u'“',
+ u'\\textquotedblright': u'”', u'\\textquoteright': u'’',
+ u'\\textregistered': u'®', u'\\textrightarrow': u'→',
+ u'\\textsection': u'§', u'\\texttrademark': u'™',
+ u'\\texttwosuperior': u'²', u'\\textvisiblespace': u' ',
+ u'\\therefore': u'∴', u'\\third': u'‴', u'\\top': u'⊤', u'\\triangle': u'△',
+ u'\\triangleleft': u'⊲', u'\\trianglelefteq': u'⊴', u'\\triangleq': u'≜',
+ u'\\triangleright': u'▷', u'\\trianglerighteq': u'⊵',
+ u'\\twoheadleftarrow': u'↞', u'\\twoheadrightarrow': u'↠',
+ u'\\twonotes': u'♫', u'\\udot': u'⊍', u'\\ulcorner': u'⌜', u'\\unlhd': u'⊴',
+ u'\\unrhd': u'⊵', u'\\unrhl': u'⊵', u'\\uparrow': u'↑',
+ u'\\updownarrow': u'↕', u'\\upharpoonleft': u'↿', u'\\upharpoonright': u'↾',
+ u'\\uplus': u'⊎', u'\\upuparrows': u'⇈', u'\\uranus': u'♅',
+ u'\\urcorner': u'⌝', u'\\vDash': u'⊨', u'\\varclubsuit': u'♧',
+ u'\\vardiamondsuit': u'♦', u'\\varheartsuit': u'♥', u'\\varnothing': u'∅',
+ u'\\varspadesuit': u'♤', u'\\vdash': u'⊢', u'\\vdots': u'⋮', u'\\vee': u'∨',
+ u'\\vee)': u'∨', u'\\veebar': u'⊻', u'\\vert': u'∣', u'\\virgo': u'♍',
+ u'\\warning': u'⚠', u'\\wasylozenge': u'⌑', u'\\wedge': u'∧',
+ u'\\wedge)': u'∧', u'\\wp': u'℘', u'\\wr': u'≀', u'\\yen': u'¥',
+ u'\\yinyang': u'☯', u'\\{': u'{', u'\\|': u'∥', u'\\}': u'}',
+ }
+
+ decoratedcommand = {
+ }
+
+ decoratingfunctions = {
+ u'\\overleftarrow': u'⟵', u'\\overrightarrow': u'⟶', u'\\widehat': u'^',
+ }
+
+ endings = {
+ u'bracket': u'}', u'complex': u'\\]', u'endafter': u'}',
+ u'endbefore': u'\\end{', u'squarebracket': u']',
+ }
+
+ environments = {
+ u'align': [u'r', u'l',], u'eqnarray': [u'r', u'c', u'l',],
+ u'gathered': [u'l', u'l',],
+ }
+
+ fontfunctions = {
+ u'\\boldsymbol': u'b', u'\\mathbb': u'span class="blackboard"',
+ u'\\mathbb{A}': u'𝔸', u'\\mathbb{B}': u'𝔹', u'\\mathbb{C}': u'ℂ',
+ u'\\mathbb{D}': u'𝔻', u'\\mathbb{E}': u'𝔼', u'\\mathbb{F}': u'𝔽',
+ u'\\mathbb{G}': u'𝔾', u'\\mathbb{H}': u'ℍ', u'\\mathbb{J}': u'𝕁',
+ u'\\mathbb{K}': u'𝕂', u'\\mathbb{L}': u'𝕃', u'\\mathbb{N}': u'ℕ',
+ u'\\mathbb{O}': u'𝕆', u'\\mathbb{P}': u'ℙ', u'\\mathbb{Q}': u'ℚ',
+ u'\\mathbb{R}': u'ℝ', u'\\mathbb{S}': u'𝕊', u'\\mathbb{T}': u'𝕋',
+ u'\\mathbb{W}': u'𝕎', u'\\mathbb{Z}': u'ℤ', u'\\mathbf': u'b',
+ u'\\mathcal': u'span class="scriptfont"', u'\\mathcal{B}': u'ℬ',
+ u'\\mathcal{E}': u'ℰ', u'\\mathcal{F}': u'ℱ', u'\\mathcal{H}': u'ℋ',
+ u'\\mathcal{I}': u'ℐ', u'\\mathcal{L}': u'ℒ', u'\\mathcal{M}': u'ℳ',
+ u'\\mathcal{R}': u'ℛ', u'\\mathfrak': u'span class="fraktur"',
+ u'\\mathfrak{C}': u'ℭ', u'\\mathfrak{F}': u'𝔉', u'\\mathfrak{H}': u'ℌ',
+ u'\\mathfrak{I}': u'ℑ', u'\\mathfrak{R}': u'ℜ', u'\\mathfrak{Z}': u'ℨ',
+ u'\\mathit': u'i', u'\\mathring{A}': u'Å', u'\\mathring{U}': u'Ů',
+ u'\\mathring{a}': u'å', u'\\mathring{u}': u'ů', u'\\mathring{w}': u'ẘ',
+ u'\\mathring{y}': u'ẙ', u'\\mathrm': u'span class="mathrm"',
+ u'\\mathscr': u'span class="scriptfont"', u'\\mathscr{B}': u'ℬ',
+ u'\\mathscr{E}': u'ℰ', u'\\mathscr{F}': u'ℱ', u'\\mathscr{H}': u'ℋ',
+ u'\\mathscr{I}': u'ℐ', u'\\mathscr{L}': u'ℒ', u'\\mathscr{M}': u'ℳ',
+ u'\\mathscr{R}': u'ℛ', u'\\mathsf': u'span class="mathsf"',
+ u'\\mathtt': u'tt',
+ }
+
+ hybridfunctions = {
+ u'\\addcontentsline': [u'{$p!}{$q!}{$r!}', u'f0{}', u'ignored',],
+ u'\\addtocontents': [u'{$p!}{$q!}', u'f0{}', u'ignored',],
+ u'\\backmatter': [u'', u'f0{}', u'ignored',],
+ u'\\binom': [u'{$1}{$2}', u'f2{(}f0{f1{$1}f1{$2}}f2{)}', u'span class="binom"', u'span class="binomstack"', u'span class="bigsymbol"',],
+ u'\\boxed': [u'{$1}', u'f0{$1}', u'span class="boxed"',],
+ u'\\cfrac': [u'[$p!]{$1}{$2}', u'f0{f3{(}f1{$1}f3{)/(}f2{$2}f3{)}}', u'span class="fullfraction"', u'span class="numerator align-$p"', u'span class="denominator"', u'span class="ignored"',],
+ u'\\color': [u'{$p!}{$1}', u'f0{$1}', u'span style="color: $p;"',],
+ u'\\colorbox': [u'{$p!}{$1}', u'f0{$1}', u'span class="colorbox" style="background: $p;"',],
+ u'\\dbinom': [u'{$1}{$2}', u'(f0{f1{f2{$1}}f1{f2{ }}f1{f2{$2}}})', u'span class="binomial"', u'span class="binomrow"', u'span class="binomcell"',],
+ u'\\dfrac': [u'{$1}{$2}', u'f0{f3{(}f1{$1}f3{)/(}f2{$2}f3{)}}', u'span class="fullfraction"', u'span class="numerator"', u'span class="denominator"', u'span class="ignored"',],
+ u'\\displaystyle': [u'{$1}', u'f0{$1}', u'span class="displaystyle"',],
+ u'\\fancyfoot': [u'[$p!]{$q!}', u'f0{}', u'ignored',],
+ u'\\fancyhead': [u'[$p!]{$q!}', u'f0{}', u'ignored',],
+ u'\\fbox': [u'{$1}', u'f0{$1}', u'span class="fbox"',],
+ u'\\fboxrule': [u'{$p!}', u'f0{}', u'ignored',],
+ u'\\fboxsep': [u'{$p!}', u'f0{}', u'ignored',],
+ u'\\fcolorbox': [u'{$p!}{$q!}{$1}', u'f0{$1}', u'span class="boxed" style="border-color: $p; background: $q;"',],
+ u'\\frac': [u'{$1}{$2}', u'f0{f3{(}f1{$1}f3{)/(}f2{$2}f3{)}}', u'span class="fraction"', u'span class="numerator"', u'span class="denominator"', u'span class="ignored"',],
+ u'\\framebox': [u'[$p!][$q!]{$1}', u'f0{$1}', u'span class="framebox align-$q" style="width: $p;"',],
+ u'\\frontmatter': [u'', u'f0{}', u'ignored',],
+ u'\\href': [u'[$o]{$u!}{$t!}', u'f0{$t}', u'a href="$u"',],
+ u'\\hspace': [u'{$p!}', u'f0{ }', u'span class="hspace" style="width: $p;"',],
+ u'\\leftroot': [u'{$p!}', u'f0{ }', u'span class="leftroot" style="width: $p;px"',],
+ u'\\mainmatter': [u'', u'f0{}', u'ignored',],
+ u'\\markboth': [u'{$p!}{$q!}', u'f0{}', u'ignored',],
+ u'\\markright': [u'{$p!}', u'f0{}', u'ignored',],
+ u'\\nicefrac': [u'{$1}{$2}', u'f0{f1{$1}⁄f2{$2}}', u'span class="fraction"', u'sup class="numerator"', u'sub class="denominator"', u'span class="ignored"',],
+ u'\\parbox': [u'[$p!]{$w!}{$1}', u'f0{1}', u'div class="Boxed" style="width: $w;"',],
+ u'\\raisebox': [u'{$p!}{$1}', u'f0{$1.font}', u'span class="raisebox" style="vertical-align: $p;"',],
+ u'\\renewenvironment': [u'{$1!}{$2!}{$3!}', u'',],
+ u'\\rule': [u'[$v!]{$w!}{$h!}', u'f0/', u'hr class="line" style="width: $w; height: $h;"',],
+ u'\\scriptscriptstyle': [u'{$1}', u'f0{$1}', u'span class="scriptscriptstyle"',],
+ u'\\scriptstyle': [u'{$1}', u'f0{$1}', u'span class="scriptstyle"',],
+ u'\\sqrt': [u'[$0]{$1}', u'f0{f1{$0}f2{√}f4{(}f3{$1}f4{)}}', u'span class="sqrt"', u'sup class="root"', u'span class="radical"', u'span class="root"', u'span class="ignored"',],
+ u'\\stackrel': [u'{$1}{$2}', u'f0{f1{$1}f2{$2}}', u'span class="stackrel"', u'span class="upstackrel"', u'span class="downstackrel"',],
+ u'\\tbinom': [u'{$1}{$2}', u'(f0{f1{f2{$1}}f1{f2{ }}f1{f2{$2}}})', u'span class="binomial"', u'span class="binomrow"', u'span class="binomcell"',],
+ u'\\textcolor': [u'{$p!}{$1}', u'f0{$1}', u'span style="color: $p;"',],
+ u'\\textstyle': [u'{$1}', u'f0{$1}', u'span class="textstyle"',],
+ u'\\thispagestyle': [u'{$p!}', u'f0{}', u'ignored',],
+ u'\\unit': [u'[$0]{$1}', u'$0f0{$1.font}', u'span class="unit"',],
+ u'\\unitfrac': [u'[$0]{$1}{$2}', u'$0f0{f1{$1.font}⁄f2{$2.font}}', u'span class="fraction"', u'sup class="unit"', u'sub class="unit"',],
+ u'\\uproot': [u'{$p!}', u'f0{ }', u'span class="uproot" style="width: $p;px"',],
+ u'\\url': [u'{$u!}', u'f0{$u}', u'a href="$u"',],
+ u'\\vspace': [u'{$p!}', u'f0{ }', u'span class="vspace" style="height: $p;"',],
+ }
+
+ hybridsizes = {
+ u'\\binom': u'$1+$2', u'\\cfrac': u'$1+$2', u'\\dbinom': u'$1+$2+1',
+ u'\\dfrac': u'$1+$2', u'\\frac': u'$1+$2', u'\\tbinom': u'$1+$2+1',
+ }
+
+ labelfunctions = {
+ u'\\label': u'a name="#"',
+ }
+
+ limitcommands = {
+ u'\\biginterleave': u'⫼', u'\\bigsqcap': u'⨅', u'\\fint': u'⨏',
+ u'\\iiiint': u'⨌', u'\\int': u'∫', u'\\intop': u'∫', u'\\lim': u'lim',
+ u'\\prod': u'∏', u'\\smallint': u'∫', u'\\sqint': u'⨖', u'\\sum': u'∑',
+ u'\\varointclockwise': u'∲', u'\\varprod': u'⨉', u'\\zcmp': u'⨟',
+ u'\\zhide': u'⧹', u'\\zpipe': u'⨠', u'\\zproject': u'⨡',
+ }
+
+ misccommands = {
+ u'\\limits': u'LimitPreviousCommand', u'\\newcommand': u'MacroDefinition',
+ u'\\renewcommand': u'MacroDefinition',
+ u'\\setcounter': u'SetCounterFunction', u'\\tag': u'FormulaTag',
+ u'\\tag*': u'FormulaTag', u'\\today': u'TodayCommand',
+ }
+
+ modified = {
+ u'\n': u'', u' ': u'', u'$': u'', u'&': u' ', u'\'': u'’', u'+': u' + ',
+ u',': u', ', u'-': u' − ', u'/': u' ⁄ ', u':': u' : ', u'<': u' < ',
+ u'=': u' = ', u'>': u' > ', u'@': u'', u'~': u'',
+ }
+
+ onefunctions = {
+ u'\\Big': u'span class="bigsymbol"', u'\\Bigg': u'span class="hugesymbol"',
+ u'\\bar': u'span class="bar"', u'\\begin{array}': u'span class="arraydef"',
+ u'\\big': u'span class="symbol"', u'\\bigg': u'span class="largesymbol"',
+ u'\\bigl': u'span class="bigsymbol"', u'\\bigr': u'span class="bigsymbol"',
+ u'\\centering': u'span class="align-center"',
+ u'\\ensuremath': u'span class="ensuremath"',
+ u'\\hphantom': u'span class="phantom"',
+ u'\\noindent': u'span class="noindent"',
+ u'\\overbrace': u'span class="overbrace"',
+ u'\\overline': u'span class="overline"',
+ u'\\phantom': u'span class="phantom"',
+ u'\\underbrace': u'span class="underbrace"', u'\\underline': u'u',
+ u'\\vphantom': u'span class="phantom"',
+ }
+
+ spacedcommands = {
+ u'\\Bot': u'⫫', u'\\Doteq': u'≑', u'\\DownArrowBar': u'⤓',
+ u'\\DownLeftTeeVector': u'⥞', u'\\DownLeftVectorBar': u'⥖',
+ u'\\DownRightTeeVector': u'⥟', u'\\DownRightVectorBar': u'⥗',
+ u'\\Equal': u'⩵', u'\\LeftArrowBar': u'⇤', u'\\LeftDownTeeVector': u'⥡',
+ u'\\LeftDownVectorBar': u'⥙', u'\\LeftTeeVector': u'⥚',
+ u'\\LeftTriangleBar': u'⧏', u'\\LeftUpTeeVector': u'⥠',
+ u'\\LeftUpVectorBar': u'⥘', u'\\LeftVectorBar': u'⥒',
+ u'\\Leftrightarrow': u'⇔', u'\\Longmapsfrom': u'⟽', u'\\Longmapsto': u'⟾',
+ u'\\MapsDown': u'↧', u'\\MapsUp': u'↥', u'\\Nearrow': u'⇗',
+ u'\\NestedGreaterGreater': u'⪢', u'\\NestedLessLess': u'⪡',
+ u'\\NotGreaterLess': u'≹', u'\\NotGreaterTilde': u'≵',
+ u'\\NotLessTilde': u'≴', u'\\Nwarrow': u'⇖', u'\\Proportion': u'∷',
+ u'\\RightArrowBar': u'⇥', u'\\RightDownTeeVector': u'⥝',
+ u'\\RightDownVectorBar': u'⥕', u'\\RightTeeVector': u'⥛',
+ u'\\RightTriangleBar': u'⧐', u'\\RightUpTeeVector': u'⥜',
+ u'\\RightUpVectorBar': u'⥔', u'\\RightVectorBar': u'⥓',
+ u'\\Rightarrow': u'⇒', u'\\Same': u'⩶', u'\\Searrow': u'⇘',
+ u'\\Swarrow': u'⇙', u'\\Top': u'⫪', u'\\UpArrowBar': u'⤒', u'\\VDash': u'⊫',
+ u'\\approx': u'≈', u'\\approxeq': u'≊', u'\\backsim': u'∽', u'\\barin': u'⋶',
+ u'\\barleftharpoon': u'⥫', u'\\barrightharpoon': u'⥭', u'\\bij': u'⤖',
+ u'\\coloneq': u'≔', u'\\corresponds': u'≙', u'\\curlyeqprec': u'⋞',
+ u'\\curlyeqsucc': u'⋟', u'\\dashrightarrow': u'⇢', u'\\dlsh': u'↲',
+ u'\\downdownharpoons': u'⥥', u'\\downuparrows': u'⇵',
+ u'\\downupharpoons': u'⥯', u'\\drsh': u'↳', u'\\eqslantgtr': u'⪖',
+ u'\\eqslantless': u'⪕', u'\\equiv': u'≡', u'\\ffun': u'⇻', u'\\finj': u'⤕',
+ u'\\ge': u'≥', u'\\geq': u'≥', u'\\ggcurly': u'⪼', u'\\gnapprox': u'⪊',
+ u'\\gneq': u'⪈', u'\\gtrapprox': u'⪆', u'\\hash': u'⋕', u'\\iddots': u'⋰',
+ u'\\implies': u' ⇒ ', u'\\in': u'∈', u'\\le': u'≤', u'\\leftarrow': u'←',
+ u'\\leftarrowtriangle': u'⇽', u'\\leftbarharpoon': u'⥪',
+ u'\\leftrightarrowtriangle': u'⇿', u'\\leftrightharpoon': u'⥊',
+ u'\\leftrightharpoondown': u'⥐', u'\\leftrightharpoonup': u'⥎',
+ u'\\leftrightsquigarrow': u'↭', u'\\leftslice': u'⪦',
+ u'\\leftsquigarrow': u'⇜', u'\\leftupdownharpoon': u'⥑', u'\\leq': u'≤',
+ u'\\lessapprox': u'⪅', u'\\llcurly': u'⪻', u'\\lnapprox': u'⪉',
+ u'\\lneq': u'⪇', u'\\longmapsfrom': u'⟻', u'\\multimapboth': u'⧟',
+ u'\\multimapdotbothA': u'⊶', u'\\multimapdotbothB': u'⊷',
+ u'\\multimapinv': u'⟜', u'\\nVdash': u'⊮', u'\\ne': u'≠', u'\\neq': u'≠',
+ u'\\ngeq': u'≱', u'\\nleq': u'≰', u'\\nni': u'∌', u'\\not\\in': u'∉',
+ u'\\notasymp': u'≭', u'\\npreceq': u'⋠', u'\\nsqsubseteq': u'⋢',
+ u'\\nsqsupseteq': u'⋣', u'\\nsubset': u'⊄', u'\\nsucceq': u'⋡',
+ u'\\pfun': u'⇸', u'\\pinj': u'⤔', u'\\precapprox': u'⪷', u'\\preceqq': u'⪳',
+ u'\\precnapprox': u'⪹', u'\\precnsim': u'⋨', u'\\propto': u'∝',
+ u'\\psur': u'⤀', u'\\rightarrow': u'→', u'\\rightarrowtriangle': u'⇾',
+ u'\\rightbarharpoon': u'⥬', u'\\rightleftharpoon': u'⥋',
+ u'\\rightslice': u'⪧', u'\\rightsquigarrow': u'⇝',
+ u'\\rightupdownharpoon': u'⥏', u'\\sim': u'~', u'\\strictfi': u'⥼',
+ u'\\strictif': u'⥽', u'\\subset': u'⊂', u'\\subseteq': u'⊆',
+ u'\\subsetneq': u'⊊', u'\\succapprox': u'⪸', u'\\succeqq': u'⪴',
+ u'\\succnapprox': u'⪺', u'\\supset': u'⊃', u'\\supseteq': u'⊇',
+ u'\\supsetneq': u'⊋', u'\\times': u'×', u'\\to': u'→',
+ u'\\updownarrows': u'⇅', u'\\updownharpoons': u'⥮', u'\\upupharpoons': u'⥣',
+ u'\\vartriangleleft': u'⊲', u'\\vartriangleright': u'⊳',
+ }
+
+ starts = {
+ u'beginafter': u'}', u'beginbefore': u'\\begin{', u'bracket': u'{',
+ u'command': u'\\', u'comment': u'%', u'complex': u'\\[', u'simple': u'$',
+ u'squarebracket': u'[', u'unnumbered': u'*',
+ }
+
+ symbolfunctions = {
+ u'^': u'sup', u'_': u'sub',
+ }
+
+ textfunctions = {
+ u'\\mbox': u'span class="mbox"', u'\\text': u'span class="text"',
+ u'\\textbf': u'b', u'\\textipa': u'span class="textipa"', u'\\textit': u'i',
+ u'\\textnormal': u'span class="textnormal"',
+ u'\\textrm': u'span class="textrm"',
+ u'\\textsc': u'span class="versalitas"',
+ u'\\textsf': u'span class="textsf"', u'\\textsl': u'i', u'\\texttt': u'tt',
+ u'\\textup': u'span class="normal"',
+ }
+
+ unmodified = {
+ u'characters': [u'.', u'*', u'€', u'(', u')', u'[', u']', u'·', u'!', u';', u'|', u'§', u'"',],
+ }
+
+ urls = {
+ u'googlecharts': u'http://chart.googleapis.com/chart?cht=tx&chl=',
+ }
+
+class GeneralConfig(object):
+ "Configuration class from elyxer.config file"
+
+ version = {
+ u'date': u'2015-02-26', u'lyxformat': u'413', u'number': u'1.2.5',
+ }
+
+class HeaderConfig(object):
+ "Configuration class from elyxer.config file"
+
+ parameters = {
+ u'beginpreamble': u'\\begin_preamble', u'branch': u'\\branch',
+ u'documentclass': u'\\textclass', u'endbranch': u'\\end_branch',
+ u'endpreamble': u'\\end_preamble', u'language': u'\\language',
+ u'lstset': u'\\lstset', u'outputchanges': u'\\output_changes',
+ u'paragraphseparation': u'\\paragraph_separation',
+ u'pdftitle': u'\\pdf_title', u'secnumdepth': u'\\secnumdepth',
+ u'tocdepth': u'\\tocdepth',
+ }
+
+ styles = {
+ u'article': [u'article', u'aastex', u'aapaper', u'acmsiggraph', u'sigplanconf', u'achemso', u'amsart', u'apa', u'arab-article', u'armenian-article', u'article-beamer', u'chess', u'dtk', u'elsarticle', u'heb-article', u'IEEEtran', u'iopart', u'kluwer', u'scrarticle-beamer', u'scrartcl', u'extarticle', u'paper', u'mwart', u'revtex4', u'spie', u'svglobal3', u'ltugboat', u'agu-dtd', u'jgrga', u'agums', u'entcs', u'egs', u'ijmpc', u'ijmpd', u'singlecol-new', u'doublecol-new', u'isprs', u'tarticle', u'jsarticle', u'jarticle', u'jss', u'literate-article', u'siamltex', u'cl2emult', u'llncs', u'svglobal', u'svjog', u'svprobth',],
+ u'book': [u'book', u'amsbook', u'scrbook', u'extbook', u'tufte-book', u'report', u'extreport', u'scrreprt', u'memoir', u'tbook', u'jsbook', u'jbook', u'mwbk', u'svmono', u'svmult', u'treport', u'jreport', u'mwrep',],
+ }
+
+class ImageConfig(object):
+ "Configuration class from elyxer.config file"
+
+ converters = {
+ u'imagemagick': u'convert[ -density $scale][ -define $format:use-cropbox=true] "$input" "$output"',
+ u'inkscape': u'inkscape "$input" --export-png="$output"',
+ u'lyx': u'lyx -C "$input" "$output"',
+ }
+
+ cropboxformats = {
+ u'.eps': u'ps', u'.pdf': u'pdf', u'.ps': u'ps',
+ }
+
+ formats = {
+ u'default': u'.png', u'vector': [u'.svg', u'.eps',],
+ }
+
+class LayoutConfig(object):
+ "Configuration class from elyxer.config file"
+
+ groupable = {
+ u'allowed': [u'StringContainer', u'Constant', u'TaggedText', u'Align', u'TextFamily', u'EmphaticText', u'VersalitasText', u'BarredText', u'SizeText', u'ColorText', u'LangLine', u'Formula',],
+ }
+
+class NewfangleConfig(object):
+ "Configuration class from elyxer.config file"
+
+ constants = {
+ u'chunkref': u'chunkref{', u'endcommand': u'}', u'endmark': u'>',
+ u'startcommand': u'\\', u'startmark': u'=<',
+ }
+
+class NumberingConfig(object):
+ "Configuration class from elyxer.config file"
+
+ layouts = {
+ u'ordered': [u'Chapter', u'Section', u'Subsection', u'Subsubsection', u'Paragraph',],
+ u'roman': [u'Part', u'Book',],
+ }
+
+ sequence = {
+ u'symbols': [u'*', u'**', u'†', u'‡', u'§', u'§§', u'¶', u'¶¶', u'#', u'##',],
+ }
+
+class StyleConfig(object):
+ "Configuration class from elyxer.config file"
+
+ hspaces = {
+ u'\\enskip{}': u' ', u'\\hfill{}': u'<span class="hfill"> </span>',
+ u'\\hspace*{\\fill}': u' ', u'\\hspace*{}': u'', u'\\hspace{}': u' ',
+ u'\\negthinspace{}': u'', u'\\qquad{}': u' ', u'\\quad{}': u' ',
+ u'\\space{}': u' ', u'\\thinspace{}': u' ', u'~': u' ',
+ }
+
+ quotes = {
+ u'ald': u'»', u'als': u'›', u'ard': u'«', u'ars': u'‹', u'eld': u'“',
+ u'els': u'‘', u'erd': u'”', u'ers': u'’', u'fld': u'«',
+ u'fls': u'‹', u'frd': u'»', u'frs': u'›', u'gld': u'„', u'gls': u'‚',
+ u'grd': u'“', u'grs': u'‘', u'pld': u'„', u'pls': u'‚', u'prd': u'”',
+ u'prs': u'’', u'sld': u'”', u'srd': u'”',
+ }
+
+ referenceformats = {
+ u'eqref': u'(@↕)', u'formatted': u'¶↕', u'nameref': u'$↕', u'pageref': u'#↕',
+ u'ref': u'@↕', u'vpageref': u'on-page#↕', u'vref': u'@on-page#↕',
+ }
+
+ size = {
+ u'ignoredtexts': [u'col', u'text', u'line', u'page', u'theight', u'pheight',],
+ }
+
+ vspaces = {
+ u'bigskip': u'<div class="bigskip"> </div>',
+ u'defskip': u'<div class="defskip"> </div>',
+ u'medskip': u'<div class="medskip"> </div>',
+ u'smallskip': u'<div class="smallskip"> </div>',
+ u'vfill': u'<div class="vfill"> </div>',
+ }
+
+class TOCConfig(object):
+ "Configuration class from elyxer.config file"
+
+ extractplain = {
+ u'allowed': [u'StringContainer', u'Constant', u'TaggedText', u'Align', u'TextFamily', u'EmphaticText', u'VersalitasText', u'BarredText', u'SizeText', u'ColorText', u'LangLine', u'Formula',],
+ u'cloned': [u'',], u'extracted': [u'',],
+ }
+
+ extracttitle = {
+ u'allowed': [u'StringContainer', u'Constant', u'Space',],
+ u'cloned': [u'TextFamily', u'EmphaticText', u'VersalitasText', u'BarredText', u'SizeText', u'ColorText', u'LangLine', u'Formula',],
+ u'extracted': [u'PlainLayout', u'TaggedText', u'Align', u'Caption', u'StandardLayout', u'FlexInset',],
+ }
+
+class TagConfig(object):
+ "Configuration class from elyxer.config file"
+
+ barred = {
+ u'under': u'u',
+ }
+
+ family = {
+ u'sans': u'span class="sans"', u'typewriter': u'tt',
+ }
+
+ flex = {
+ u'CharStyle:Code': u'span class="code"',
+ u'CharStyle:MenuItem': u'span class="menuitem"',
+ u'Code': u'span class="code"', u'MenuItem': u'span class="menuitem"',
+ u'Noun': u'span class="noun"', u'Strong': u'span class="strong"',
+ }
+
+ group = {
+ u'layouts': [u'Quotation', u'Quote',],
+ }
+
+ layouts = {
+ u'Center': u'div', u'Chapter': u'h?', u'Date': u'h2', u'Paragraph': u'div',
+ u'Part': u'h1', u'Quotation': u'blockquote', u'Quote': u'blockquote',
+ u'Section': u'h?', u'Subsection': u'h?', u'Subsubsection': u'h?',
+ }
+
+ listitems = {
+ u'Enumerate': u'ol', u'Itemize': u'ul',
+ }
+
+ notes = {
+ u'Comment': u'', u'Greyedout': u'span class="greyedout"', u'Note': u'',
+ }
+
+ script = {
+ u'subscript': u'sub', u'superscript': u'sup',
+ }
+
+ shaped = {
+ u'italic': u'i', u'slanted': u'i', u'smallcaps': u'span class="versalitas"',
+ }
+
+class TranslationConfig(object):
+ "Configuration class from elyxer.config file"
+
+ constants = {
+ u'Appendix': u'Appendix', u'Book': u'Book', u'Chapter': u'Chapter',
+ u'Paragraph': u'Paragraph', u'Part': u'Part', u'Section': u'Section',
+ u'Subsection': u'Subsection', u'Subsubsection': u'Subsubsection',
+ u'abstract': u'Abstract', u'bibliography': u'Bibliography',
+ u'figure': u'figure', u'float-algorithm': u'Algorithm ',
+ u'float-figure': u'Figure ', u'float-listing': u'Listing ',
+ u'float-table': u'Table ', u'float-tableau': u'Tableau ',
+ u'footnotes': u'Footnotes', u'generated-by': u'Document generated by ',
+ u'generated-on': u' on ', u'index': u'Index',
+ u'jsmath-enable': u'Please enable JavaScript on your browser.',
+ u'jsmath-requires': u' requires JavaScript to correctly process the mathematics on this page. ',
+ u'jsmath-warning': u'Warning: ', u'list-algorithm': u'List of Algorithms',
+ u'list-figure': u'List of Figures', u'list-table': u'List of Tables',
+ u'list-tableau': u'List of Tableaux', u'main-page': u'Main page',
+ u'next': u'Next', u'nomenclature': u'Nomenclature',
+ u'on-page': u' on page ', u'prev': u'Prev', u'references': u'References',
+ u'toc': u'Table of Contents', u'toc-for': u'Contents for ', u'up': u'Up',
+ }
+
+ languages = {
+ u'american': u'en', u'british': u'en', u'deutsch': u'de', u'dutch': u'nl',
+ u'english': u'en', u'french': u'fr', u'ngerman': u'de', u'russian': u'ru',
+ u'spanish': u'es',
+ }
+
+
+class CommandLineParser(object):
+ "A parser for runtime options"
+
+ def __init__(self, options):
+ self.options = options
+
+ def parseoptions(self, args):
+ "Parse command line options"
+ if len(args) == 0:
+ return None
+ while len(args) > 0 and args[0].startswith('--'):
+ key, value = self.readoption(args)
+ if not key:
+ return 'Option ' + value + ' not recognized'
+ if not value:
+ return 'Option ' + key + ' needs a value'
+ setattr(self.options, key, value)
+ return None
+
+ def readoption(self, args):
+ "Read the key and value for an option"
+ arg = args[0][2:]
+ del args[0]
+ if '=' in arg:
+ key = self.readequalskey(arg, args)
+ else:
+ key = arg.replace('-', '')
+ if not hasattr(self.options, key):
+ return None, key
+ current = getattr(self.options, key)
+ if isinstance(current, bool):
+ return key, True
+ # read value
+ if len(args) == 0:
+ return key, None
+ if args[0].startswith('"'):
+ initial = args[0]
+ del args[0]
+ return key, self.readquoted(args, initial)
+ value = args[0].decode('utf-8')
+ del args[0]
+ if isinstance(current, list):
+ current.append(value)
+ return key, current
+ return key, value
+
+ def readquoted(self, args, initial):
+ "Read a value between quotes"
+ Trace.error('Oops')
+ value = initial[1:]
+ while len(args) > 0 and not args[0].endswith('"') and not args[0].startswith('--'):
+ Trace.error('Appending ' + args[0])
+ value += ' ' + args[0]
+ del args[0]
+ if len(args) == 0 or args[0].startswith('--'):
+ return None
+ value += ' ' + args[0:-1]
+ return value
+
+ def readequalskey(self, arg, args):
+ "Read a key using equals"
+ split = arg.split('=', 1)
+ key = split[0]
+ value = split[1]
+ args.insert(0, value)
+ return key
+
+
+class Options(object):
+ "A set of runtime options"
+
+ instance = None
+
+ location = None
+ nocopy = False
+ copyright = False
+ debug = False
+ quiet = False
+ version = False
+ hardversion = False
+ versiondate = False
+ html = False
+ help = False
+ showlines = True
+ unicode = False
+ iso885915 = False
+ css = []
+ favicon = ''
+ title = None
+ directory = None
+ destdirectory = None
+ toc = False
+ toctarget = ''
+ tocfor = None
+ forceformat = None
+ lyxformat = False
+ target = None
+ splitpart = None
+ memory = True
+ lowmem = False
+ nobib = False
+ converter = 'imagemagick'
+ raw = False
+ jsmath = None
+ mathjax = None
+ nofooter = False
+ simplemath = False
+ template = None
+ noconvert = False
+ notoclabels = False
+ letterfoot = True
+ numberfoot = False
+ symbolfoot = False
+ hoverfoot = True
+ marginfoot = False
+ endfoot = False
+ supfoot = True
+ alignfoot = False
+ footnotes = None
+ imageformat = None
+ copyimages = False
+ googlecharts = False
+ embedcss = []
+
+ branches = dict()
+
+ def parseoptions(self, args):
+ "Parse command line options"
+ Options.location = args[0]
+ del args[0]
+ parser = CommandLineParser(Options)
+ result = parser.parseoptions(args)
+ if result:
+ Trace.error(result)
+ self.usage()
+ self.processoptions()
+
+ def processoptions(self):
+ "Process all options parsed."
+ if Options.help:
+ self.usage()
+ if Options.version:
+ self.showversion()
+ if Options.hardversion:
+ self.showhardversion()
+ if Options.versiondate:
+ self.showversiondate()
+ if Options.lyxformat:
+ self.showlyxformat()
+ if Options.splitpart:
+ try:
+ Options.splitpart = int(Options.splitpart)
+ if Options.splitpart <= 0:
+ Trace.error('--splitpart requires a number bigger than zero')
+ self.usage()
+ except:
+ Trace.error('--splitpart needs a numeric argument, not ' + Options.splitpart)
+ self.usage()
+ if Options.lowmem or Options.toc or Options.tocfor:
+ Options.memory = False
+ self.parsefootnotes()
+ if Options.forceformat and not Options.imageformat:
+ Options.imageformat = Options.forceformat
+ if Options.imageformat == 'copy':
+ Options.copyimages = True
+ if Options.css == []:
+ Options.css = ['http://elyxer.nongnu.org/lyx.css']
+ if Options.favicon == '':
+ pass # no default favicon
+ if Options.html:
+ Options.simplemath = True
+ if Options.toc and not Options.tocfor:
+ Trace.error('Option --toc is deprecated; use --tocfor "page" instead')
+ Options.tocfor = Options.toctarget
+ if Options.nocopy:
+ Trace.error('Option --nocopy is deprecated; it is no longer needed')
+ if Options.jsmath:
+ Trace.error('Option --jsmath is deprecated; use --mathjax instead')
+ # set in Trace if necessary
+ for param in dir(Trace):
+ if param.endswith('mode'):
+ setattr(Trace, param, getattr(self, param[:-4]))
+
+ def usage(self):
+ "Show correct usage"
+ Trace.error('Usage: ' + os.path.basename(Options.location) + ' [options] [filein] [fileout]')
+ Trace.error('Convert LyX input file "filein" to HTML file "fileout".')
+ Trace.error('If filein (or fileout) is not given use standard input (or output).')
+ Trace.error('Main program of the eLyXer package (http://elyxer.nongnu.org/).')
+ self.showoptions()
+
+ def parsefootnotes(self):
+ "Parse footnotes options."
+ if not Options.footnotes:
+ return
+ Options.marginfoot = False
+ Options.letterfoot = False
+ Options.hoverfoot = False
+ options = Options.footnotes.split(',')
+ for option in options:
+ footoption = option + 'foot'
+ if hasattr(Options, footoption):
+ setattr(Options, footoption, True)
+ else:
+ Trace.error('Unknown footnotes option: ' + option)
+ if not Options.endfoot and not Options.marginfoot and not Options.hoverfoot:
+ Options.hoverfoot = True
+ if not Options.numberfoot and not Options.symbolfoot:
+ Options.letterfoot = True
+
+ def showoptions(self):
+ "Show all possible options"
+ Trace.error(' Common options:')
+ Trace.error(' --help: show this online help')
+ Trace.error(' --quiet: disables all runtime messages')
+ Trace.error('')
+ Trace.error(' Advanced options:')
+ Trace.error(' --debug: enable debugging messages (for developers)')
+ Trace.error(' --version: show version number and release date')
+ Trace.error(' --lyxformat: return the highest LyX version supported')
+ Trace.error(' Options for HTML output:')
+ Trace.error(' --title "title": set the generated page title')
+ Trace.error(' --css "file.css": use a custom CSS file')
+ Trace.error(' --embedcss "file.css": embed styles from a CSS file into the output')
+ Trace.error(' --favicon "icon.ico": insert the specified favicon in the header.')
+ Trace.error(' --html: output HTML 4.0 instead of the default XHTML')
+ Trace.error(' --unicode: full Unicode output')
+ Trace.error(' --iso885915: output a document with ISO-8859-15 encoding')
+ Trace.error(' --nofooter: remove the footer "generated by eLyXer"')
+ Trace.error(' --simplemath: do not generate fancy math constructions')
+ Trace.error(' Options for image output:')
+ Trace.error(' --directory "img_dir": look for images in the specified directory')
+ Trace.error(' --destdirectory "dest": put converted images into this directory')
+ Trace.error(' --imageformat ".ext": image output format, or "copy" to copy images')
+ Trace.error(' --noconvert: do not convert images, use in original locations')
+ Trace.error(' --converter "inkscape": use an alternative program to convert images')
+ Trace.error(' Options for footnote display:')
+ Trace.error(' --numberfoot: mark footnotes with numbers instead of letters')
+ Trace.error(' --symbolfoot: mark footnotes with symbols (*, **...)')
+ Trace.error(' --hoverfoot: show footnotes as hovering text (default)')
+ Trace.error(' --marginfoot: show footnotes on the page margin')
+ Trace.error(' --endfoot: show footnotes at the end of the page')
+ Trace.error(' --supfoot: use superscript for footnote markers (default)')
+ Trace.error(' --alignfoot: use aligned text for footnote markers')
+ Trace.error(' --footnotes "options": specify several comma-separated footnotes options')
+ Trace.error(' Available options are: "number", "symbol", "hover", "margin", "end",')
+ Trace.error(' "sup", "align"')
+ Trace.error(' Advanced output options:')
+ Trace.error(' --splitpart "depth": split the resulting webpage at the given depth')
+ Trace.error(' --tocfor "page": generate a TOC that points to the given page')
+ Trace.error(' --target "frame": make all links point to the given frame')
+ Trace.error(' --notoclabels: omit the part labels in the TOC, such as Chapter')
+ Trace.error(' --lowmem: do the conversion on the fly (conserve memory)')
+ Trace.error(' --raw: generate HTML without header or footer.')
+ Trace.error(' --mathjax remote: use MathJax remotely to display equations')
+ Trace.error(' --mathjax "URL": use MathJax from the given URL to display equations')
+ Trace.error(' --googlecharts: use Google Charts to generate formula images')
+ Trace.error(' --template "file": use a template, put everything in <!--$content-->')
+ Trace.error(' --copyright: add a copyright notice at the bottom')
+ Trace.error(' Deprecated options:')
+ Trace.error(' --toc: (deprecated) create a table of contents')
+ Trace.error(' --toctarget "page": (deprecated) generate a TOC for the given page')
+ Trace.error(' --nocopy: (deprecated) maintained for backwards compatibility')
+ Trace.error(' --jsmath "URL": use jsMath from the given URL to display equations')
+ sys.exit()
+
+ def showversion(self):
+ "Return the current eLyXer version string"
+ string = 'eLyXer version ' + GeneralConfig.version['number']
+ string += ' (' + GeneralConfig.version['date'] + ')'
+ Trace.error(string)
+ sys.exit()
+
+ def showhardversion(self):
+ "Return just the version string"
+ Trace.message(GeneralConfig.version['number'])
+ sys.exit()
+
+ def showversiondate(self):
+ "Return just the version dte"
+ Trace.message(GeneralConfig.version['date'])
+ sys.exit()
+
+ def showlyxformat(self):
+ "Return just the lyxformat parameter"
+ Trace.message(GeneralConfig.version['lyxformat'])
+ sys.exit()
+
+class BranchOptions(object):
+ "A set of options for a branch"
+
+ def __init__(self, name):
+ self.name = name
+ self.options = {'color':'#ffffff'}
+
+ def set(self, key, value):
+ "Set a branch option"
+ if not key.startswith(ContainerConfig.string['startcommand']):
+ Trace.error('Invalid branch option ' + key)
+ return
+ key = key.replace(ContainerConfig.string['startcommand'], '')
+ self.options[key] = value
+
+ def isselected(self):
+ "Return if the branch is selected"
+ if not 'selected' in self.options:
+ return False
+ return self.options['selected'] == '1'
+
+ def __unicode__(self):
+ "String representation"
+ return 'options for ' + self.name + ': ' + unicode(self.options)
+
+ if sys.version_info >= (3, 0):
+ __str__ = __unicode__
+
+
+class Cloner(object):
+ "An object used to clone other objects."
+
+ def clone(cls, original):
+ "Return an exact copy of an object."
+ "The original object must have an empty constructor."
+ return cls.create(original.__class__)
+
+ def create(cls, type):
+ "Create an object of a given class."
+ clone = type.__new__(type)
+ clone.__init__()
+ return clone
+
+ clone = classmethod(clone)
+ create = classmethod(create)
+
+class ContainerExtractor(object):
+ "A class to extract certain containers."
+
+ def __init__(self, config):
+ "The config parameter is a map containing three lists: allowed, copied and extracted."
+ "Each of the three is a list of class names for containers."
+ "Allowed containers are included as is into the result."
+ "Cloned containers are cloned and placed into the result."
+ "Extracted containers are looked into."
+ "All other containers are silently ignored."
+ self.allowed = config['allowed']
+ self.cloned = config['cloned']
+ self.extracted = config['extracted']
+
+ def extract(self, container):
+ "Extract a group of selected containers from elyxer.a container."
+ list = []
+ locate = lambda c: c.__class__.__name__ in self.allowed + self.cloned
+ recursive = lambda c: c.__class__.__name__ in self.extracted
+ process = lambda c: self.process(c, list)
+ container.recursivesearch(locate, recursive, process)
+ return list
+
+ def process(self, container, list):
+ "Add allowed containers, clone cloned containers and add the clone."
+ name = container.__class__.__name__
+ if name in self.allowed:
+ list.append(container)
+ elif name in self.cloned:
+ list.append(self.safeclone(container))
+ else:
+ Trace.error('Unknown container class ' + name)
+
+ def safeclone(self, container):
+ "Return a new container with contents only in a safe list, recursively."
+ clone = Cloner.clone(container)
+ clone.output = container.output
+ clone.contents = self.extract(container)
+ return clone
+
+
+
+
+
+
+class Parser(object):
+ "A generic parser"
+
+ def __init__(self):
+ self.begin = 0
+ self.parameters = dict()
+
+ def parseheader(self, reader):
+ "Parse the header"
+ header = reader.currentline().split()
+ reader.nextline()
+ self.begin = reader.linenumber
+ return header
+
+ def parseparameter(self, reader):
+ "Parse a parameter"
+ if reader.currentline().strip().startswith('<'):
+ key, value = self.parsexml(reader)
+ self.parameters[key] = value
+ return
+ split = reader.currentline().strip().split(' ', 1)
+ reader.nextline()
+ if len(split) == 0:
+ return
+ key = split[0]
+ if len(split) == 1:
+ self.parameters[key] = True
+ return
+ if not '"' in split[1]:
+ self.parameters[key] = split[1].strip()
+ return
+ doublesplit = split[1].split('"')
+ self.parameters[key] = doublesplit[1]
+
+ def parsexml(self, reader):
+ "Parse a parameter in xml form: <param attr1=value...>"
+ strip = reader.currentline().strip()
+ reader.nextline()
+ if not strip.endswith('>'):
+ Trace.error('XML parameter ' + strip + ' should be <...>')
+ split = strip[1:-1].split()
+ if len(split) == 0:
+ Trace.error('Empty XML parameter <>')
+ return None, None
+ key = split[0]
+ del split[0]
+ if len(split) == 0:
+ return key, dict()
+ attrs = dict()
+ for attr in split:
+ if not '=' in attr:
+ Trace.error('Erroneous attribute for ' + key + ': ' + attr)
+ attr += '="0"'
+ parts = attr.split('=')
+ attrkey = parts[0]
+ value = parts[1].split('"')[1]
+ attrs[attrkey] = value
+ return key, attrs
+
+ def parseending(self, reader, process):
+ "Parse until the current ending is found"
+ if not self.ending:
+ Trace.error('No ending for ' + unicode(self))
+ return
+ while not reader.currentline().startswith(self.ending):
+ process()
+
+ def parsecontainer(self, reader, contents):
+ container = self.factory.createcontainer(reader)
+ if container:
+ container.parent = self.parent
+ contents.append(container)
+
+ def __unicode__(self):
+ "Return a description"
+ return self.__class__.__name__ + ' (' + unicode(self.begin) + ')'
+
+ if sys.version_info >= (3, 0):
+ __str__ = __unicode__
+
+
+class LoneCommand(Parser):
+ "A parser for just one command line"
+
+ def parse(self, reader):
+ "Read nothing"
+ return []
+
+class TextParser(Parser):
+ "A parser for a command and a bit of text"
+
+ stack = []
+
+ def __init__(self, container):
+ Parser.__init__(self)
+ self.ending = None
+ if container.__class__.__name__ in ContainerConfig.endings:
+ self.ending = ContainerConfig.endings[container.__class__.__name__]
+ self.endings = []
+
+ def parse(self, reader):
+ "Parse lines as long as they are text"
+ TextParser.stack.append(self.ending)
+ self.endings = TextParser.stack + [ContainerConfig.endings['Layout'],
+ ContainerConfig.endings['Inset'], self.ending]
+ contents = []
+ while not self.isending(reader):
+ self.parsecontainer(reader, contents)
+ return contents
+
+ def isending(self, reader):
+ "Check if text is ending"
+ current = reader.currentline().split()
+ if len(current) == 0:
+ return False
+ if current[0] in self.endings:
+ if current[0] in TextParser.stack:
+ TextParser.stack.remove(current[0])
+ else:
+ TextParser.stack = []
+ return True
+ return False
+
+class ExcludingParser(Parser):
+ "A parser that excludes the final line"
+
+ def parse(self, reader):
+ "Parse everything up to (and excluding) the final line"
+ contents = []
+ self.parseending(reader, lambda: self.parsecontainer(reader, contents))
+ return contents
+
+class BoundedParser(ExcludingParser):
+ "A parser bound by a final line"
+
+ def parse(self, reader):
+ "Parse everything, including the final line"
+ contents = ExcludingParser.parse(self, reader)
+ # skip last line
+ reader.nextline()
+ return contents
+
+class BoundedDummy(Parser):
+ "A bound parser that ignores everything"
+
+ def parse(self, reader):
+ "Parse the contents of the container"
+ self.parseending(reader, lambda: reader.nextline())
+ # skip last line
+ reader.nextline()
+ return []
+
+class StringParser(Parser):
+ "Parses just a string"
+
+ def parseheader(self, reader):
+ "Do nothing, just take note"
+ self.begin = reader.linenumber + 1
+ return []
+
+ def parse(self, reader):
+ "Parse a single line"
+ contents = reader.currentline()
+ reader.nextline()
+ return contents
+
+class InsetParser(BoundedParser):
+ "Parses a LyX inset"
+
+ def parse(self, reader):
+ "Parse inset parameters into a dictionary"
+ startcommand = ContainerConfig.string['startcommand']
+ while reader.currentline() != '' and not reader.currentline().startswith(startcommand):
+ self.parseparameter(reader)
+ return BoundedParser.parse(self, reader)
+
+
+
+
+
+
+class ContainerOutput(object):
+ "The generic HTML output for a container."
+
+ def gethtml(self, container):
+ "Show an error."
+ Trace.error('gethtml() not implemented for ' + unicode(self))
+
+ def isempty(self):
+ "Decide if the output is empty: by default, not empty."
+ return False
+
+class EmptyOutput(ContainerOutput):
+
+ def gethtml(self, container):
+ "Return empty HTML code."
+ return []
+
+ def isempty(self):
+ "This output is particularly empty."
+ return True
+
+class FixedOutput(ContainerOutput):
+ "Fixed output"
+
+ def gethtml(self, container):
+ "Return constant HTML code"
+ return container.html
+
+class ContentsOutput(ContainerOutput):
+ "Outputs the contents converted to HTML"
+
+ def gethtml(self, container):
+ "Return the HTML code"
+ html = []
+ if container.contents == None:
+ return html
+ for element in container.contents:
+ if not hasattr(element, 'gethtml'):
+ Trace.error('No html in ' + element.__class__.__name__ + ': ' + unicode(element))
+ return html
+ html += element.gethtml()
+ return html
+
+class TaggedOutput(ContentsOutput):
+ "Outputs an HTML tag surrounding the contents."
+
+ tag = None
+ breaklines = False
+ empty = False
+
+ def settag(self, tag, breaklines=False, empty=False):
+ "Set the value for the tag and other attributes."
+ self.tag = tag
+ if breaklines:
+ self.breaklines = breaklines
+ if empty:
+ self.empty = empty
+ return self
+
+ def setbreaklines(self, breaklines):
+ "Set the value for breaklines."
+ self.breaklines = breaklines
+ return self
+
+ def gethtml(self, container):
+ "Return the HTML code."
+ if self.empty:
+ return [self.selfclosing(container)]
+ html = [self.open(container)]
+ html += ContentsOutput.gethtml(self, container)
+ html.append(self.close(container))
+ return html
+
+ def open(self, container):
+ "Get opening line."
+ if not self.checktag(container):
+ return ''
+ open = '<' + self.tag + '>'
+ if self.breaklines:
+ return open + '\n'
+ return open
+
+ def close(self, container):
+ "Get closing line."
+ if not self.checktag(container):
+ return ''
+ close = '</' + self.tag.split()[0] + '>'
+ if self.breaklines:
+ return '\n' + close + '\n'
+ return close
+
+ def selfclosing(self, container):
+ "Get self-closing line."
+ if not self.checktag(container):
+ return ''
+ selfclosing = '<' + self.tag + '/>'
+ if self.breaklines:
+ return selfclosing + '\n'
+ return selfclosing
+
+ def checktag(self, container):
+ "Check that the tag is valid."
+ if not self.tag:
+ Trace.error('No tag in ' + unicode(container))
+ return False
+ if self.tag == '':
+ return False
+ return True
+
+class FilteredOutput(ContentsOutput):
+ "Returns the output in the contents, but filtered:"
+ "some strings are replaced by others."
+
+ def __init__(self):
+ "Initialize the filters."
+ self.filters = []
+
+ def addfilter(self, original, replacement):
+ "Add a new filter: replace the original by the replacement."
+ self.filters.append((original, replacement))
+
+ def gethtml(self, container):
+ "Return the HTML code"
+ result = []
+ html = ContentsOutput.gethtml(self, container)
+ for line in html:
+ result.append(self.filter(line))
+ return result
+
+ def filter(self, line):
+ "Filter a single line with all available filters."
+ for original, replacement in self.filters:
+ if original in line:
+ line = line.replace(original, replacement)
+ return line
+
+class StringOutput(ContainerOutput):
+ "Returns a bare string as output"
+
+ def gethtml(self, container):
+ "Return a bare string"
+ return [container.string]
+
+
+class LineReader(object):
+ "Reads a file line by line"
+
+ def __init__(self, filename):
+ if isinstance(filename, file):
+ self.file = filename
+ else:
+ self.file = codecs.open(filename, 'rU', 'utf-8')
+ self.linenumber = 1
+ self.lastline = None
+ self.current = None
+ self.mustread = True
+ self.depleted = False
+ try:
+ self.readline()
+ except UnicodeDecodeError:
+ # try compressed file
+ import gzip
+ self.file = gzip.open(filename, 'rb')
+ self.readline()
+
+ def setstart(self, firstline):
+ "Set the first line to read."
+ for i in range(firstline):
+ self.file.readline()
+ self.linenumber = firstline
+
+ def setend(self, lastline):
+ "Set the last line to read."
+ self.lastline = lastline
+
+ def currentline(self):
+ "Get the current line"
+ if self.mustread:
+ self.readline()
+ return self.current
+
+ def nextline(self):
+ "Go to next line"
+ if self.depleted:
+ Trace.fatal('Read beyond file end')
+ self.mustread = True
+
+ def readline(self):
+ "Read a line from elyxer.file"
+ self.current = self.file.readline()
+ if not isinstance(self.file, codecs.StreamReaderWriter):
+ self.current = self.current.decode('utf-8')
+ if len(self.current) == 0:
+ self.depleted = True
+ self.current = self.current.rstrip('\n\r')
+ self.linenumber += 1
+ self.mustread = False
+ Trace.prefix = 'Line ' + unicode(self.linenumber) + ': '
+ if self.linenumber % 1000 == 0:
+ Trace.message('Parsing')
+
+ def finished(self):
+ "Find out if the file is finished"
+ if self.lastline and self.linenumber == self.lastline:
+ return True
+ if self.mustread:
+ self.readline()
+ return self.depleted
+
+ def close(self):
+ self.file.close()
+
+class LineWriter(object):
+ "Writes a file as a series of lists"
+
+ file = False
+
+ def __init__(self, filename):
+ if isinstance(filename, file):
+ self.file = filename
+ self.filename = None
+ else:
+ self.filename = filename
+
+ def write(self, strings):
+ "Write a list of strings"
+ for string in strings:
+ if not isinstance(string, basestring):
+ Trace.error('Not a string: ' + unicode(string) + ' in ' + unicode(strings))
+ return
+ self.writestring(string)
+
+ def writestring(self, string):
+ "Write a string"
+ if not self.file:
+ self.file = codecs.open(self.filename, 'w', "utf-8")
+ if self.file == sys.stdout and sys.version_info < (3, 0):
+ string = string.encode('utf-8')
+ self.file.write(string)
+
+ def writeline(self, line):
+ "Write a line to file"
+ self.writestring(line + '\n')
+
+ def close(self):
+ self.file.close()
+
+
+
+
+
+
+class Globable(object):
+ """A bit of text which can be globbed (lumped together in bits).
+ Methods current(), skipcurrent(), checkfor() and isout() have to be
+ implemented by subclasses."""
+
+ leavepending = False
+
+ def __init__(self):
+ self.endinglist = EndingList()
+
+ def checkbytemark(self):
+ "Check for a Unicode byte mark and skip it."
+ if self.finished():
+ return
+ if ord(self.current()) == 0xfeff:
+ self.skipcurrent()
+
+ def isout(self):
+ "Find out if we are out of the position yet."
+ Trace.error('Unimplemented isout()')
+ return True
+
+ def current(self):
+ "Return the current character."
+ Trace.error('Unimplemented current()')
+ return ''
+
+ def checkfor(self, string):
+ "Check for the given string in the current position."
+ Trace.error('Unimplemented checkfor()')
+ return False
+
+ def finished(self):
+ "Find out if the current text has finished."
+ if self.isout():
+ if not self.leavepending:
+ self.endinglist.checkpending()
+ return True
+ return self.endinglist.checkin(self)
+
+ def skipcurrent(self):
+ "Return the current character and skip it."
+ Trace.error('Unimplemented skipcurrent()')
+ return ''
+
+ def glob(self, currentcheck):
+ "Glob a bit of text that satisfies a check on the current char."
+ glob = ''
+ while not self.finished() and currentcheck():
+ glob += self.skipcurrent()
+ return glob
+
+ def globalpha(self):
+ "Glob a bit of alpha text"
+ return self.glob(lambda: self.current().isalpha())
+
+ def globnumber(self):
+ "Glob a row of digits."
+ return self.glob(lambda: self.current().isdigit())
+
+ def isidentifier(self):
+ "Return if the current character is alphanumeric or _."
+ if self.current().isalnum() or self.current() == '_':
+ return True
+ return False
+
+ def globidentifier(self):
+ "Glob alphanumeric and _ symbols."
+ return self.glob(self.isidentifier)
+
+ def isvalue(self):
+ "Return if the current character is a value character:"
+ "not a bracket or a space."
+ if self.current().isspace():
+ return False
+ if self.current() in '{}()':
+ return False
+ return True
+
+ def globvalue(self):
+ "Glob a value: any symbols but brackets."
+ return self.glob(self.isvalue)
+
+ def skipspace(self):
+ "Skip all whitespace at current position."
+ return self.glob(lambda: self.current().isspace())
+
+ def globincluding(self, magicchar):
+ "Glob a bit of text up to (including) the magic char."
+ glob = self.glob(lambda: self.current() != magicchar) + magicchar
+ self.skip(magicchar)
+ return glob
+
+ def globexcluding(self, excluded):
+ "Glob a bit of text up until (excluding) any excluded character."
+ return self.glob(lambda: self.current() not in excluded)
+
+ def pushending(self, ending, optional = False):
+ "Push a new ending to the bottom"
+ self.endinglist.add(ending, optional)
+
+ def popending(self, expected = None):
+ "Pop the ending found at the current position"
+ if self.isout() and self.leavepending:
+ return expected
+ ending = self.endinglist.pop(self)
+ if expected and expected != ending:
+ Trace.error('Expected ending ' + expected + ', got ' + ending)
+ self.skip(ending)
+ return ending
+
+ def nextending(self):
+ "Return the next ending in the queue."
+ nextending = self.endinglist.findending(self)
+ if not nextending:
+ return None
+ return nextending.ending
+
+class EndingList(object):
+ "A list of position endings"
+
+ def __init__(self):
+ self.endings = []
+
+ def add(self, ending, optional = False):
+ "Add a new ending to the list"
+ self.endings.append(PositionEnding(ending, optional))
+
+ def pickpending(self, pos):
+ "Pick any pending endings from a parse position."
+ self.endings += pos.endinglist.endings
+
+ def checkin(self, pos):
+ "Search for an ending"
+ if self.findending(pos):
+ return True
+ return False
+
+ def pop(self, pos):
+ "Remove the ending at the current position"
+ if pos.isout():
+ Trace.error('No ending out of bounds')
+ return ''
+ ending = self.findending(pos)
+ if not ending:
+ Trace.error('No ending at ' + pos.current())
+ return ''
+ for each in reversed(self.endings):
+ self.endings.remove(each)
+ if each == ending:
+ return each.ending
+ elif not each.optional:
+ Trace.error('Removed non-optional ending ' + each)
+ Trace.error('No endings left')
+ return ''
+
+ def findending(self, pos):
+ "Find the ending at the current position"
+ if len(self.endings) == 0:
+ return None
+ for index, ending in enumerate(reversed(self.endings)):
+ if ending.checkin(pos):
+ return ending
+ if not ending.optional:
+ return None
+ return None
+
+ def checkpending(self):
+ "Check if there are any pending endings"
+ if len(self.endings) != 0:
+ Trace.error('Pending ' + unicode(self) + ' left open')
+
+ def __unicode__(self):
+ "Printable representation"
+ string = 'endings ['
+ for ending in self.endings:
+ string += unicode(ending) + ','
+ if len(self.endings) > 0:
+ string = string[:-1]
+ return string + ']'
+
+ if sys.version_info >= (3, 0):
+ __str__ = __unicode__
+
+
+class PositionEnding(object):
+ "An ending for a parsing position"
+
+ def __init__(self, ending, optional):
+ self.ending = ending
+ self.optional = optional
+
+ def checkin(self, pos):
+ "Check for the ending"
+ return pos.checkfor(self.ending)
+
+ def __unicode__(self):
+ "Printable representation"
+ string = 'Ending ' + self.ending
+ if self.optional:
+ string += ' (optional)'
+ return string
+
+ if sys.version_info >= (3, 0):
+ __str__ = __unicode__
+
+
+class Position(Globable):
+ """A position in a text to parse.
+ Including those in Globable, functions to implement by subclasses are:
+ skip(), identifier(), extract(), isout() and current()."""
+
+ def __init__(self):
+ Globable.__init__(self)
+
+ def skip(self, string):
+ "Skip a string"
+ Trace.error('Unimplemented skip()')
+
+ def identifier(self):
+ "Return an identifier for the current position."
+ Trace.error('Unimplemented identifier()')
+ return 'Error'
+
+ def extract(self, length):
+ "Extract the next string of the given length, or None if not enough text,"
+ "without advancing the parse position."
+ Trace.error('Unimplemented extract()')
+ return None
+
+ def checkfor(self, string):
+ "Check for a string at the given position."
+ return string == self.extract(len(string))
+
+ def checkforlower(self, string):
+ "Check for a string in lower case."
+ extracted = self.extract(len(string))
+ if not extracted:
+ return False
+ return string.lower() == self.extract(len(string)).lower()
+
+ def skipcurrent(self):
+ "Return the current character and skip it."
+ current = self.current()
+ self.skip(current)
+ return current
+
+ def __next__(self):
+ "Advance the position and return the next character."
+ self.skipcurrent()
+ return self.current()
+
+ if sys.version_info < (3, 0):
+ next = __next__
+
+ def checkskip(self, string):
+ "Check for a string at the given position; if there, skip it"
+ if not self.checkfor(string):
+ return False
+ self.skip(string)
+ return True
+
+ def error(self, message):
+ "Show an error message and the position identifier."
+ Trace.error(message + ': ' + self.identifier())
+
+class TextPosition(Position):
+ "A parse position based on a raw text."
+
+ def __init__(self, text):
+ "Create the position from elyxer.some text."
+ Position.__init__(self)
+ self.pos = 0
+ self.text = text
+ self.checkbytemark()
+
+ def skip(self, string):
+ "Skip a string of characters."
+ self.pos += len(string)
+
+ def identifier(self):
+ "Return a sample of the remaining text."
+ length = 30
+ if self.pos + length > len(self.text):
+ length = len(self.text) - self.pos
+ return '*' + self.text[self.pos:self.pos + length] + '*'
+
+ def isout(self):
+ "Find out if we are out of the text yet."
+ return self.pos >= len(self.text)
+
+ def current(self):
+ "Return the current character, assuming we are not out."
+ return self.text[self.pos]
+
+ def extract(self, length):
+ "Extract the next string of the given length, or None if not enough text."
+ if self.pos + length > len(self.text):
+ return None
+ return self.text[self.pos : self.pos + length]
+
+class FilePosition(Position):
+ "A parse position based on an underlying file."
+
+ def __init__(self, filename):
+ "Create the position from a file."
+ Position.__init__(self)
+ self.reader = LineReader(filename)
+ self.pos = 0
+ self.checkbytemark()
+
+ def skip(self, string):
+ "Skip a string of characters."
+ length = len(string)
+ while self.pos + length > len(self.reader.currentline()):
+ length -= len(self.reader.currentline()) - self.pos + 1
+ self.nextline()
+ self.pos += length
+
+ def currentline(self):
+ "Get the current line of the underlying file."
+ return self.reader.currentline()
+
+ def nextline(self):
+ "Go to the next line."
+ self.reader.nextline()
+ self.pos = 0
+
+ def linenumber(self):
+ "Return the line number of the file."
+ return self.reader.linenumber + 1
+
+ def identifier(self):
+ "Return the current line and line number in the file."
+ before = self.reader.currentline()[:self.pos - 1]
+ after = self.reader.currentline()[self.pos:]
+ return 'line ' + unicode(self.getlinenumber()) + ': ' + before + '*' + after
+
+ def isout(self):
+ "Find out if we are out of the text yet."
+ if self.pos > len(self.reader.currentline()):
+ if self.pos > len(self.reader.currentline()) + 1:
+ Trace.error('Out of the line ' + self.reader.currentline() + ': ' + unicode(self.pos))
+ self.nextline()
+ return self.reader.finished()
+
+ def current(self):
+ "Return the current character, assuming we are not out."
+ if self.pos == len(self.reader.currentline()):
+ return '\n'
+ if self.pos > len(self.reader.currentline()):
+ Trace.error('Out of the line ' + self.reader.currentline() + ': ' + unicode(self.pos))
+ return '*'
+ return self.reader.currentline()[self.pos]
+
+ def extract(self, length):
+ "Extract the next string of the given length, or None if not enough text."
+ if self.pos + length > len(self.reader.currentline()):
+ return None
+ return self.reader.currentline()[self.pos : self.pos + length]
+
+
+
+class Container(object):
+ "A container for text and objects in a lyx file"
+
+ partkey = None
+ parent = None
+ begin = None
+
+ def __init__(self):
+ self.contents = list()
+
+ def process(self):
+ "Process contents"
+ pass
+
+ def gethtml(self):
+ "Get the resulting HTML"
+ html = self.output.gethtml(self)
+ if isinstance(html, basestring):
+ Trace.error('Raw string ' + html)
+ html = [html]
+ return self.escapeall(html)
+
+ def escapeall(self, lines):
+ "Escape all lines in an array according to the output options."
+ result = []
+ for line in lines:
+ if Options.html:
+ line = self.escape(line, EscapeConfig.html)
+ if Options.iso885915:
+ line = self.escape(line, EscapeConfig.iso885915)
+ line = self.escapeentities(line)
+ elif not Options.unicode:
+ line = self.escape(line, EscapeConfig.nonunicode)
+ result.append(line)
+ return result
+
+ def escape(self, line, replacements = EscapeConfig.entities):
+ "Escape a line with replacements from elyxer.a map"
+ pieces = sorted(replacements.keys())
+ # do them in order
+ for piece in pieces:
+ if piece in line:
+ line = line.replace(piece, replacements[piece])
+ return line
+
+ def escapeentities(self, line):
+ "Escape all Unicode characters to HTML entities."
+ result = ''
+ pos = TextPosition(line)
+ while not pos.finished():
+ if ord(pos.current()) > 128:
+ codepoint = hex(ord(pos.current()))
+ if codepoint == '0xd835':
+ codepoint = hex(ord(next(pos)) + 0xf800)
+ result += '&#' + codepoint[1:] + ';'
+ else:
+ result += pos.current()
+ pos.skipcurrent()
+ return result
+
+ def searchall(self, type):
+ "Search for all embedded containers of a given type"
+ list = []
+ self.searchprocess(type, lambda container: list.append(container))
+ return list
+
+ def searchremove(self, type):
+ "Search for all containers of a type and remove them"
+ list = self.searchall(type)
+ for container in list:
+ container.parent.contents.remove(container)
+ return list
+
+ def searchprocess(self, type, process):
+ "Search for elements of a given type and process them"
+ self.locateprocess(lambda container: isinstance(container, type), process)
+
+ def locateprocess(self, locate, process):
+ "Search for all embedded containers and process them"
+ for container in self.contents:
+ container.locateprocess(locate, process)
+ if locate(container):
+ process(container)
+
+ def recursivesearch(self, locate, recursive, process):
+ "Perform a recursive search in the container."
+ for container in self.contents:
+ if recursive(container):
+ container.recursivesearch(locate, recursive, process)
+ if locate(container):
+ process(container)
+
+ def extracttext(self):
+ "Extract all text from elyxer.allowed containers."
+ result = ''
+ constants = ContainerExtractor(ContainerConfig.extracttext).extract(self)
+ for constant in constants:
+ result += constant.string
+ return result
+
+ def group(self, index, group, isingroup):
+ "Group some adjoining elements into a group"
+ if index >= len(self.contents):
+ return
+ if hasattr(self.contents[index], 'grouped'):
+ return
+ while index < len(self.contents) and isingroup(self.contents[index]):
+ self.contents[index].grouped = True
+ group.contents.append(self.contents[index])
+ self.contents.pop(index)
+ self.contents.insert(index, group)
+
+ def remove(self, index):
+ "Remove a container but leave its contents"
+ container = self.contents[index]
+ self.contents.pop(index)
+ while len(container.contents) > 0:
+ self.contents.insert(index, container.contents.pop())
+
+ def tree(self, level = 0):
+ "Show in a tree"
+ Trace.debug(" " * level + unicode(self))
+ for container in self.contents:
+ container.tree(level + 1)
+
+ def getparameter(self, name):
+ "Get the value of a parameter, if present."
+ if not name in self.parameters:
+ return None
+ return self.parameters[name]
+
+ def getparameterlist(self, name):
+ "Get the value of a comma-separated parameter as a list."
+ paramtext = self.getparameter(name)
+ if not paramtext:
+ return []
+ return paramtext.split(',')
+
+ def hasemptyoutput(self):
+ "Check if the parent's output is empty."
+ current = self.parent
+ while current:
+ if current.output.isempty():
+ return True
+ current = current.parent
+ return False
+
+ def __unicode__(self):
+ "Get a description"
+ if not self.begin:
+ return self.__class__.__name__
+ return self.__class__.__name__ + '@' + unicode(self.begin)
+
+ if sys.version_info >= (3, 0):
+ __str__ = __unicode__
+
+
+class BlackBox(Container):
+ "A container that does not output anything"
+
+ def __init__(self):
+ self.parser = LoneCommand()
+ self.output = EmptyOutput()
+ self.contents = []
+
+class LyXFormat(BlackBox):
+ "Read the lyxformat command"
+
+ def process(self):
+ "Show warning if version < 276"
+ version = int(self.header[1])
+ if version < 276:
+ Trace.error('Warning: unsupported old format version ' + str(version))
+ if version > int(GeneralConfig.version['lyxformat']):
+ Trace.error('Warning: unsupported new format version ' + str(version))
+
+class StringContainer(Container):
+ "A container for a single string"
+
+ parsed = None
+
+ def __init__(self):
+ self.parser = StringParser()
+ self.output = StringOutput()
+ self.string = ''
+
+ def process(self):
+ "Replace special chars from elyxer.the contents."
+ if self.parsed:
+ self.string = self.replacespecial(self.parsed)
+ self.parsed = None
+
+ def replacespecial(self, line):
+ "Replace all special chars from elyxer.a line"
+ replaced = self.escape(line, EscapeConfig.entities)
+ replaced = self.changeline(replaced)
+ if ContainerConfig.string['startcommand'] in replaced and len(replaced) > 1:
+ # unprocessed commands
+ if self.begin:
+ message = 'Unknown command at ' + unicode(self.begin) + ': '
+ else:
+ message = 'Unknown command: '
+ Trace.error(message + replaced.strip())
+ return replaced
+
+ def changeline(self, line):
+ line = self.escape(line, EscapeConfig.chars)
+ if not ContainerConfig.string['startcommand'] in line:
+ return line
+ line = self.escape(line, EscapeConfig.commands)
+ return line
+
+ def extracttext(self):
+ "Return all text."
+ return self.string
+
+ def __unicode__(self):
+ "Return a printable representation."
+ result = 'StringContainer'
+ if self.begin:
+ result += '@' + unicode(self.begin)
+ ellipsis = '...'
+ if len(self.string.strip()) <= 15:
+ ellipsis = ''
+ return result + ' (' + self.string.strip()[:15] + ellipsis + ')'
+
+ if sys.version_info >= (3, 0):
+ __str__ = __unicode__
+
+
+class Constant(StringContainer):
+ "A constant string"
+
+ def __init__(self, text):
+ self.contents = []
+ self.string = text
+ self.output = StringOutput()
+
+ def __unicode__(self):
+ return 'Constant: ' + self.string
+
+ if sys.version_info >= (3, 0):
+ __str__ = __unicode__
+
+
+class TaggedText(Container):
+ "Text inside a tag"
+
+ output = None
+
+ def __init__(self):
+ self.parser = TextParser(self)
+ self.output = TaggedOutput()
+
+ def complete(self, contents, tag, breaklines=False):
+ "Complete the tagged text and return it"
+ self.contents = contents
+ self.output.tag = tag
+ self.output.breaklines = breaklines
+ return self
+
+ def constant(self, text, tag, breaklines=False):
+ "Complete the tagged text with a constant"
+ constant = Constant(text)
+ return self.complete([constant], tag, breaklines)
+
+ def __unicode__(self):
+ "Return a printable representation."
+ if not hasattr(self.output, 'tag'):
+ return 'Emtpy tagged text'
+ if not self.output.tag:
+ return 'Tagged <unknown tag>'
+ return 'Tagged <' + self.output.tag + '>'
+
+ if sys.version_info >= (3, 0):
+ __str__ = __unicode__
+
+
+class DocumentParameters(object):
+ "Global parameters for the document."
+
+ pdftitle = None
+ indentstandard = False
+ tocdepth = 10
+ startinglevel = 0
+ maxdepth = 10
+ language = None
+ bibliography = None
+ outputchanges = False
+ displaymode = False
+
+
+
+
+
+
+class FormulaParser(Parser):
+ "Parses a formula"
+
+ def parseheader(self, reader):
+ "See if the formula is inlined"
+ self.begin = reader.linenumber + 1
+ type = self.parsetype(reader)
+ if not type:
+ reader.nextline()
+ type = self.parsetype(reader)
+ if not type:
+ Trace.error('Unknown formula type in ' + reader.currentline().strip())
+ return ['unknown']
+ return [type]
+
+ def parsetype(self, reader):
+ "Get the formula type from the first line."
+ if reader.currentline().find(FormulaConfig.starts['simple']) >= 0:
+ return 'inline'
+ if reader.currentline().find(FormulaConfig.starts['complex']) >= 0:
+ return 'block'
+ if reader.currentline().find(FormulaConfig.starts['unnumbered']) >= 0:
+ return 'block'
+ if reader.currentline().find(FormulaConfig.starts['beginbefore']) >= 0:
+ return 'numbered'
+ return None
+
+ def parse(self, reader):
+ "Parse the formula until the end"
+ formula = self.parseformula(reader)
+ while not reader.currentline().startswith(self.ending):
+ stripped = reader.currentline().strip()
+ if len(stripped) > 0:
+ Trace.error('Unparsed formula line ' + stripped)
+ reader.nextline()
+ reader.nextline()
+ return formula
+
+ def parseformula(self, reader):
+ "Parse the formula contents"
+ simple = FormulaConfig.starts['simple']
+ if simple in reader.currentline():
+ rest = reader.currentline().split(simple, 1)[1]
+ if simple in rest:
+ # formula is $...$
+ return self.parsesingleliner(reader, simple, simple)
+ # formula is multiline $...$
+ return self.parsemultiliner(reader, simple, simple)
+ if FormulaConfig.starts['complex'] in reader.currentline():
+ # formula of the form \[...\]
+ return self.parsemultiliner(reader, FormulaConfig.starts['complex'],
+ FormulaConfig.endings['complex'])
+ beginbefore = FormulaConfig.starts['beginbefore']
+ beginafter = FormulaConfig.starts['beginafter']
+ if beginbefore in reader.currentline():
+ if reader.currentline().strip().endswith(beginafter):
+ current = reader.currentline().strip()
+ endsplit = current.split(beginbefore)[1].split(beginafter)
+ startpiece = beginbefore + endsplit[0] + beginafter
+ endbefore = FormulaConfig.endings['endbefore']
+ endafter = FormulaConfig.endings['endafter']
+ endpiece = endbefore + endsplit[0] + endafter
+ return startpiece + self.parsemultiliner(reader, startpiece, endpiece) + endpiece
+ Trace.error('Missing ' + beginafter + ' in ' + reader.currentline())
+ return ''
+ begincommand = FormulaConfig.starts['command']
+ beginbracket = FormulaConfig.starts['bracket']
+ if begincommand in reader.currentline() and beginbracket in reader.currentline():
+ endbracket = FormulaConfig.endings['bracket']
+ return self.parsemultiliner(reader, beginbracket, endbracket)
+ Trace.error('Formula beginning ' + reader.currentline() + ' is unknown')
+ return ''
+
+ def parsesingleliner(self, reader, start, ending):
+ "Parse a formula in one line"
+ line = reader.currentline().strip()
+ if not start in line:
+ Trace.error('Line ' + line + ' does not contain formula start ' + start)
+ return ''
+ if not line.endswith(ending):
+ Trace.error('Formula ' + line + ' does not end with ' + ending)
+ return ''
+ index = line.index(start)
+ rest = line[index + len(start):-len(ending)]
+ reader.nextline()
+ return rest
+
+ def parsemultiliner(self, reader, start, ending):
+ "Parse a formula in multiple lines"
+ formula = ''
+ line = reader.currentline()
+ if not start in line:
+ Trace.error('Line ' + line.strip() + ' does not contain formula start ' + start)
+ return ''
+ index = line.index(start)
+ line = line[index + len(start):].strip()
+ while not line.endswith(ending):
+ formula += line + '\n'
+ reader.nextline()
+ line = reader.currentline()
+ formula += line[:-len(ending)]
+ reader.nextline()
+ return formula
+
+class MacroParser(FormulaParser):
+ "A parser for a formula macro."
+
+ def parseheader(self, reader):
+ "See if the formula is inlined"
+ self.begin = reader.linenumber + 1
+ return ['inline']
+
+ def parse(self, reader):
+ "Parse the formula until the end"
+ formula = self.parsemultiliner(reader, self.parent.start, self.ending)
+ reader.nextline()
+ return formula
+
+
+class FormulaBit(Container):
+ "A bit of a formula"
+
+ type = None
+ size = 1
+ original = ''
+
+ def __init__(self):
+ "The formula bit type can be 'alpha', 'number', 'font'."
+ self.contents = []
+ self.output = ContentsOutput()
+
+ def setfactory(self, factory):
+ "Set the internal formula factory."
+ self.factory = factory
+ return self
+
+ def add(self, bit):
+ "Add any kind of formula bit already processed"
+ self.contents.append(bit)
+ self.original += bit.original
+ bit.parent = self
+
+ def skiporiginal(self, string, pos):
+ "Skip a string and add it to the original formula"
+ self.original += string
+ if not pos.checkskip(string):
+ Trace.error('String ' + string + ' not at ' + pos.identifier())
+
+ def computesize(self):
+ "Compute the size of the bit as the max of the sizes of all contents."
+ if len(self.contents) == 0:
+ return 1
+ self.size = max([element.size for element in self.contents])
+ return self.size
+
+ def clone(self):
+ "Return a copy of itself."
+ return self.factory.parseformula(self.original)
+
+ def __unicode__(self):
+ "Get a string representation"
+ return self.__class__.__name__ + ' read in ' + self.original
+
+ if sys.version_info >= (3, 0):
+ __str__ = __unicode__
+
+
+class TaggedBit(FormulaBit):
+ "A tagged string in a formula"
+
+ def constant(self, constant, tag):
+ "Set the constant and the tag"
+ self.output = TaggedOutput().settag(tag)
+ self.add(FormulaConstant(constant))
+ return self
+
+ def complete(self, contents, tag, breaklines = False):
+ "Set the constant and the tag"
+ self.contents = contents
+ self.output = TaggedOutput().settag(tag, breaklines)
+ return self
+
+ def selfcomplete(self, tag):
+ "Set the self-closing tag, no contents (as in <hr/>)."
+ self.output = TaggedOutput().settag(tag, empty = True)
+ return self
+
+class FormulaConstant(Constant):
+ "A constant string in a formula"
+
+ def __init__(self, string):
+ "Set the constant string"
+ Constant.__init__(self, string)
+ self.original = string
+ self.size = 1
+ self.type = None
+
+ def computesize(self):
+ "Compute the size of the constant: always 1."
+ return self.size
+
+ def clone(self):
+ "Return a copy of itself."
+ return FormulaConstant(self.original)
+
+ def __unicode__(self):
+ "Return a printable representation."
+ return 'Formula constant: ' + self.string
+
+ if sys.version_info >= (3, 0):
+ __str__ = __unicode__
+
+
+class RawText(FormulaBit):
+ "A bit of text inside a formula"
+
+ def detect(self, pos):
+ "Detect a bit of raw text"
+ return pos.current().isalpha()
+
+ def parsebit(self, pos):
+ "Parse alphabetic text"
+ alpha = pos.globalpha()
+ self.add(FormulaConstant(alpha))
+ self.type = 'alpha'
+
+class FormulaSymbol(FormulaBit):
+ "A symbol inside a formula"
+
+ modified = FormulaConfig.modified
+ unmodified = FormulaConfig.unmodified['characters']
+
+ def detect(self, pos):
+ "Detect a symbol"
+ if pos.current() in FormulaSymbol.unmodified:
+ return True
+ if pos.current() in FormulaSymbol.modified:
+ return True
+ return False
+
+ def parsebit(self, pos):
+ "Parse the symbol"
+ if pos.current() in FormulaSymbol.unmodified:
+ self.addsymbol(pos.current(), pos)
+ return
+ if pos.current() in FormulaSymbol.modified:
+ self.addsymbol(FormulaSymbol.modified[pos.current()], pos)
+ return
+ Trace.error('Symbol ' + pos.current() + ' not found')
+
+ def addsymbol(self, symbol, pos):
+ "Add a symbol"
+ self.skiporiginal(pos.current(), pos)
+ self.contents.append(FormulaConstant(symbol))
+
+class FormulaNumber(FormulaBit):
+ "A string of digits in a formula"
+
+ def detect(self, pos):
+ "Detect a digit"
+ return pos.current().isdigit()
+
+ def parsebit(self, pos):
+ "Parse a bunch of digits"
+ digits = pos.glob(lambda: pos.current().isdigit())
+ self.add(FormulaConstant(digits))
+ self.type = 'number'
+
+class Comment(FormulaBit):
+ "A LaTeX comment: % to the end of the line."
+
+ start = FormulaConfig.starts['comment']
+
+ def detect(self, pos):
+ "Detect the %."
+ return pos.current() == self.start
+
+ def parsebit(self, pos):
+ "Parse to the end of the line."
+ self.original += pos.globincluding('\n')
+
+class WhiteSpace(FormulaBit):
+ "Some white space inside a formula."
+
+ def detect(self, pos):
+ "Detect the white space."
+ return pos.current().isspace()
+
+ def parsebit(self, pos):
+ "Parse all whitespace."
+ self.original += pos.skipspace()
+
+ def __unicode__(self):
+ "Return a printable representation."
+ return 'Whitespace: *' + self.original + '*'
+
+ if sys.version_info >= (3, 0):
+ __str__ = __unicode__
+
+
+class Bracket(FormulaBit):
+ "A {} bracket inside a formula"
+
+ start = FormulaConfig.starts['bracket']
+ ending = FormulaConfig.endings['bracket']
+
+ def __init__(self):
+ "Create a (possibly literal) new bracket"
+ FormulaBit.__init__(self)
+ self.inner = None
+
+ def detect(self, pos):
+ "Detect the start of a bracket"
+ return pos.checkfor(self.start)
+
+ def parsebit(self, pos):
+ "Parse the bracket"
+ self.parsecomplete(pos, self.innerformula)
+ return self
+
+ def parsetext(self, pos):
+ "Parse a text bracket"
+ self.parsecomplete(pos, self.innertext)
+ return self
+
+ def parseliteral(self, pos):
+ "Parse a literal bracket"
+ self.parsecomplete(pos, self.innerliteral)
+ return self
+
+ def parsecomplete(self, pos, innerparser):
+ "Parse the start and end marks"
+ if not pos.checkfor(self.start):
+ Trace.error('Bracket should start with ' + self.start + ' at ' + pos.identifier())
+ return None
+ self.skiporiginal(self.start, pos)
+ pos.pushending(self.ending)
+ innerparser(pos)
+ self.original += pos.popending(self.ending)
+ self.computesize()
+
+ def innerformula(self, pos):
+ "Parse a whole formula inside the bracket"
+ while not pos.finished():
+ self.add(self.factory.parseany(pos))
+
+ def innertext(self, pos):
+ "Parse some text inside the bracket, following textual rules."
+ specialchars = list(FormulaConfig.symbolfunctions.keys())
+ specialchars.append(FormulaConfig.starts['command'])
+ specialchars.append(FormulaConfig.starts['bracket'])
+ specialchars.append(Comment.start)
+ while not pos.finished():
+ if pos.current() in specialchars:
+ self.add(self.factory.parseany(pos))
+ if pos.checkskip(' '):
+ self.original += ' '
+ else:
+ self.add(FormulaConstant(pos.skipcurrent()))
+
+ def innerliteral(self, pos):
+ "Parse a literal inside the bracket, which does not generate HTML."
+ self.literal = ''
+ while not pos.finished() and not pos.current() == self.ending:
+ if pos.current() == self.start:
+ self.parseliteral(pos)
+ else:
+ self.literal += pos.skipcurrent()
+ self.original += self.literal
+
+class SquareBracket(Bracket):
+ "A [] bracket inside a formula"
+
+ start = FormulaConfig.starts['squarebracket']
+ ending = FormulaConfig.endings['squarebracket']
+
+ def clone(self):
+ "Return a new square bracket with the same contents."
+ bracket = SquareBracket()
+ bracket.contents = self.contents
+ return bracket
+
+
+class MathsProcessor(object):
+ "A processor for a maths construction inside the FormulaProcessor."
+
+ def process(self, contents, index):
+ "Process an element inside a formula."
+ Trace.error('Unimplemented process() in ' + unicode(self))
+
+ def __unicode__(self):
+ "Return a printable description."
+ return 'Maths processor ' + self.__class__.__name__
+
+ if sys.version_info >= (3, 0):
+ __str__ = __unicode__
+
+
+class FormulaProcessor(object):
+ "A processor specifically for formulas."
+
+ processors = []
+
+ def process(self, bit):
+ "Process the contents of every formula bit, recursively."
+ self.processcontents(bit)
+ self.processinsides(bit)
+ self.traversewhole(bit)
+
+ def processcontents(self, bit):
+ "Process the contents of a formula bit."
+ if not isinstance(bit, FormulaBit):
+ return
+ bit.process()
+ for element in bit.contents:
+ self.processcontents(element)
+
+ def processinsides(self, bit):
+ "Process the insides (limits, brackets) in a formula bit."
+ if not isinstance(bit, FormulaBit):
+ return
+ for index, element in enumerate(bit.contents):
+ for processor in self.processors:
+ processor.process(bit.contents, index)
+ # continue with recursive processing
+ self.processinsides(element)
+
+ def traversewhole(self, formula):
+ "Traverse over the contents to alter variables and space units."
+ last = None
+ for bit, contents in self.traverse(formula):
+ if bit.type == 'alpha':
+ self.italicize(bit, contents)
+ elif bit.type == 'font' and last and last.type == 'number':
+ bit.contents.insert(0, FormulaConstant(u' '))
+ last = bit
+
+ def traverse(self, bit):
+ "Traverse a formula and yield a flattened structure of (bit, list) pairs."
+ for element in bit.contents:
+ if hasattr(element, 'type') and element.type:
+ yield (element, bit.contents)
+ elif isinstance(element, FormulaBit):
+ for pair in self.traverse(element):
+ yield pair
+
+ def italicize(self, bit, contents):
+ "Italicize the given bit of text."
+ index = contents.index(bit)
+ contents[index] = TaggedBit().complete([bit], 'i')
+
+
+
+
+class Formula(Container):
+ "A LaTeX formula"
+
+ def __init__(self):
+ self.parser = FormulaParser()
+ self.output = TaggedOutput().settag('span class="formula"')
+
+ def process(self):
+ "Convert the formula to tags"
+ if self.header[0] == 'inline':
+ DocumentParameters.displaymode = False
+ else:
+ DocumentParameters.displaymode = True
+ self.output.settag('div class="formula"', True)
+ if Options.jsmath:
+ self.jsmath()
+ elif Options.mathjax:
+ self.mathjax()
+ elif Options.googlecharts:
+ self.googlecharts()
+ else:
+ self.classic()
+
+ def jsmath(self):
+ "Make the contents for jsMath."
+ if self.header[0] != 'inline':
+ self.output = TaggedOutput().settag('div class="math"')
+ else:
+ self.output = TaggedOutput().settag('span class="math"')
+ self.contents = [Constant(self.parsed)]
+
+ def mathjax(self):
+ "Make the contents for MathJax."
+ self.output.tag = 'span class="MathJax_Preview"'
+ tag = 'script type="math/tex'
+ if self.header[0] != 'inline':
+ tag += ';mode=display'
+ self.contents = [TaggedText().constant(self.parsed, tag + '"', True)]
+
+ def googlecharts(self):
+ "Make the contents using Google Charts http://code.google.com/apis/chart/."
+ url = FormulaConfig.urls['googlecharts'] + quote_plus(self.parsed)
+ img = '<img class="chart" src="' + url + '" alt="' + self.parsed + '"/>'
+ self.contents = [Constant(img)]
+
+ def classic(self):
+ "Make the contents using classic output generation with XHTML and CSS."
+ whole = FormulaFactory().parseformula(self.parsed)
+ FormulaProcessor().process(whole)
+ whole.parent = self
+ self.contents = [whole]
+
+ def parse(self, pos):
+ "Parse using a parse position instead of self.parser."
+ if pos.checkskip('$$'):
+ self.parsedollarblock(pos)
+ elif pos.checkskip('$'):
+ self.parsedollarinline(pos)
+ elif pos.checkskip('\\('):
+ self.parseinlineto(pos, '\\)')
+ elif pos.checkskip('\\['):
+ self.parseblockto(pos, '\\]')
+ else:
+ pos.error('Unparseable formula')
+ self.process()
+ return self
+
+ def parsedollarinline(self, pos):
+ "Parse a $...$ formula."
+ self.header = ['inline']
+ self.parsedollar(pos)
+
+ def parsedollarblock(self, pos):
+ "Parse a $$...$$ formula."
+ self.header = ['block']
+ self.parsedollar(pos)
+ if not pos.checkskip('$'):
+ pos.error('Formula should be $$...$$, but last $ is missing.')
+
+ def parsedollar(self, pos):
+ "Parse to the next $."
+ pos.pushending('$')
+ self.parsed = pos.globexcluding('$')
+ pos.popending('$')
+
+ def parseinlineto(self, pos, limit):
+ "Parse a \\(...\\) formula."
+ self.header = ['inline']
+ self.parseupto(pos, limit)
+
+ def parseblockto(self, pos, limit):
+ "Parse a \\[...\\] formula."
+ self.header = ['block']
+ self.parseupto(pos, limit)
+
+ def parseupto(self, pos, limit):
+ "Parse a formula that ends with the given command."
+ pos.pushending(limit)
+ self.parsed = pos.glob(lambda: True)
+ pos.popending(limit)
+
+ def __unicode__(self):
+ "Return a printable representation."
+ if self.partkey and self.partkey.number:
+ return 'Formula (' + self.partkey.number + ')'
+ return 'Unnumbered formula'
+
+ if sys.version_info >= (3, 0):
+ __str__ = __unicode__
+
+
+class WholeFormula(FormulaBit):
+ "Parse a whole formula"
+
+ def detect(self, pos):
+ "Not outside the formula is enough."
+ return not pos.finished()
+
+ def parsebit(self, pos):
+ "Parse with any formula bit"
+ while not pos.finished():
+ self.add(self.factory.parseany(pos))
+
+class FormulaFactory(object):
+ "Construct bits of formula"
+
+ # bit types will be appended later
+ types = [FormulaSymbol, RawText, FormulaNumber, Bracket, Comment, WhiteSpace]
+ skippedtypes = [Comment, WhiteSpace]
+ defining = False
+
+ def __init__(self):
+ "Initialize the map of instances."
+ self.instances = dict()
+
+ def detecttype(self, type, pos):
+ "Detect a bit of a given type."
+ if pos.finished():
+ return False
+ return self.instance(type).detect(pos)
+
+ def instance(self, type):
+ "Get an instance of the given type."
+ if not type in self.instances or not self.instances[type]:
+ self.instances[type] = self.create(type)
+ return self.instances[type]
+
+ def create(self, type):
+ "Create a new formula bit of the given type."
+ return Cloner.create(type).setfactory(self)
+
+ def clearskipped(self, pos):
+ "Clear any skipped types."
+ while not pos.finished():
+ if not self.skipany(pos):
+ return
+ return
+
+ def skipany(self, pos):
+ "Skip any skipped types."
+ for type in self.skippedtypes:
+ if self.instance(type).detect(pos):
+ return self.parsetype(type, pos)
+ return None
+
+ def parseany(self, pos):
+ "Parse any formula bit at the current location."
+ for type in self.types + self.skippedtypes:
+ if self.detecttype(type, pos):
+ return self.parsetype(type, pos)
+ Trace.error('Unrecognized formula at ' + pos.identifier())
+ return FormulaConstant(pos.skipcurrent())
+
+ def parsetype(self, type, pos):
+ "Parse the given type and return it."
+ bit = self.instance(type)
+ self.instances[type] = None
+ returnedbit = bit.parsebit(pos)
+ if returnedbit:
+ return returnedbit.setfactory(self)
+ return bit
+
+ def parseformula(self, formula):
+ "Parse a string of text that contains a whole formula."
+ pos = TextPosition(formula)
+ whole = self.create(WholeFormula)
+ if whole.detect(pos):
+ whole.parsebit(pos)
+ return whole
+ # no formula found
+ if not pos.finished():
+ Trace.error('Unknown formula at: ' + pos.identifier())
+ whole.add(TaggedBit().constant(formula, 'span class="unknown"'))
+ return whole
+
+
+class Translator(object):
+ "Reads the configuration file and tries to find a translation."
+ "Otherwise falls back to the messages in the config file."
+
+ instance = None
+
+ def translate(cls, key):
+ "Get the translated message for a key."
+ return cls.instance.getmessage(key)
+
+ translate = classmethod(translate)
+
+ def __init__(self):
+ self.translation = None
+ self.first = True
+
+ def findtranslation(self):
+ "Find the translation for the document language."
+ self.langcodes = None
+ if not DocumentParameters.language:
+ Trace.error('No language in document')
+ return
+ if not DocumentParameters.language in TranslationConfig.languages:
+ Trace.error('Unknown language ' + DocumentParameters.language)
+ return
+ if TranslationConfig.languages[DocumentParameters.language] == 'en':
+ return
+ langcodes = [TranslationConfig.languages[DocumentParameters.language]]
+ try:
+ self.translation = gettext.translation('elyxer', None, langcodes)
+ except IOError:
+ Trace.error('No translation for ' + unicode(langcodes))
+
+ def getmessage(self, key):
+ "Get the translated message for the given key."
+ if self.first:
+ self.findtranslation()
+ self.first = False
+ message = self.getuntranslated(key)
+ if not self.translation:
+ return message
+ try:
+ message = self.translation.ugettext(message)
+ except IOError:
+ pass
+ return message
+
+ def getuntranslated(self, key):
+ "Get the untranslated message."
+ if not key in TranslationConfig.constants:
+ Trace.error('Cannot translate ' + key)
+ return key
+ return TranslationConfig.constants[key]
+
+Translator.instance = Translator()
+
+
+
+class NumberCounter(object):
+ "A counter for numbers (by default)."
+ "The type can be changed to return letters, roman numbers..."
+
+ name = None
+ value = None
+ mode = None
+ master = None
+
+ letters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+ symbols = NumberingConfig.sequence['symbols']
+ romannumerals = [
+ ('M', 1000), ('CM', 900), ('D', 500), ('CD', 400), ('C', 100),
+ ('XC', 90), ('L', 50), ('XL', 40), ('X', 10), ('IX', 9), ('V', 5),
+ ('IV', 4), ('I', 1)
+ ]
+
+ def __init__(self, name):
+ "Give a name to the counter."
+ self.name = name
+
+ def setmode(self, mode):
+ "Set the counter mode. Can be changed at runtime."
+ self.mode = mode
+ return self
+
+ def init(self, value):
+ "Set an initial value."
+ self.value = value
+
+ def gettext(self):
+ "Get the next value as a text string."
+ return unicode(self.value)
+
+ def getletter(self):
+ "Get the next value as a letter."
+ return self.getsequence(self.letters)
+
+ def getsymbol(self):
+ "Get the next value as a symbol."
+ return self.getsequence(self.symbols)
+
+ def getsequence(self, sequence):
+ "Get the next value from elyxer.a sequence."
+ return sequence[(self.value - 1) % len(sequence)]
+
+ def getroman(self):
+ "Get the next value as a roman number."
+ result = ''
+ number = self.value
+ for numeral, value in self.romannumerals:
+ if number >= value:
+ result += numeral * (number / value)
+ number = number % value
+ return result
+
+ def getvalue(self):
+ "Get the current value as configured in the current mode."
+ if not self.mode or self.mode in ['text', '1']:
+ return self.gettext()
+ if self.mode == 'A':
+ return self.getletter()
+ if self.mode == 'a':
+ return self.getletter().lower()
+ if self.mode == 'I':
+ return self.getroman()
+ if self.mode == '*':
+ return self.getsymbol()
+ Trace.error('Unknown counter mode ' + self.mode)
+ return self.gettext()
+
+ def getnext(self):
+ "Increase the current value and get the next value as configured."
+ if not self.value:
+ self.value = 0
+ self.value += 1
+ return self.getvalue()
+
+ def reset(self):
+ "Reset the counter."
+ self.value = 0
+
+ def __unicode__(self):
+ "Return a printable representation."
+ result = 'Counter ' + self.name
+ if self.mode:
+ result += ' in mode ' + self.mode
+ return result
+
+ if sys.version_info >= (3, 0):
+ __str__ = __unicode__
+
+
+class DependentCounter(NumberCounter):
+ "A counter which depends on another one (the master)."
+
+ def setmaster(self, master):
+ "Set the master counter."
+ self.master = master
+ self.last = self.master.getvalue()
+ return self
+
+ def getnext(self):
+ "Increase or, if the master counter has changed, restart."
+ if self.last != self.master.getvalue():
+ self.reset()
+ value = NumberCounter.getnext(self)
+ self.last = self.master.getvalue()
+ return value
+
+ def getvalue(self):
+ "Get the value of the combined counter: master.dependent."
+ return self.master.getvalue() + '.' + NumberCounter.getvalue(self)
+
+class NumberGenerator(object):
+ "A number generator for unique sequences and hierarchical structures. Used in:"
+ " * ordered part numbers: Chapter 3, Section 5.3."
+ " * unique part numbers: Footnote 15, Bibliography cite [15]."
+ " * chaptered part numbers: Figure 3.15, Equation (8.3)."
+ " * unique roman part numbers: Part I, Book IV."
+
+ chaptered = None
+ generator = None
+
+ romanlayouts = [x.lower() for x in NumberingConfig.layouts['roman']]
+ orderedlayouts = [x.lower() for x in NumberingConfig.layouts['ordered']]
+
+ counters = dict()
+ appendix = None
+
+ def deasterisk(self, type):
+ "Remove the possible asterisk in a layout type."
+ return type.replace('*', '')
+
+ def isunique(self, type):
+ "Find out if the layout type corresponds to a unique part."
+ return self.isroman(type)
+
+ def isroman(self, type):
+ "Find out if the layout type should have roman numeration."
+ return self.deasterisk(type).lower() in self.romanlayouts
+
+ def isinordered(self, type):
+ "Find out if the layout type corresponds to an (un)ordered part."
+ return self.deasterisk(type).lower() in self.orderedlayouts
+
+ def isnumbered(self, type):
+ "Find out if the type for a layout corresponds to a numbered layout."
+ if '*' in type:
+ return False
+ if self.isroman(type):
+ return True
+ if not self.isinordered(type):
+ return False
+ if self.getlevel(type) > DocumentParameters.maxdepth:
+ return False
+ return True
+
+ def isunordered(self, type):
+ "Find out if the type contains an asterisk, basically."
+ return '*' in type
+
+ def getlevel(self, type):
+ "Get the level that corresponds to a layout type."
+ if self.isunique(type):
+ return 0
+ if not self.isinordered(type):
+ Trace.error('Unknown layout type ' + type)
+ return 0
+ type = self.deasterisk(type).lower()
+ level = self.orderedlayouts.index(type) + 1
+ return level - DocumentParameters.startinglevel
+
+ def getparttype(self, type):
+ "Obtain the type for the part: without the asterisk, "
+ "and switched to Appendix if necessary."
+ if NumberGenerator.appendix and self.getlevel(type) == 1:
+ return 'Appendix'
+ return self.deasterisk(type)
+
+ def generate(self, type):
+ "Generate a number for a layout type."
+ "Unique part types such as Part or Book generate roman numbers: Part I."
+ "Ordered part types return dot-separated tuples: Chapter 5, Subsection 2.3.5."
+ "Everything else generates unique numbers: Bibliography [1]."
+ "Each invocation results in a new number."
+ return self.getcounter(type).getnext()
+
+ def getcounter(self, type):
+ "Get the counter for the given type."
+ type = type.lower()
+ if not type in self.counters:
+ self.counters[type] = self.create(type)
+ return self.counters[type]
+
+ def create(self, type):
+ "Create a counter for the given type."
+ if self.isnumbered(type) and self.getlevel(type) > 1:
+ index = self.orderedlayouts.index(type)
+ above = self.orderedlayouts[index - 1]
+ master = self.getcounter(above)
+ return self.createdependent(type, master)
+ counter = NumberCounter(type)
+ if self.isroman(type):
+ counter.setmode('I')
+ return counter
+
+ def getdependentcounter(self, type, master):
+ "Get (or create) a counter of the given type that depends on another."
+ if not type in self.counters or not self.counters[type].master:
+ self.counters[type] = self.createdependent(type, master)
+ return self.counters[type]
+
+ def createdependent(self, type, master):
+ "Create a dependent counter given the master."
+ return DependentCounter(type).setmaster(master)
+
+ def startappendix(self):
+ "Start appendices here."
+ firsttype = self.orderedlayouts[DocumentParameters.startinglevel]
+ counter = self.getcounter(firsttype)
+ counter.setmode('A').reset()
+ NumberGenerator.appendix = True
+
+class ChapteredGenerator(NumberGenerator):
+ "Generate chaptered numbers, as in Chapter.Number."
+ "Used in equations, figures: Equation (5.3), figure 8.15."
+
+ def generate(self, type):
+ "Generate a number which goes with first-level numbers (chapters). "
+ "For the article classes a unique number is generated."
+ if DocumentParameters.startinglevel > 0:
+ return NumberGenerator.generator.generate(type)
+ chapter = self.getcounter('Chapter')
+ return self.getdependentcounter(type, chapter).getnext()
+
+
+NumberGenerator.chaptered = ChapteredGenerator()
+NumberGenerator.generator = NumberGenerator()
+
+
+
+
+
+
+class ContainerSize(object):
+ "The size of a container."
+
+ width = None
+ height = None
+ maxwidth = None
+ maxheight = None
+ scale = None
+
+ def set(self, width = None, height = None):
+ "Set the proper size with width and height."
+ self.setvalue('width', width)
+ self.setvalue('height', height)
+ return self
+
+ def setmax(self, maxwidth = None, maxheight = None):
+ "Set max width and/or height."
+ self.setvalue('maxwidth', maxwidth)
+ self.setvalue('maxheight', maxheight)
+ return self
+
+ def readparameters(self, container):
+ "Read some size parameters off a container."
+ self.setparameter(container, 'width')
+ self.setparameter(container, 'height')
+ self.setparameter(container, 'scale')
+ self.checkvalidheight(container)
+ return self
+
+ def setparameter(self, container, name):
+ "Read a size parameter off a container, and set it if present."
+ value = container.getparameter(name)
+ self.setvalue(name, value)
+
+ def setvalue(self, name, value):
+ "Set the value of a parameter name, only if it's valid."
+ value = self.processparameter(value)
+ if value:
+ setattr(self, name, value)
+
+ def checkvalidheight(self, container):
+ "Check if the height parameter is valid; otherwise erase it."
+ heightspecial = container.getparameter('height_special')
+ if self.height and self.extractnumber(self.height) == '1' and heightspecial == 'totalheight':
+ self.height = None
+
+ def processparameter(self, value):
+ "Do the full processing on a parameter."
+ if not value:
+ return None
+ if self.extractnumber(value) == '0':
+ return None
+ for ignored in StyleConfig.size['ignoredtexts']:
+ if ignored in value:
+ value = value.replace(ignored, '')
+ return value
+
+ def extractnumber(self, text):
+ "Extract the first number in the given text."
+ result = ''
+ decimal = False
+ for char in text:
+ if char.isdigit():
+ result += char
+ elif char == '.' and not decimal:
+ result += char
+ decimal = True
+ else:
+ return result
+ return result
+
+ def checkimage(self, width, height):
+ "Check image dimensions, set them if possible."
+ if width:
+ self.maxwidth = unicode(width) + 'px'
+ if self.scale and not self.width:
+ self.width = self.scalevalue(width)
+ if height:
+ self.maxheight = unicode(height) + 'px'
+ if self.scale and not self.height:
+ self.height = self.scalevalue(height)
+ if self.width and not self.height:
+ self.height = 'auto'
+ if self.height and not self.width:
+ self.width = 'auto'
+
+ def scalevalue(self, value):
+ "Scale the value according to the image scale and return it as unicode."
+ scaled = value * int(self.scale) / 100
+ return unicode(int(scaled)) + 'px'
+
+ def removepercentwidth(self):
+ "Remove percent width if present, to set it at the figure level."
+ if not self.width:
+ return None
+ if not '%' in self.width:
+ return None
+ width = self.width
+ self.width = None
+ if self.height == 'auto':
+ self.height = None
+ return width
+
+ def addstyle(self, container):
+ "Add the proper style attribute to the output tag."
+ if not isinstance(container.output, TaggedOutput):
+ Trace.error('No tag to add style, in ' + unicode(container))
+ if not self.width and not self.height and not self.maxwidth and not self.maxheight:
+ # nothing to see here; move along
+ return
+ tag = ' style="'
+ tag += self.styleparameter('width')
+ tag += self.styleparameter('maxwidth')
+ tag += self.styleparameter('height')
+ tag += self.styleparameter('maxheight')
+ if tag[-1] == ' ':
+ tag = tag[:-1]
+ tag += '"'
+ container.output.tag += tag
+
+ def styleparameter(self, name):
+ "Get the style for a single parameter."
+ value = getattr(self, name)
+ if value:
+ return name.replace('max', 'max-') + ': ' + value + '; '
+ return ''
+
+
+
+class QuoteContainer(Container):
+ "A container for a pretty quote"
+
+ def __init__(self):
+ self.parser = BoundedParser()
+ self.output = FixedOutput()
+
+ def process(self):
+ "Process contents"
+ self.type = self.header[2]
+ if not self.type in StyleConfig.quotes:
+ Trace.error('Quote type ' + self.type + ' not found')
+ self.html = ['"']
+ return
+ self.html = [StyleConfig.quotes[self.type]]
+
+class LyXLine(Container):
+ "A Lyx line"
+
+ def __init__(self):
+ self.parser = LoneCommand()
+ self.output = FixedOutput()
+
+ def process(self):
+ self.html = ['<hr class="line" />']
+
+class EmphaticText(TaggedText):
+ "Text with emphatic mode"
+
+ def process(self):
+ self.output.tag = 'i'
+
+class ShapedText(TaggedText):
+ "Text shaped (italic, slanted)"
+
+ def process(self):
+ self.type = self.header[1]
+ if not self.type in TagConfig.shaped:
+ Trace.error('Unrecognized shape ' + self.header[1])
+ self.output.tag = 'span'
+ return
+ self.output.tag = TagConfig.shaped[self.type]
+
+class VersalitasText(TaggedText):
+ "Text in versalitas"
+
+ def process(self):
+ self.output.tag = 'span class="versalitas"'
+
+class ColorText(TaggedText):
+ "Colored text"
+
+ def process(self):
+ self.color = self.header[1]
+ self.output.tag = 'span class="' + self.color + '"'
+
+class SizeText(TaggedText):
+ "Sized text"
+
+ def process(self):
+ self.size = self.header[1]
+ self.output.tag = 'span class="' + self.size + '"'
+
+class BoldText(TaggedText):
+ "Bold text"
+
+ def process(self):
+ self.output.tag = 'b'
+
+class TextFamily(TaggedText):
+ "A bit of text from elyxer.a different family"
+
+ def process(self):
+ "Parse the type of family"
+ self.type = self.header[1]
+ if not self.type in TagConfig.family:
+ Trace.error('Unrecognized family ' + type)
+ self.output.tag = 'span'
+ return
+ self.output.tag = TagConfig.family[self.type]
+
+class Hfill(TaggedText):
+ "Horizontall fill"
+
+ def process(self):
+ self.output.tag = 'span class="hfill"'
+
+class BarredText(TaggedText):
+ "Text with a bar somewhere"
+
+ def process(self):
+ "Parse the type of bar"
+ self.type = self.header[1]
+ if not self.type in TagConfig.barred:
+ Trace.error('Unknown bar type ' + self.type)
+ self.output.tag = 'span'
+ return
+ self.output.tag = TagConfig.barred[self.type]
+
+class LangLine(TaggedText):
+ "A line with language information"
+
+ def process(self):
+ "Only generate a span with lang info when the language is recognized."
+ lang = self.header[1]
+ if not lang in TranslationConfig.languages:
+ self.output = ContentsOutput()
+ return
+ isolang = TranslationConfig.languages[lang]
+ self.output = TaggedOutput().settag('span lang="' + isolang + '"', False)
+
+class InsetLength(BlackBox):
+ "A length measure inside an inset."
+
+ def process(self):
+ self.length = self.header[1]
+
+class Space(Container):
+ "A space of several types"
+
+ def __init__(self):
+ self.parser = InsetParser()
+ self.output = FixedOutput()
+
+ def process(self):
+ self.type = self.header[2]
+ if self.type not in StyleConfig.hspaces:
+ Trace.error('Unknown space type ' + self.type)
+ self.html = [' ']
+ return
+ self.html = [StyleConfig.hspaces[self.type]]
+ length = self.getlength()
+ if not length:
+ return
+ self.output = TaggedOutput().settag('span class="hspace"', False)
+ ContainerSize().set(length).addstyle(self)
+
+ def getlength(self):
+ "Get the space length from elyxer.the contents or parameters."
+ if len(self.contents) == 0 or not isinstance(self.contents[0], InsetLength):
+ return None
+ return self.contents[0].length
+
+class VerticalSpace(Container):
+ "An inset that contains a vertical space."
+
+ def __init__(self):
+ self.parser = InsetParser()
+ self.output = FixedOutput()
+
+ def process(self):
+ "Set the correct tag"
+ self.type = self.header[2]
+ if self.type not in StyleConfig.vspaces:
+ self.output = TaggedOutput().settag('div class="vspace" style="height: ' + self.type + ';"', True)
+ return
+ self.html = [StyleConfig.vspaces[self.type]]
+
+class Align(Container):
+ "Bit of aligned text"
+
+ def __init__(self):
+ self.parser = ExcludingParser()
+ self.output = TaggedOutput().setbreaklines(True)
+
+ def process(self):
+ self.output.tag = 'div class="' + self.header[1] + '"'
+
+class Newline(Container):
+ "A newline"
+
+ def __init__(self):
+ self.parser = LoneCommand()
+ self.output = FixedOutput()
+
+ def process(self):
+ "Process contents"
+ self.html = ['<br/>\n']
+
+class NewPage(Newline):
+ "A new page"
+
+ def process(self):
+ "Process contents"
+ self.html = ['<p><br/>\n</p>\n']
+
+class Separator(Container):
+ "A separator string which is not extracted by extracttext()."
+
+ def __init__(self, constant):
+ self.output = FixedOutput()
+ self.contents = []
+ self.html = [constant]
+
+class StrikeOut(TaggedText):
+ "Striken out text."
+
+ def process(self):
+ "Set the output tag to strike."
+ self.output.tag = 'strike'
+
+class StartAppendix(BlackBox):
+ "Mark to start an appendix here."
+ "From this point on, all chapters become appendices."
+
+ def process(self):
+ "Activate the special numbering scheme for appendices, using letters."
+ NumberGenerator.generator.startappendix()
+
+
+
+
+
+
+class Link(Container):
+ "A link to another part of the document"
+
+ anchor = None
+ url = None
+ type = None
+ page = None
+ target = None
+ destination = None
+ title = None
+
+ def __init__(self):
+ "Initialize the link, add target if configured."
+ self.contents = []
+ self.parser = InsetParser()
+ self.output = LinkOutput()
+ if Options.target:
+ self.target = Options.target
+
+ def complete(self, text, anchor = None, url = None, type = None, title = None):
+ "Complete the link."
+ self.contents = [Constant(text)]
+ if anchor:
+ self.anchor = anchor
+ if url:
+ self.url = url
+ if type:
+ self.type = type
+ if title:
+ self.title = title
+ return self
+
+ def computedestination(self):
+ "Use the destination link to fill in the destination URL."
+ if not self.destination:
+ return
+ self.url = ''
+ if self.destination.anchor:
+ self.url = '#' + self.destination.anchor
+ if self.destination.page:
+ self.url = self.destination.page + self.url
+
+ def setmutualdestination(self, destination):
+ "Set another link as destination, and set its destination to this one."
+ self.destination = destination
+ destination.destination = self
+
+ def __unicode__(self):
+ "Return a printable representation."
+ result = 'Link'
+ if self.anchor:
+ result += ' #' + self.anchor
+ if self.url:
+ result += ' to ' + self.url
+ return result
+
+ if sys.version_info >= (3, 0):
+ __str__ = __unicode__
+
+
+class URL(Link):
+ "A clickable URL"
+
+ def process(self):
+ "Read URL from elyxer.parameters"
+ target = self.escape(self.getparameter('target'))
+ self.url = target
+ type = self.getparameter('type')
+ if type:
+ self.url = self.escape(type) + target
+ name = self.getparameter('name')
+ if not name:
+ name = target
+ self.contents = [Constant(name)]
+
+class FlexURL(URL):
+ "A flexible URL"
+
+ def process(self):
+ "Read URL from elyxer.contents"
+ self.url = self.extracttext()
+
+class LinkOutput(ContainerOutput):
+ "A link pointing to some destination"
+ "Or an anchor (destination)"
+
+ def gethtml(self, link):
+ "Get the HTML code for the link"
+ type = link.__class__.__name__
+ if link.type:
+ type = link.type
+ tag = 'a class="' + type + '"'
+ if link.anchor:
+ tag += ' name="' + link.anchor + '"'
+ if link.destination:
+ link.computedestination()
+ if link.url:
+ tag += ' href="' + link.url + '"'
+ if link.target:
+ tag += ' target="' + link.target + '"'
+ if link.title:
+ tag += ' title="' + link.title + '"'
+ return TaggedOutput().settag(tag).gethtml(link)
+
+
+
+
+
+class Postprocessor(object):
+ "Postprocess a container keeping some context"
+
+ stages = []
+
+ def __init__(self):
+ self.stages = StageDict(Postprocessor.stages, self)
+ self.current = None
+ self.last = None
+
+ def postprocess(self, next):
+ "Postprocess a container and its contents."
+ self.postrecursive(self.current)
+ result = self.postcurrent(next)
+ self.last = self.current
+ self.current = next
+ return result
+
+ def postrecursive(self, container):
+ "Postprocess the container contents recursively"
+ if not hasattr(container, 'contents'):
+ return
+ if len(container.contents) == 0:
+ return
+ if hasattr(container, 'postprocess'):
+ if not container.postprocess:
+ return
+ postprocessor = Postprocessor()
+ contents = []
+ for element in container.contents:
+ post = postprocessor.postprocess(element)
+ if post:
+ contents.append(post)
+ # two rounds to empty the pipeline
+ for i in range(2):
+ post = postprocessor.postprocess(None)
+ if post:
+ contents.append(post)
+ container.contents = contents
+
+ def postcurrent(self, next):
+ "Postprocess the current element taking into account next and last."
+ stage = self.stages.getstage(self.current)
+ if not stage:
+ return self.current
+ return stage.postprocess(self.last, self.current, next)
+
+class StageDict(object):
+ "A dictionary of stages corresponding to classes"
+
+ def __init__(self, classes, postprocessor):
+ "Instantiate an element from elyxer.each class and store as a dictionary"
+ instances = self.instantiate(classes, postprocessor)
+ self.stagedict = dict([(x.processedclass, x) for x in instances])
+
+ def instantiate(self, classes, postprocessor):
+ "Instantiate an element from elyxer.each class"
+ stages = [x.__new__(x) for x in classes]
+ for element in stages:
+ element.__init__()
+ element.postprocessor = postprocessor
+ return stages
+
+ def getstage(self, element):
+ "Get the stage for a given element, if the type is in the dict"
+ if not element.__class__ in self.stagedict:
+ return None
+ return self.stagedict[element.__class__]
+
+
+
+class Label(Link):
+ "A label to be referenced"
+
+ names = dict()
+ lastlayout = None
+
+ def __init__(self):
+ Link.__init__(self)
+ self.lastnumbered = None
+
+ def process(self):
+ "Process a label container."
+ key = self.getparameter('name')
+ self.create(' ', key)
+ self.lastnumbered = Label.lastlayout
+
+ def create(self, text, key, type = 'Label'):
+ "Create the label for a given key."
+ self.key = key
+ self.complete(text, anchor = key, type = type)
+ Label.names[key] = self
+ if key in Reference.references:
+ for reference in Reference.references[key]:
+ reference.destination = self
+ return self
+
+ def findpartkey(self):
+ "Get the part key for the latest numbered container seen."
+ numbered = self.numbered(self)
+ if numbered and numbered.partkey:
+ return numbered.partkey
+ return ''
+
+ def numbered(self, container):
+ "Get the numbered container for the label."
+ if container.partkey:
+ return container
+ if not container.parent:
+ if self.lastnumbered:
+ return self.lastnumbered
+ return None
+ return self.numbered(container.parent)
+
+ def __unicode__(self):
+ "Return a printable representation."
+ if not hasattr(self, 'key'):
+ return 'Unnamed label'
+ return 'Label ' + self.key
+
+ if sys.version_info >= (3, 0):
+ __str__ = __unicode__
+
+
+class Reference(Link):
+ "A reference to a label."
+
+ references = dict()
+ key = 'none'
+
+ def process(self):
+ "Read the reference and set the arrow."
+ self.key = self.getparameter('reference')
+ if self.key in Label.names:
+ self.direction = u'↑'
+ label = Label.names[self.key]
+ else:
+ self.direction = u'↓'
+ label = Label().complete(' ', self.key, 'preref')
+ self.destination = label
+ self.formatcontents()
+ if not self.key in Reference.references:
+ Reference.references[self.key] = []
+ Reference.references[self.key].append(self)
+
+ def formatcontents(self):
+ "Format the reference contents."
+ formatkey = self.getparameter('LatexCommand')
+ if not formatkey:
+ formatkey = 'ref'
+ self.formatted = u'↕'
+ if formatkey in StyleConfig.referenceformats:
+ self.formatted = StyleConfig.referenceformats[formatkey]
+ else:
+ Trace.error('Unknown reference format ' + formatkey)
+ self.replace(u'↕', self.direction)
+ self.replace('#', '1')
+ self.replace('on-page', Translator.translate('on-page'))
+ partkey = self.destination.findpartkey()
+ # only if partkey and partkey.number are not null, send partkey.number
+ self.replace('@', partkey and partkey.number)
+ self.replace(u'¶', partkey and partkey.tocentry)
+ if not '$' in self.formatted or not partkey or not partkey.titlecontents:
+ # there is a $ left, but it should go away on preprocessing
+ self.contents = [Constant(self.formatted)]
+ return
+ pieces = self.formatted.split('$')
+ self.contents = [Constant(pieces[0])]
+ for piece in pieces[1:]:
+ self.contents += partkey.titlecontents
+ self.contents.append(Constant(piece))
+
+ def replace(self, key, value):
+ "Replace a key in the format template with a value."
+ if not key in self.formatted:
+ return
+ if not value:
+ value = ''
+ self.formatted = self.formatted.replace(key, value)
+
+ def __unicode__(self):
+ "Return a printable representation."
+ return 'Reference ' + self.key
+
+ if sys.version_info >= (3, 0):
+ __str__ = __unicode__
+
+
+class FormulaCommand(FormulaBit):
+ "A LaTeX command inside a formula"
+
+ types = []
+ start = FormulaConfig.starts['command']
+ commandmap = None
+
+ def detect(self, pos):
+ "Find the current command."
+ return pos.checkfor(FormulaCommand.start)
+
+ def parsebit(self, pos):
+ "Parse the command."
+ command = self.extractcommand(pos)
+ bit = self.parsewithcommand(command, pos)
+ if bit:
+ return bit
+ if command.startswith('\\up') or command.startswith('\\Up'):
+ upgreek = self.parseupgreek(command, pos)
+ if upgreek:
+ return upgreek
+ if not self.factory.defining:
+ Trace.error('Unknown command ' + command)
+ self.output = TaggedOutput().settag('span class="unknown"')
+ self.add(FormulaConstant(command))
+ return None
+
+ def parsewithcommand(self, command, pos):
+ "Parse the command type once we have the command."
+ for type in FormulaCommand.types:
+ if command in type.commandmap:
+ return self.parsecommandtype(command, type, pos)
+ return None
+
+ def parsecommandtype(self, command, type, pos):
+ "Parse a given command type."
+ bit = self.factory.create(type)
+ bit.setcommand(command)
+ returned = bit.parsebit(pos)
+ if returned:
+ return returned
+ return bit
+
+ def extractcommand(self, pos):
+ "Extract the command from elyxer.the current position."
+ if not pos.checkskip(FormulaCommand.start):
+ pos.error('Missing command start ' + FormulaCommand.start)
+ return
+ if pos.finished():
+ return self.emptycommand(pos)
+ if pos.current().isalpha():
+ # alpha command
+ command = FormulaCommand.start + pos.globalpha()
+ # skip mark of short command
+ pos.checkskip('*')
+ return command
+ # symbol command
+ return FormulaCommand.start + pos.skipcurrent()
+
+ def emptycommand(self, pos):
+ """Check for an empty command: look for command disguised as ending.
+ Special case against '{ \\{ \\} }' situation."""
+ command = ''
+ if not pos.isout():
+ ending = pos.nextending()
+ if ending and pos.checkskip(ending):
+ command = ending
+ return FormulaCommand.start + command
+
+ def parseupgreek(self, command, pos):
+ "Parse the Greek \\up command.."
+ if len(command) < 4:
+ return None
+ if command.startswith('\\up'):
+ upcommand = '\\' + command[3:]
+ elif pos.checkskip('\\Up'):
+ upcommand = '\\' + command[3:4].upper() + command[4:]
+ else:
+ Trace.error('Impossible upgreek command: ' + command)
+ return
+ upgreek = self.parsewithcommand(upcommand, pos)
+ if upgreek:
+ upgreek.type = 'font'
+ return upgreek
+
+class CommandBit(FormulaCommand):
+ "A formula bit that includes a command"
+
+ def setcommand(self, command):
+ "Set the command in the bit"
+ self.command = command
+ if self.commandmap:
+ self.original += command
+ self.translated = self.commandmap[self.command]
+
+ def parseparameter(self, pos):
+ "Parse a parameter at the current position"
+ self.factory.clearskipped(pos)
+ if pos.finished():
+ return None
+ parameter = self.factory.parseany(pos)
+ self.add(parameter)
+ return parameter
+
+ def parsesquare(self, pos):
+ "Parse a square bracket"
+ self.factory.clearskipped(pos)
+ if not self.factory.detecttype(SquareBracket, pos):
+ return None
+ bracket = self.factory.parsetype(SquareBracket, pos)
+ self.add(bracket)
+ return bracket
+
+ def parseliteral(self, pos):
+ "Parse a literal bracket."
+ self.factory.clearskipped(pos)
+ if not self.factory.detecttype(Bracket, pos):
+ if not pos.isvalue():
+ Trace.error('No literal parameter found at: ' + pos.identifier())
+ return None
+ return pos.globvalue()
+ bracket = Bracket().setfactory(self.factory)
+ self.add(bracket.parseliteral(pos))
+ return bracket.literal
+
+ def parsesquareliteral(self, pos):
+ "Parse a square bracket literally."
+ self.factory.clearskipped(pos)
+ if not self.factory.detecttype(SquareBracket, pos):
+ return None
+ bracket = SquareBracket().setfactory(self.factory)
+ self.add(bracket.parseliteral(pos))
+ return bracket.literal
+
+ def parsetext(self, pos):
+ "Parse a text parameter."
+ self.factory.clearskipped(pos)
+ if not self.factory.detecttype(Bracket, pos):
+ Trace.error('No text parameter for ' + self.command)
+ return None
+ bracket = Bracket().setfactory(self.factory).parsetext(pos)
+ self.add(bracket)
+ return bracket
+
+class EmptyCommand(CommandBit):
+ "An empty command (without parameters)"
+
+ commandmap = FormulaConfig.commands
+
+ def parsebit(self, pos):
+ "Parse a command without parameters"
+ self.contents = [FormulaConstant(self.translated)]
+
+class SpacedCommand(CommandBit):
+ "An empty command which should have math spacing in formulas."
+
+ commandmap = FormulaConfig.spacedcommands
+
+ def parsebit(self, pos):
+ "Place as contents the command translated and spaced."
+ self.contents = [FormulaConstant(u' ' + self.translated + u' ')]
+
+class AlphaCommand(EmptyCommand):
+ "A command without paramters whose result is alphabetical"
+
+ commandmap = FormulaConfig.alphacommands
+
+ def parsebit(self, pos):
+ "Parse the command and set type to alpha"
+ EmptyCommand.parsebit(self, pos)
+ self.type = 'alpha'
+
+class OneParamFunction(CommandBit):
+ "A function of one parameter"
+
+ commandmap = FormulaConfig.onefunctions
+ simplified = False
+
+ def parsebit(self, pos):
+ "Parse a function with one parameter"
+ self.output = TaggedOutput().settag(self.translated)
+ self.parseparameter(pos)
+ self.simplifyifpossible()
+
+ def simplifyifpossible(self):
+ "Try to simplify to a single character."
+ if self.original in self.commandmap:
+ self.output = FixedOutput()
+ self.html = [self.commandmap[self.original]]
+ self.simplified = True
+
+class SymbolFunction(CommandBit):
+ "Find a function which is represented by a symbol (like _ or ^)"
+
+ commandmap = FormulaConfig.symbolfunctions
+
+ def detect(self, pos):
+ "Find the symbol"
+ return pos.current() in SymbolFunction.commandmap
+
+ def parsebit(self, pos):
+ "Parse the symbol"
+ self.setcommand(pos.current())
+ pos.skip(self.command)
+ self.output = TaggedOutput().settag(self.translated)
+ self.parseparameter(pos)
+
+class TextFunction(CommandBit):
+ "A function where parameters are read as text."
+
+ commandmap = FormulaConfig.textfunctions
+
+ def parsebit(self, pos):
+ "Parse a text parameter"
+ self.output = TaggedOutput().settag(self.translated)
+ self.parsetext(pos)
+
+ def process(self):
+ "Set the type to font"
+ self.type = 'font'
+
+class LabelFunction(CommandBit):
+ "A function that acts as a label"
+
+ commandmap = FormulaConfig.labelfunctions
+
+ def parsebit(self, pos):
+ "Parse a literal parameter"
+ self.key = self.parseliteral(pos)
+
+ def process(self):
+ "Add an anchor with the label contents."
+ self.type = 'font'
+ self.label = Label().create(' ', self.key, type = 'eqnumber')
+ self.contents = [self.label]
+ # store as a Label so we know it's been seen
+ Label.names[self.key] = self.label
+
+class FontFunction(OneParamFunction):
+ "A function of one parameter that changes the font"
+
+ commandmap = FormulaConfig.fontfunctions
+
+ def process(self):
+ "Simplify if possible using a single character."
+ self.type = 'font'
+ self.simplifyifpossible()
+
+FormulaFactory.types += [FormulaCommand, SymbolFunction]
+FormulaCommand.types = [
+ AlphaCommand, EmptyCommand, OneParamFunction, FontFunction, LabelFunction,
+ TextFunction, SpacedCommand,
+ ]
+
+
+
+
+
+
+
+
+
+
+
+
+class BigSymbol(object):
+ "A big symbol generator."
+
+ symbols = FormulaConfig.bigsymbols
+
+ def __init__(self, symbol):
+ "Create the big symbol."
+ self.symbol = symbol
+
+ def getpieces(self):
+ "Get an array with all pieces."
+ if not self.symbol in self.symbols:
+ return [self.symbol]
+ if self.smalllimit():
+ return [self.symbol]
+ return self.symbols[self.symbol]
+
+ def smalllimit(self):
+ "Decide if the limit should be a small, one-line symbol."
+ if not DocumentParameters.displaymode:
+ return True
+ if len(self.symbols[self.symbol]) == 1:
+ return True
+ return Options.simplemath
+
+class BigBracket(BigSymbol):
+ "A big bracket generator."
+
+ def __init__(self, size, bracket, alignment='l'):
+ "Set the size and symbol for the bracket."
+ self.size = size
+ self.original = bracket
+ self.alignment = alignment
+ self.pieces = None
+ if bracket in FormulaConfig.bigbrackets:
+ self.pieces = FormulaConfig.bigbrackets[bracket]
+
+ def getpiece(self, index):
+ "Return the nth piece for the bracket."
+ function = getattr(self, 'getpiece' + unicode(len(self.pieces)))
+ return function(index)
+
+ def getpiece1(self, index):
+ "Return the only piece for a single-piece bracket."
+ return self.pieces[0]
+
+ def getpiece3(self, index):
+ "Get the nth piece for a 3-piece bracket: parenthesis or square bracket."
+ if index == 0:
+ return self.pieces[0]
+ if index == self.size - 1:
+ return self.pieces[-1]
+ return self.pieces[1]
+
+ def getpiece4(self, index):
+ "Get the nth piece for a 4-piece bracket: curly bracket."
+ if index == 0:
+ return self.pieces[0]
+ if index == self.size - 1:
+ return self.pieces[3]
+ if index == (self.size - 1)/2:
+ return self.pieces[2]
+ return self.pieces[1]
+
+ def getcell(self, index):
+ "Get the bracket piece as an array cell."
+ piece = self.getpiece(index)
+ span = 'span class="bracket align-' + self.alignment + '"'
+ return TaggedBit().constant(piece, span)
+
+ def getcontents(self):
+ "Get the bracket as an array or as a single bracket."
+ if self.size == 1 or not self.pieces:
+ return self.getsinglebracket()
+ rows = []
+ for index in range(self.size):
+ cell = self.getcell(index)
+ rows.append(TaggedBit().complete([cell], 'span class="arrayrow"'))
+ return [TaggedBit().complete(rows, 'span class="array"')]
+
+ def getsinglebracket(self):
+ "Return the bracket as a single sign."
+ if self.original == '.':
+ return [TaggedBit().constant('', 'span class="emptydot"')]
+ return [TaggedBit().constant(self.original, 'span class="symbol"')]
+
+
+
+
+
+
+class FormulaEquation(CommandBit):
+ "A simple numbered equation."
+
+ piece = 'equation'
+
+ def parsebit(self, pos):
+ "Parse the array"
+ self.output = ContentsOutput()
+ self.add(self.factory.parsetype(WholeFormula, pos))
+
+class FormulaCell(FormulaCommand):
+ "An array cell inside a row"
+
+ def setalignment(self, alignment):
+ self.alignment = alignment
+ self.output = TaggedOutput().settag('span class="arraycell align-' + alignment +'"', True)
+ return self
+
+ def parsebit(self, pos):
+ self.factory.clearskipped(pos)
+ if pos.finished():
+ return
+ self.add(self.factory.parsetype(WholeFormula, pos))
+
+class FormulaRow(FormulaCommand):
+ "An array row inside an array"
+
+ cellseparator = FormulaConfig.array['cellseparator']
+
+ def setalignments(self, alignments):
+ self.alignments = alignments
+ self.output = TaggedOutput().settag('span class="arrayrow"', True)
+ return self
+
+ def parsebit(self, pos):
+ "Parse a whole row"
+ index = 0
+ pos.pushending(self.cellseparator, optional=True)
+ while not pos.finished():
+ cell = self.createcell(index)
+ cell.parsebit(pos)
+ self.add(cell)
+ index += 1
+ pos.checkskip(self.cellseparator)
+ if len(self.contents) == 0:
+ self.output = EmptyOutput()
+
+ def createcell(self, index):
+ "Create the cell that corresponds to the given index."
+ alignment = self.alignments[index % len(self.alignments)]
+ return self.factory.create(FormulaCell).setalignment(alignment)
+
+class MultiRowFormula(CommandBit):
+ "A formula with multiple rows."
+
+ def parserows(self, pos):
+ "Parse all rows, finish when no more row ends"
+ self.rows = []
+ first = True
+ for row in self.iteraterows(pos):
+ if first:
+ first = False
+ else:
+ # intersparse empty rows
+ self.addempty()
+ row.parsebit(pos)
+ self.addrow(row)
+ self.size = len(self.rows)
+
+ def iteraterows(self, pos):
+ "Iterate over all rows, end when no more row ends"
+ rowseparator = FormulaConfig.array['rowseparator']
+ while True:
+ pos.pushending(rowseparator, True)
+ row = self.factory.create(FormulaRow)
+ yield row.setalignments(self.alignments)
+ if pos.checkfor(rowseparator):
+ self.original += pos.popending(rowseparator)
+ else:
+ return
+
+ def addempty(self):
+ "Add an empty row."
+ row = self.factory.create(FormulaRow).setalignments(self.alignments)
+ for index, originalcell in enumerate(self.rows[-1].contents):
+ cell = row.createcell(index)
+ cell.add(FormulaConstant(u' '))
+ row.add(cell)
+ self.addrow(row)
+
+ def addrow(self, row):
+ "Add a row to the contents and to the list of rows."
+ self.rows.append(row)
+ self.add(row)
+
+class FormulaArray(MultiRowFormula):
+ "An array within a formula"
+
+ piece = 'array'
+
+ def parsebit(self, pos):
+ "Parse the array"
+ self.output = TaggedOutput().settag('span class="array"', False)
+ self.parsealignments(pos)
+ self.parserows(pos)
+
+ def parsealignments(self, pos):
+ "Parse the different alignments"
+ # vertical
+ self.valign = 'c'
+ literal = self.parsesquareliteral(pos)
+ if literal:
+ self.valign = literal
+ # horizontal
+ literal = self.parseliteral(pos)
+ self.alignments = []
+ for l in literal:
+ self.alignments.append(l)
+
+class FormulaMatrix(MultiRowFormula):
+ "A matrix (array with center alignment)."
+
+ piece = 'matrix'
+
+ def parsebit(self, pos):
+ "Parse the matrix, set alignments to 'c'."
+ self.output = TaggedOutput().settag('span class="array"', False)
+ self.valign = 'c'
+ self.alignments = ['c']
+ self.parserows(pos)
+
+class FormulaCases(MultiRowFormula):
+ "A cases statement"
+
+ piece = 'cases'
+
+ def parsebit(self, pos):
+ "Parse the cases"
+ self.output = ContentsOutput()
+ self.alignments = ['l', 'l']
+ self.parserows(pos)
+ for row in self.contents:
+ for cell in row.contents:
+ cell.output.settag('span class="case align-l"', True)
+ cell.contents.append(FormulaConstant(u' '))
+ array = TaggedBit().complete(self.contents, 'span class="bracketcases"', True)
+ brace = BigBracket(len(self.contents), '{', 'l')
+ self.contents = brace.getcontents() + [array]
+
+class EquationEnvironment(MultiRowFormula):
+ "A \\begin{}...\\end equation environment with rows and cells."
+
+ def parsebit(self, pos):
+ "Parse the whole environment."
+ self.output = TaggedOutput().settag('span class="environment"', False)
+ environment = self.piece.replace('*', '')
+ if environment in FormulaConfig.environments:
+ self.alignments = FormulaConfig.environments[environment]
+ else:
+ Trace.error('Unknown equation environment ' + self.piece)
+ self.alignments = ['l']
+ self.parserows(pos)
+
+class BeginCommand(CommandBit):
+ "A \\begin{}...\\end command and what it entails (array, cases, aligned)"
+
+ commandmap = {FormulaConfig.array['begin']:''}
+
+ types = [FormulaEquation, FormulaArray, FormulaCases, FormulaMatrix]
+
+ def parsebit(self, pos):
+ "Parse the begin command"
+ command = self.parseliteral(pos)
+ bit = self.findbit(command)
+ ending = FormulaConfig.array['end'] + '{' + command + '}'
+ pos.pushending(ending)
+ bit.parsebit(pos)
+ self.add(bit)
+ self.original += pos.popending(ending)
+ self.size = bit.size
+
+ def findbit(self, piece):
+ "Find the command bit corresponding to the \\begin{piece}"
+ for type in BeginCommand.types:
+ if piece.replace('*', '') == type.piece:
+ return self.factory.create(type)
+ bit = self.factory.create(EquationEnvironment)
+ bit.piece = piece
+ return bit
+
+FormulaCommand.types += [BeginCommand]
+
+
+
+class CombiningFunction(OneParamFunction):
+
+ commandmap = FormulaConfig.combiningfunctions
+
+ def parsebit(self, pos):
+ "Parse a combining function."
+ self.type = 'alpha'
+ combining = self.translated
+ parameter = self.parsesingleparameter(pos)
+ if not parameter:
+ Trace.error('Empty parameter for combining function ' + self.command)
+ elif len(parameter.extracttext()) != 1:
+ Trace.error('Applying combining function ' + self.command + ' to invalid string "' + parameter.extracttext() + '"')
+ self.contents.append(Constant(combining))
+
+ def parsesingleparameter(self, pos):
+ "Parse a parameter, or a single letter."
+ self.factory.clearskipped(pos)
+ if pos.finished():
+ Trace.error('Error while parsing single parameter at ' + pos.identifier())
+ return None
+ if self.factory.detecttype(Bracket, pos) \
+ or self.factory.detecttype(FormulaCommand, pos):
+ return self.parseparameter(pos)
+ letter = FormulaConstant(pos.skipcurrent())
+ self.add(letter)
+ return letter
+
+class DecoratingFunction(OneParamFunction):
+ "A function that decorates some bit of text"
+
+ commandmap = FormulaConfig.decoratingfunctions
+
+ def parsebit(self, pos):
+ "Parse a decorating function"
+ self.type = 'alpha'
+ symbol = self.translated
+ self.symbol = TaggedBit().constant(symbol, 'span class="symbolover"')
+ self.parameter = self.parseparameter(pos)
+ self.output = TaggedOutput().settag('span class="withsymbol"')
+ self.contents.insert(0, self.symbol)
+ self.parameter.output = TaggedOutput().settag('span class="undersymbol"')
+ self.simplifyifpossible()
+
+class LimitCommand(EmptyCommand):
+ "A command which accepts limits above and below, in display mode."
+
+ commandmap = FormulaConfig.limitcommands
+
+ def parsebit(self, pos):
+ "Parse a limit command."
+ pieces = BigSymbol(self.translated).getpieces()
+ self.output = TaggedOutput().settag('span class="limits"')
+ for piece in pieces:
+ self.contents.append(TaggedBit().constant(piece, 'span class="limit"'))
+
+class LimitPreviousCommand(LimitCommand):
+ "A command to limit the previous command."
+
+ commandmap = None
+
+ def parsebit(self, pos):
+ "Do nothing."
+ self.output = TaggedOutput().settag('span class="limits"')
+ self.factory.clearskipped(pos)
+
+ def __unicode__(self):
+ "Return a printable representation."
+ return 'Limit previous command'
+
+ if sys.version_info >= (3, 0):
+ __str__ = __unicode__
+
+
+class LimitsProcessor(MathsProcessor):
+ "A processor for limits inside an element."
+
+ def process(self, contents, index):
+ "Process the limits for an element."
+ if Options.simplemath:
+ return
+ if self.checklimits(contents, index):
+ self.modifylimits(contents, index)
+ if self.checkscript(contents, index) and self.checkscript(contents, index + 1):
+ self.modifyscripts(contents, index)
+
+ def checklimits(self, contents, index):
+ "Check if the current position has a limits command."
+ if not DocumentParameters.displaymode:
+ return False
+ if self.checkcommand(contents, index + 1, LimitPreviousCommand):
+ self.limitsahead(contents, index)
+ return False
+ if not isinstance(contents[index], LimitCommand):
+ return False
+ return self.checkscript(contents, index + 1)
+
+ def limitsahead(self, contents, index):
+ "Limit the current element based on the next."
+ contents[index + 1].add(contents[index].clone())
+ contents[index].output = EmptyOutput()
+
+ def modifylimits(self, contents, index):
+ "Modify a limits commands so that the limits appear above and below."
+ limited = contents[index]
+ subscript = self.getlimit(contents, index + 1)
+ limited.contents.append(subscript)
+ if self.checkscript(contents, index + 1):
+ superscript = self.getlimit(contents, index + 1)
+ else:
+ superscript = TaggedBit().constant(u' ', 'sup class="limit"')
+ limited.contents.insert(0, superscript)
+
+ def getlimit(self, contents, index):
+ "Get the limit for a limits command."
+ limit = self.getscript(contents, index)
+ limit.output.tag = limit.output.tag.replace('script', 'limit')
+ return limit
+
+ def modifyscripts(self, contents, index):
+ "Modify the super- and subscript to appear vertically aligned."
+ subscript = self.getscript(contents, index)
+ # subscript removed so instead of index + 1 we get index again
+ superscript = self.getscript(contents, index)
+ scripts = TaggedBit().complete([superscript, subscript], 'span class="scripts"')
+ contents.insert(index, scripts)
+
+ def checkscript(self, contents, index):
+ "Check if the current element is a sub- or superscript."
+ return self.checkcommand(contents, index, SymbolFunction)
+
+ def checkcommand(self, contents, index, type):
+ "Check for the given type as the current element."
+ if len(contents) <= index:
+ return False
+ return isinstance(contents[index], type)
+
+ def getscript(self, contents, index):
+ "Get the sub- or superscript."
+ bit = contents[index]
+ bit.output.tag += ' class="script"'
+ del contents[index]
+ return bit
+
+class BracketCommand(OneParamFunction):
+ "A command which defines a bracket."
+
+ commandmap = FormulaConfig.bracketcommands
+
+ def parsebit(self, pos):
+ "Parse the bracket."
+ OneParamFunction.parsebit(self, pos)
+
+ def create(self, direction, character):
+ "Create the bracket for the given character."
+ self.original = character
+ self.command = '\\' + direction
+ self.contents = [FormulaConstant(character)]
+ return self
+
+class BracketProcessor(MathsProcessor):
+ "A processor for bracket commands."
+
+ def process(self, contents, index):
+ "Convert the bracket using Unicode pieces, if possible."
+ if Options.simplemath:
+ return
+ if self.checkleft(contents, index):
+ return self.processleft(contents, index)
+
+ def processleft(self, contents, index):
+ "Process a left bracket."
+ rightindex = self.findright(contents, index + 1)
+ if not rightindex:
+ return
+ size = self.findmax(contents, index, rightindex)
+ self.resize(contents[index], size)
+ self.resize(contents[rightindex], size)
+
+ def checkleft(self, contents, index):
+ "Check if the command at the given index is left."
+ return self.checkdirection(contents[index], '\\left')
+
+ def checkright(self, contents, index):
+ "Check if the command at the given index is right."
+ return self.checkdirection(contents[index], '\\right')
+
+ def checkdirection(self, bit, command):
+ "Check if the given bit is the desired bracket command."
+ if not isinstance(bit, BracketCommand):
+ return False
+ return bit.command == command
+
+ def findright(self, contents, index):
+ "Find the right bracket starting at the given index, or 0."
+ depth = 1
+ while index < len(contents):
+ if self.checkleft(contents, index):
+ depth += 1
+ if self.checkright(contents, index):
+ depth -= 1
+ if depth == 0:
+ return index
+ index += 1
+ return None
+
+ def findmax(self, contents, leftindex, rightindex):
+ "Find the max size of the contents between the two given indices."
+ sliced = contents[leftindex:rightindex]
+ return max([element.size for element in sliced])
+
+ def resize(self, command, size):
+ "Resize a bracket command to the given size."
+ character = command.extracttext()
+ alignment = command.command.replace('\\', '')
+ bracket = BigBracket(size, character, alignment)
+ command.output = ContentsOutput()
+ command.contents = bracket.getcontents()
+
+class TodayCommand(EmptyCommand):
+ "Shows today's date."
+
+ commandmap = None
+
+ def parsebit(self, pos):
+ "Parse a command without parameters"
+ self.output = FixedOutput()
+ self.html = [datetime.date.today().strftime('%b %d, %Y')]
+
+
+FormulaCommand.types += [
+ DecoratingFunction, CombiningFunction, LimitCommand, BracketCommand,
+ ]
+
+FormulaProcessor.processors += [
+ LimitsProcessor(), BracketProcessor(),
+ ]
+
+
+
+class ParameterDefinition(object):
+ "The definition of a parameter in a hybrid function."
+ "[] parameters are optional, {} parameters are mandatory."
+ "Each parameter has a one-character name, like {$1} or {$p}."
+ "A parameter that ends in ! like {$p!} is a literal."
+ "Example: [$1]{$p!} reads an optional parameter $1 and a literal mandatory parameter p."
+
+ parambrackets = [('[', ']'), ('{', '}')]
+
+ def __init__(self):
+ self.name = None
+ self.literal = False
+ self.optional = False
+ self.value = None
+ self.literalvalue = None
+
+ def parse(self, pos):
+ "Parse a parameter definition: [$0], {$x}, {$1!}..."
+ for (opening, closing) in ParameterDefinition.parambrackets:
+ if pos.checkskip(opening):
+ if opening == '[':
+ self.optional = True
+ if not pos.checkskip('$'):
+ Trace.error('Wrong parameter name, did you mean $' + pos.current() + '?')
+ return None
+ self.name = pos.skipcurrent()
+ if pos.checkskip('!'):
+ self.literal = True
+ if not pos.checkskip(closing):
+ Trace.error('Wrong parameter closing ' + pos.skipcurrent())
+ return None
+ return self
+ Trace.error('Wrong character in parameter template: ' + pos.skipcurrent())
+ return None
+
+ def read(self, pos, function):
+ "Read the parameter itself using the definition."
+ if self.literal:
+ if self.optional:
+ self.literalvalue = function.parsesquareliteral(pos)
+ else:
+ self.literalvalue = function.parseliteral(pos)
+ if self.literalvalue:
+ self.value = FormulaConstant(self.literalvalue)
+ elif self.optional:
+ self.value = function.parsesquare(pos)
+ else:
+ self.value = function.parseparameter(pos)
+
+ def __unicode__(self):
+ "Return a printable representation."
+ result = 'param ' + self.name
+ if self.value:
+ result += ': ' + unicode(self.value)
+ else:
+ result += ' (empty)'
+ return result
+
+ if sys.version_info >= (3, 0):
+ __str__ = __unicode__
+
+
+class ParameterFunction(CommandBit):
+ "A function with a variable number of parameters defined in a template."
+ "The parameters are defined as a parameter definition."
+
+ def readparams(self, readtemplate, pos):
+ "Read the params according to the template."
+ self.params = dict()
+ for paramdef in self.paramdefs(readtemplate):
+ paramdef.read(pos, self)
+ self.params['$' + paramdef.name] = paramdef
+
+ def paramdefs(self, readtemplate):
+ "Read each param definition in the template"
+ pos = TextPosition(readtemplate)
+ while not pos.finished():
+ paramdef = ParameterDefinition().parse(pos)
+ if paramdef:
+ yield paramdef
+
+ def getparam(self, name):
+ "Get a parameter as parsed."
+ if not name in self.params:
+ return None
+ return self.params[name]
+
+ def getvalue(self, name):
+ "Get the value of a parameter."
+ return self.getparam(name).value
+
+ def getliteralvalue(self, name):
+ "Get the literal value of a parameter."
+ param = self.getparam(name)
+ if not param or not param.literalvalue:
+ return None
+ return param.literalvalue
+
+class HybridFunction(ParameterFunction):
+ """
+ A parameter function where the output is also defined using a template.
+ The template can use a number of functions; each function has an associated
+ tag.
+ Example: [f0{$1},span class="fbox"] defines a function f0 which corresponds
+ to a span of class fbox, yielding <span class="fbox">$1</span>.
+ Literal parameters can be used in tags definitions:
+ [f0{$1},span style="color: $p;"]
+ yields <span style="color: $p;">$1</span>, where $p is a literal parameter.
+ Sizes can be specified in hybridsizes, e.g. adding parameter sizes. By
+ default the resulting size is the max of all arguments. Sizes are used
+ to generate the right parameters.
+ A function followed by a single / is output as a self-closing XHTML tag:
+ [f0/,hr]
+ will generate <hr/>.
+ """
+
+ commandmap = FormulaConfig.hybridfunctions
+
+ def parsebit(self, pos):
+ "Parse a function with [] and {} parameters"
+ readtemplate = self.translated[0]
+ writetemplate = self.translated[1]
+ self.readparams(readtemplate, pos)
+ self.contents = self.writeparams(writetemplate)
+ self.computehybridsize()
+
+ def writeparams(self, writetemplate):
+ "Write all params according to the template"
+ return self.writepos(TextPosition(writetemplate))
+
+ def writepos(self, pos):
+ "Write all params as read in the parse position."
+ result = []
+ while not pos.finished():
+ if pos.checkskip('$'):
+ param = self.writeparam(pos)
+ if param:
+ result.append(param)
+ elif pos.checkskip('f'):
+ function = self.writefunction(pos)
+ if function:
+ function.type = None
+ result.append(function)
+ elif pos.checkskip('('):
+ result.append(self.writebracket('left', '('))
+ elif pos.checkskip(')'):
+ result.append(self.writebracket('right', ')'))
+ else:
+ result.append(FormulaConstant(pos.skipcurrent()))
+ return result
+
+ def writeparam(self, pos):
+ "Write a single param of the form $0, $x..."
+ name = '$' + pos.skipcurrent()
+ if not name in self.params:
+ Trace.error('Unknown parameter ' + name)
+ return None
+ if not self.params[name]:
+ return None
+ if pos.checkskip('.'):
+ self.params[name].value.type = pos.globalpha()
+ return self.params[name].value
+
+ def writefunction(self, pos):
+ "Write a single function f0,...,fn."
+ tag = self.readtag(pos)
+ if not tag:
+ return None
+ if pos.checkskip('/'):
+ # self-closing XHTML tag, such as <hr/>
+ return TaggedBit().selfcomplete(tag)
+ if not pos.checkskip('{'):
+ Trace.error('Function should be defined in {}')
+ return None
+ pos.pushending('}')
+ contents = self.writepos(pos)
+ pos.popending()
+ if len(contents) == 0:
+ return None
+ return TaggedBit().complete(contents, tag)
+
+ def readtag(self, pos):
+ "Get the tag corresponding to the given index. Does parameter substitution."
+ if not pos.current().isdigit():
+ Trace.error('Function should be f0,...,f9: f' + pos.current())
+ return None
+ index = int(pos.skipcurrent())
+ if 2 + index > len(self.translated):
+ Trace.error('Function f' + unicode(index) + ' is not defined')
+ return None
+ tag = self.translated[2 + index]
+ if not '$' in tag:
+ return tag
+ for variable in self.params:
+ if variable in tag:
+ param = self.params[variable]
+ if not param.literal:
+ Trace.error('Parameters in tag ' + tag + ' should be literal: {' + variable + '!}')
+ continue
+ if param.literalvalue:
+ value = param.literalvalue
+ else:
+ value = ''
+ tag = tag.replace(variable, value)
+ return tag
+
+ def writebracket(self, direction, character):
+ "Return a new bracket looking at the given direction."
+ return self.factory.create(BracketCommand).create(direction, character)
+
+ def computehybridsize(self):
+ "Compute the size of the hybrid function."
+ if not self.command in HybridSize.configsizes:
+ self.computesize()
+ return
+ self.size = HybridSize().getsize(self)
+ # set the size in all elements at first level
+ for element in self.contents:
+ element.size = self.size
+
+class HybridSize(object):
+ "The size associated with a hybrid function."
+
+ configsizes = FormulaConfig.hybridsizes
+
+ def getsize(self, function):
+ "Read the size for a function and parse it."
+ sizestring = self.configsizes[function.command]
+ for name in function.params:
+ if name in sizestring:
+ size = function.params[name].value.computesize()
+ sizestring = sizestring.replace(name, unicode(size))
+ if '$' in sizestring:
+ Trace.error('Unconverted variable in hybrid size: ' + sizestring)
+ return 1
+ return eval(sizestring)
+
+
+FormulaCommand.types += [HybridFunction]
+
+
+
+
+
+
+
+
+
+class HeaderParser(Parser):
+ "Parses the LyX header"
+
+ def parse(self, reader):
+ "Parse header parameters into a dictionary, return the preamble."
+ contents = []
+ self.parseending(reader, lambda: self.parseline(reader, contents))
+ # skip last line
+ reader.nextline()
+ return contents
+
+ def parseline(self, reader, contents):
+ "Parse a single line as a parameter or as a start"
+ line = reader.currentline()
+ if line.startswith(HeaderConfig.parameters['branch']):
+ self.parsebranch(reader)
+ return
+ elif line.startswith(HeaderConfig.parameters['lstset']):
+ LstParser().parselstset(reader)
+ return
+ elif line.startswith(HeaderConfig.parameters['beginpreamble']):
+ contents.append(self.factory.createcontainer(reader))
+ return
+ # no match
+ self.parseparameter(reader)
+
+ def parsebranch(self, reader):
+ "Parse all branch definitions."
+ branch = reader.currentline().split()[1]
+ reader.nextline()
+ subparser = HeaderParser().complete(HeaderConfig.parameters['endbranch'])
+ subparser.parse(reader)
+ options = BranchOptions(branch)
+ for key in subparser.parameters:
+ options.set(key, subparser.parameters[key])
+ Options.branches[branch] = options
+
+ def complete(self, ending):
+ "Complete the parser with the given ending."
+ self.ending = ending
+ return self
+
+class PreambleParser(Parser):
+ "A parser for the LyX preamble."
+
+ preamble = []
+
+ def parse(self, reader):
+ "Parse the full preamble with all statements."
+ self.ending = HeaderConfig.parameters['endpreamble']
+ self.parseending(reader, lambda: self.parsepreambleline(reader))
+ return []
+
+ def parsepreambleline(self, reader):
+ "Parse a single preamble line."
+ PreambleParser.preamble.append(reader.currentline())
+ reader.nextline()
+
+class LstParser(object):
+ "Parse global and local lstparams."
+
+ globalparams = dict()
+
+ def parselstset(self, reader):
+ "Parse a declaration of lstparams in lstset."
+ paramtext = self.extractlstset(reader)
+ if not '{' in paramtext:
+ Trace.error('Missing opening bracket in lstset: ' + paramtext)
+ return
+ lefttext = paramtext.split('{')[1]
+ croppedtext = lefttext[:-1]
+ LstParser.globalparams = self.parselstparams(croppedtext)
+
+ def extractlstset(self, reader):
+ "Extract the global lstset parameters."
+ paramtext = ''
+ while not reader.finished():
+ paramtext += reader.currentline()
+ reader.nextline()
+ if paramtext.endswith('}'):
+ return paramtext
+ Trace.error('Could not find end of \\lstset settings; aborting')
+
+ def parsecontainer(self, container):
+ "Parse some lstparams from elyxer.a container."
+ container.lstparams = LstParser.globalparams.copy()
+ paramlist = container.getparameterlist('lstparams')
+ container.lstparams.update(self.parselstparams(paramlist))
+
+ def parselstparams(self, paramlist):
+ "Process a number of lstparams from elyxer.a list."
+ paramdict = dict()
+ for param in paramlist:
+ if not '=' in param:
+ if len(param.strip()) > 0:
+ Trace.error('Invalid listing parameter ' + param)
+ else:
+ key, value = param.split('=', 1)
+ paramdict[key] = value
+ return paramdict
+
+
+
+
+class MacroDefinition(CommandBit):
+ "A function that defines a new command (a macro)."
+
+ macros = dict()
+
+ def parsebit(self, pos):
+ "Parse the function that defines the macro."
+ self.output = EmptyOutput()
+ self.parameternumber = 0
+ self.defaults = []
+ self.factory.defining = True
+ self.parseparameters(pos)
+ self.factory.defining = False
+ Trace.debug('New command ' + self.newcommand + ' (' + \
+ unicode(self.parameternumber) + ' parameters)')
+ self.macros[self.newcommand] = self
+
+ def parseparameters(self, pos):
+ "Parse all optional parameters (number of parameters, default values)"
+ "and the mandatory definition."
+ self.newcommand = self.parsenewcommand(pos)
+ # parse number of parameters
+ literal = self.parsesquareliteral(pos)
+ if literal:
+ self.parameternumber = int(literal)
+ # parse all default values
+ bracket = self.parsesquare(pos)
+ while bracket:
+ self.defaults.append(bracket)
+ bracket = self.parsesquare(pos)
+ # parse mandatory definition
+ self.definition = self.parseparameter(pos)
+
+ def parsenewcommand(self, pos):
+ "Parse the name of the new command."
+ self.factory.clearskipped(pos)
+ if self.factory.detecttype(Bracket, pos):
+ return self.parseliteral(pos)
+ if self.factory.detecttype(FormulaCommand, pos):
+ return self.factory.create(FormulaCommand).extractcommand(pos)
+ Trace.error('Unknown formula bit in defining function at ' + pos.identifier())
+ return 'unknown'
+
+ def instantiate(self):
+ "Return an instance of the macro."
+ return self.definition.clone()
+
+class MacroParameter(FormulaBit):
+ "A parameter from elyxer.a macro."
+
+ def detect(self, pos):
+ "Find a macro parameter: #n."
+ return pos.checkfor('#')
+
+ def parsebit(self, pos):
+ "Parse the parameter: #n."
+ if not pos.checkskip('#'):
+ Trace.error('Missing parameter start #.')
+ return
+ self.number = int(pos.skipcurrent())
+ self.original = '#' + unicode(self.number)
+ self.contents = [TaggedBit().constant('#' + unicode(self.number), 'span class="unknown"')]
+
+class MacroFunction(CommandBit):
+ "A function that was defined using a macro."
+
+ commandmap = MacroDefinition.macros
+
+ def parsebit(self, pos):
+ "Parse a number of input parameters."
+ self.output = FilteredOutput()
+ self.values = []
+ macro = self.translated
+ self.parseparameters(pos, macro)
+ self.completemacro(macro)
+
+ def parseparameters(self, pos, macro):
+ "Parse as many parameters as are needed."
+ self.parseoptional(pos, list(macro.defaults))
+ self.parsemandatory(pos, macro.parameternumber - len(macro.defaults))
+ if len(self.values) < macro.parameternumber:
+ Trace.error('Missing parameters in macro ' + unicode(self))
+
+ def parseoptional(self, pos, defaults):
+ "Parse optional parameters."
+ optional = []
+ while self.factory.detecttype(SquareBracket, pos):
+ optional.append(self.parsesquare(pos))
+ if len(optional) > len(defaults):
+ break
+ for value in optional:
+ default = defaults.pop()
+ if len(value.contents) > 0:
+ self.values.append(value)
+ else:
+ self.values.append(default)
+ self.values += defaults
+
+ def parsemandatory(self, pos, number):
+ "Parse a number of mandatory parameters."
+ for index in range(number):
+ parameter = self.parsemacroparameter(pos, number - index)
+ if not parameter:
+ return
+ self.values.append(parameter)
+
+ def parsemacroparameter(self, pos, remaining):
+ "Parse a macro parameter. Could be a bracket or a single letter."
+ "If there are just two values remaining and there is a running number,"
+ "parse as two separater numbers."
+ self.factory.clearskipped(pos)
+ if pos.finished():
+ return None
+ if self.factory.detecttype(FormulaNumber, pos):
+ return self.parsenumbers(pos, remaining)
+ return self.parseparameter(pos)
+
+ def parsenumbers(self, pos, remaining):
+ "Parse the remaining parameters as a running number."
+ "For example, 12 would be {1}{2}."
+ number = self.factory.parsetype(FormulaNumber, pos)
+ if not len(number.original) == remaining:
+ return number
+ for digit in number.original:
+ value = self.factory.create(FormulaNumber)
+ value.add(FormulaConstant(digit))
+ value.type = number
+ self.values.append(value)
+ return None
+
+ def completemacro(self, macro):
+ "Complete the macro with the parameters read."
+ self.contents = [macro.instantiate()]
+ replaced = [False] * len(self.values)
+ for parameter in self.searchall(MacroParameter):
+ index = parameter.number - 1
+ if index >= len(self.values):
+ Trace.error('Macro parameter index out of bounds: ' + unicode(index))
+ return
+ replaced[index] = True
+ parameter.contents = [self.values[index].clone()]
+ for index in range(len(self.values)):
+ if not replaced[index]:
+ self.addfilter(index, self.values[index])
+
+ def addfilter(self, index, value):
+ "Add a filter for the given parameter number and parameter value."
+ original = '#' + unicode(index + 1)
+ value = ''.join(self.values[0].gethtml())
+ self.output.addfilter(original, value)
+
+class FormulaMacro(Formula):
+ "A math macro defined in an inset."
+
+ def __init__(self):
+ self.parser = MacroParser()
+ self.output = EmptyOutput()
+
+ def __unicode__(self):
+ "Return a printable representation."
+ return 'Math macro'
+
+ if sys.version_info >= (3, 0):
+ __str__ = __unicode__
+
+
+FormulaFactory.types += [ MacroParameter ]
+
+FormulaCommand.types += [
+ MacroFunction,
+ ]
+
+
+
+def math2html(formula):
+ "Convert some TeX math to HTML."
+ factory = FormulaFactory()
+ whole = factory.parseformula(formula)
+ FormulaProcessor().process(whole)
+ whole.process()
+ return ''.join(whole.gethtml())
+
+def main():
+ "Main function, called if invoked from elyxer.the command line"
+ args = sys.argv
+ Options().parseoptions(args)
+ if len(args) != 1:
+ Trace.error('Usage: math2html.py escaped_string')
+ exit()
+ result = math2html(args[0])
+ Trace.message(result)
+
+if __name__ == '__main__':
+ main()
+
--- /dev/null
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+# :Id: $Id: tex2mathml_extern.py 8376 2019-08-27 19:49:29Z 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
+
+# Wrappers for TeX->MathML conversion by external tools
+# =====================================================
+
+from __future__ import print_function
+import subprocess
+
+document_template = r"""\documentclass{article}
+\usepackage{amsmath}
+\begin{document}
+%s
+\end{document}
+"""
+
+def latexml(math_code, reporter=None):
+ """Convert LaTeX math code to MathML with LaTeXML_
+
+ .. _LaTeXML: http://dlmf.nist.gov/LaTeXML/
+ """
+ p = subprocess.Popen(['latexml',
+ '-', # read from stdin
+ # '--preload=amsmath',
+ '--inputencoding=utf8',
+ ],
+ stdin=subprocess.PIPE,
+ stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE,
+ close_fds=True)
+ p.stdin.write((document_template % math_code).encode('utf8'))
+ p.stdin.close()
+ latexml_code = p.stdout.read()
+ latexml_err = p.stderr.read().decode('utf8')
+ if reporter and (latexml_err.find('Error') >= 0 or not latexml_code):
+ reporter.error(latexml_err)
+
+ post_p = subprocess.Popen(['latexmlpost',
+ '-',
+ '--nonumbersections',
+ '--format=xhtml',
+ # '--linelength=78', # experimental
+ '--'
+ ],
+ stdin=subprocess.PIPE,
+ stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE,
+ close_fds=True)
+ post_p.stdin.write(latexml_code)
+ post_p.stdin.close()
+ result = post_p.stdout.read().decode('utf8')
+ post_p_err = post_p.stderr.read().decode('utf8')
+ if reporter and (post_p_err.find('Error') >= 0 or not result):
+ reporter.error(post_p_err)
+
+ # extract MathML code:
+ start, end = result.find('<math'), result.find('</math>')+7
+ result = result[start:end]
+ if 'class="ltx_ERROR' in result:
+ raise SyntaxError(result)
+ return result
+
+def ttm(math_code, reporter=None):
+ """Convert LaTeX math code to MathML with TtM_
+
+ .. _TtM: http://hutchinson.belmont.ma.us/tth/mml/
+ """
+ p = subprocess.Popen(['ttm',
+ # '-i', # italic font for equations. Default roman.
+ '-u', # unicode character encoding. (Default iso-8859-1).
+ '-r', # output raw MathML (no preamble or postlude)
+ ],
+ stdin=subprocess.PIPE,
+ stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE,
+ close_fds=True)
+ p.stdin.write((document_template % math_code).encode('utf8'))
+ p.stdin.close()
+ result = p.stdout.read()
+ err = p.stderr.read().decode('utf8')
+ if err.find('**** Unknown') >= 0:
+ msg = '\n'.join([line for line in err.splitlines()
+ if line.startswith('****')])
+ raise SyntaxError('\nMessage from external converter TtM:\n'+ msg)
+ if reporter and err.find('**** Error') >= 0 or not result:
+ reporter.error(err)
+ start, end = result.find('<math'), result.find('</math>')+7
+ result = result[start:end]
+ return result
+
+def blahtexml(math_code, inline=True, reporter=None):
+ """Convert LaTeX math code to MathML with blahtexml_
+
+ .. _blahtexml: http://gva.noekeon.org/blahtexml/
+ """
+ options = ['--mathml',
+ '--indented',
+ '--spacing', 'moderate',
+ '--mathml-encoding', 'raw',
+ '--other-encoding', 'raw',
+ '--doctype-xhtml+mathml',
+ '--annotate-TeX',
+ ]
+ if inline:
+ mathmode_arg = ''
+ else:
+ mathmode_arg = 'mode="display"'
+ options.append('--displaymath')
+
+ p = subprocess.Popen(['blahtexml']+options,
+ stdin=subprocess.PIPE,
+ stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE,
+ close_fds=True)
+ p.stdin.write(math_code.encode('utf8'))
+ p.stdin.close()
+ result = p.stdout.read().decode('utf8')
+ err = p.stderr.read().decode('utf8')
+
+ if result.find('<error>') >= 0:
+ raise SyntaxError('\nMessage from external converter blahtexml:\n'
+ +result[result.find('<message>')+9:result.find('</message>')])
+ if reporter and (err.find('**** Error') >= 0 or not result):
+ reporter.error(err)
+ start, end = result.find('<markup>')+9, result.find('</markup>')
+ result = ('<math xmlns="http://www.w3.org/1998/Math/MathML"%s>\n'
+ '%s</math>\n') % (mathmode_arg, result[start:end])
+ return result
+
+# self-test
+
+if __name__ == "__main__":
+ example = (u'\\frac{\\partial \\sin^2(\\alpha)}{\\partial \\vec r}'
+ u'\\varpi \\, \\text{Grüße}')
+ # print(latexml(example).encode('utf8'))
+ # print(ttm(example))
+ print(blahtexml(example).encode('utf8'))
--- /dev/null
+# -*- coding: utf-8 -*-
+
+# LaTeX math to Unicode symbols translation dictionaries.
+# Generated with ``write_tex2unichar.py`` from the data in
+# http://milde.users.sourceforge.net/LUCR/Math/
+
+# Includes commands from: wasysym, stmaryrd, mathdots, mathabx, esint, bbold, amsxtra, amsmath, amssymb, standard LaTeX
+
+mathaccent = {
+ 'acute': u'\u0301', # x́ COMBINING ACUTE ACCENT
+ 'bar': u'\u0304', # x̄ COMBINING MACRON
+ 'breve': u'\u0306', # x̆ COMBINING BREVE
+ 'check': u'\u030c', # x̌ COMBINING CARON
+ 'ddddot': u'\u20dc', # x⃜ COMBINING FOUR DOTS ABOVE
+ 'dddot': u'\u20db', # x⃛ COMBINING THREE DOTS ABOVE
+ 'ddot': u'\u0308', # ẍ COMBINING DIAERESIS
+ 'dot': u'\u0307', # ẋ COMBINING DOT ABOVE
+ 'grave': u'\u0300', # x̀ COMBINING GRAVE ACCENT
+ 'hat': u'\u0302', # x̂ COMBINING CIRCUMFLEX ACCENT
+ 'mathring': u'\u030a', # x̊ COMBINING RING ABOVE
+ 'not': u'\u0338', # x̸ COMBINING LONG SOLIDUS OVERLAY
+ 'overleftarrow': u'\u20d6', # x⃖ COMBINING LEFT ARROW ABOVE
+ 'overleftrightarrow': u'\u20e1', # x⃡ COMBINING LEFT RIGHT ARROW ABOVE
+ 'overline': u'\u0305', # x̅ COMBINING OVERLINE
+ 'overrightarrow': u'\u20d7', # x⃗ COMBINING RIGHT ARROW ABOVE
+ 'tilde': u'\u0303', # x̃ COMBINING TILDE
+ 'underbar': u'\u0331', # x̱ COMBINING MACRON BELOW
+ 'underleftarrow': u'\u20ee', # x⃮ COMBINING LEFT ARROW BELOW
+ 'underline': u'\u0332', # x̲ COMBINING LOW LINE
+ 'underrightarrow': u'\u20ef', # x⃯ COMBINING RIGHT ARROW BELOW
+ 'vec': u'\u20d7', # x⃗ COMBINING RIGHT ARROW ABOVE
+ 'widehat': u'\u0302', # x̂ COMBINING CIRCUMFLEX ACCENT
+ 'widetilde': u'\u0303', # x̃ COMBINING TILDE
+ }
+mathalpha = {
+ 'Bbbk': u'\U0001d55c', # 𝕜 MATHEMATICAL DOUBLE-STRUCK SMALL K
+ 'Delta': u'\u0394', # Δ GREEK CAPITAL LETTER DELTA
+ 'Gamma': u'\u0393', # Γ GREEK CAPITAL LETTER GAMMA
+ 'Im': u'\u2111', # ℑ BLACK-LETTER CAPITAL I
+ 'Lambda': u'\u039b', # Λ GREEK CAPITAL LETTER LAMDA
+ 'Omega': u'\u03a9', # Ω GREEK CAPITAL LETTER OMEGA
+ 'Phi': u'\u03a6', # Φ GREEK CAPITAL LETTER PHI
+ 'Pi': u'\u03a0', # Π GREEK CAPITAL LETTER PI
+ 'Psi': u'\u03a8', # Ψ GREEK CAPITAL LETTER PSI
+ 'Re': u'\u211c', # ℜ BLACK-LETTER CAPITAL R
+ 'Sigma': u'\u03a3', # Σ GREEK CAPITAL LETTER SIGMA
+ 'Theta': u'\u0398', # Θ GREEK CAPITAL LETTER THETA
+ 'Upsilon': u'\u03a5', # Υ GREEK CAPITAL LETTER UPSILON
+ 'Xi': u'\u039e', # Ξ GREEK CAPITAL LETTER XI
+ 'aleph': u'\u2135', # ℵ ALEF SYMBOL
+ 'alpha': u'\u03b1', # α GREEK SMALL LETTER ALPHA
+ 'beta': u'\u03b2', # β GREEK SMALL LETTER BETA
+ 'beth': u'\u2136', # ℶ BET SYMBOL
+ 'chi': u'\u03c7', # χ GREEK SMALL LETTER CHI
+ 'daleth': u'\u2138', # ℸ DALET SYMBOL
+ 'delta': u'\u03b4', # δ GREEK SMALL LETTER DELTA
+ 'digamma': u'\u03dc', # Ϝ GREEK LETTER DIGAMMA
+ 'ell': u'\u2113', # ℓ SCRIPT SMALL L
+ 'epsilon': u'\u03f5', # ϵ GREEK LUNATE EPSILON SYMBOL
+ 'eta': u'\u03b7', # η GREEK SMALL LETTER ETA
+ 'eth': u'\xf0', # ð LATIN SMALL LETTER ETH
+ 'gamma': u'\u03b3', # γ GREEK SMALL LETTER GAMMA
+ 'gimel': u'\u2137', # ℷ GIMEL SYMBOL
+ 'hbar': u'\u210f', # ℏ PLANCK CONSTANT OVER TWO PI
+ 'hslash': u'\u210f', # ℏ PLANCK CONSTANT OVER TWO PI
+ 'imath': u'\u0131', # ı LATIN SMALL LETTER DOTLESS I
+ 'iota': u'\u03b9', # ι GREEK SMALL LETTER IOTA
+ 'jmath': u'\u0237', # ȷ LATIN SMALL LETTER DOTLESS J
+ 'kappa': u'\u03ba', # κ GREEK SMALL LETTER KAPPA
+ 'lambda': u'\u03bb', # λ GREEK SMALL LETTER LAMDA
+ 'mu': u'\u03bc', # μ GREEK SMALL LETTER MU
+ 'nu': u'\u03bd', # ν GREEK SMALL LETTER NU
+ 'omega': u'\u03c9', # ω GREEK SMALL LETTER OMEGA
+ 'phi': u'\u03d5', # ϕ GREEK PHI SYMBOL
+ 'pi': u'\u03c0', # π GREEK SMALL LETTER PI
+ 'psi': u'\u03c8', # ψ GREEK SMALL LETTER PSI
+ 'rho': u'\u03c1', # ρ GREEK SMALL LETTER RHO
+ 'sigma': u'\u03c3', # σ GREEK SMALL LETTER SIGMA
+ 'tau': u'\u03c4', # τ GREEK SMALL LETTER TAU
+ 'theta': u'\u03b8', # θ GREEK SMALL LETTER THETA
+ 'upsilon': u'\u03c5', # υ GREEK SMALL LETTER UPSILON
+ 'varDelta': u'\U0001d6e5', # 𝛥 MATHEMATICAL ITALIC CAPITAL DELTA
+ 'varGamma': u'\U0001d6e4', # 𝛤 MATHEMATICAL ITALIC CAPITAL GAMMA
+ 'varLambda': u'\U0001d6ec', # 𝛬 MATHEMATICAL ITALIC CAPITAL LAMDA
+ 'varOmega': u'\U0001d6fa', # 𝛺 MATHEMATICAL ITALIC CAPITAL OMEGA
+ 'varPhi': u'\U0001d6f7', # 𝛷 MATHEMATICAL ITALIC CAPITAL PHI
+ 'varPi': u'\U0001d6f1', # 𝛱 MATHEMATICAL ITALIC CAPITAL PI
+ 'varPsi': u'\U0001d6f9', # 𝛹 MATHEMATICAL ITALIC CAPITAL PSI
+ 'varSigma': u'\U0001d6f4', # 𝛴 MATHEMATICAL ITALIC CAPITAL SIGMA
+ 'varTheta': u'\U0001d6e9', # 𝛩 MATHEMATICAL ITALIC CAPITAL THETA
+ 'varUpsilon': u'\U0001d6f6', # 𝛶 MATHEMATICAL ITALIC CAPITAL UPSILON
+ 'varXi': u'\U0001d6ef', # 𝛯 MATHEMATICAL ITALIC CAPITAL XI
+ 'varepsilon': u'\u03b5', # ε GREEK SMALL LETTER EPSILON
+ 'varkappa': u'\U0001d718', # 𝜘 MATHEMATICAL ITALIC KAPPA SYMBOL
+ 'varphi': u'\u03c6', # φ GREEK SMALL LETTER PHI
+ 'varpi': u'\u03d6', # ϖ GREEK PI SYMBOL
+ 'varrho': u'\u03f1', # ϱ GREEK RHO SYMBOL
+ 'varsigma': u'\u03c2', # ς GREEK SMALL LETTER FINAL SIGMA
+ 'vartheta': u'\u03d1', # ϑ GREEK THETA SYMBOL
+ 'wp': u'\u2118', # ℘ SCRIPT CAPITAL P
+ 'xi': u'\u03be', # ξ GREEK SMALL LETTER XI
+ 'zeta': u'\u03b6', # ζ GREEK SMALL LETTER ZETA
+ }
+mathbin = {
+ 'Cap': u'\u22d2', # ⋒ DOUBLE INTERSECTION
+ 'Circle': u'\u25cb', # ○ WHITE CIRCLE
+ 'Cup': u'\u22d3', # ⋓ DOUBLE UNION
+ 'LHD': u'\u25c0', # ◀ BLACK LEFT-POINTING TRIANGLE
+ 'RHD': u'\u25b6', # ▶ BLACK RIGHT-POINTING TRIANGLE
+ 'amalg': u'\u2a3f', # ⨿ AMALGAMATION OR COPRODUCT
+ 'ast': u'\u2217', # ∗ ASTERISK OPERATOR
+ 'barwedge': u'\u22bc', # ⊼ NAND
+ 'bigtriangledown': u'\u25bd', # ▽ WHITE DOWN-POINTING TRIANGLE
+ 'bigtriangleup': u'\u25b3', # △ WHITE UP-POINTING TRIANGLE
+ 'bindnasrepma': u'\u214b', # ⅋ TURNED AMPERSAND
+ 'blacklozenge': u'\u29eb', # ⧫ BLACK LOZENGE
+ 'blacktriangledown': u'\u25be', # ▾ BLACK DOWN-POINTING SMALL TRIANGLE
+ 'blacktriangleleft': u'\u25c2', # ◂ BLACK LEFT-POINTING SMALL TRIANGLE
+ 'blacktriangleright': u'\u25b8', # ▸ BLACK RIGHT-POINTING SMALL TRIANGLE
+ 'blacktriangleup': u'\u25b4', # ▴ BLACK UP-POINTING SMALL TRIANGLE
+ 'boxast': u'\u29c6', # ⧆ SQUARED ASTERISK
+ 'boxbar': u'\u25eb', # ◫ WHITE SQUARE WITH VERTICAL BISECTING LINE
+ 'boxbox': u'\u29c8', # ⧈ SQUARED SQUARE
+ 'boxbslash': u'\u29c5', # ⧅ SQUARED FALLING DIAGONAL SLASH
+ 'boxcircle': u'\u29c7', # ⧇ SQUARED SMALL CIRCLE
+ 'boxdot': u'\u22a1', # ⊡ SQUARED DOT OPERATOR
+ 'boxminus': u'\u229f', # ⊟ SQUARED MINUS
+ 'boxplus': u'\u229e', # ⊞ SQUARED PLUS
+ 'boxslash': u'\u29c4', # ⧄ SQUARED RISING DIAGONAL SLASH
+ 'boxtimes': u'\u22a0', # ⊠ SQUARED TIMES
+ 'bullet': u'\u2219', # ∙ BULLET OPERATOR
+ 'cap': u'\u2229', # ∩ INTERSECTION
+ 'cdot': u'\u22c5', # ⋅ DOT OPERATOR
+ 'circ': u'\u2218', # ∘ RING OPERATOR
+ 'circledast': u'\u229b', # ⊛ CIRCLED ASTERISK OPERATOR
+ 'circledcirc': u'\u229a', # ⊚ CIRCLED RING OPERATOR
+ 'circleddash': u'\u229d', # ⊝ CIRCLED DASH
+ 'cup': u'\u222a', # ∪ UNION
+ 'curlyvee': u'\u22ce', # ⋎ CURLY LOGICAL OR
+ 'curlywedge': u'\u22cf', # ⋏ CURLY LOGICAL AND
+ 'dagger': u'\u2020', # † DAGGER
+ 'ddagger': u'\u2021', # ‡ DOUBLE DAGGER
+ 'diamond': u'\u22c4', # ⋄ DIAMOND OPERATOR
+ 'div': u'\xf7', # ÷ DIVISION SIGN
+ 'divideontimes': u'\u22c7', # ⋇ DIVISION TIMES
+ 'dotplus': u'\u2214', # ∔ DOT PLUS
+ 'doublebarwedge': u'\u2a5e', # ⩞ LOGICAL AND WITH DOUBLE OVERBAR
+ 'intercal': u'\u22ba', # ⊺ INTERCALATE
+ 'interleave': u'\u2af4', # ⫴ TRIPLE VERTICAL BAR BINARY RELATION
+ 'land': u'\u2227', # ∧ LOGICAL AND
+ 'leftthreetimes': u'\u22cb', # ⋋ LEFT SEMIDIRECT PRODUCT
+ 'lhd': u'\u25c1', # ◁ WHITE LEFT-POINTING TRIANGLE
+ 'lor': u'\u2228', # ∨ LOGICAL OR
+ 'ltimes': u'\u22c9', # ⋉ LEFT NORMAL FACTOR SEMIDIRECT PRODUCT
+ 'mp': u'\u2213', # ∓ MINUS-OR-PLUS SIGN
+ 'odot': u'\u2299', # ⊙ CIRCLED DOT OPERATOR
+ 'ominus': u'\u2296', # ⊖ CIRCLED MINUS
+ 'oplus': u'\u2295', # ⊕ CIRCLED PLUS
+ 'oslash': u'\u2298', # ⊘ CIRCLED DIVISION SLASH
+ 'otimes': u'\u2297', # ⊗ CIRCLED TIMES
+ 'pm': u'\xb1', # ± PLUS-MINUS SIGN
+ 'rhd': u'\u25b7', # ▷ WHITE RIGHT-POINTING TRIANGLE
+ 'rightthreetimes': u'\u22cc', # ⋌ RIGHT SEMIDIRECT PRODUCT
+ 'rtimes': u'\u22ca', # ⋊ RIGHT NORMAL FACTOR SEMIDIRECT PRODUCT
+ 'setminus': u'\u29f5', # ⧵ REVERSE SOLIDUS OPERATOR
+ 'slash': u'\u2215', # ∕ DIVISION SLASH
+ 'smallsetminus': u'\u2216', # ∖ SET MINUS
+ 'smalltriangledown': u'\u25bf', # ▿ WHITE DOWN-POINTING SMALL TRIANGLE
+ 'smalltriangleleft': u'\u25c3', # ◃ WHITE LEFT-POINTING SMALL TRIANGLE
+ 'smalltriangleright': u'\u25b9', # ▹ WHITE RIGHT-POINTING SMALL TRIANGLE
+ 'smalltriangleup': u'\u25b5', # ▵ WHITE UP-POINTING SMALL TRIANGLE
+ 'sqcap': u'\u2293', # ⊓ SQUARE CAP
+ 'sqcup': u'\u2294', # ⊔ SQUARE CUP
+ 'sslash': u'\u2afd', # ⫽ DOUBLE SOLIDUS OPERATOR
+ 'star': u'\u22c6', # ⋆ STAR OPERATOR
+ 'talloblong': u'\u2afe', # ⫾ WHITE VERTICAL BAR
+ 'times': u'\xd7', # × MULTIPLICATION SIGN
+ 'triangle': u'\u25b3', # △ WHITE UP-POINTING TRIANGLE
+ 'triangledown': u'\u25bf', # ▿ WHITE DOWN-POINTING SMALL TRIANGLE
+ 'triangleleft': u'\u25c3', # ◃ WHITE LEFT-POINTING SMALL TRIANGLE
+ 'triangleright': u'\u25b9', # ▹ WHITE RIGHT-POINTING SMALL TRIANGLE
+ 'uplus': u'\u228e', # ⊎ MULTISET UNION
+ 'vartriangle': u'\u25b3', # △ WHITE UP-POINTING TRIANGLE
+ 'vee': u'\u2228', # ∨ LOGICAL OR
+ 'veebar': u'\u22bb', # ⊻ XOR
+ 'wedge': u'\u2227', # ∧ LOGICAL AND
+ 'wr': u'\u2240', # ≀ WREATH PRODUCT
+ }
+mathclose = {
+ 'Rbag': u'\u27c6', # ⟆ RIGHT S-SHAPED BAG DELIMITER
+ 'lrcorner': u'\u231f', # ⌟ BOTTOM RIGHT CORNER
+ 'rangle': u'\u27e9', # ⟩ MATHEMATICAL RIGHT ANGLE BRACKET
+ 'rbag': u'\u27c6', # ⟆ RIGHT S-SHAPED BAG DELIMITER
+ 'rbrace': u'}', # } RIGHT CURLY BRACKET
+ 'rbrack': u']', # ] RIGHT SQUARE BRACKET
+ 'rceil': u'\u2309', # ⌉ RIGHT CEILING
+ 'rfloor': u'\u230b', # ⌋ RIGHT FLOOR
+ 'rgroup': u'\u27ef', # ⟯ MATHEMATICAL RIGHT FLATTENED PARENTHESIS
+ 'rrbracket': u'\u27e7', # ⟧ MATHEMATICAL RIGHT WHITE SQUARE BRACKET
+ 'rrparenthesis': u'\u2988', # ⦈ Z NOTATION RIGHT IMAGE BRACKET
+ 'urcorner': u'\u231d', # ⌝ TOP RIGHT CORNER
+ '}': u'}', # } RIGHT CURLY BRACKET
+ }
+mathfence = {
+ 'Vert': u'\u2016', # ‖ DOUBLE VERTICAL LINE
+ 'vert': u'|', # | VERTICAL LINE
+ '|': u'\u2016', # ‖ DOUBLE VERTICAL LINE
+ }
+mathop = {
+ 'Join': u'\u2a1d', # ⨝ JOIN
+ 'bigcap': u'\u22c2', # ⋂ N-ARY INTERSECTION
+ 'bigcup': u'\u22c3', # ⋃ N-ARY UNION
+ 'biginterleave': u'\u2afc', # ⫼ LARGE TRIPLE VERTICAL BAR OPERATOR
+ 'bigodot': u'\u2a00', # ⨀ N-ARY CIRCLED DOT OPERATOR
+ 'bigoplus': u'\u2a01', # ⨁ N-ARY CIRCLED PLUS OPERATOR
+ 'bigotimes': u'\u2a02', # ⨂ N-ARY CIRCLED TIMES OPERATOR
+ 'bigsqcup': u'\u2a06', # ⨆ N-ARY SQUARE UNION OPERATOR
+ 'biguplus': u'\u2a04', # ⨄ N-ARY UNION OPERATOR WITH PLUS
+ 'bigvee': u'\u22c1', # ⋁ N-ARY LOGICAL OR
+ 'bigwedge': u'\u22c0', # ⋀ N-ARY LOGICAL AND
+ 'coprod': u'\u2210', # ∐ N-ARY COPRODUCT
+ 'fatsemi': u'\u2a1f', # ⨟ Z NOTATION SCHEMA COMPOSITION
+ 'fint': u'\u2a0f', # ⨏ INTEGRAL AVERAGE WITH SLASH
+ 'iiiint': u'\u2a0c', # ⨌ QUADRUPLE INTEGRAL OPERATOR
+ 'iiint': u'\u222d', # ∭ TRIPLE INTEGRAL
+ 'iint': u'\u222c', # ∬ DOUBLE INTEGRAL
+ 'int': u'\u222b', # ∫ INTEGRAL
+ 'oiint': u'\u222f', # ∯ SURFACE INTEGRAL
+ 'oint': u'\u222e', # ∮ CONTOUR INTEGRAL
+ 'ointctrclockwise': u'\u2233', # ∳ ANTICLOCKWISE CONTOUR INTEGRAL
+ 'prod': u'\u220f', # ∏ N-ARY PRODUCT
+ 'sqint': u'\u2a16', # ⨖ QUATERNION INTEGRAL OPERATOR
+ 'sum': u'\u2211', # ∑ N-ARY SUMMATION
+ 'varointclockwise': u'\u2232', # ∲ CLOCKWISE CONTOUR INTEGRAL
+ }
+mathopen = {
+ 'Lbag': u'\u27c5', # ⟅ LEFT S-SHAPED BAG DELIMITER
+ 'langle': u'\u27e8', # ⟨ MATHEMATICAL LEFT ANGLE BRACKET
+ 'lbag': u'\u27c5', # ⟅ LEFT S-SHAPED BAG DELIMITER
+ 'lbrace': u'{', # { LEFT CURLY BRACKET
+ 'lbrack': u'[', # [ LEFT SQUARE BRACKET
+ 'lceil': u'\u2308', # ⌈ LEFT CEILING
+ 'lfloor': u'\u230a', # ⌊ LEFT FLOOR
+ 'lgroup': u'\u27ee', # ⟮ MATHEMATICAL LEFT FLATTENED PARENTHESIS
+ 'llbracket': u'\u27e6', # ⟦ MATHEMATICAL LEFT WHITE SQUARE BRACKET
+ 'llcorner': u'\u231e', # ⌞ BOTTOM LEFT CORNER
+ 'llparenthesis': u'\u2987', # ⦇ Z NOTATION LEFT IMAGE BRACKET
+ 'ulcorner': u'\u231c', # ⌜ TOP LEFT CORNER
+ '{': u'{', # { LEFT CURLY BRACKET
+ }
+mathord = {
+ '#': u'#', # # NUMBER SIGN
+ '$': u'$', # $ DOLLAR SIGN
+ '%': u'%', # % PERCENT SIGN
+ '&': u'&', # & AMPERSAND
+ 'AC': u'\u223f', # ∿ SINE WAVE
+ 'APLcomment': u'\u235d', # ⍝ APL FUNCTIONAL SYMBOL UP SHOE JOT
+ 'APLdownarrowbox': u'\u2357', # ⍗ APL FUNCTIONAL SYMBOL QUAD DOWNWARDS ARROW
+ 'APLinput': u'\u235e', # ⍞ APL FUNCTIONAL SYMBOL QUOTE QUAD
+ 'APLinv': u'\u2339', # ⌹ APL FUNCTIONAL SYMBOL QUAD DIVIDE
+ 'APLleftarrowbox': u'\u2347', # ⍇ APL FUNCTIONAL SYMBOL QUAD LEFTWARDS ARROW
+ 'APLlog': u'\u235f', # ⍟ APL FUNCTIONAL SYMBOL CIRCLE STAR
+ 'APLrightarrowbox': u'\u2348', # ⍈ APL FUNCTIONAL SYMBOL QUAD RIGHTWARDS ARROW
+ 'APLuparrowbox': u'\u2350', # ⍐ APL FUNCTIONAL SYMBOL QUAD UPWARDS ARROW
+ 'Aries': u'\u2648', # ♈ ARIES
+ 'CIRCLE': u'\u25cf', # ● BLACK CIRCLE
+ 'CheckedBox': u'\u2611', # ☑ BALLOT BOX WITH CHECK
+ 'Diamond': u'\u25c7', # ◇ WHITE DIAMOND
+ 'Finv': u'\u2132', # Ⅎ TURNED CAPITAL F
+ 'Game': u'\u2141', # ⅁ TURNED SANS-SERIF CAPITAL G
+ 'Gemini': u'\u264a', # ♊ GEMINI
+ 'Jupiter': u'\u2643', # ♃ JUPITER
+ 'LEFTCIRCLE': u'\u25d6', # ◖ LEFT HALF BLACK CIRCLE
+ 'LEFTcircle': u'\u25d0', # ◐ CIRCLE WITH LEFT HALF BLACK
+ 'Leo': u'\u264c', # ♌ LEO
+ 'Libra': u'\u264e', # ♎ LIBRA
+ 'Mars': u'\u2642', # ♂ MALE SIGN
+ 'Mercury': u'\u263f', # ☿ MERCURY
+ 'Neptune': u'\u2646', # ♆ NEPTUNE
+ 'Pluto': u'\u2647', # ♇ PLUTO
+ 'RIGHTCIRCLE': u'\u25d7', # ◗ RIGHT HALF BLACK CIRCLE
+ 'RIGHTcircle': u'\u25d1', # ◑ CIRCLE WITH RIGHT HALF BLACK
+ 'Saturn': u'\u2644', # ♄ SATURN
+ 'Scorpio': u'\u264f', # ♏ SCORPIUS
+ 'Square': u'\u2610', # ☐ BALLOT BOX
+ 'Sun': u'\u2609', # ☉ SUN
+ 'Taurus': u'\u2649', # ♉ TAURUS
+ 'Uranus': u'\u2645', # ♅ URANUS
+ 'Venus': u'\u2640', # ♀ FEMALE SIGN
+ 'XBox': u'\u2612', # ☒ BALLOT BOX WITH X
+ 'Yup': u'\u2144', # ⅄ TURNED SANS-SERIF CAPITAL Y
+ '_': u'_', # _ LOW LINE
+ 'angle': u'\u2220', # ∠ ANGLE
+ 'aquarius': u'\u2652', # ♒ AQUARIUS
+ 'aries': u'\u2648', # ♈ ARIES
+ 'ast': u'*', # * ASTERISK
+ 'backepsilon': u'\u03f6', # ϶ GREEK REVERSED LUNATE EPSILON SYMBOL
+ 'backprime': u'\u2035', # ‵ REVERSED PRIME
+ 'backslash': u'\\', # \ REVERSE SOLIDUS
+ 'because': u'\u2235', # ∵ BECAUSE
+ 'bigstar': u'\u2605', # ★ BLACK STAR
+ 'binampersand': u'&', # & AMPERSAND
+ 'blacklozenge': u'\u2b27', # ⬧ BLACK MEDIUM LOZENGE
+ 'blacksmiley': u'\u263b', # ☻ BLACK SMILING FACE
+ 'blacksquare': u'\u25fc', # ◼ BLACK MEDIUM SQUARE
+ 'bot': u'\u22a5', # ⊥ UP TACK
+ 'boy': u'\u2642', # ♂ MALE SIGN
+ 'cancer': u'\u264b', # ♋ CANCER
+ 'capricornus': u'\u2651', # ♑ CAPRICORN
+ 'cdots': u'\u22ef', # ⋯ MIDLINE HORIZONTAL ELLIPSIS
+ 'cent': u'\xa2', # ¢ CENT SIGN
+ 'centerdot': u'\u2b1d', # ⬝ BLACK VERY SMALL SQUARE
+ 'checkmark': u'\u2713', # ✓ CHECK MARK
+ 'circlearrowleft': u'\u21ba', # ↺ ANTICLOCKWISE OPEN CIRCLE ARROW
+ 'circlearrowright': u'\u21bb', # ↻ CLOCKWISE OPEN CIRCLE ARROW
+ 'circledR': u'\xae', # ® REGISTERED SIGN
+ 'circledcirc': u'\u25ce', # ◎ BULLSEYE
+ 'clubsuit': u'\u2663', # ♣ BLACK CLUB SUIT
+ 'complement': u'\u2201', # ∁ COMPLEMENT
+ 'dasharrow': u'\u21e2', # ⇢ RIGHTWARDS DASHED ARROW
+ 'dashleftarrow': u'\u21e0', # ⇠ LEFTWARDS DASHED ARROW
+ 'dashrightarrow': u'\u21e2', # ⇢ RIGHTWARDS DASHED ARROW
+ 'diameter': u'\u2300', # ⌀ DIAMETER SIGN
+ 'diamondsuit': u'\u2662', # ♢ WHITE DIAMOND SUIT
+ 'earth': u'\u2641', # ♁ EARTH
+ 'exists': u'\u2203', # ∃ THERE EXISTS
+ 'female': u'\u2640', # ♀ FEMALE SIGN
+ 'flat': u'\u266d', # ♭ MUSIC FLAT SIGN
+ 'forall': u'\u2200', # ∀ FOR ALL
+ 'fourth': u'\u2057', # ⁗ QUADRUPLE PRIME
+ 'frownie': u'\u2639', # ☹ WHITE FROWNING FACE
+ 'gemini': u'\u264a', # ♊ GEMINI
+ 'girl': u'\u2640', # ♀ FEMALE SIGN
+ 'heartsuit': u'\u2661', # ♡ WHITE HEART SUIT
+ 'infty': u'\u221e', # ∞ INFINITY
+ 'invneg': u'\u2310', # ⌐ REVERSED NOT SIGN
+ 'jupiter': u'\u2643', # ♃ JUPITER
+ 'ldots': u'\u2026', # … HORIZONTAL ELLIPSIS
+ 'leftmoon': u'\u263e', # ☾ LAST QUARTER MOON
+ 'leftturn': u'\u21ba', # ↺ ANTICLOCKWISE OPEN CIRCLE ARROW
+ 'leo': u'\u264c', # ♌ LEO
+ 'libra': u'\u264e', # ♎ LIBRA
+ 'lnot': u'\xac', # ¬ NOT SIGN
+ 'lozenge': u'\u25ca', # ◊ LOZENGE
+ 'male': u'\u2642', # ♂ MALE SIGN
+ 'maltese': u'\u2720', # ✠ MALTESE CROSS
+ 'mathdollar': u'$', # $ DOLLAR SIGN
+ 'measuredangle': u'\u2221', # ∡ MEASURED ANGLE
+ 'mercury': u'\u263f', # ☿ MERCURY
+ 'mho': u'\u2127', # ℧ INVERTED OHM SIGN
+ 'nabla': u'\u2207', # ∇ NABLA
+ 'natural': u'\u266e', # ♮ MUSIC NATURAL SIGN
+ 'neg': u'\xac', # ¬ NOT SIGN
+ 'neptune': u'\u2646', # ♆ NEPTUNE
+ 'nexists': u'\u2204', # ∄ THERE DOES NOT EXIST
+ 'notbackslash': u'\u2340', # ⍀ APL FUNCTIONAL SYMBOL BACKSLASH BAR
+ 'partial': u'\u2202', # ∂ PARTIAL DIFFERENTIAL
+ 'pisces': u'\u2653', # ♓ PISCES
+ 'pluto': u'\u2647', # ♇ PLUTO
+ 'pounds': u'\xa3', # £ POUND SIGN
+ 'prime': u'\u2032', # ′ PRIME
+ 'quarternote': u'\u2669', # ♩ QUARTER NOTE
+ 'rightmoon': u'\u263d', # ☽ FIRST QUARTER MOON
+ 'rightturn': u'\u21bb', # ↻ CLOCKWISE OPEN CIRCLE ARROW
+ 'sagittarius': u'\u2650', # ♐ SAGITTARIUS
+ 'saturn': u'\u2644', # ♄ SATURN
+ 'scorpio': u'\u264f', # ♏ SCORPIUS
+ 'second': u'\u2033', # ″ DOUBLE PRIME
+ 'sharp': u'\u266f', # ♯ MUSIC SHARP SIGN
+ 'sim': u'~', # ~ TILDE
+ 'slash': u'/', # / SOLIDUS
+ 'smiley': u'\u263a', # ☺ WHITE SMILING FACE
+ 'spadesuit': u'\u2660', # ♠ BLACK SPADE SUIT
+ 'spddot': u'\xa8', # ¨ DIAERESIS
+ 'sphat': u'^', # ^ CIRCUMFLEX ACCENT
+ 'sphericalangle': u'\u2222', # ∢ SPHERICAL ANGLE
+ 'sptilde': u'~', # ~ TILDE
+ 'square': u'\u25fb', # ◻ WHITE MEDIUM SQUARE
+ 'sun': u'\u263c', # ☼ WHITE SUN WITH RAYS
+ 'taurus': u'\u2649', # ♉ TAURUS
+ 'therefore': u'\u2234', # ∴ THEREFORE
+ 'third': u'\u2034', # ‴ TRIPLE PRIME
+ 'top': u'\u22a4', # ⊤ DOWN TACK
+ 'triangleleft': u'\u25c5', # ◅ WHITE LEFT-POINTING POINTER
+ 'triangleright': u'\u25bb', # ▻ WHITE RIGHT-POINTING POINTER
+ 'twonotes': u'\u266b', # ♫ BEAMED EIGHTH NOTES
+ 'uranus': u'\u2645', # ♅ URANUS
+ 'varEarth': u'\u2641', # ♁ EARTH
+ 'varnothing': u'\u2205', # ∅ EMPTY SET
+ 'virgo': u'\u264d', # ♍ VIRGO
+ 'wasylozenge': u'\u2311', # ⌑ SQUARE LOZENGE
+ 'wasytherefore': u'\u2234', # ∴ THEREFORE
+ 'yen': u'\xa5', # ¥ YEN SIGN
+ }
+mathover = {
+ 'overbrace': u'\u23de', # ⏞ TOP CURLY BRACKET
+ 'wideparen': u'\u23dc', # ⏜ TOP PARENTHESIS
+ }
+mathradical = {
+ 'sqrt': u'\u221a', # √ SQUARE ROOT
+ 'sqrt[3]': u'\u221b', # ∛ CUBE ROOT
+ 'sqrt[4]': u'\u221c', # ∜ FOURTH ROOT
+ }
+mathrel = {
+ 'Bumpeq': u'\u224e', # ≎ GEOMETRICALLY EQUIVALENT TO
+ 'Doteq': u'\u2251', # ≑ GEOMETRICALLY EQUAL TO
+ 'Downarrow': u'\u21d3', # ⇓ DOWNWARDS DOUBLE ARROW
+ 'Leftarrow': u'\u21d0', # ⇐ LEFTWARDS DOUBLE ARROW
+ 'Leftrightarrow': u'\u21d4', # ⇔ LEFT RIGHT DOUBLE ARROW
+ 'Lleftarrow': u'\u21da', # ⇚ LEFTWARDS TRIPLE ARROW
+ 'Longleftarrow': u'\u27f8', # ⟸ LONG LEFTWARDS DOUBLE ARROW
+ 'Longleftrightarrow': u'\u27fa', # ⟺ LONG LEFT RIGHT DOUBLE ARROW
+ 'Longmapsfrom': u'\u27fd', # ⟽ LONG LEFTWARDS DOUBLE ARROW FROM BAR
+ 'Longmapsto': u'\u27fe', # ⟾ LONG RIGHTWARDS DOUBLE ARROW FROM BAR
+ 'Longrightarrow': u'\u27f9', # ⟹ LONG RIGHTWARDS DOUBLE ARROW
+ 'Lsh': u'\u21b0', # ↰ UPWARDS ARROW WITH TIP LEFTWARDS
+ 'Mapsfrom': u'\u2906', # ⤆ LEFTWARDS DOUBLE ARROW FROM BAR
+ 'Mapsto': u'\u2907', # ⤇ RIGHTWARDS DOUBLE ARROW FROM BAR
+ 'Rightarrow': u'\u21d2', # ⇒ RIGHTWARDS DOUBLE ARROW
+ 'Rrightarrow': u'\u21db', # ⇛ RIGHTWARDS TRIPLE ARROW
+ 'Rsh': u'\u21b1', # ↱ UPWARDS ARROW WITH TIP RIGHTWARDS
+ 'Subset': u'\u22d0', # ⋐ DOUBLE SUBSET
+ 'Supset': u'\u22d1', # ⋑ DOUBLE SUPERSET
+ 'Uparrow': u'\u21d1', # ⇑ UPWARDS DOUBLE ARROW
+ 'Updownarrow': u'\u21d5', # ⇕ UP DOWN DOUBLE ARROW
+ 'VDash': u'\u22ab', # ⊫ DOUBLE VERTICAL BAR DOUBLE RIGHT TURNSTILE
+ 'Vdash': u'\u22a9', # ⊩ FORCES
+ 'Vvdash': u'\u22aa', # ⊪ TRIPLE VERTICAL BAR RIGHT TURNSTILE
+ 'apprge': u'\u2273', # ≳ GREATER-THAN OR EQUIVALENT TO
+ 'apprle': u'\u2272', # ≲ LESS-THAN OR EQUIVALENT TO
+ 'approx': u'\u2248', # ≈ ALMOST EQUAL TO
+ 'approxeq': u'\u224a', # ≊ ALMOST EQUAL OR EQUAL TO
+ 'asymp': u'\u224d', # ≍ EQUIVALENT TO
+ 'backsim': u'\u223d', # ∽ REVERSED TILDE
+ 'backsimeq': u'\u22cd', # ⋍ REVERSED TILDE EQUALS
+ 'barin': u'\u22f6', # ⋶ ELEMENT OF WITH OVERBAR
+ 'barleftharpoon': u'\u296b', # ⥫ LEFTWARDS HARPOON WITH BARB DOWN BELOW LONG DASH
+ 'barrightharpoon': u'\u296d', # ⥭ RIGHTWARDS HARPOON WITH BARB DOWN BELOW LONG DASH
+ 'between': u'\u226c', # ≬ BETWEEN
+ 'bowtie': u'\u22c8', # ⋈ BOWTIE
+ 'bumpeq': u'\u224f', # ≏ DIFFERENCE BETWEEN
+ 'circeq': u'\u2257', # ≗ RING EQUAL TO
+ 'coloneq': u'\u2254', # ≔ COLON EQUALS
+ 'cong': u'\u2245', # ≅ APPROXIMATELY EQUAL TO
+ 'corresponds': u'\u2259', # ≙ ESTIMATES
+ 'curlyeqprec': u'\u22de', # ⋞ EQUAL TO OR PRECEDES
+ 'curlyeqsucc': u'\u22df', # ⋟ EQUAL TO OR SUCCEEDS
+ 'curvearrowleft': u'\u21b6', # ↶ ANTICLOCKWISE TOP SEMICIRCLE ARROW
+ 'curvearrowright': u'\u21b7', # ↷ CLOCKWISE TOP SEMICIRCLE ARROW
+ 'dashv': u'\u22a3', # ⊣ LEFT TACK
+ 'ddots': u'\u22f1', # ⋱ DOWN RIGHT DIAGONAL ELLIPSIS
+ 'dlsh': u'\u21b2', # ↲ DOWNWARDS ARROW WITH TIP LEFTWARDS
+ 'doteq': u'\u2250', # ≐ APPROACHES THE LIMIT
+ 'doteqdot': u'\u2251', # ≑ GEOMETRICALLY EQUAL TO
+ 'downarrow': u'\u2193', # ↓ DOWNWARDS ARROW
+ 'downdownarrows': u'\u21ca', # ⇊ DOWNWARDS PAIRED ARROWS
+ 'downdownharpoons': u'\u2965', # ⥥ DOWNWARDS HARPOON WITH BARB LEFT BESIDE DOWNWARDS HARPOON WITH BARB RIGHT
+ 'downharpoonleft': u'\u21c3', # ⇃ DOWNWARDS HARPOON WITH BARB LEFTWARDS
+ 'downharpoonright': u'\u21c2', # ⇂ DOWNWARDS HARPOON WITH BARB RIGHTWARDS
+ 'downuparrows': u'\u21f5', # ⇵ DOWNWARDS ARROW LEFTWARDS OF UPWARDS ARROW
+ 'downupharpoons': u'\u296f', # ⥯ DOWNWARDS HARPOON WITH BARB LEFT BESIDE UPWARDS HARPOON WITH BARB RIGHT
+ 'drsh': u'\u21b3', # ↳ DOWNWARDS ARROW WITH TIP RIGHTWARDS
+ 'eqcirc': u'\u2256', # ≖ RING IN EQUAL TO
+ 'eqcolon': u'\u2255', # ≕ EQUALS COLON
+ 'eqsim': u'\u2242', # ≂ MINUS TILDE
+ 'eqslantgtr': u'\u2a96', # ⪖ SLANTED EQUAL TO OR GREATER-THAN
+ 'eqslantless': u'\u2a95', # ⪕ SLANTED EQUAL TO OR LESS-THAN
+ 'equiv': u'\u2261', # ≡ IDENTICAL TO
+ 'fallingdotseq': u'\u2252', # ≒ APPROXIMATELY EQUAL TO OR THE IMAGE OF
+ 'frown': u'\u2322', # ⌢ FROWN
+ 'ge': u'\u2265', # ≥ GREATER-THAN OR EQUAL TO
+ 'geq': u'\u2265', # ≥ GREATER-THAN OR EQUAL TO
+ 'geqq': u'\u2267', # ≧ GREATER-THAN OVER EQUAL TO
+ 'geqslant': u'\u2a7e', # ⩾ GREATER-THAN OR SLANTED EQUAL TO
+ 'gets': u'\u2190', # ← LEFTWARDS ARROW
+ 'gg': u'\u226b', # ≫ MUCH GREATER-THAN
+ 'ggcurly': u'\u2abc', # ⪼ DOUBLE SUCCEEDS
+ 'ggg': u'\u22d9', # ⋙ VERY MUCH GREATER-THAN
+ 'gnapprox': u'\u2a8a', # ⪊ GREATER-THAN AND NOT APPROXIMATE
+ 'gneq': u'\u2a88', # ⪈ GREATER-THAN AND SINGLE-LINE NOT EQUAL TO
+ 'gneqq': u'\u2269', # ≩ GREATER-THAN BUT NOT EQUAL TO
+ 'gnsim': u'\u22e7', # ⋧ GREATER-THAN BUT NOT EQUIVALENT TO
+ 'gtrapprox': u'\u2a86', # ⪆ GREATER-THAN OR APPROXIMATE
+ 'gtrdot': u'\u22d7', # ⋗ GREATER-THAN WITH DOT
+ 'gtreqless': u'\u22db', # ⋛ GREATER-THAN EQUAL TO OR LESS-THAN
+ 'gtreqqless': u'\u2a8c', # ⪌ GREATER-THAN ABOVE DOUBLE-LINE EQUAL ABOVE LESS-THAN
+ 'gtrless': u'\u2277', # ≷ GREATER-THAN OR LESS-THAN
+ 'gtrsim': u'\u2273', # ≳ GREATER-THAN OR EQUIVALENT TO
+ 'hash': u'\u22d5', # ⋕ EQUAL AND PARALLEL TO
+ 'hookleftarrow': u'\u21a9', # ↩ LEFTWARDS ARROW WITH HOOK
+ 'hookrightarrow': u'\u21aa', # ↪ RIGHTWARDS ARROW WITH HOOK
+ 'iddots': u'\u22f0', # ⋰ UP RIGHT DIAGONAL ELLIPSIS
+ 'impliedby': u'\u27f8', # ⟸ LONG LEFTWARDS DOUBLE ARROW
+ 'implies': u'\u27f9', # ⟹ LONG RIGHTWARDS DOUBLE ARROW
+ 'in': u'\u2208', # ∈ ELEMENT OF
+ 'le': u'\u2264', # ≤ LESS-THAN OR EQUAL TO
+ 'leftarrow': u'\u2190', # ← LEFTWARDS ARROW
+ 'leftarrowtail': u'\u21a2', # ↢ LEFTWARDS ARROW WITH TAIL
+ 'leftarrowtriangle': u'\u21fd', # ⇽ LEFTWARDS OPEN-HEADED ARROW
+ 'leftbarharpoon': u'\u296a', # ⥪ LEFTWARDS HARPOON WITH BARB UP ABOVE LONG DASH
+ 'leftharpoondown': u'\u21bd', # ↽ LEFTWARDS HARPOON WITH BARB DOWNWARDS
+ 'leftharpoonup': u'\u21bc', # ↼ LEFTWARDS HARPOON WITH BARB UPWARDS
+ 'leftleftarrows': u'\u21c7', # ⇇ LEFTWARDS PAIRED ARROWS
+ 'leftleftharpoons': u'\u2962', # ⥢ LEFTWARDS HARPOON WITH BARB UP ABOVE LEFTWARDS HARPOON WITH BARB DOWN
+ 'leftrightarrow': u'\u2194', # ↔ LEFT RIGHT ARROW
+ 'leftrightarrows': u'\u21c6', # ⇆ LEFTWARDS ARROW OVER RIGHTWARDS ARROW
+ 'leftrightarrowtriangle': u'\u21ff', # ⇿ LEFT RIGHT OPEN-HEADED ARROW
+ 'leftrightharpoon': u'\u294a', # ⥊ LEFT BARB UP RIGHT BARB DOWN HARPOON
+ 'leftrightharpoons': u'\u21cb', # ⇋ LEFTWARDS HARPOON OVER RIGHTWARDS HARPOON
+ 'leftrightsquigarrow': u'\u21ad', # ↭ LEFT RIGHT WAVE ARROW
+ 'leftslice': u'\u2aa6', # ⪦ LESS-THAN CLOSED BY CURVE
+ 'leftsquigarrow': u'\u21dc', # ⇜ LEFTWARDS SQUIGGLE ARROW
+ 'leq': u'\u2264', # ≤ LESS-THAN OR EQUAL TO
+ 'leqq': u'\u2266', # ≦ LESS-THAN OVER EQUAL TO
+ 'leqslant': u'\u2a7d', # ⩽ LESS-THAN OR SLANTED EQUAL TO
+ 'lessapprox': u'\u2a85', # ⪅ LESS-THAN OR APPROXIMATE
+ 'lessdot': u'\u22d6', # ⋖ LESS-THAN WITH DOT
+ 'lesseqgtr': u'\u22da', # ⋚ LESS-THAN EQUAL TO OR GREATER-THAN
+ 'lesseqqgtr': u'\u2a8b', # ⪋ LESS-THAN ABOVE DOUBLE-LINE EQUAL ABOVE GREATER-THAN
+ 'lessgtr': u'\u2276', # ≶ LESS-THAN OR GREATER-THAN
+ 'lesssim': u'\u2272', # ≲ LESS-THAN OR EQUIVALENT TO
+ 'lightning': u'\u21af', # ↯ DOWNWARDS ZIGZAG ARROW
+ 'll': u'\u226a', # ≪ MUCH LESS-THAN
+ 'llcurly': u'\u2abb', # ⪻ DOUBLE PRECEDES
+ 'lll': u'\u22d8', # ⋘ VERY MUCH LESS-THAN
+ 'lnapprox': u'\u2a89', # ⪉ LESS-THAN AND NOT APPROXIMATE
+ 'lneq': u'\u2a87', # ⪇ LESS-THAN AND SINGLE-LINE NOT EQUAL TO
+ 'lneqq': u'\u2268', # ≨ LESS-THAN BUT NOT EQUAL TO
+ 'lnsim': u'\u22e6', # ⋦ LESS-THAN BUT NOT EQUIVALENT TO
+ 'longleftarrow': u'\u27f5', # ⟵ LONG LEFTWARDS ARROW
+ 'longleftrightarrow': u'\u27f7', # ⟷ LONG LEFT RIGHT ARROW
+ 'longmapsfrom': u'\u27fb', # ⟻ LONG LEFTWARDS ARROW FROM BAR
+ 'longmapsto': u'\u27fc', # ⟼ LONG RIGHTWARDS ARROW FROM BAR
+ 'longrightarrow': u'\u27f6', # ⟶ LONG RIGHTWARDS ARROW
+ 'looparrowleft': u'\u21ab', # ↫ LEFTWARDS ARROW WITH LOOP
+ 'looparrowright': u'\u21ac', # ↬ RIGHTWARDS ARROW WITH LOOP
+ 'mapsfrom': u'\u21a4', # ↤ LEFTWARDS ARROW FROM BAR
+ 'mapsto': u'\u21a6', # ↦ RIGHTWARDS ARROW FROM BAR
+ 'mid': u'\u2223', # ∣ DIVIDES
+ 'models': u'\u22a7', # ⊧ MODELS
+ 'multimap': u'\u22b8', # ⊸ MULTIMAP
+ 'nLeftarrow': u'\u21cd', # ⇍ LEFTWARDS DOUBLE ARROW WITH STROKE
+ 'nLeftrightarrow': u'\u21ce', # ⇎ LEFT RIGHT DOUBLE ARROW WITH STROKE
+ 'nRightarrow': u'\u21cf', # ⇏ RIGHTWARDS DOUBLE ARROW WITH STROKE
+ 'nVDash': u'\u22af', # ⊯ NEGATED DOUBLE VERTICAL BAR DOUBLE RIGHT TURNSTILE
+ 'nVdash': u'\u22ae', # ⊮ DOES NOT FORCE
+ 'ncong': u'\u2247', # ≇ NEITHER APPROXIMATELY NOR ACTUALLY EQUAL TO
+ 'ne': u'\u2260', # ≠ NOT EQUAL TO
+ 'nearrow': u'\u2197', # ↗ NORTH EAST ARROW
+ 'neq': u'\u2260', # ≠ NOT EQUAL TO
+ 'ngeq': u'\u2271', # ≱ NEITHER GREATER-THAN NOR EQUAL TO
+ 'ngtr': u'\u226f', # ≯ NOT GREATER-THAN
+ 'ni': u'\u220b', # ∋ CONTAINS AS MEMBER
+ 'nleftarrow': u'\u219a', # ↚ LEFTWARDS ARROW WITH STROKE
+ 'nleftrightarrow': u'\u21ae', # ↮ LEFT RIGHT ARROW WITH STROKE
+ 'nleq': u'\u2270', # ≰ NEITHER LESS-THAN NOR EQUAL TO
+ 'nless': u'\u226e', # ≮ NOT LESS-THAN
+ 'nmid': u'\u2224', # ∤ DOES NOT DIVIDE
+ 'notasymp': u'\u226d', # ≭ NOT EQUIVALENT TO
+ 'notin': u'\u2209', # ∉ NOT AN ELEMENT OF
+ 'notowner': u'\u220c', # ∌ DOES NOT CONTAIN AS MEMBER
+ 'notslash': u'\u233f', # ⌿ APL FUNCTIONAL SYMBOL SLASH BAR
+ 'nparallel': u'\u2226', # ∦ NOT PARALLEL TO
+ 'nprec': u'\u2280', # ⊀ DOES NOT PRECEDE
+ 'npreceq': u'\u22e0', # ⋠ DOES NOT PRECEDE OR EQUAL
+ 'nrightarrow': u'\u219b', # ↛ RIGHTWARDS ARROW WITH STROKE
+ 'nsim': u'\u2241', # ≁ NOT TILDE
+ 'nsubseteq': u'\u2288', # ⊈ NEITHER A SUBSET OF NOR EQUAL TO
+ 'nsucc': u'\u2281', # ⊁ DOES NOT SUCCEED
+ 'nsucceq': u'\u22e1', # ⋡ DOES NOT SUCCEED OR EQUAL
+ 'nsupseteq': u'\u2289', # ⊉ NEITHER A SUPERSET OF NOR EQUAL TO
+ 'ntriangleleft': u'\u22ea', # ⋪ NOT NORMAL SUBGROUP OF
+ 'ntrianglelefteq': u'\u22ec', # ⋬ NOT NORMAL SUBGROUP OF OR EQUAL TO
+ 'ntriangleright': u'\u22eb', # ⋫ DOES NOT CONTAIN AS NORMAL SUBGROUP
+ 'ntrianglerighteq': u'\u22ed', # ⋭ DOES NOT CONTAIN AS NORMAL SUBGROUP OR EQUAL
+ 'nvDash': u'\u22ad', # ⊭ NOT TRUE
+ 'nvdash': u'\u22ac', # ⊬ DOES NOT PROVE
+ 'nwarrow': u'\u2196', # ↖ NORTH WEST ARROW
+ 'owns': u'\u220b', # ∋ CONTAINS AS MEMBER
+ 'parallel': u'\u2225', # ∥ PARALLEL TO
+ 'perp': u'\u27c2', # ⟂ PERPENDICULAR
+ 'pitchfork': u'\u22d4', # ⋔ PITCHFORK
+ 'prec': u'\u227a', # ≺ PRECEDES
+ 'precapprox': u'\u2ab7', # ⪷ PRECEDES ABOVE ALMOST EQUAL TO
+ 'preccurlyeq': u'\u227c', # ≼ PRECEDES OR EQUAL TO
+ 'preceq': u'\u2aaf', # ⪯ PRECEDES ABOVE SINGLE-LINE EQUALS SIGN
+ 'precnapprox': u'\u2ab9', # ⪹ PRECEDES ABOVE NOT ALMOST EQUAL TO
+ 'precnsim': u'\u22e8', # ⋨ PRECEDES BUT NOT EQUIVALENT TO
+ 'precsim': u'\u227e', # ≾ PRECEDES OR EQUIVALENT TO
+ 'propto': u'\u221d', # ∝ PROPORTIONAL TO
+ 'restriction': u'\u21be', # ↾ UPWARDS HARPOON WITH BARB RIGHTWARDS
+ 'rightarrow': u'\u2192', # → RIGHTWARDS ARROW
+ 'rightarrowtail': u'\u21a3', # ↣ RIGHTWARDS ARROW WITH TAIL
+ 'rightarrowtriangle': u'\u21fe', # ⇾ RIGHTWARDS OPEN-HEADED ARROW
+ 'rightbarharpoon': u'\u296c', # ⥬ RIGHTWARDS HARPOON WITH BARB UP ABOVE LONG DASH
+ 'rightharpoondown': u'\u21c1', # ⇁ RIGHTWARDS HARPOON WITH BARB DOWNWARDS
+ 'rightharpoonup': u'\u21c0', # ⇀ RIGHTWARDS HARPOON WITH BARB UPWARDS
+ 'rightleftarrows': u'\u21c4', # ⇄ RIGHTWARDS ARROW OVER LEFTWARDS ARROW
+ 'rightleftharpoon': u'\u294b', # ⥋ LEFT BARB DOWN RIGHT BARB UP HARPOON
+ 'rightleftharpoons': u'\u21cc', # ⇌ RIGHTWARDS HARPOON OVER LEFTWARDS HARPOON
+ 'rightrightarrows': u'\u21c9', # ⇉ RIGHTWARDS PAIRED ARROWS
+ 'rightrightharpoons': u'\u2964', # ⥤ RIGHTWARDS HARPOON WITH BARB UP ABOVE RIGHTWARDS HARPOON WITH BARB DOWN
+ 'rightslice': u'\u2aa7', # ⪧ GREATER-THAN CLOSED BY CURVE
+ 'rightsquigarrow': u'\u21dd', # ⇝ RIGHTWARDS SQUIGGLE ARROW
+ 'risingdotseq': u'\u2253', # ≓ IMAGE OF OR APPROXIMATELY EQUAL TO
+ 'searrow': u'\u2198', # ↘ SOUTH EAST ARROW
+ 'sim': u'\u223c', # ∼ TILDE OPERATOR
+ 'simeq': u'\u2243', # ≃ ASYMPTOTICALLY EQUAL TO
+ 'smallfrown': u'\u2322', # ⌢ FROWN
+ 'smallsmile': u'\u2323', # ⌣ SMILE
+ 'smile': u'\u2323', # ⌣ SMILE
+ 'sqsubset': u'\u228f', # ⊏ SQUARE IMAGE OF
+ 'sqsubseteq': u'\u2291', # ⊑ SQUARE IMAGE OF OR EQUAL TO
+ 'sqsupset': u'\u2290', # ⊐ SQUARE ORIGINAL OF
+ 'sqsupseteq': u'\u2292', # ⊒ SQUARE ORIGINAL OF OR EQUAL TO
+ 'subset': u'\u2282', # ⊂ SUBSET OF
+ 'subseteq': u'\u2286', # ⊆ SUBSET OF OR EQUAL TO
+ 'subseteqq': u'\u2ac5', # ⫅ SUBSET OF ABOVE EQUALS SIGN
+ 'subsetneq': u'\u228a', # ⊊ SUBSET OF WITH NOT EQUAL TO
+ 'subsetneqq': u'\u2acb', # ⫋ SUBSET OF ABOVE NOT EQUAL TO
+ 'succ': u'\u227b', # ≻ SUCCEEDS
+ 'succapprox': u'\u2ab8', # ⪸ SUCCEEDS ABOVE ALMOST EQUAL TO
+ 'succcurlyeq': u'\u227d', # ≽ SUCCEEDS OR EQUAL TO
+ 'succeq': u'\u2ab0', # ⪰ SUCCEEDS ABOVE SINGLE-LINE EQUALS SIGN
+ 'succnapprox': u'\u2aba', # ⪺ SUCCEEDS ABOVE NOT ALMOST EQUAL TO
+ 'succnsim': u'\u22e9', # ⋩ SUCCEEDS BUT NOT EQUIVALENT TO
+ 'succsim': u'\u227f', # ≿ SUCCEEDS OR EQUIVALENT TO
+ 'supset': u'\u2283', # ⊃ SUPERSET OF
+ 'supseteq': u'\u2287', # ⊇ SUPERSET OF OR EQUAL TO
+ 'supseteqq': u'\u2ac6', # ⫆ SUPERSET OF ABOVE EQUALS SIGN
+ 'supsetneq': u'\u228b', # ⊋ SUPERSET OF WITH NOT EQUAL TO
+ 'supsetneqq': u'\u2acc', # ⫌ SUPERSET OF ABOVE NOT EQUAL TO
+ 'swarrow': u'\u2199', # ↙ SOUTH WEST ARROW
+ 'to': u'\u2192', # → RIGHTWARDS ARROW
+ 'trianglelefteq': u'\u22b4', # ⊴ NORMAL SUBGROUP OF OR EQUAL TO
+ 'triangleq': u'\u225c', # ≜ DELTA EQUAL TO
+ 'trianglerighteq': u'\u22b5', # ⊵ CONTAINS AS NORMAL SUBGROUP OR EQUAL TO
+ 'twoheadleftarrow': u'\u219e', # ↞ LEFTWARDS TWO HEADED ARROW
+ 'twoheadrightarrow': u'\u21a0', # ↠ RIGHTWARDS TWO HEADED ARROW
+ 'uparrow': u'\u2191', # ↑ UPWARDS ARROW
+ 'updownarrow': u'\u2195', # ↕ UP DOWN ARROW
+ 'updownarrows': u'\u21c5', # ⇅ UPWARDS ARROW LEFTWARDS OF DOWNWARDS ARROW
+ 'updownharpoons': u'\u296e', # ⥮ UPWARDS HARPOON WITH BARB LEFT BESIDE DOWNWARDS HARPOON WITH BARB RIGHT
+ 'upharpoonleft': u'\u21bf', # ↿ UPWARDS HARPOON WITH BARB LEFTWARDS
+ 'upharpoonright': u'\u21be', # ↾ UPWARDS HARPOON WITH BARB RIGHTWARDS
+ 'upuparrows': u'\u21c8', # ⇈ UPWARDS PAIRED ARROWS
+ 'upupharpoons': u'\u2963', # ⥣ UPWARDS HARPOON WITH BARB LEFT BESIDE UPWARDS HARPOON WITH BARB RIGHT
+ 'vDash': u'\u22a8', # ⊨ TRUE
+ 'varpropto': u'\u221d', # ∝ PROPORTIONAL TO
+ 'vartriangleleft': u'\u22b2', # ⊲ NORMAL SUBGROUP OF
+ 'vartriangleright': u'\u22b3', # ⊳ CONTAINS AS NORMAL SUBGROUP
+ 'vdash': u'\u22a2', # ⊢ RIGHT TACK
+ 'vdots': u'\u22ee', # ⋮ VERTICAL ELLIPSIS
+ }
+mathunder = {
+ 'underbrace': u'\u23df', # ⏟ BOTTOM CURLY BRACKET
+ }
+space = {
+ ':': u'\u205f', # MEDIUM MATHEMATICAL SPACE
+ 'medspace': u'\u205f', # MEDIUM MATHEMATICAL SPACE
+ 'quad': u'\u2001', # EM QUAD
+ }
--- /dev/null
+# LaTeX math to Unicode symbols translation table
+# for use with the translate() method of unicode objects.
+# Generated with ``write_unichar2tex.py`` from the data in
+# http://milde.users.sourceforge.net/LUCR/Math/
+
+# Includes commands from: standard LaTeX, amssymb, amsmath
+
+uni2tex_table = {
+160: u'~',
+163: u'\\pounds ',
+165: u'\\yen ',
+172: u'\\neg ',
+174: u'\\circledR ',
+177: u'\\pm ',
+215: u'\\times ',
+240: u'\\eth ',
+247: u'\\div ',
+305: u'\\imath ',
+567: u'\\jmath ',
+915: u'\\Gamma ',
+916: u'\\Delta ',
+920: u'\\Theta ',
+923: u'\\Lambda ',
+926: u'\\Xi ',
+928: u'\\Pi ',
+931: u'\\Sigma ',
+933: u'\\Upsilon ',
+934: u'\\Phi ',
+936: u'\\Psi ',
+937: u'\\Omega ',
+945: u'\\alpha ',
+946: u'\\beta ',
+947: u'\\gamma ',
+948: u'\\delta ',
+949: u'\\varepsilon ',
+950: u'\\zeta ',
+951: u'\\eta ',
+952: u'\\theta ',
+953: u'\\iota ',
+954: u'\\kappa ',
+955: u'\\lambda ',
+956: u'\\mu ',
+957: u'\\nu ',
+958: u'\\xi ',
+960: u'\\pi ',
+961: u'\\rho ',
+962: u'\\varsigma ',
+963: u'\\sigma ',
+964: u'\\tau ',
+965: u'\\upsilon ',
+966: u'\\varphi ',
+967: u'\\chi ',
+968: u'\\psi ',
+969: u'\\omega ',
+977: u'\\vartheta ',
+981: u'\\phi ',
+982: u'\\varpi ',
+989: u'\\digamma ',
+1014: u'\\backepsilon ',
+8193: u'\\quad ',
+8214: u'\\| ',
+8224: u'\\dagger ',
+8225: u'\\ddagger ',
+8230: u'\\ldots ',
+8242: u'\\prime ',
+8245: u'\\backprime ',
+8287: u'\\: ',
+8450: u'\\mathbb{C}',
+8459: u'\\mathcal{H}',
+8460: u'\\mathfrak{H}',
+8461: u'\\mathbb{H}',
+8463: u'\\hslash ',
+8464: u'\\mathcal{I}',
+8465: u'\\Im ',
+8466: u'\\mathcal{L}',
+8467: u'\\ell ',
+8469: u'\\mathbb{N}',
+8472: u'\\wp ',
+8473: u'\\mathbb{P}',
+8474: u'\\mathbb{Q}',
+8475: u'\\mathcal{R}',
+8476: u'\\Re ',
+8477: u'\\mathbb{R}',
+8484: u'\\mathbb{Z}',
+8487: u'\\mho ',
+8488: u'\\mathfrak{Z}',
+8492: u'\\mathcal{B}',
+8493: u'\\mathfrak{C}',
+8496: u'\\mathcal{E}',
+8497: u'\\mathcal{F}',
+8498: u'\\Finv ',
+8499: u'\\mathcal{M}',
+8501: u'\\aleph ',
+8502: u'\\beth ',
+8503: u'\\gimel ',
+8504: u'\\daleth ',
+8592: u'\\leftarrow ',
+8593: u'\\uparrow ',
+8594: u'\\rightarrow ',
+8595: u'\\downarrow ',
+8596: u'\\leftrightarrow ',
+8597: u'\\updownarrow ',
+8598: u'\\nwarrow ',
+8599: u'\\nearrow ',
+8600: u'\\searrow ',
+8601: u'\\swarrow ',
+8602: u'\\nleftarrow ',
+8603: u'\\nrightarrow ',
+8606: u'\\twoheadleftarrow ',
+8608: u'\\twoheadrightarrow ',
+8610: u'\\leftarrowtail ',
+8611: u'\\rightarrowtail ',
+8614: u'\\mapsto ',
+8617: u'\\hookleftarrow ',
+8618: u'\\hookrightarrow ',
+8619: u'\\looparrowleft ',
+8620: u'\\looparrowright ',
+8621: u'\\leftrightsquigarrow ',
+8622: u'\\nleftrightarrow ',
+8624: u'\\Lsh ',
+8625: u'\\Rsh ',
+8630: u'\\curvearrowleft ',
+8631: u'\\curvearrowright ',
+8634: u'\\circlearrowleft ',
+8635: u'\\circlearrowright ',
+8636: u'\\leftharpoonup ',
+8637: u'\\leftharpoondown ',
+8638: u'\\upharpoonright ',
+8639: u'\\upharpoonleft ',
+8640: u'\\rightharpoonup ',
+8641: u'\\rightharpoondown ',
+8642: u'\\downharpoonright ',
+8643: u'\\downharpoonleft ',
+8644: u'\\rightleftarrows ',
+8646: u'\\leftrightarrows ',
+8647: u'\\leftleftarrows ',
+8648: u'\\upuparrows ',
+8649: u'\\rightrightarrows ',
+8650: u'\\downdownarrows ',
+8651: u'\\leftrightharpoons ',
+8652: u'\\rightleftharpoons ',
+8653: u'\\nLeftarrow ',
+8654: u'\\nLeftrightarrow ',
+8655: u'\\nRightarrow ',
+8656: u'\\Leftarrow ',
+8657: u'\\Uparrow ',
+8658: u'\\Rightarrow ',
+8659: u'\\Downarrow ',
+8660: u'\\Leftrightarrow ',
+8661: u'\\Updownarrow ',
+8666: u'\\Lleftarrow ',
+8667: u'\\Rrightarrow ',
+8669: u'\\rightsquigarrow ',
+8672: u'\\dashleftarrow ',
+8674: u'\\dashrightarrow ',
+8704: u'\\forall ',
+8705: u'\\complement ',
+8706: u'\\partial ',
+8707: u'\\exists ',
+8708: u'\\nexists ',
+8709: u'\\varnothing ',
+8711: u'\\nabla ',
+8712: u'\\in ',
+8713: u'\\notin ',
+8715: u'\\ni ',
+8719: u'\\prod ',
+8720: u'\\coprod ',
+8721: u'\\sum ',
+8722: u'-',
+8723: u'\\mp ',
+8724: u'\\dotplus ',
+8725: u'\\slash ',
+8726: u'\\smallsetminus ',
+8727: u'\\ast ',
+8728: u'\\circ ',
+8729: u'\\bullet ',
+8730: u'\\sqrt ',
+8731: u'\\sqrt[3] ',
+8732: u'\\sqrt[4] ',
+8733: u'\\propto ',
+8734: u'\\infty ',
+8736: u'\\angle ',
+8737: u'\\measuredangle ',
+8738: u'\\sphericalangle ',
+8739: u'\\mid ',
+8740: u'\\nmid ',
+8741: u'\\parallel ',
+8742: u'\\nparallel ',
+8743: u'\\wedge ',
+8744: u'\\vee ',
+8745: u'\\cap ',
+8746: u'\\cup ',
+8747: u'\\int ',
+8748: u'\\iint ',
+8749: u'\\iiint ',
+8750: u'\\oint ',
+8756: u'\\therefore ',
+8757: u'\\because ',
+8758: u':',
+8764: u'\\sim ',
+8765: u'\\backsim ',
+8768: u'\\wr ',
+8769: u'\\nsim ',
+8770: u'\\eqsim ',
+8771: u'\\simeq ',
+8773: u'\\cong ',
+8775: u'\\ncong ',
+8776: u'\\approx ',
+8778: u'\\approxeq ',
+8781: u'\\asymp ',
+8782: u'\\Bumpeq ',
+8783: u'\\bumpeq ',
+8784: u'\\doteq ',
+8785: u'\\Doteq ',
+8786: u'\\fallingdotseq ',
+8787: u'\\risingdotseq ',
+8790: u'\\eqcirc ',
+8791: u'\\circeq ',
+8796: u'\\triangleq ',
+8800: u'\\neq ',
+8801: u'\\equiv ',
+8804: u'\\leq ',
+8805: u'\\geq ',
+8806: u'\\leqq ',
+8807: u'\\geqq ',
+8808: u'\\lneqq ',
+8809: u'\\gneqq ',
+8810: u'\\ll ',
+8811: u'\\gg ',
+8812: u'\\between ',
+8814: u'\\nless ',
+8815: u'\\ngtr ',
+8816: u'\\nleq ',
+8817: u'\\ngeq ',
+8818: u'\\lesssim ',
+8819: u'\\gtrsim ',
+8822: u'\\lessgtr ',
+8823: u'\\gtrless ',
+8826: u'\\prec ',
+8827: u'\\succ ',
+8828: u'\\preccurlyeq ',
+8829: u'\\succcurlyeq ',
+8830: u'\\precsim ',
+8831: u'\\succsim ',
+8832: u'\\nprec ',
+8833: u'\\nsucc ',
+8834: u'\\subset ',
+8835: u'\\supset ',
+8838: u'\\subseteq ',
+8839: u'\\supseteq ',
+8840: u'\\nsubseteq ',
+8841: u'\\nsupseteq ',
+8842: u'\\subsetneq ',
+8843: u'\\supsetneq ',
+8846: u'\\uplus ',
+8847: u'\\sqsubset ',
+8848: u'\\sqsupset ',
+8849: u'\\sqsubseteq ',
+8850: u'\\sqsupseteq ',
+8851: u'\\sqcap ',
+8852: u'\\sqcup ',
+8853: u'\\oplus ',
+8854: u'\\ominus ',
+8855: u'\\otimes ',
+8856: u'\\oslash ',
+8857: u'\\odot ',
+8858: u'\\circledcirc ',
+8859: u'\\circledast ',
+8861: u'\\circleddash ',
+8862: u'\\boxplus ',
+8863: u'\\boxminus ',
+8864: u'\\boxtimes ',
+8865: u'\\boxdot ',
+8866: u'\\vdash ',
+8867: u'\\dashv ',
+8868: u'\\top ',
+8869: u'\\bot ',
+8871: u'\\models ',
+8872: u'\\vDash ',
+8873: u'\\Vdash ',
+8874: u'\\Vvdash ',
+8876: u'\\nvdash ',
+8877: u'\\nvDash ',
+8878: u'\\nVdash ',
+8879: u'\\nVDash ',
+8882: u'\\vartriangleleft ',
+8883: u'\\vartriangleright ',
+8884: u'\\trianglelefteq ',
+8885: u'\\trianglerighteq ',
+8888: u'\\multimap ',
+8890: u'\\intercal ',
+8891: u'\\veebar ',
+8892: u'\\barwedge ',
+8896: u'\\bigwedge ',
+8897: u'\\bigvee ',
+8898: u'\\bigcap ',
+8899: u'\\bigcup ',
+8900: u'\\diamond ',
+8901: u'\\cdot ',
+8902: u'\\star ',
+8903: u'\\divideontimes ',
+8904: u'\\bowtie ',
+8905: u'\\ltimes ',
+8906: u'\\rtimes ',
+8907: u'\\leftthreetimes ',
+8908: u'\\rightthreetimes ',
+8909: u'\\backsimeq ',
+8910: u'\\curlyvee ',
+8911: u'\\curlywedge ',
+8912: u'\\Subset ',
+8913: u'\\Supset ',
+8914: u'\\Cap ',
+8915: u'\\Cup ',
+8916: u'\\pitchfork ',
+8918: u'\\lessdot ',
+8919: u'\\gtrdot ',
+8920: u'\\lll ',
+8921: u'\\ggg ',
+8922: u'\\lesseqgtr ',
+8923: u'\\gtreqless ',
+8926: u'\\curlyeqprec ',
+8927: u'\\curlyeqsucc ',
+8928: u'\\npreceq ',
+8929: u'\\nsucceq ',
+8934: u'\\lnsim ',
+8935: u'\\gnsim ',
+8936: u'\\precnsim ',
+8937: u'\\succnsim ',
+8938: u'\\ntriangleleft ',
+8939: u'\\ntriangleright ',
+8940: u'\\ntrianglelefteq ',
+8941: u'\\ntrianglerighteq ',
+8942: u'\\vdots ',
+8943: u'\\cdots ',
+8945: u'\\ddots ',
+8968: u'\\lceil ',
+8969: u'\\rceil ',
+8970: u'\\lfloor ',
+8971: u'\\rfloor ',
+8988: u'\\ulcorner ',
+8989: u'\\urcorner ',
+8990: u'\\llcorner ',
+8991: u'\\lrcorner ',
+8994: u'\\frown ',
+8995: u'\\smile ',
+9182: u'\\overbrace ',
+9183: u'\\underbrace ',
+9651: u'\\bigtriangleup ',
+9655: u'\\rhd ',
+9661: u'\\bigtriangledown ',
+9665: u'\\lhd ',
+9671: u'\\Diamond ',
+9674: u'\\lozenge ',
+9723: u'\\square ',
+9724: u'\\blacksquare ',
+9733: u'\\bigstar ',
+9824: u'\\spadesuit ',
+9825: u'\\heartsuit ',
+9826: u'\\diamondsuit ',
+9827: u'\\clubsuit ',
+9837: u'\\flat ',
+9838: u'\\natural ',
+9839: u'\\sharp ',
+10003: u'\\checkmark ',
+10016: u'\\maltese ',
+10178: u'\\perp ',
+10216: u'\\langle ',
+10217: u'\\rangle ',
+10222: u'\\lgroup ',
+10223: u'\\rgroup ',
+10229: u'\\longleftarrow ',
+10230: u'\\longrightarrow ',
+10231: u'\\longleftrightarrow ',
+10232: u'\\Longleftarrow ',
+10233: u'\\Longrightarrow ',
+10234: u'\\Longleftrightarrow ',
+10236: u'\\longmapsto ',
+10731: u'\\blacklozenge ',
+10741: u'\\setminus ',
+10752: u'\\bigodot ',
+10753: u'\\bigoplus ',
+10754: u'\\bigotimes ',
+10756: u'\\biguplus ',
+10758: u'\\bigsqcup ',
+10764: u'\\iiiint ',
+10781: u'\\Join ',
+10815: u'\\amalg ',
+10846: u'\\doublebarwedge ',
+10877: u'\\leqslant ',
+10878: u'\\geqslant ',
+10885: u'\\lessapprox ',
+10886: u'\\gtrapprox ',
+10887: u'\\lneq ',
+10888: u'\\gneq ',
+10889: u'\\lnapprox ',
+10890: u'\\gnapprox ',
+10891: u'\\lesseqqgtr ',
+10892: u'\\gtreqqless ',
+10901: u'\\eqslantless ',
+10902: u'\\eqslantgtr ',
+10927: u'\\preceq ',
+10928: u'\\succeq ',
+10935: u'\\precapprox ',
+10936: u'\\succapprox ',
+10937: u'\\precnapprox ',
+10938: u'\\succnapprox ',
+10949: u'\\subseteqq ',
+10950: u'\\supseteqq ',
+10955: u'\\subsetneqq ',
+10956: u'\\supsetneqq ',
+119808: u'\\mathbf{A}',
+119809: u'\\mathbf{B}',
+119810: u'\\mathbf{C}',
+119811: u'\\mathbf{D}',
+119812: u'\\mathbf{E}',
+119813: u'\\mathbf{F}',
+119814: u'\\mathbf{G}',
+119815: u'\\mathbf{H}',
+119816: u'\\mathbf{I}',
+119817: u'\\mathbf{J}',
+119818: u'\\mathbf{K}',
+119819: u'\\mathbf{L}',
+119820: u'\\mathbf{M}',
+119821: u'\\mathbf{N}',
+119822: u'\\mathbf{O}',
+119823: u'\\mathbf{P}',
+119824: u'\\mathbf{Q}',
+119825: u'\\mathbf{R}',
+119826: u'\\mathbf{S}',
+119827: u'\\mathbf{T}',
+119828: u'\\mathbf{U}',
+119829: u'\\mathbf{V}',
+119830: u'\\mathbf{W}',
+119831: u'\\mathbf{X}',
+119832: u'\\mathbf{Y}',
+119833: u'\\mathbf{Z}',
+119834: u'\\mathbf{a}',
+119835: u'\\mathbf{b}',
+119836: u'\\mathbf{c}',
+119837: u'\\mathbf{d}',
+119838: u'\\mathbf{e}',
+119839: u'\\mathbf{f}',
+119840: u'\\mathbf{g}',
+119841: u'\\mathbf{h}',
+119842: u'\\mathbf{i}',
+119843: u'\\mathbf{j}',
+119844: u'\\mathbf{k}',
+119845: u'\\mathbf{l}',
+119846: u'\\mathbf{m}',
+119847: u'\\mathbf{n}',
+119848: u'\\mathbf{o}',
+119849: u'\\mathbf{p}',
+119850: u'\\mathbf{q}',
+119851: u'\\mathbf{r}',
+119852: u'\\mathbf{s}',
+119853: u'\\mathbf{t}',
+119854: u'\\mathbf{u}',
+119855: u'\\mathbf{v}',
+119856: u'\\mathbf{w}',
+119857: u'\\mathbf{x}',
+119858: u'\\mathbf{y}',
+119859: u'\\mathbf{z}',
+119860: u'A',
+119861: u'B',
+119862: u'C',
+119863: u'D',
+119864: u'E',
+119865: u'F',
+119866: u'G',
+119867: u'H',
+119868: u'I',
+119869: u'J',
+119870: u'K',
+119871: u'L',
+119872: u'M',
+119873: u'N',
+119874: u'O',
+119875: u'P',
+119876: u'Q',
+119877: u'R',
+119878: u'S',
+119879: u'T',
+119880: u'U',
+119881: u'V',
+119882: u'W',
+119883: u'X',
+119884: u'Y',
+119885: u'Z',
+119886: u'a',
+119887: u'b',
+119888: u'c',
+119889: u'd',
+119890: u'e',
+119891: u'f',
+119892: u'g',
+119894: u'i',
+119895: u'j',
+119896: u'k',
+119897: u'l',
+119898: u'm',
+119899: u'n',
+119900: u'o',
+119901: u'p',
+119902: u'q',
+119903: u'r',
+119904: u's',
+119905: u't',
+119906: u'u',
+119907: u'v',
+119908: u'w',
+119909: u'x',
+119910: u'y',
+119911: u'z',
+119964: u'\\mathcal{A}',
+119966: u'\\mathcal{C}',
+119967: u'\\mathcal{D}',
+119970: u'\\mathcal{G}',
+119973: u'\\mathcal{J}',
+119974: u'\\mathcal{K}',
+119977: u'\\mathcal{N}',
+119978: u'\\mathcal{O}',
+119979: u'\\mathcal{P}',
+119980: u'\\mathcal{Q}',
+119982: u'\\mathcal{S}',
+119983: u'\\mathcal{T}',
+119984: u'\\mathcal{U}',
+119985: u'\\mathcal{V}',
+119986: u'\\mathcal{W}',
+119987: u'\\mathcal{X}',
+119988: u'\\mathcal{Y}',
+119989: u'\\mathcal{Z}',
+120068: u'\\mathfrak{A}',
+120069: u'\\mathfrak{B}',
+120071: u'\\mathfrak{D}',
+120072: u'\\mathfrak{E}',
+120073: u'\\mathfrak{F}',
+120074: u'\\mathfrak{G}',
+120077: u'\\mathfrak{J}',
+120078: u'\\mathfrak{K}',
+120079: u'\\mathfrak{L}',
+120080: u'\\mathfrak{M}',
+120081: u'\\mathfrak{N}',
+120082: u'\\mathfrak{O}',
+120083: u'\\mathfrak{P}',
+120084: u'\\mathfrak{Q}',
+120086: u'\\mathfrak{S}',
+120087: u'\\mathfrak{T}',
+120088: u'\\mathfrak{U}',
+120089: u'\\mathfrak{V}',
+120090: u'\\mathfrak{W}',
+120091: u'\\mathfrak{X}',
+120092: u'\\mathfrak{Y}',
+120094: u'\\mathfrak{a}',
+120095: u'\\mathfrak{b}',
+120096: u'\\mathfrak{c}',
+120097: u'\\mathfrak{d}',
+120098: u'\\mathfrak{e}',
+120099: u'\\mathfrak{f}',
+120100: u'\\mathfrak{g}',
+120101: u'\\mathfrak{h}',
+120102: u'\\mathfrak{i}',
+120103: u'\\mathfrak{j}',
+120104: u'\\mathfrak{k}',
+120105: u'\\mathfrak{l}',
+120106: u'\\mathfrak{m}',
+120107: u'\\mathfrak{n}',
+120108: u'\\mathfrak{o}',
+120109: u'\\mathfrak{p}',
+120110: u'\\mathfrak{q}',
+120111: u'\\mathfrak{r}',
+120112: u'\\mathfrak{s}',
+120113: u'\\mathfrak{t}',
+120114: u'\\mathfrak{u}',
+120115: u'\\mathfrak{v}',
+120116: u'\\mathfrak{w}',
+120117: u'\\mathfrak{x}',
+120118: u'\\mathfrak{y}',
+120119: u'\\mathfrak{z}',
+120120: u'\\mathbb{A}',
+120121: u'\\mathbb{B}',
+120123: u'\\mathbb{D}',
+120124: u'\\mathbb{E}',
+120125: u'\\mathbb{F}',
+120126: u'\\mathbb{G}',
+120128: u'\\mathbb{I}',
+120129: u'\\mathbb{J}',
+120130: u'\\mathbb{K}',
+120131: u'\\mathbb{L}',
+120132: u'\\mathbb{M}',
+120134: u'\\mathbb{O}',
+120138: u'\\mathbb{S}',
+120139: u'\\mathbb{T}',
+120140: u'\\mathbb{U}',
+120141: u'\\mathbb{V}',
+120142: u'\\mathbb{W}',
+120143: u'\\mathbb{X}',
+120144: u'\\mathbb{Y}',
+120156: u'\\Bbbk ',
+120224: u'\\mathsf{A}',
+120225: u'\\mathsf{B}',
+120226: u'\\mathsf{C}',
+120227: u'\\mathsf{D}',
+120228: u'\\mathsf{E}',
+120229: u'\\mathsf{F}',
+120230: u'\\mathsf{G}',
+120231: u'\\mathsf{H}',
+120232: u'\\mathsf{I}',
+120233: u'\\mathsf{J}',
+120234: u'\\mathsf{K}',
+120235: u'\\mathsf{L}',
+120236: u'\\mathsf{M}',
+120237: u'\\mathsf{N}',
+120238: u'\\mathsf{O}',
+120239: u'\\mathsf{P}',
+120240: u'\\mathsf{Q}',
+120241: u'\\mathsf{R}',
+120242: u'\\mathsf{S}',
+120243: u'\\mathsf{T}',
+120244: u'\\mathsf{U}',
+120245: u'\\mathsf{V}',
+120246: u'\\mathsf{W}',
+120247: u'\\mathsf{X}',
+120248: u'\\mathsf{Y}',
+120249: u'\\mathsf{Z}',
+120250: u'\\mathsf{a}',
+120251: u'\\mathsf{b}',
+120252: u'\\mathsf{c}',
+120253: u'\\mathsf{d}',
+120254: u'\\mathsf{e}',
+120255: u'\\mathsf{f}',
+120256: u'\\mathsf{g}',
+120257: u'\\mathsf{h}',
+120258: u'\\mathsf{i}',
+120259: u'\\mathsf{j}',
+120260: u'\\mathsf{k}',
+120261: u'\\mathsf{l}',
+120262: u'\\mathsf{m}',
+120263: u'\\mathsf{n}',
+120264: u'\\mathsf{o}',
+120265: u'\\mathsf{p}',
+120266: u'\\mathsf{q}',
+120267: u'\\mathsf{r}',
+120268: u'\\mathsf{s}',
+120269: u'\\mathsf{t}',
+120270: u'\\mathsf{u}',
+120271: u'\\mathsf{v}',
+120272: u'\\mathsf{w}',
+120273: u'\\mathsf{x}',
+120274: u'\\mathsf{y}',
+120275: u'\\mathsf{z}',
+120432: u'\\mathtt{A}',
+120433: u'\\mathtt{B}',
+120434: u'\\mathtt{C}',
+120435: u'\\mathtt{D}',
+120436: u'\\mathtt{E}',
+120437: u'\\mathtt{F}',
+120438: u'\\mathtt{G}',
+120439: u'\\mathtt{H}',
+120440: u'\\mathtt{I}',
+120441: u'\\mathtt{J}',
+120442: u'\\mathtt{K}',
+120443: u'\\mathtt{L}',
+120444: u'\\mathtt{M}',
+120445: u'\\mathtt{N}',
+120446: u'\\mathtt{O}',
+120447: u'\\mathtt{P}',
+120448: u'\\mathtt{Q}',
+120449: u'\\mathtt{R}',
+120450: u'\\mathtt{S}',
+120451: u'\\mathtt{T}',
+120452: u'\\mathtt{U}',
+120453: u'\\mathtt{V}',
+120454: u'\\mathtt{W}',
+120455: u'\\mathtt{X}',
+120456: u'\\mathtt{Y}',
+120457: u'\\mathtt{Z}',
+120458: u'\\mathtt{a}',
+120459: u'\\mathtt{b}',
+120460: u'\\mathtt{c}',
+120461: u'\\mathtt{d}',
+120462: u'\\mathtt{e}',
+120463: u'\\mathtt{f}',
+120464: u'\\mathtt{g}',
+120465: u'\\mathtt{h}',
+120466: u'\\mathtt{i}',
+120467: u'\\mathtt{j}',
+120468: u'\\mathtt{k}',
+120469: u'\\mathtt{l}',
+120470: u'\\mathtt{m}',
+120471: u'\\mathtt{n}',
+120472: u'\\mathtt{o}',
+120473: u'\\mathtt{p}',
+120474: u'\\mathtt{q}',
+120475: u'\\mathtt{r}',
+120476: u'\\mathtt{s}',
+120477: u'\\mathtt{t}',
+120478: u'\\mathtt{u}',
+120479: u'\\mathtt{v}',
+120480: u'\\mathtt{w}',
+120481: u'\\mathtt{x}',
+120482: u'\\mathtt{y}',
+120483: u'\\mathtt{z}',
+120484: u'\\imath ',
+120485: u'\\jmath ',
+120490: u'\\mathbf{\\Gamma}',
+120491: u'\\mathbf{\\Delta}',
+120495: u'\\mathbf{\\Theta}',
+120498: u'\\mathbf{\\Lambda}',
+120501: u'\\mathbf{\\Xi}',
+120503: u'\\mathbf{\\Pi}',
+120506: u'\\mathbf{\\Sigma}',
+120508: u'\\mathbf{\\Upsilon}',
+120509: u'\\mathbf{\\Phi}',
+120511: u'\\mathbf{\\Psi}',
+120512: u'\\mathbf{\\Omega}',
+120548: u'\\mathit{\\Gamma}',
+120549: u'\\mathit{\\Delta}',
+120553: u'\\mathit{\\Theta}',
+120556: u'\\mathit{\\Lambda}',
+120559: u'\\mathit{\\Xi}',
+120561: u'\\mathit{\\Pi}',
+120564: u'\\mathit{\\Sigma}',
+120566: u'\\mathit{\\Upsilon}',
+120567: u'\\mathit{\\Phi}',
+120569: u'\\mathit{\\Psi}',
+120570: u'\\mathit{\\Omega}',
+120572: u'\\alpha ',
+120573: u'\\beta ',
+120574: u'\\gamma ',
+120575: u'\\delta ',
+120576: u'\\varepsilon ',
+120577: u'\\zeta ',
+120578: u'\\eta ',
+120579: u'\\theta ',
+120580: u'\\iota ',
+120581: u'\\kappa ',
+120582: u'\\lambda ',
+120583: u'\\mu ',
+120584: u'\\nu ',
+120585: u'\\xi ',
+120587: u'\\pi ',
+120588: u'\\rho ',
+120589: u'\\varsigma ',
+120590: u'\\sigma ',
+120591: u'\\tau ',
+120592: u'\\upsilon ',
+120593: u'\\varphi ',
+120594: u'\\chi ',
+120595: u'\\psi ',
+120596: u'\\omega ',
+120597: u'\\partial ',
+120598: u'\\epsilon ',
+120599: u'\\vartheta ',
+120600: u'\\varkappa ',
+120601: u'\\phi ',
+120602: u'\\varrho ',
+120603: u'\\varpi ',
+120782: u'\\mathbf{0}',
+120783: u'\\mathbf{1}',
+120784: u'\\mathbf{2}',
+120785: u'\\mathbf{3}',
+120786: u'\\mathbf{4}',
+120787: u'\\mathbf{5}',
+120788: u'\\mathbf{6}',
+120789: u'\\mathbf{7}',
+120790: u'\\mathbf{8}',
+120791: u'\\mathbf{9}',
+120802: u'\\mathsf{0}',
+120803: u'\\mathsf{1}',
+120804: u'\\mathsf{2}',
+120805: u'\\mathsf{3}',
+120806: u'\\mathsf{4}',
+120807: u'\\mathsf{5}',
+120808: u'\\mathsf{6}',
+120809: u'\\mathsf{7}',
+120810: u'\\mathsf{8}',
+120811: u'\\mathsf{9}',
+120822: u'\\mathtt{0}',
+120823: u'\\mathtt{1}',
+120824: u'\\mathtt{2}',
+120825: u'\\mathtt{3}',
+120826: u'\\mathtt{4}',
+120827: u'\\mathtt{5}',
+120828: u'\\mathtt{6}',
+120829: u'\\mathtt{7}',
+120830: u'\\mathtt{8}',
+120831: u'\\mathtt{9}',
+}
--- /dev/null
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+# :Id: $Id: punctuation_chars.py 8016 2017-01-17 15:06:17Z milde $
+# :Copyright: © 2011, 2017 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 file is generated by
+# ``docutils/tools/dev/generate_punctuation_chars.py``.
+# ::
+
+import sys, re
+import unicodedata
+
+"""Docutils character category patterns.
+
+ Patterns for the implementation of the `inline markup recognition rules`_
+ in the reStructuredText parser `docutils.parsers.rst.states.py` based
+ on Unicode character categories.
+ The patterns are used inside ``[ ]`` in regular expressions.
+
+ Rule (5) requires determination of matching open/close pairs. However, the
+ pairing of open/close quotes is ambiguous due to different typographic
+ conventions in different languages. The ``quote_pairs`` function tests
+ whether two characters form an open/close pair.
+
+ The patterns are generated by
+ ``docutils/tools/dev/generate_punctuation_chars.py`` to prevent dependence
+ on the Python version and avoid the time-consuming generation with every
+ Docutils run. See there for motives and implementation details.
+
+ The category of some characters changed with the development of the
+ Unicode standard. The current lists are generated with the help of the
+ "unicodedata" module of Python 2.7.13 (based on Unicode version 5.2.0).
+
+ .. _inline markup recognition rules:
+ http://docutils.sf.net/docs/ref/rst/restructuredtext.html#inline-markup-recognition-rules
+"""
+
+openers = (u'"\'(<\\[{\u0f3a\u0f3c\u169b\u2045\u207d\u208d\u2329\u2768'
+ u'\u276a\u276c\u276e\u2770\u2772\u2774\u27c5\u27e6\u27e8\u27ea'
+ u'\u27ec\u27ee\u2983\u2985\u2987\u2989\u298b\u298d\u298f\u2991'
+ u'\u2993\u2995\u2997\u29d8\u29da\u29fc\u2e22\u2e24\u2e26\u2e28'
+ u'\u3008\u300a\u300c\u300e\u3010\u3014\u3016\u3018\u301a\u301d'
+ u'\u301d\ufd3e\ufe17\ufe35\ufe37\ufe39\ufe3b\ufe3d\ufe3f\ufe41'
+ u'\ufe43\ufe47\ufe59\ufe5b\ufe5d\uff08\uff3b\uff5b\uff5f\uff62'
+ u'\xab\u2018\u201c\u2039\u2e02\u2e04\u2e09\u2e0c\u2e1c\u2e20'
+ u'\u201a\u201e\xbb\u2019\u201d\u203a\u2e03\u2e05\u2e0a\u2e0d'
+ u'\u2e1d\u2e21\u201b\u201f')
+closers = (u'"\')>\\]}\u0f3b\u0f3d\u169c\u2046\u207e\u208e\u232a\u2769'
+ u'\u276b\u276d\u276f\u2771\u2773\u2775\u27c6\u27e7\u27e9\u27eb'
+ u'\u27ed\u27ef\u2984\u2986\u2988\u298a\u298c\u298e\u2990\u2992'
+ u'\u2994\u2996\u2998\u29d9\u29db\u29fd\u2e23\u2e25\u2e27\u2e29'
+ u'\u3009\u300b\u300d\u300f\u3011\u3015\u3017\u3019\u301b\u301e'
+ u'\u301f\ufd3f\ufe18\ufe36\ufe38\ufe3a\ufe3c\ufe3e\ufe40\ufe42'
+ u'\ufe44\ufe48\ufe5a\ufe5c\ufe5e\uff09\uff3d\uff5d\uff60\uff63'
+ u'\xbb\u2019\u201d\u203a\u2e03\u2e05\u2e0a\u2e0d\u2e1d\u2e21'
+ u'\u201b\u201f\xab\u2018\u201c\u2039\u2e02\u2e04\u2e09\u2e0c'
+ u'\u2e1c\u2e20\u201a\u201e')
+delimiters = (u'\\-/:\u058a\xa1\xb7\xbf\u037e\u0387\u055a-\u055f\u0589'
+ u'\u05be\u05c0\u05c3\u05c6\u05f3\u05f4\u0609\u060a\u060c'
+ u'\u060d\u061b\u061e\u061f\u066a-\u066d\u06d4\u0700-\u070d'
+ u'\u07f7-\u07f9\u0830-\u083e\u0964\u0965\u0970\u0df4\u0e4f'
+ u'\u0e5a\u0e5b\u0f04-\u0f12\u0f85\u0fd0-\u0fd4\u104a-\u104f'
+ u'\u10fb\u1361-\u1368\u1400\u166d\u166e\u16eb-\u16ed\u1735'
+ u'\u1736\u17d4-\u17d6\u17d8-\u17da\u1800-\u180a\u1944\u1945'
+ u'\u19de\u19df\u1a1e\u1a1f\u1aa0-\u1aa6\u1aa8-\u1aad\u1b5a-'
+ u'\u1b60\u1c3b-\u1c3f\u1c7e\u1c7f\u1cd3\u2010-\u2017\u2020-'
+ u'\u2027\u2030-\u2038\u203b-\u203e\u2041-\u2043\u2047-'
+ u'\u2051\u2053\u2055-\u205e\u2cf9-\u2cfc\u2cfe\u2cff\u2e00'
+ u'\u2e01\u2e06-\u2e08\u2e0b\u2e0e-\u2e1b\u2e1e\u2e1f\u2e2a-'
+ u'\u2e2e\u2e30\u2e31\u3001-\u3003\u301c\u3030\u303d\u30a0'
+ u'\u30fb\ua4fe\ua4ff\ua60d-\ua60f\ua673\ua67e\ua6f2-\ua6f7'
+ u'\ua874-\ua877\ua8ce\ua8cf\ua8f8-\ua8fa\ua92e\ua92f\ua95f'
+ u'\ua9c1-\ua9cd\ua9de\ua9df\uaa5c-\uaa5f\uaade\uaadf\uabeb'
+ u'\ufe10-\ufe16\ufe19\ufe30-\ufe32\ufe45\ufe46\ufe49-\ufe4c'
+ u'\ufe50-\ufe52\ufe54-\ufe58\ufe5f-\ufe61\ufe63\ufe68\ufe6a'
+ u'\ufe6b\uff01-\uff03\uff05-\uff07\uff0a\uff0c-\uff0f\uff1a'
+ u'\uff1b\uff1f\uff20\uff3c\uff61\uff64\uff65')
+if sys.maxunicode >= 0x10FFFF: # "wide" build
+ delimiters += (u'\U00010100\U00010101\U0001039f\U000103d0\U00010857'
+ u'\U0001091f\U0001093f\U00010a50-\U00010a58\U00010a7f'
+ u'\U00010b39-\U00010b3f\U000110bb\U000110bc\U000110be-'
+ u'\U000110c1\U00012470-\U00012473')
+closing_delimiters = u'\\\\.,;!?'
+
+
+# Matching open/close quotes
+# --------------------------
+
+quote_pairs = {# open char: matching closing characters # usage example
+ u'\xbb': u'\xbb', # » » Swedish
+ u'\u2018': u'\u201a', # ‘ ‚ Albanian/Greek/Turkish
+ u'\u2019': u'\u2019', # ’ ’ Swedish
+ u'\u201a': u'\u2018\u2019', # ‚ ‘ German ‚ ’ Polish
+ u'\u201c': u'\u201e', # “ „ Albanian/Greek/Turkish
+ u'\u201e': u'\u201c\u201d', # „ “ German „ ” Polish
+ u'\u201d': u'\u201d', # ” ” Swedish
+ u'\u203a': u'\u203a', # › › Swedish
+ }
+"""Additional open/close quote pairs."""
+
+def match_chars(c1, c2):
+ """Test whether `c1` and `c2` are a matching open/close character pair.
+
+ Matching open/close pairs are at the same position in
+ `punctuation_chars.openers` and `punctuation_chars.closers`.
+ The pairing of open/close quotes is ambiguous due to different
+ typographic conventions in different languages,
+ so we test for additional matches stored in `quote_pairs`.
+ """
+ try:
+ i = openers.index(c1)
+ except ValueError: # c1 not in openers
+ return False
+ return c2 == closers[i] or c2 in quote_pairs.get(c1, u'')
--- /dev/null
+"""Convert to and from Roman numerals"""
+
+__author__ = "Mark Pilgrim (f8dy@diveintopython.org)"
+__version__ = "1.4"
+__date__ = "8 August 2001"
+__copyright__ = """Copyright (c) 2001 Mark Pilgrim
+
+This program is part of "Dive Into Python", a free Python tutorial for
+experienced programmers. Visit http://diveintopython.org/ for the
+latest version.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the Python 2.1.1 license, available at
+http://www.python.org/2.1.1/license.html
+"""
+
+import re
+
+#Define exceptions
+class RomanError(Exception): pass
+class OutOfRangeError(RomanError): pass
+class NotIntegerError(RomanError): pass
+class InvalidRomanNumeralError(RomanError): pass
+
+#Define digit mapping
+romanNumeralMap = (('M', 1000),
+ ('CM', 900),
+ ('D', 500),
+ ('CD', 400),
+ ('C', 100),
+ ('XC', 90),
+ ('L', 50),
+ ('XL', 40),
+ ('X', 10),
+ ('IX', 9),
+ ('V', 5),
+ ('IV', 4),
+ ('I', 1))
+
+def toRoman(n):
+ """convert integer to Roman numeral"""
+ if not (0 < n < 5000):
+ raise OutOfRangeError("number out of range (must be 1..4999)")
+ if int(n) != n:
+ raise NotIntegerError("decimals can not be converted")
+
+ result = ""
+ for numeral, integer in romanNumeralMap:
+ while n >= integer:
+ result += numeral
+ n -= integer
+ return result
+
+#Define pattern to detect valid Roman numerals
+romanNumeralPattern = re.compile("""
+ ^ # beginning of string
+ M{0,4} # thousands - 0 to 4 M's
+ (CM|CD|D?C{0,3}) # hundreds - 900 (CM), 400 (CD), 0-300 (0 to 3 C's),
+ # or 500-800 (D, followed by 0 to 3 C's)
+ (XC|XL|L?X{0,3}) # tens - 90 (XC), 40 (XL), 0-30 (0 to 3 X's),
+ # or 50-80 (L, followed by 0 to 3 X's)
+ (IX|IV|V?I{0,3}) # ones - 9 (IX), 4 (IV), 0-3 (0 to 3 I's),
+ # or 5-8 (V, followed by 0 to 3 I's)
+ $ # end of string
+ """, re.VERBOSE)
+
+def fromRoman(s):
+ """convert Roman numeral to integer"""
+ if not s:
+ raise InvalidRomanNumeralError('Input can not be blank')
+
+ if not romanNumeralPattern.search(s):
+ raise InvalidRomanNumeralError('Invalid Roman numeral: %s' % s)
+
+ result = 0
+ index = 0
+ for numeral, integer in romanNumeralMap:
+ while s[index:index+len(numeral)] == numeral:
+ result += integer
+ index += len(numeral)
+ return result
+
--- /dev/null
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+# :Id: $Id: smartquotes.py 8376 2019-08-27 19:49:29Z milde $
+# :Copyright: © 2010 Günter Milde,
+# original `SmartyPants`_: © 2003 John Gruber
+# smartypants.py: © 2004, 2007 Chad Miller
+# :Maintainer: docutils-develop@lists.sourceforge.net
+# :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
+# notices 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
+
+
+r"""
+=========================
+Smart Quotes for Docutils
+=========================
+
+Synopsis
+========
+
+"SmartyPants" is a free web publishing plug-in for Movable Type, Blosxom, and
+BBEdit that easily translates plain ASCII punctuation characters into "smart"
+typographic punctuation characters.
+
+``smartquotes.py`` is an adaption of "SmartyPants" to Docutils_.
+
+* Using Unicode instead of HTML entities for typographic punctuation
+ characters, it works for any output format that supports Unicode.
+* Supports `language specific quote characters`__.
+
+__ http://en.wikipedia.org/wiki/Non-English_usage_of_quotation_marks
+
+
+Authors
+=======
+
+`John Gruber`_ did all of the hard work of writing this software in Perl for
+`Movable Type`_ and almost all of this useful documentation. `Chad Miller`_
+ported it to Python to use with Pyblosxom_.
+Adapted to Docutils_ by Günter Milde.
+
+Additional Credits
+==================
+
+Portions of the SmartyPants original work are based on Brad Choate's nifty
+MTRegex plug-in. `Brad Choate`_ also contributed a few bits of source code to
+this plug-in. Brad Choate is a fine hacker indeed.
+
+`Jeremy Hedley`_ and `Charles Wiltgen`_ deserve mention for exemplary beta
+testing of the original SmartyPants.
+
+`Rael Dornfest`_ ported SmartyPants to Blosxom.
+
+.. _Brad Choate: http://bradchoate.com/
+.. _Jeremy Hedley: http://antipixel.com/
+.. _Charles Wiltgen: http://playbacktime.com/
+.. _Rael Dornfest: http://raelity.org/
+
+
+Copyright and License
+=====================
+
+SmartyPants_ license (3-Clause BSD license):
+
+ Copyright (c) 2003 John Gruber (http://daringfireball.net/)
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are
+ met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+
+ * Neither the name "SmartyPants" nor the names of its contributors
+ may be used to endorse or promote products derived from this
+ software without specific prior written permission.
+
+ This software is provided by the copyright holders and contributors
+ "as is" and any express or implied warranties, including, but not
+ limited to, the implied warranties of merchantability and fitness for
+ a particular purpose are disclaimed. In no event shall the copyright
+ owner or contributors be liable for any direct, indirect, incidental,
+ special, exemplary, or consequential damages (including, but not
+ limited to, procurement of substitute goods or services; loss of use,
+ data, or profits; or business interruption) however caused and on any
+ theory of liability, whether in contract, strict liability, or tort
+ (including negligence or otherwise) arising in any way out of the use
+ of this software, even if advised of the possibility of such damage.
+
+smartypants.py license (2-Clause BSD license):
+
+ smartypants.py is a derivative work of SmartyPants.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are
+ met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+
+ This software is provided by the copyright holders and contributors
+ "as is" and any express or implied warranties, including, but not
+ limited to, the implied warranties of merchantability and fitness for
+ a particular purpose are disclaimed. In no event shall the copyright
+ owner or contributors be liable for any direct, indirect, incidental,
+ special, exemplary, or consequential damages (including, but not
+ limited to, procurement of substitute goods or services; loss of use,
+ data, or profits; or business interruption) however caused and on any
+ theory of liability, whether in contract, strict liability, or tort
+ (including negligence or otherwise) arising in any way out of the use
+ of this software, even if advised of the possibility of such damage.
+
+.. _John Gruber: http://daringfireball.net/
+.. _Chad Miller: http://web.chad.org/
+
+.. _Pyblosxom: http://pyblosxom.bluesock.org/
+.. _SmartyPants: http://daringfireball.net/projects/smartypants/
+.. _Movable Type: http://www.movabletype.org/
+.. _2-Clause BSD license: http://www.spdx.org/licenses/BSD-2-Clause
+.. _Docutils: http://docutils.sf.net/
+
+Description
+===========
+
+SmartyPants can perform the following transformations:
+
+- Straight quotes ( " and ' ) into "curly" quote characters
+- Backticks-style quotes (\`\`like this'') into "curly" quote characters
+- Dashes (``--`` and ``---``) into en- and em-dash entities
+- Three consecutive dots (``...`` or ``. . .``) into an ellipsis entity
+
+This means you can write, edit, and save your posts using plain old
+ASCII straight quotes, plain dashes, and plain dots, but your published
+posts (and final HTML output) will appear with smart quotes, em-dashes,
+and proper ellipses.
+
+SmartyPants does not modify characters within ``<pre>``, ``<code>``, ``<kbd>``,
+``<math>`` or ``<script>`` tag blocks. Typically, these tags are used to
+display text where smart quotes and other "smart punctuation" would not be
+appropriate, such as source code or example markup.
+
+
+Backslash Escapes
+=================
+
+If you need to use literal straight quotes (or plain hyphens and periods),
+`smartquotes` accepts the following backslash escape sequences to force
+ASCII-punctuation. Mind, that you need two backslashes as Docutils expands it,
+too.
+
+======== =========
+Escape Character
+======== =========
+``\\`` \\
+``\\"`` \\"
+``\\'`` \\'
+``\\.`` \\.
+``\\-`` \\-
+``\\``` \\`
+======== =========
+
+This is useful, for example, when you want to use straight quotes as
+foot and inch marks: 6\\'2\\" tall; a 17\\" iMac.
+
+
+Caveats
+=======
+
+Why You Might Not Want to Use Smart Quotes in Your Weblog
+---------------------------------------------------------
+
+For one thing, you might not care.
+
+Most normal, mentally stable individuals do not take notice of proper
+typographic punctuation. Many design and typography nerds, however, break
+out in a nasty rash when they encounter, say, a restaurant sign that uses
+a straight apostrophe to spell "Joe's".
+
+If you're the sort of person who just doesn't care, you might well want to
+continue not caring. Using straight quotes -- and sticking to the 7-bit
+ASCII character set in general -- is certainly a simpler way to live.
+
+Even if you *do* care about accurate typography, you still might want to
+think twice before educating the quote characters in your weblog. One side
+effect of publishing curly quote characters is that it makes your
+weblog a bit harder for others to quote from using copy-and-paste. What
+happens is that when someone copies text from your blog, the copied text
+contains the 8-bit curly quote characters (as well as the 8-bit characters
+for em-dashes and ellipses, if you use these options). These characters
+are not standard across different text encoding methods, which is why they
+need to be encoded as characters.
+
+People copying text from your weblog, however, may not notice that you're
+using curly quotes, and they'll go ahead and paste the unencoded 8-bit
+characters copied from their browser into an email message or their own
+weblog. When pasted as raw "smart quotes", these characters are likely to
+get mangled beyond recognition.
+
+That said, my own opinion is that any decent text editor or email client
+makes it easy to stupefy smart quote characters into their 7-bit
+equivalents, and I don't consider it my problem if you're using an
+indecent text editor or email client.
+
+
+Algorithmic Shortcomings
+------------------------
+
+One situation in which quotes will get curled the wrong way is when
+apostrophes are used at the start of leading contractions. For example::
+
+ 'Twas the night before Christmas.
+
+In the case above, SmartyPants will turn the apostrophe into an opening
+single-quote, when in fact it should be the `right single quotation mark`
+character which is also "the preferred character to use for apostrophe"
+(Unicode). I don't think this problem can be solved in the general case --
+every word processor I've tried gets this wrong as well. In such cases, it's
+best to use the proper character for closing single-quotes (’) by hand.
+
+In English, the same character is used for apostrophe and closing single
+quote (both plain and "smart" ones). For other locales (French, Italean,
+Swiss, ...) "smart" single closing quotes differ from the curly apostrophe.
+
+ .. class:: language-fr
+
+ Il dit : "C'est 'super' !"
+
+If the apostrophe is used at the end of a word, it cannot be distinguished
+from a single quote by the algorithm. Therefore, a text like::
+
+ .. class:: language-de-CH
+
+ "Er sagt: 'Ich fass' es nicht.'"
+
+will get a single closing guillemet instead of an apostrophe.
+
+This can be prevented by use use of the curly apostrophe character (’) in
+the source::
+
+ - "Er sagt: 'Ich fass' es nicht.'"
+ + "Er sagt: 'Ich fass’ es nicht.'"
+
+
+Version History
+===============
+
+1.8.1 2017-10-25
+ - Use open quote after Unicode whitespace, ZWSP, and ZWNJ.
+ - Code cleanup.
+
+1.8: 2017-04-24
+ - Command line front-end.
+
+1.7.1: 2017-03-19
+ - Update and extend language-dependent quotes.
+ - Differentiate apostrophe from single quote.
+
+1.7: 2012-11-19
+ - Internationalization: language-dependent quotes.
+
+1.6.1: 2012-11-06
+ - Refactor code, code cleanup,
+ - `educate_tokens()` generator as interface for Docutils.
+
+1.6: 2010-08-26
+ - Adaption to Docutils:
+ - Use Unicode instead of HTML entities,
+ - Remove code special to pyblosxom.
+
+1.5_1.6: Fri, 27 Jul 2007 07:06:40 -0400
+ - Fixed bug where blocks of precious unalterable text was instead
+ interpreted. Thanks to Le Roux and Dirk van Oosterbosch.
+
+1.5_1.5: Sat, 13 Aug 2005 15:50:24 -0400
+ - Fix bogus magical quotation when there is no hint that the
+ user wants it, e.g., in "21st century". Thanks to Nathan Hamblen.
+ - Be smarter about quotes before terminating numbers in an en-dash'ed
+ range.
+
+1.5_1.4: Thu, 10 Feb 2005 20:24:36 -0500
+ - Fix a date-processing bug, as reported by jacob childress.
+ - Begin a test-suite for ensuring correct output.
+ - Removed import of "string", since I didn't really need it.
+ (This was my first every Python program. Sue me!)
+
+1.5_1.3: Wed, 15 Sep 2004 18:25:58 -0400
+ - Abort processing if the flavour is in forbidden-list. Default of
+ [ "rss" ] (Idea of Wolfgang SCHNERRING.)
+ - Remove stray virgules from en-dashes. Patch by Wolfgang SCHNERRING.
+
+1.5_1.2: Mon, 24 May 2004 08:14:54 -0400
+ - Some single quotes weren't replaced properly. Diff-tesuji played
+ by Benjamin GEIGER.
+
+1.5_1.1: Sun, 14 Mar 2004 14:38:28 -0500
+ - Support upcoming pyblosxom 0.9 plugin verification feature.
+
+1.5_1.0: Tue, 09 Mar 2004 08:08:35 -0500
+ - Initial release
+"""
+from __future__ import print_function
+
+options = r"""
+Options
+=======
+
+Numeric values are the easiest way to configure SmartyPants' behavior:
+
+:0: Suppress all transformations. (Do nothing.)
+
+:1: Performs default SmartyPants transformations: quotes (including
+ \`\`backticks'' -style), em-dashes, and ellipses. "``--``" (dash dash)
+ is used to signify an em-dash; there is no support for en-dashes
+
+:2: Same as smarty_pants="1", except that it uses the old-school typewriter
+ shorthand for dashes: "``--``" (dash dash) for en-dashes, "``---``"
+ (dash dash dash)
+ for em-dashes.
+
+:3: Same as smarty_pants="2", but inverts the shorthand for dashes:
+ "``--``" (dash dash) for em-dashes, and "``---``" (dash dash dash) for
+ en-dashes.
+
+:-1: Stupefy mode. Reverses the SmartyPants transformation process, turning
+ the characters produced by SmartyPants into their ASCII equivalents.
+ E.g. the LEFT DOUBLE QUOTATION MARK (“) is turned into a simple
+ double-quote (\"), "—" is turned into two dashes, etc.
+
+
+The following single-character attribute values can be combined to toggle
+individual transformations from within the smarty_pants attribute. For
+example, ``"1"`` is equivalent to ``"qBde"``.
+
+:q: Educates normal quote characters: (") and (').
+
+:b: Educates \`\`backticks'' -style double quotes.
+
+:B: Educates \`\`backticks'' -style double quotes and \`single' quotes.
+
+:d: Educates em-dashes.
+
+:D: Educates em-dashes and en-dashes, using old-school typewriter shorthand:
+ (dash dash) for en-dashes, (dash dash dash) for em-dashes.
+
+:i: Educates em-dashes and en-dashes, using inverted old-school typewriter
+ shorthand: (dash dash) for em-dashes, (dash dash dash) for en-dashes.
+
+:e: Educates ellipses.
+
+:w: Translates any instance of ``"`` into a normal double-quote character.
+ This should be of no interest to most people, but of particular interest
+ to anyone who writes their posts using Dreamweaver, as Dreamweaver
+ inexplicably uses this entity to represent a literal double-quote
+ character. SmartyPants only educates normal quotes, not entities (because
+ ordinarily, entities are used for the explicit purpose of representing the
+ specific character they represent). The "w" option must be used in
+ conjunction with one (or both) of the other quote options ("q" or "b").
+ Thus, if you wish to apply all SmartyPants transformations (quotes, en-
+ and em-dashes, and ellipses) and also translate ``"`` entities into
+ regular quotes so SmartyPants can educate them, you should pass the
+ following to the smarty_pants attribute:
+"""
+
+
+default_smartypants_attr = "1"
+
+
+import re, sys
+
+class smartchars(object):
+ """Smart quotes and dashes
+ """
+
+ endash = u'–' # "–" EN DASH
+ emdash = u'—' # "—" EM DASH
+ ellipsis = u'…' # "…" HORIZONTAL ELLIPSIS
+ apostrophe = u'’' # "’" RIGHT SINGLE QUOTATION MARK
+
+ # quote characters (language-specific, set in __init__())
+ # [1] http://en.wikipedia.org/wiki/Non-English_usage_of_quotation_marks
+ # [2] http://de.wikipedia.org/wiki/Anf%C3%BChrungszeichen#Andere_Sprachen
+ # [3] https://fr.wikipedia.org/wiki/Guillemet
+ # [4] http://typographisme.net/post/Les-espaces-typographiques-et-le-web
+ # [5] http://www.btb.termiumplus.gc.ca/tpv2guides/guides/redac/index-fra.html
+ # [6] https://en.wikipedia.org/wiki/Hebrew_punctuation#Quotation_marks
+ # [7] http://www.tustep.uni-tuebingen.de/bi/bi00/bi001t1-anfuehrung.pdf
+ # [8] http://www.korrekturavdelingen.no/anforselstegn.htm
+ # [9] Typografisk håndbok. Oslo: Spartacus. 2000. s. 67. ISBN 8243001530.
+ # [10] http://www.typografi.org/sitat/sitatart.html
+ #
+ # See also configuration option "smartquote-locales".
+ quotes = {'af': u'“”‘’',
+ 'af-x-altquot': u'„”‚’',
+ 'bg': u'„“‚‘', # Bulgarian, https://bg.wikipedia.org/wiki/Кавички
+ 'ca': u'«»“”',
+ 'ca-x-altquot': u'“”‘’',
+ 'cs': u'„“‚‘',
+ 'cs-x-altquot': u'»«›‹',
+ 'da': u'»«›‹',
+ 'da-x-altquot': u'„“‚‘',
+ # 'da-x-altquot2': u'””’’',
+ 'de': u'„“‚‘',
+ 'de-x-altquot': u'»«›‹',
+ 'de-ch': u'«»‹›',
+ 'el': u'«»“”',
+ 'en': u'“”‘’',
+ 'en-uk-x-altquot': u'‘’“”', # Attention: " → ‘ and ' → “ !
+ 'eo': u'“”‘’',
+ 'es': u'«»“”',
+ 'es-x-altquot': u'“”‘’',
+ 'et': u'„“‚‘', # no secondary quote listed in
+ 'et-x-altquot': u'«»‹›', # the sources above (wikipedia.org)
+ 'eu': u'«»‹›',
+ 'fi': u'””’’',
+ 'fi-x-altquot': u'»»››',
+ 'fr': (u'« ', u' »', u'“', u'”'), # full no-break space
+ 'fr-x-altquot': (u'« ', u' »', u'“', u'”'), # narrow no-break space
+ 'fr-ch': u'«»‹›',
+ 'fr-ch-x-altquot': (u'« ', u' »', u'‹ ', u' ›'), # narrow no-break space, http://typoguide.ch/
+ 'gl': u'«»“”',
+ 'he': u'”“»«', # Hebrew is RTL, test position:
+ 'he-x-altquot': u'„”‚’', # low quotation marks are opening.
+ # 'he-x-altquot': u'“„‘‚', # RTL: low quotation marks opening
+ 'hr': u'„”‘’', # http://hrvatska-tipografija.com/polunavodnici/
+ 'hr-x-altquot': u'»«›‹',
+ 'hsb': u'„“‚‘',
+ 'hsb-x-altquot': u'»«›‹',
+ 'hu': u'„”«»',
+ 'is': u'„“‚‘',
+ 'it': u'«»“”',
+ 'it-ch': u'«»‹›',
+ 'it-x-altquot': u'“”‘’',
+ # 'it-x-altquot2': u'“„‘‚', # [7] in headlines
+ 'ja': u'「」『』',
+ 'ko': u'《》〈〉',
+ 'lt': u'„“‚‘',
+ 'lv': u'„“‚‘',
+ 'mk': u'„“‚‘', # Macedonian, https://mk.wikipedia.org/wiki/Правопис_и_правоговор_на_македонскиот_јазик
+ 'nl': u'“”‘’',
+ 'nl-x-altquot': u'„”‚’',
+ # 'nl-x-altquot2': u'””’’',
+ 'nb': u'«»’’', # Norsk bokmål (canonical form 'no')
+ 'nn': u'«»’’', # Nynorsk [10]
+ 'nn-x-altquot': u'«»‘’', # [8], [10]
+ # 'nn-x-altquot2': u'«»«»', # [9], [10
+ # 'nn-x-altquot3': u'„“‚‘', # [10]
+ 'no': u'«»’’', # Norsk bokmål [10]
+ 'no-x-altquot': u'«»‘’', # [8], [10]
+ # 'no-x-altquot2': u'«»«»', # [9], [10
+ # 'no-x-altquot3': u'„“‚‘', # [10]
+ 'pl': u'„”«»',
+ 'pl-x-altquot': u'«»‚’',
+ # 'pl-x-altquot2': u'„”‚’', # https://pl.wikipedia.org/wiki/Cudzys%C5%82%C3%B3w
+ 'pt': u'«»“”',
+ 'pt-br': u'“”‘’',
+ 'ro': u'„”«»',
+ 'ru': u'«»„“',
+ 'sh': u'„”‚’', # Serbo-Croatian
+ 'sh-x-altquot': u'»«›‹',
+ 'sk': u'„“‚‘', # Slovak
+ 'sk-x-altquot': u'»«›‹',
+ 'sl': u'„“‚‘', # Slovenian
+ 'sl-x-altquot': u'»«›‹',
+ 'sq': u'«»‹›', # Albanian
+ 'sq-x-altquot': u'“„‘‚',
+ 'sr': u'„”’’',
+ 'sr-x-altquot': u'»«›‹',
+ 'sv': u'””’’',
+ 'sv-x-altquot': u'»»››',
+ 'tr': u'“”‘’',
+ 'tr-x-altquot': u'«»‹›',
+ # 'tr-x-altquot2': u'“„‘‚', # [7] antiquated?
+ 'uk': u'«»„“',
+ 'uk-x-altquot': u'„“‚‘',
+ 'zh-cn': u'“”‘’',
+ 'zh-tw': u'「」『』',
+ }
+
+ def __init__(self, language='en'):
+ self.language = language
+ try:
+ (self.opquote, self.cpquote,
+ self.osquote, self.csquote) = self.quotes[language.lower()]
+ except KeyError:
+ self.opquote, self.cpquote, self.osquote, self.csquote = u'""\'\''
+
+
+def smartyPants(text, attr=default_smartypants_attr, language='en'):
+ """Main function for "traditional" use."""
+
+ return "".join([t for t in educate_tokens(tokenize(text),
+ attr, language)])
+
+
+def educate_tokens(text_tokens, attr=default_smartypants_attr, language='en'):
+ """Return iterator that "educates" the items of `text_tokens`.
+ """
+
+ # Parse attributes:
+ # 0 : do nothing
+ # 1 : set all
+ # 2 : set all, using old school en- and em- dash shortcuts
+ # 3 : set all, using inverted old school en and em- dash shortcuts
+ #
+ # q : quotes
+ # b : backtick quotes (``double'' only)
+ # B : backtick quotes (``double'' and `single')
+ # d : dashes
+ # D : old school dashes
+ # i : inverted old school dashes
+ # e : ellipses
+ # w : convert " entities to " for Dreamweaver users
+
+ convert_quot = False # translate " entities into normal quotes?
+ do_dashes = False
+ do_backticks = False
+ do_quotes = False
+ do_ellipses = False
+ do_stupefy = False
+
+ # if attr == "0": # pass tokens unchanged (see below).
+ if attr == "1": # Do everything, turn all options on.
+ do_quotes = True
+ do_backticks = True
+ do_dashes = 1
+ do_ellipses = True
+ elif attr == "2":
+ # Do everything, turn all options on, use old school dash shorthand.
+ do_quotes = True
+ do_backticks = True
+ do_dashes = 2
+ do_ellipses = True
+ elif attr == "3":
+ # Do everything, use inverted old school dash shorthand.
+ do_quotes = True
+ do_backticks = True
+ do_dashes = 3
+ do_ellipses = True
+ elif attr == "-1": # Special "stupefy" mode.
+ do_stupefy = True
+ else:
+ if "q" in attr: do_quotes = True
+ if "b" in attr: do_backticks = True
+ if "B" in attr: do_backticks = 2
+ if "d" in attr: do_dashes = 1
+ if "D" in attr: do_dashes = 2
+ if "i" in attr: do_dashes = 3
+ if "e" in attr: do_ellipses = True
+ if "w" in attr: convert_quot = True
+
+ prev_token_last_char = " "
+ # Last character of the previous text token. Used as
+ # context to curl leading quote characters correctly.
+
+ for (ttype, text) in text_tokens:
+
+ # skip HTML and/or XML tags as well as emtpy text tokens
+ # without updating the last character
+ if ttype == 'tag' or not text:
+ yield text
+ continue
+
+ # skip literal text (math, literal, raw, ...)
+ if ttype == 'literal':
+ prev_token_last_char = text[-1:]
+ yield text
+ continue
+
+ last_char = text[-1:] # Remember last char before processing.
+
+ text = processEscapes(text)
+
+ if convert_quot:
+ text = re.sub('"', '"', text)
+
+ if do_dashes == 1:
+ text = educateDashes(text)
+ elif do_dashes == 2:
+ text = educateDashesOldSchool(text)
+ elif do_dashes == 3:
+ text = educateDashesOldSchoolInverted(text)
+
+ if do_ellipses:
+ text = educateEllipses(text)
+
+ # Note: backticks need to be processed before quotes.
+ if do_backticks:
+ text = educateBackticks(text, language)
+
+ if do_backticks == 2:
+ text = educateSingleBackticks(text, language)
+
+ if do_quotes:
+ # Replace plain quotes in context to prevent converstion to
+ # 2-character sequence in French.
+ context = prev_token_last_char.replace('"', ';').replace("'", ';')
+ text = educateQuotes(context+text, language)[1:]
+
+ if do_stupefy:
+ text = stupefyEntities(text, language)
+
+ # Remember last char as context for the next token
+ prev_token_last_char = last_char
+
+ text = processEscapes(text, restore=True)
+
+ yield text
+
+
+
+def educateQuotes(text, language='en'):
+ """
+ Parameter: - text string (unicode or bytes).
+ - language (`BCP 47` language tag.)
+ Returns: The `text`, with "educated" curly quote characters.
+
+ Example input: "Isn't this fun?"
+ Example output: “Isn’t this fun?“;
+ """
+
+ smart = smartchars(language)
+
+ punct_class = r"""[!"#\$\%'()*+,-.\/:;<=>?\@\[\\\]\^_`{|}~]"""
+ close_class = r"""[^\ \t\r\n\[\{\(\-]"""
+ open_class = u'[\u200B\u200C]' # ZWSP, ZWNJ
+ dec_dashes = r"""–|—"""
+
+ # Special case if the very first character is a quote
+ # followed by punctuation at a non-word-break.
+ # Close the quotes by brute force:
+ text = re.sub(r"^'(?=%s\\B)" % (punct_class,), smart.csquote, text)
+ text = re.sub(r'^"(?=%s\\B)' % (punct_class,), smart.cpquote, text)
+
+ # Special case for double sets of quotes, e.g.:
+ # <p>He said, "'Quoted' words in a larger quote."</p>
+ text = re.sub(r""""'(?=\w)""", smart.opquote+smart.osquote, text)
+ text = re.sub(r"""'"(?=\w)""", smart.osquote+smart.opquote, text)
+
+ # Special case for decade abbreviations (the '80s):
+ if language.startswith('en'): # TODO similar cases in other languages?
+ text = re.sub(r"'(?=\d{2}s)", smart.apostrophe, text)
+
+ # Get most opening single quotes:
+ opening_single_quotes_regex = re.compile(u"""
+ (# ?<= # look behind fails: requires fixed-width pattern
+ \\s | # a whitespace char, or
+ %s | # another separating char, or
+ | # a non-breaking space entity, or
+ [\u2013 \u2014 ] | # literal dashes, or
+ -- | # dumb dashes, or
+ &[mn]dash; | # dash entities (named or
+ %s | # decimal or
+ &\\#x201[34]; # hex)
+ )
+ ' # the quote
+ (?=\\w) # followed by a word character
+ """ % (open_class, dec_dashes), re.VERBOSE | re.UNICODE)
+
+ text = opening_single_quotes_regex.sub(r'\1'+smart.osquote, text)
+
+ # In many locales, single closing quotes are different from apostrophe:
+ if smart.csquote != smart.apostrophe:
+ apostrophe_regex = re.compile(r"(?<=(\w|\d))'(?=\w)", re.UNICODE)
+ text = apostrophe_regex.sub(smart.apostrophe, text)
+ # TODO: keep track of quoting level to recognize apostrophe in, e.g.,
+ # "Ich fass' es nicht."
+
+ closing_single_quotes_regex = re.compile(r"""
+ (?<=%s)
+ '
+ """ % close_class, re.VERBOSE)
+ text = closing_single_quotes_regex.sub(smart.csquote, text)
+
+ # Any remaining single quotes should be opening ones:
+ text = re.sub(r"""'""", smart.osquote, text)
+
+ # Get most opening double quotes:
+ opening_double_quotes_regex = re.compile(u"""
+ (
+ \\s | # a whitespace char, or
+ %s | # another separating char, or
+ | # a non-breaking space entity, or
+ [\u2013 \u2014 ] | # literal dashes, or
+ -- | # dumb dashes, or
+ &[mn]dash; | # dash entities (named or
+ %s | # decimal or
+ &\\#x201[34]; # hex)
+ )
+ " # the quote
+ (?=\\w) # followed by a word character
+ """ % (open_class, dec_dashes), re.VERBOSE | re.UNICODE)
+
+ text = opening_double_quotes_regex.sub(r'\1'+smart.opquote, text)
+
+ # Double closing quotes:
+ closing_double_quotes_regex = re.compile(r"""
+ (
+ (?<=%s)" | # char indicating the quote should be closing
+ "(?=\s) # whitespace behind
+ )
+ """ % (close_class,), re.VERBOSE | re.UNICODE)
+ text = closing_double_quotes_regex.sub(smart.cpquote, text)
+
+ # Any remaining quotes should be opening ones.
+ text = re.sub(r'"', smart.opquote, text)
+
+ return text
+
+
+def educateBackticks(text, language='en'):
+ """
+ Parameter: String (unicode or bytes).
+ Returns: The `text`, with ``backticks'' -style double quotes
+ translated into HTML curly quote entities.
+ Example input: ``Isn't this fun?''
+ Example output: “Isn't this fun?“;
+ """
+ smart = smartchars(language)
+
+ text = re.sub(r"""``""", smart.opquote, text)
+ text = re.sub(r"""''""", smart.cpquote, text)
+ return text
+
+
+def educateSingleBackticks(text, language='en'):
+ """
+ Parameter: String (unicode or bytes).
+ Returns: The `text`, with `backticks' -style single quotes
+ translated into HTML curly quote entities.
+
+ Example input: `Isn't this fun?'
+ Example output: ‘Isn’t this fun?’
+ """
+ smart = smartchars(language)
+
+ text = re.sub(r"""`""", smart.osquote, text)
+ text = re.sub(r"""'""", smart.csquote, text)
+ return text
+
+
+def educateDashes(text):
+ """
+ Parameter: String (unicode or bytes).
+ Returns: The `text`, with each instance of "--" translated to
+ an em-dash character.
+ """
+
+ text = re.sub(r"""---""", smartchars.endash, text) # en (yes, backwards)
+ text = re.sub(r"""--""", smartchars.emdash, text) # em (yes, backwards)
+ return text
+
+
+def educateDashesOldSchool(text):
+ """
+ Parameter: String (unicode or bytes).
+ Returns: The `text`, with each instance of "--" translated to
+ an en-dash character, and each "---" translated to
+ an em-dash character.
+ """
+
+ text = re.sub(r"""---""", smartchars.emdash, text)
+ text = re.sub(r"""--""", smartchars.endash, text)
+ return text
+
+
+def educateDashesOldSchoolInverted(text):
+ """
+ Parameter: String (unicode or bytes).
+ Returns: The `text`, with each instance of "--" translated to
+ an em-dash character, and each "---" translated to
+ an en-dash character. Two reasons why: First, unlike the
+ en- and em-dash syntax supported by
+ EducateDashesOldSchool(), it's compatible with existing
+ entries written before SmartyPants 1.1, back when "--" was
+ only used for em-dashes. Second, em-dashes are more
+ common than en-dashes, and so it sort of makes sense that
+ the shortcut should be shorter to type. (Thanks to Aaron
+ Swartz for the idea.)
+ """
+ text = re.sub(r"""---""", smartchars.endash, text) # em
+ text = re.sub(r"""--""", smartchars.emdash, text) # en
+ return text
+
+
+
+def educateEllipses(text):
+ """
+ Parameter: String (unicode or bytes).
+ Returns: The `text`, with each instance of "..." translated to
+ an ellipsis character.
+
+ Example input: Huh...?
+ Example output: Huh…?
+ """
+
+ text = re.sub(r"""\.\.\.""", smartchars.ellipsis, text)
+ text = re.sub(r"""\. \. \.""", smartchars.ellipsis, text)
+ return text
+
+
+def stupefyEntities(text, language='en'):
+ """
+ Parameter: String (unicode or bytes).
+ Returns: The `text`, with each SmartyPants character translated to
+ its ASCII counterpart.
+
+ Example input: “Hello — world.”
+ Example output: "Hello -- world."
+ """
+ smart = smartchars(language)
+
+ text = re.sub(smart.endash, "-", text) # en-dash
+ text = re.sub(smart.emdash, "--", text) # em-dash
+
+ text = re.sub(smart.osquote, "'", text) # open single quote
+ text = re.sub(smart.csquote, "'", text) # close single quote
+
+ text = re.sub(smart.opquote, '"', text) # open double quote
+ text = re.sub(smart.cpquote, '"', text) # close double quote
+
+ text = re.sub(smart.ellipsis, '...', text)# ellipsis
+
+ return text
+
+
+def processEscapes(text, restore=False):
+ r"""
+ Parameter: String (unicode or bytes).
+ Returns: The `text`, with after processing the following backslash
+ escape sequences. This is useful if you want to force a "dumb"
+ quote or other character to appear.
+
+ Escape Value
+ ------ -----
+ \\ \
+ \" "
+ \' '
+ \. .
+ \- -
+ \` `
+ """
+ replacements = ((r'\\', r'\'),
+ (r'\"', r'"'),
+ (r"\'", r'''),
+ (r'\.', r'.'),
+ (r'\-', r'-'),
+ (r'\`', r'`'))
+ if restore:
+ for (ch, rep) in replacements:
+ text = text.replace(rep, ch[1])
+ else:
+ for (ch, rep) in replacements:
+ text = text.replace(ch, rep)
+
+ return text
+
+
+def tokenize(text):
+ """
+ Parameter: String containing HTML markup.
+ Returns: An iterator that yields the tokens comprising the input
+ string. Each token is either a tag (possibly with nested,
+ tags contained therein, such as <a href="<MTFoo>">, or a
+ run of text between tags. Each yielded element is a
+ two-element tuple; the first is either 'tag' or 'text';
+ the second is the actual value.
+
+ Based on the _tokenize() subroutine from Brad Choate's MTRegex plugin.
+ <http://www.bradchoate.com/past/mtregex.php>
+ """
+
+ pos = 0
+ length = len(text)
+ # tokens = []
+
+ depth = 6
+ nested_tags = "|".join(['(?:<(?:[^<>]',] * depth) + (')*>)' * depth)
+ #match = r"""(?: <! ( -- .*? -- \s* )+ > ) | # comments
+ # (?: <\? .*? \?> ) | # directives
+ # %s # nested tags """ % (nested_tags,)
+ tag_soup = re.compile(r"""([^<]*)(<[^>]*>)""")
+
+ token_match = tag_soup.search(text)
+
+ previous_end = 0
+ while token_match is not None:
+ if token_match.group(1):
+ yield ('text', token_match.group(1))
+
+ yield ('tag', token_match.group(2))
+
+ previous_end = token_match.end()
+ token_match = tag_soup.search(text, token_match.end())
+
+ if previous_end < len(text):
+ yield ('text', text[previous_end:])
+
+
+
+if __name__ == "__main__":
+
+ import itertools
+ try:
+ import locale # module missing in Jython
+ locale.setlocale(locale.LC_ALL, '') # set to user defaults
+ defaultlanguage = locale.getdefaultlocale()[0]
+ except:
+ defaultlanguage = 'en'
+
+ # Normalize and drop unsupported subtags:
+ defaultlanguage = defaultlanguage.lower().replace('-', '_')
+ # split (except singletons, which mark the following tag as non-standard):
+ defaultlanguage = re.sub(r'_([a-zA-Z0-9])_', r'_\1-', defaultlanguage)
+ _subtags = [subtag for subtag in defaultlanguage.split('_')]
+ _basetag = _subtags.pop(0)
+ # find all combinations of subtags
+ for n in range(len(_subtags), 0, -1):
+ for tags in itertools.combinations(_subtags, n):
+ _tag = '-'.join((_basetag,)+tags)
+ if _tag in smartchars.quotes:
+ defaultlanguage = _tag
+ break
+ else:
+ if _basetag in smartchars.quotes:
+ defaultlanguage = _basetag
+ else:
+ defaultlanguage = 'en'
+
+
+ import argparse
+ parser = argparse.ArgumentParser(
+ description='Filter stdin making ASCII punctuation "smart".')
+ # parser.add_argument("text", help="text to be acted on")
+ parser.add_argument("-a", "--action", default="1",
+ help="what to do with the input (see --actionhelp)")
+ parser.add_argument("-e", "--encoding", default="utf8",
+ help="text encoding")
+ parser.add_argument("-l", "--language", default=defaultlanguage,
+ help="text language (BCP47 tag), "
+ "Default: %s"% defaultlanguage)
+ parser.add_argument("-q", "--alternative-quotes", action="store_true",
+ help="use alternative quote style")
+ parser.add_argument("--doc", action="store_true",
+ help="print documentation")
+ parser.add_argument("--actionhelp", action="store_true",
+ help="list available actions")
+ parser.add_argument("--stylehelp", action="store_true",
+ help="list available quote styles")
+ parser.add_argument("--test", action="store_true",
+ help="perform short self-test")
+ args = parser.parse_args()
+
+ if args.doc:
+ print(__doc__)
+ elif args.actionhelp:
+ print(options)
+ elif args.stylehelp:
+ print()
+ print("Available styles (primary open/close, secondary open/close)")
+ print("language tag quotes")
+ print("============ ======")
+ for key in sorted(smartchars.quotes.keys()):
+ print("%-14s %s" % (key, smartchars.quotes[key]))
+ elif args.test:
+ # Unit test output goes to stderr.
+ import unittest
+
+ class TestSmartypantsAllAttributes(unittest.TestCase):
+ # the default attribute is "1", which means "all".
+ def test_dates(self):
+ self.assertEqual(smartyPants("1440-80's"), u"1440-80’s")
+ self.assertEqual(smartyPants("1440-'80s"), u"1440-’80s")
+ self.assertEqual(smartyPants("1440---'80s"), u"1440–’80s")
+ self.assertEqual(smartyPants("1960's"), u"1960’s")
+ self.assertEqual(smartyPants("one two '60s"), u"one two ’60s")
+ self.assertEqual(smartyPants("'60s"), u"’60s")
+
+ def test_educated_quotes(self):
+ self.assertEqual(smartyPants('"Isn\'t this fun?"'), u'“Isn’t this fun?”')
+
+ def test_html_tags(self):
+ text = '<a src="foo">more</a>'
+ self.assertEqual(smartyPants(text), text)
+
+ suite = unittest.TestLoader().loadTestsFromTestCase(
+ TestSmartypantsAllAttributes)
+ unittest.TextTestRunner().run(suite)
+
+ else:
+ if args.alternative_quotes:
+ if '-x-altquot' in args.language:
+ args.language = args.language.replace('-x-altquot', '')
+ else:
+ args.language += '-x-altquot'
+ text = sys.stdin.read().decode(args.encoding)
+ print(smartyPants(text, attr=args.action,
+ language=args.language).encode(args.encoding))
--- /dev/null
+# $Id: urischemes.py 8376 2019-08-27 19:49:29Z milde $
+# Author: David Goodger <goodger@python.org>
+# Copyright: This module has been placed in the public domain.
+
+"""
+`schemes` is a dictionary with lowercase URI addressing schemes as
+keys and descriptions as values. It was compiled from the index at
+http://www.iana.org/assignments/uri-schemes (revised 2005-11-28)
+and an older list at http://www.w3.org/Addressing/schemes.html.
+"""
+
+# Many values are blank and should be filled in with useful descriptions.
+
+schemes = {
+ 'about': 'provides information on Navigator',
+ 'acap': 'Application Configuration Access Protocol; RFC 2244',
+ 'addbook': "To add vCard entries to Communicator's Address Book",
+ 'afp': 'Apple Filing Protocol',
+ 'afs': 'Andrew File System global file names',
+ 'aim': 'AOL Instant Messenger',
+ 'callto': 'for NetMeeting links',
+ 'castanet': 'Castanet Tuner URLs for Netcaster',
+ 'chttp': 'cached HTTP supported by RealPlayer',
+ 'cid': 'content identifier; RFC 2392',
+ 'crid': 'TV-Anytime Content Reference Identifier; RFC 4078',
+ 'data': ('allows inclusion of small data items as "immediate" data; '
+ 'RFC 2397'),
+ 'dav': 'Distributed Authoring and Versioning Protocol; RFC 2518',
+ 'dict': 'dictionary service protocol; RFC 2229',
+ 'dns': 'Domain Name System resources',
+ 'eid': ('External ID; non-URL data; general escape mechanism to allow '
+ 'access to information for applications that are too '
+ 'specialized to justify their own schemes'),
+ 'fax': ('a connection to a terminal that can handle telefaxes '
+ '(facsimiles); RFC 2806'),
+ 'feed': 'NetNewsWire feed',
+ 'file': 'Host-specific file names; RFC 1738',
+ 'finger': '',
+ 'freenet': '',
+ 'ftp': 'File Transfer Protocol; RFC 1738',
+ 'go': 'go; RFC 3368',
+ 'gopher': 'The Gopher Protocol',
+ 'gsm-sms': ('Global System for Mobile Communications Short Message '
+ 'Service'),
+ 'h323': ('video (audiovisual) communication on local area networks; '
+ 'RFC 3508'),
+ 'h324': ('video and audio communications over low bitrate connections '
+ 'such as POTS modem connections'),
+ 'hdl': 'CNRI handle system',
+ 'hnews': 'an HTTP-tunneling variant of the NNTP news protocol',
+ 'http': 'Hypertext Transfer Protocol; RFC 2616',
+ 'https': 'HTTP over SSL; RFC 2818',
+ 'hydra': 'SubEthaEdit URI. See http://www.codingmonkeys.de/subethaedit.',
+ 'iioploc': 'Internet Inter-ORB Protocol Location?',
+ 'ilu': 'Inter-Language Unification',
+ 'im': 'Instant Messaging; RFC 3860',
+ 'imap': 'Internet Message Access Protocol; RFC 2192',
+ 'info': 'Information Assets with Identifiers in Public Namespaces',
+ 'ior': 'CORBA interoperable object reference',
+ 'ipp': 'Internet Printing Protocol; RFC 3510',
+ 'irc': 'Internet Relay Chat',
+ 'iris.beep': 'iris.beep; RFC 3983',
+ 'iseek': 'See www.ambrosiasw.com; a little util for OS X.',
+ 'jar': 'Java archive',
+ 'javascript': ('JavaScript code; evaluates the expression after the '
+ 'colon'),
+ 'jdbc': 'JDBC connection URI.',
+ 'ldap': 'Lightweight Directory Access Protocol',
+ 'lifn': '',
+ 'livescript': '',
+ 'lrq': '',
+ 'mailbox': 'Mail folder access',
+ 'mailserver': 'Access to data available from mail servers',
+ 'mailto': 'Electronic mail address; RFC 2368',
+ 'md5': '',
+ 'mid': 'message identifier; RFC 2392',
+ 'mocha': '',
+ 'modem': ('a connection to a terminal that can handle incoming data '
+ 'calls; RFC 2806'),
+ 'mtqp': 'Message Tracking Query Protocol; RFC 3887',
+ 'mupdate': 'Mailbox Update (MUPDATE) Protocol; RFC 3656',
+ 'news': 'USENET news; RFC 1738',
+ 'nfs': 'Network File System protocol; RFC 2224',
+ 'nntp': 'USENET news using NNTP access; RFC 1738',
+ 'opaquelocktoken': 'RFC 2518',
+ 'phone': '',
+ 'pop': 'Post Office Protocol; RFC 2384',
+ 'pop3': 'Post Office Protocol v3',
+ 'pres': 'Presence; RFC 3859',
+ 'printer': '',
+ 'prospero': 'Prospero Directory Service; RFC 4157',
+ 'rdar': ('URLs found in Darwin source '
+ '(http://www.opensource.apple.com/darwinsource/).'),
+ 'res': '',
+ 'rtsp': 'real time streaming protocol; RFC 2326',
+ 'rvp': '',
+ 'rwhois': '',
+ 'rx': 'Remote Execution',
+ 'sdp': '',
+ 'service': 'service location; RFC 2609',
+ 'shttp': 'secure hypertext transfer protocol',
+ 'sip': 'Session Initiation Protocol; RFC 3261',
+ 'sips': 'secure session intitiaion protocol; RFC 3261',
+ 'smb': 'SAMBA filesystems.',
+ 'snews': 'For NNTP postings via SSL',
+ 'snmp': 'Simple Network Management Protocol; RFC 4088',
+ 'soap.beep': 'RFC 3288',
+ 'soap.beeps': 'RFC 3288',
+ 'ssh': 'Reference to interactive sessions via ssh.',
+ 't120': 'real time data conferencing (audiographics)',
+ 'tag': 'RFC 4151',
+ 'tcp': '',
+ 'tel': ('a connection to a terminal that handles normal voice '
+ 'telephone calls, a voice mailbox or another voice messaging '
+ 'system or a service that can be operated using DTMF tones; '
+ 'RFC 3966.'),
+ 'telephone': 'telephone',
+ 'telnet': 'Reference to interactive sessions; RFC 4248',
+ 'tftp': 'Trivial File Transfer Protocol; RFC 3617',
+ 'tip': 'Transaction Internet Protocol; RFC 2371',
+ 'tn3270': 'Interactive 3270 emulation sessions',
+ 'tv': '',
+ 'urn': 'Uniform Resource Name; RFC 2141',
+ 'uuid': '',
+ 'vemmi': 'versatile multimedia interface; RFC 2122',
+ 'videotex': '',
+ 'view-source': 'displays HTML code that was generated with JavaScript',
+ 'wais': 'Wide Area Information Servers; RFC 4156',
+ 'whodp': '',
+ 'whois++': 'Distributed directory service.',
+ 'x-man-page': ('Opens man page in Terminal.app on OS X '
+ '(see macosxhints.com)'),
+ 'xmlrpc.beep': 'RFC 3529',
+ 'xmlrpc.beeps': 'RFC 3529',
+ 'z39.50r': 'Z39.50 Retrieval; RFC 2056',
+ 'z39.50s': 'Z39.50 Session; RFC 2056',}
--- /dev/null
+# $Id: __init__.py 8239 2018-11-21 21:46:00Z 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'
+
+import os.path
+import sys
+
+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 Component.get_transforms(self) + [
+ universal.Messages,
+ universal.FilterMessages,
+ universal.StripClassesAndElements,]
+
+ document = None
+ """The document to write (Docutils doctree); set by `write`."""
+
+ output = None
+ """Final translated form of `document` (Unicode string for text, binary
+ string for other forms); 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):
+
+ # Used by HTML and LaTeX writer for output fragments:
+ self.parts = {}
+ """Mapping of document part names to fragments of `self.output`.
+ Values are Unicode strings; encoding is up to the client. The 'whole'
+ key should contain the entire document output.
+ """
+
+ 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()
+ output = self.destination.write(self.output)
+ return 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."""
+ self.parts['whole'] = self.output
+ self.parts['encoding'] = self.document.settings.output_encoding
+ 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',
+ 'html5': 'html5_polyglot',
+ 'latex': 'latex2e',
+ 'pprint': 'pseudoxml',
+ 'pformat': 'pseudoxml',
+ 'pdf': 'rlpdf',
+ 's5': 's5_html',
+ 'xelatex': 'xetex',
+ 'xhtml': 'html5_polyglot',
+ 'xhtml10': 'html4css1',
+ 'xml': 'docutils_xml'}
+
+def get_writer_class(writer_name):
+ """Return the Writer class from the `writer_name` module."""
+ writer_name = writer_name.lower()
+ if writer_name in _writer_aliases:
+ writer_name = _writer_aliases[writer_name]
+ try:
+ module = __import__(writer_name, globals(), locals(), level=1)
+ except ImportError:
+ module = __import__(writer_name, globals(), locals(), level=0)
+ return module.Writer
--- /dev/null
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+# :Author: David Goodger, Günter Milde
+# Based on the html4css1 writer by David Goodger.
+# :Maintainer: docutils-develop@lists.sourceforge.net
+# :Revision: $Revision: 8412 $
+# :Date: $Date: 2005-06-28$
+# :Copyright: © 2016 David Goodger, 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
+
+"""common definitions for Docutils HTML writers"""
+
+import sys
+import os.path
+import re
+
+try: # check for the Python Imaging Library
+ import PIL.Image
+except ImportError:
+ try: # sometimes PIL modules are put in PYTHONPATH's root
+ import Image
+ class PIL(object): pass # dummy wrapper
+ PIL.Image = Image
+ except ImportError:
+ PIL = None
+
+import docutils
+from docutils import nodes, utils, writers, languages, io
+from docutils.utils.error_reporting import SafeString
+from docutils.transforms import writer_aux
+from docutils.utils.math import (unichar2tex, pick_math_environment,
+ math2html, latex2mathml, tex2mathml_extern)
+
+if sys.version_info >= (3, 0):
+ from urllib.request import url2pathname
+else:
+ from urllib import url2pathname
+
+if sys.version_info >= (3, 0):
+ unicode = str # noqa
+
+
+class Writer(writers.Writer):
+
+ supported = ('html', 'xhtml') # update in subclass
+ """Formats this writer supports."""
+
+ # default_stylesheets = [] # set in subclass!
+ # default_stylesheet_dirs = ['.'] # set in subclass!
+ default_template = 'template.txt'
+ # default_template_path = ... # set in subclass!
+ # settings_spec = ... # set in subclass!
+
+ settings_defaults = {'output_encoding_error_handler': 'xmlcharrefreplace'}
+
+ # config_section = ... # set in subclass!
+ config_section_dependencies = ('writers', 'html writers')
+
+ visitor_attributes = (
+ 'head_prefix', 'head', 'stylesheet', 'body_prefix',
+ 'body_pre_docinfo', 'docinfo', 'body', 'body_suffix',
+ 'title', 'subtitle', 'header', 'footer', 'meta', 'fragment',
+ 'html_prolog', 'html_head', 'html_title', 'html_subtitle',
+ 'html_body')
+
+ def get_transforms(self):
+ return writers.Writer.get_transforms(self) + [writer_aux.Admonitions]
+
+ def translate(self):
+ self.visitor = visitor = self.translator_class(self.document)
+ self.document.walkabout(visitor)
+ for attr in self.visitor_attributes:
+ setattr(self, attr, getattr(visitor, attr))
+ self.output = self.apply_template()
+
+ def apply_template(self):
+ template_file = open(self.document.settings.template, 'rb')
+ template = unicode(template_file.read(), 'utf-8')
+ template_file.close()
+ subs = self.interpolation_dict()
+ return template % subs
+
+ def interpolation_dict(self):
+ subs = {}
+ settings = self.document.settings
+ for attr in self.visitor_attributes:
+ subs[attr] = ''.join(getattr(self, attr)).rstrip('\n')
+ subs['encoding'] = settings.output_encoding
+ subs['version'] = docutils.__version__
+ return subs
+
+ def assemble_parts(self):
+ writers.Writer.assemble_parts(self)
+ for part in self.visitor_attributes:
+ self.parts[part] = ''.join(getattr(self, part))
+
+
+class HTMLTranslator(nodes.NodeVisitor):
+
+ """
+ Generic Docutils to HTML translator.
+
+ See the `html4css1` and `html5_polyglot` writers for full featured
+ HTML writers.
+
+ .. IMPORTANT::
+ The `visit_*` and `depart_*` methods use a
+ heterogeneous stack, `self.context`.
+ When subclassing, make sure to be consistent in its use!
+
+ Examples for robust coding:
+
+ a) Override both `visit_*` and `depart_*` methods, don't call the
+ parent functions.
+
+ b) Extend both and unconditionally call the parent functions::
+
+ def visit_example(self, node):
+ if foo:
+ self.body.append('<div class="foo">')
+ html4css1.HTMLTranslator.visit_example(self, node)
+
+ def depart_example(self, node):
+ html4css1.HTMLTranslator.depart_example(self, node)
+ if foo:
+ self.body.append('</div>')
+
+ c) Extend both, calling the parent functions under the same
+ conditions::
+
+ def visit_example(self, node):
+ if foo:
+ self.body.append('<div class="foo">\n')
+ else: # call the parent method
+ _html_base.HTMLTranslator.visit_example(self, node)
+
+ def depart_example(self, node):
+ if foo:
+ self.body.append('</div>\n')
+ else: # call the parent method
+ _html_base.HTMLTranslator.depart_example(self, node)
+
+ d) Extend one method (call the parent), but don't otherwise use the
+ `self.context` stack::
+
+ def depart_example(self, node):
+ _html_base.HTMLTranslator.depart_example(self, node)
+ if foo:
+ # implementation-specific code
+ # that does not use `self.context`
+ self.body.append('</div>\n')
+
+ This way, changes in stack use will not bite you.
+ """
+
+ xml_declaration = '<?xml version="1.0" encoding="%s" ?>\n'
+ doctype = '<!DOCTYPE html>\n'
+ doctype_mathml = doctype
+
+ head_prefix_template = ('<html xmlns="http://www.w3.org/1999/xhtml"'
+ ' xml:lang="%(lang)s" lang="%(lang)s">\n<head>\n')
+ content_type = ('<meta charset="%s"/>\n')
+ generator = ('<meta name="generator" content="Docutils %s: '
+ 'http://docutils.sourceforge.net/" />\n')
+
+ # Template for the MathJax script in the header:
+ mathjax_script = '<script type="text/javascript" src="%s"></script>\n'
+
+ mathjax_url = 'file:/usr/share/javascript/mathjax/MathJax.js'
+ """
+ URL of the MathJax javascript library.
+
+ The MathJax library ought to be installed on the same
+ server as the rest of the deployed site files and specified
+ in the `math-output` setting appended to "mathjax".
+ See `Docutils Configuration`__.
+
+ __ http://docutils.sourceforge.net/docs/user/config.html#math-output
+
+ The fallback tries a local MathJax installation at
+ ``/usr/share/javascript/mathjax/MathJax.js``.
+ """
+
+ stylesheet_link = '<link rel="stylesheet" href="%s" type="text/css" />\n'
+ embedded_stylesheet = '<style type="text/css">\n\n%s\n</style>\n'
+ words_and_spaces = re.compile(r'[^ \n]+| +|\n')
+ # wrap point inside word:
+ in_word_wrap_point = re.compile(r'.+\W\W.+|[-?].+', re.U)
+ lang_attribute = 'lang' # name changes to 'xml:lang' in XHTML 1.1
+
+ special_characters = {ord('&'): u'&',
+ ord('<'): u'<',
+ ord('"'): u'"',
+ ord('>'): u'>',
+ ord('@'): u'@', # may thwart address harvesters
+ }
+ """Character references for characters with a special meaning in HTML."""
+
+
+ def __init__(self, document):
+ nodes.NodeVisitor.__init__(self, document)
+ self.settings = settings = document.settings
+ lcode = settings.language_code
+ self.language = languages.get_language(lcode, document.reporter)
+ self.meta = [self.generator % docutils.__version__]
+ self.head_prefix = []
+ self.html_prolog = []
+ if settings.xml_declaration:
+ self.head_prefix.append(self.xml_declaration
+ % settings.output_encoding)
+ # self.content_type = ""
+ # encoding not interpolated:
+ self.html_prolog.append(self.xml_declaration)
+ self.head = self.meta[:]
+ self.stylesheet = [self.stylesheet_call(path)
+ for path in utils.get_stylesheet_list(settings)]
+ self.body_prefix = ['</head>\n<body>\n']
+ # document title, subtitle display
+ self.body_pre_docinfo = []
+ # author, date, etc.
+ self.docinfo = []
+ self.body = []
+ self.fragment = []
+ self.body_suffix = ['</body>\n</html>\n']
+ self.section_level = 0
+ self.initial_header_level = int(settings.initial_header_level)
+
+ self.math_output = settings.math_output.split()
+ self.math_output_options = self.math_output[1:]
+ self.math_output = self.math_output[0].lower()
+
+ self.context = []
+ """Heterogeneous stack.
+
+ Used by visit_* and depart_* functions in conjunction with the tree
+ traversal. Make sure that the pops correspond to the pushes."""
+
+ self.topic_classes = [] # TODO: replace with self_in_contents
+ self.colspecs = []
+ self.compact_p = True
+ self.compact_simple = False
+ self.compact_field_list = False
+ self.in_docinfo = False
+ self.in_sidebar = False
+ self.in_footnote_list = False
+ self.title = []
+ self.subtitle = []
+ self.header = []
+ self.footer = []
+ self.html_head = [self.content_type] # charset not interpolated
+ self.html_title = []
+ self.html_subtitle = []
+ self.html_body = []
+ self.in_document_title = 0 # len(self.body) or 0
+ self.in_mailto = False
+ self.author_in_authors = False # for html4css1
+ self.math_header = []
+
+ def astext(self):
+ return ''.join(self.head_prefix + self.head
+ + self.stylesheet + self.body_prefix
+ + self.body_pre_docinfo + self.docinfo
+ + self.body + self.body_suffix)
+
+ def encode(self, text):
+ """Encode special characters in `text` & return."""
+ # Use only named entities known in both XML and HTML
+ # other characters are automatically encoded "by number" if required.
+ # @@@ A codec to do these and all other HTML entities would be nice.
+ text = unicode(text)
+ return text.translate(self.special_characters)
+
+ def cloak_mailto(self, uri):
+ """Try to hide a mailto: URL from harvesters."""
+ # Encode "@" using a URL octet reference (see RFC 1738).
+ # Further cloaking with HTML entities will be done in the
+ # `attval` function.
+ return uri.replace('@', '%40')
+
+ def cloak_email(self, addr):
+ """Try to hide the link text of a email link from harversters."""
+ # Surround at-signs and periods with <span> tags. ("@" has
+ # already been encoded to "@" by the `encode` method.)
+ addr = addr.replace('@', '<span>@</span>')
+ addr = addr.replace('.', '<span>.</span>')
+ return addr
+
+ def attval(self, text,
+ whitespace=re.compile('[\n\r\t\v\f]')):
+ """Cleanse, HTML encode, and return attribute value text."""
+ encoded = self.encode(whitespace.sub(' ', text))
+ if self.in_mailto and self.settings.cloak_email_addresses:
+ # Cloak at-signs ("%40") and periods with HTML entities.
+ encoded = encoded.replace('%40', '%40')
+ encoded = encoded.replace('.', '.')
+ return encoded
+
+ def stylesheet_call(self, path):
+ """Return code to reference or embed stylesheet file `path`"""
+ if self.settings.embed_stylesheet:
+ try:
+ content = io.FileInput(source_path=path,
+ encoding='utf-8').read()
+ self.settings.record_dependencies.add(path)
+ except IOError as err:
+ msg = u"Cannot embed stylesheet '%s': %s." % (
+ path, SafeString(err.strerror))
+ self.document.reporter.error(msg)
+ return '<--- %s --->\n' % msg
+ return self.embedded_stylesheet % content
+ # else link to style file:
+ if self.settings.stylesheet_path:
+ # adapt path relative to output (cf. config.html#stylesheet-path)
+ path = utils.relative_path(self.settings._destination, path)
+ return self.stylesheet_link % self.encode(path)
+
+ def starttag(self, node, tagname, suffix='\n', empty=False, **attributes):
+ """
+ Construct and return a start tag given a node (id & class attributes
+ are extracted), tag name, and optional attributes.
+ """
+ tagname = tagname.lower()
+ prefix = []
+ atts = {}
+ ids = []
+ for (name, value) in attributes.items():
+ atts[name.lower()] = value
+ classes = []
+ languages = []
+ # unify class arguments and move language specification
+ for cls in node.get('classes', []) + atts.pop('class', '').split():
+ if cls.startswith('language-'):
+ languages.append(cls[9:])
+ elif cls.strip() and cls not in classes:
+ classes.append(cls)
+ if languages:
+ # attribute name is 'lang' in XHTML 1.0 but 'xml:lang' in 1.1
+ atts[self.lang_attribute] = languages[0]
+ if classes:
+ atts['class'] = ' '.join(classes)
+ assert 'id' not in atts
+ ids.extend(node.get('ids', []))
+ if 'ids' in atts:
+ ids.extend(atts['ids'])
+ del atts['ids']
+ if ids:
+ atts['id'] = ids[0]
+ for id in ids[1:]:
+ # Add empty "span" elements for additional IDs. Note
+ # that we cannot use empty "a" elements because there
+ # may be targets inside of references, but nested "a"
+ # elements aren't allowed in XHTML (even if they do
+ # not all have a "href" attribute).
+ if empty or isinstance(node,
+ (nodes.bullet_list, nodes.docinfo,
+ nodes.definition_list, nodes.enumerated_list,
+ nodes.field_list, nodes.option_list,
+ nodes.table)):
+ # Insert target right in front of element.
+ prefix.append('<span id="%s"></span>' % id)
+ else:
+ # Non-empty tag. Place the auxiliary <span> tag
+ # *inside* the element, as the first child.
+ suffix += '<span id="%s"></span>' % id
+ attlist = sorted(atts.items())
+ parts = [tagname]
+ for name, value in attlist:
+ # value=None was used for boolean attributes without
+ # value, but this isn't supported by XHTML.
+ assert value is not None
+ if isinstance(value, list):
+ values = [unicode(v) for v in value]
+ parts.append('%s="%s"' % (name.lower(),
+ self.attval(' '.join(values))))
+ else:
+ parts.append('%s="%s"' % (name.lower(),
+ self.attval(unicode(value))))
+ if empty:
+ infix = ' /'
+ else:
+ infix = ''
+ return ''.join(prefix) + '<%s%s>' % (' '.join(parts), infix) + suffix
+
+ def emptytag(self, node, tagname, suffix='\n', **attributes):
+ """Construct and return an XML-compatible empty tag."""
+ return self.starttag(node, tagname, suffix, empty=True, **attributes)
+
+ def set_class_on_child(self, node, class_, index=0):
+ """
+ Set class `class_` on the visible child no. index of `node`.
+ Do nothing if node has fewer children than `index`.
+ """
+ children = [n for n in node if not isinstance(n, nodes.Invisible)]
+ try:
+ child = children[index]
+ except IndexError:
+ return
+ child['classes'].append(class_)
+
+ def visit_Text(self, node):
+ text = node.astext()
+ encoded = self.encode(text)
+ if self.in_mailto and self.settings.cloak_email_addresses:
+ encoded = self.cloak_email(encoded)
+ self.body.append(encoded)
+
+ def depart_Text(self, node):
+ pass
+
+ def visit_abbreviation(self, node):
+ # @@@ implementation incomplete ("title" attribute)
+ self.body.append(self.starttag(node, 'abbr', ''))
+
+ def depart_abbreviation(self, node):
+ self.body.append('</abbr>')
+
+ def visit_acronym(self, node):
+ # @@@ implementation incomplete ("title" attribute)
+ self.body.append(self.starttag(node, 'acronym', ''))
+
+ def depart_acronym(self, node):
+ self.body.append('</acronym>')
+
+ def visit_address(self, node):
+ self.visit_docinfo_item(node, 'address', meta=False)
+ self.body.append(self.starttag(node, 'pre',
+ suffix= '', CLASS='address'))
+
+ def depart_address(self, node):
+ self.body.append('\n</pre>\n')
+ self.depart_docinfo_item()
+
+ def visit_admonition(self, node):
+ node['classes'].insert(0, 'admonition')
+ self.body.append(self.starttag(node, 'div'))
+
+ def depart_admonition(self, node=None):
+ self.body.append('</div>\n')
+
+ attribution_formats = {'dash': (u'\u2014', ''),
+ 'parentheses': ('(', ')'),
+ 'parens': ('(', ')'),
+ 'none': ('', '')}
+
+ def visit_attribution(self, node):
+ prefix, suffix = self.attribution_formats[self.settings.attribution]
+ self.context.append(suffix)
+ self.body.append(
+ self.starttag(node, 'p', prefix, CLASS='attribution'))
+
+ def depart_attribution(self, node):
+ self.body.append(self.context.pop() + '</p>\n')
+
+ def visit_author(self, node):
+ if not(isinstance(node.parent, nodes.authors)):
+ self.visit_docinfo_item(node, 'author')
+ self.body.append('<p>')
+
+ def depart_author(self, node):
+ self.body.append('</p>')
+ if isinstance(node.parent, nodes.authors):
+ self.body.append('\n')
+ else:
+ self.depart_docinfo_item()
+
+ def visit_authors(self, node):
+ self.visit_docinfo_item(node, 'authors')
+
+ def depart_authors(self, node):
+ self.depart_docinfo_item()
+
+ def visit_block_quote(self, node):
+ self.body.append(self.starttag(node, 'blockquote'))
+
+ def depart_block_quote(self, node):
+ self.body.append('</blockquote>\n')
+
+ def check_simple_list(self, node):
+ """Check for a simple list that can be rendered compactly."""
+ visitor = SimpleListChecker(self.document)
+ try:
+ node.walk(visitor)
+ except nodes.NodeFound:
+ return False
+ else:
+ return True
+
+ # Compact lists
+ # ------------
+ # Include definition lists and field lists (in addition to ordered
+ # and unordered lists) in the test if a list is "simple" (cf. the
+ # html4css1.HTMLTranslator docstring and the SimpleListChecker class at
+ # the end of this file).
+
+ def is_compactable(self, node):
+ # explicite class arguments have precedence
+ if 'compact' in node['classes']:
+ return True
+ if 'open' in node['classes']:
+ return False
+ # check config setting:
+ if (isinstance(node, (nodes.field_list, nodes.definition_list))
+ and not self.settings.compact_field_lists):
+ return False
+ if (isinstance(node, (nodes.enumerated_list, nodes.bullet_list))
+ and not self.settings.compact_lists):
+ return False
+ # more special cases:
+ if (self.topic_classes == ['contents']): # TODO: self.in_contents
+ return True
+ # check the list items:
+ return self.check_simple_list(node)
+
+ def visit_bullet_list(self, node):
+ atts = {}
+ 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'] = 'simple'
+ self.body.append(self.starttag(node, 'ul', **atts))
+
+ def depart_bullet_list(self, node):
+ self.compact_simple, self.compact_p = self.context.pop()
+ self.body.append('</ul>\n')
+
+ def visit_caption(self, node):
+ self.body.append(self.starttag(node, 'p', '', CLASS='caption'))
+
+ def depart_caption(self, node):
+ self.body.append('</p>\n')
+
+ # citations
+ # ---------
+ # Use definition list instead of table for bibliographic references.
+ # Join adjacent citation entries.
+
+ def visit_citation(self, node):
+ if not self.in_footnote_list:
+ self.body.append('<dl class="citation">\n')
+ self.in_footnote_list = True
+
+ def depart_citation(self, node):
+ self.body.append('</dd>\n')
+ if not isinstance(node.next_node(descend=False, siblings=True),
+ nodes.citation):
+ self.body.append('</dl>\n')
+ self.in_footnote_list = False
+
+ def visit_citation_reference(self, node):
+ href = '#'
+ if 'refid' in node:
+ href += node['refid']
+ elif 'refname' in node:
+ href += self.document.nameids[node['refname']]
+ # else: # TODO system message (or already in the transform)?
+ # 'Citation reference missing.'
+ self.body.append(self.starttag(
+ node, 'a', '[', CLASS='citation-reference', href=href))
+
+ def depart_citation_reference(self, node):
+ self.body.append(']</a>')
+
+ # classifier
+ # ----------
+ # don't insert classifier-delimiter here (done by CSS)
+
+ def visit_classifier(self, node):
+ self.body.append(self.starttag(node, 'span', '', CLASS='classifier'))
+
+ def depart_classifier(self, node):
+ self.body.append('</span>')
+
+ 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',
+ style='width: %i%%' % colwidth))
+ self.body.append('</colgroup>\n')
+
+ def visit_comment(self, node,
+ sub=re.compile('-(?=-)').sub):
+ """Escape double-dashes in comment text."""
+ self.body.append('<!-- %s -->\n' % sub('- ', node.astext()))
+ # Content already processed:
+ raise nodes.SkipNode
+
+ 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')
+
+ def visit_container(self, node):
+ self.body.append(self.starttag(node, 'div', CLASS='docutils container'))
+
+ def depart_container(self, node):
+ self.body.append('</div>\n')
+
+ def visit_contact(self, node):
+ self.visit_docinfo_item(node, 'contact', meta=False)
+
+ def depart_contact(self, node):
+ self.depart_docinfo_item()
+
+ def visit_copyright(self, node):
+ self.visit_docinfo_item(node, 'copyright')
+
+ def depart_copyright(self, node):
+ self.depart_docinfo_item()
+
+ def visit_date(self, node):
+ self.visit_docinfo_item(node, 'date')
+
+ def depart_date(self, node):
+ self.depart_docinfo_item()
+
+ def visit_decoration(self, node):
+ pass
+
+ def depart_decoration(self, node):
+ pass
+
+ def visit_definition(self, node):
+ self.body.append('</dt>\n')
+ self.body.append(self.starttag(node, 'dd', ''))
+
+ def depart_definition(self, node):
+ self.body.append('</dd>\n')
+
+ def visit_definition_list(self, node):
+ classes = node.setdefault('classes', [])
+ if self.is_compactable(node):
+ classes.append('simple')
+ self.body.append(self.starttag(node, 'dl'))
+
+ def depart_definition_list(self, node):
+ self.body.append('</dl>\n')
+
+ def visit_definition_list_item(self, node):
+ # pass class arguments, ids and names to definition term:
+ node.children[0]['classes'] = (
+ node.get('classes', []) + node.children[0].get('classes', []))
+ node.children[0]['ids'] = (
+ node.get('ids', []) + node.children[0].get('ids', []))
+ node.children[0]['names'] = (
+ node.get('names', []) + node.children[0].get('names', []))
+
+ def depart_definition_list_item(self, node):
+ pass
+
+ def visit_description(self, node):
+ self.body.append(self.starttag(node, 'dd', ''))
+
+ def depart_description(self, node):
+ self.body.append('</dd>\n')
+
+ def visit_docinfo(self, node):
+ self.context.append(len(self.body))
+ classes = 'docinfo'
+ if (self.is_compactable(node)):
+ classes += ' simple'
+ self.body.append(self.starttag(node, 'dl', CLASS=classes))
+
+ def depart_docinfo(self, node):
+ self.body.append('</dl>\n')
+ 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.add_meta(meta_tag)
+ self.body.append('<dt class="%s">%s</dt>\n'
+ % (name, self.language.labels[name]))
+ self.body.append(self.starttag(node, 'dd', '', CLASS=name))
+
+ def depart_docinfo_item(self):
+ self.body.append('</dd>\n')
+
+ def visit_doctest_block(self, node):
+ self.body.append(self.starttag(node, 'pre', suffix='',
+ CLASS='code python doctest'))
+
+ def depart_doctest_block(self, node):
+ self.body.append('\n</pre>\n')
+
+ def visit_document(self, node):
+ title = (node.get('title', '') or os.path.basename(node['source'])
+ or 'docutils document without title')
+ self.head.append('<title>%s</title>\n' % self.encode(title))
+
+ 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.meta.insert(0, self.content_type % self.settings.output_encoding)
+ self.head.insert(0, self.content_type % self.settings.output_encoding)
+ if 'name="dcterms.' in ''.join(self.meta):
+ self.head.append(
+ '<link rel="schema.dcterms" href="http://purl.org/dc/terms/">')
+ 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.body_prefix.append(self.starttag(node, 'div', CLASS='document'))
+ self.body_suffix.insert(0, '</div>\n')
+ self.fragment.extend(self.body) # self.fragment is the "naked" body
+ self.html_body.extend(self.body_prefix[1:] + self.body_pre_docinfo
+ + self.docinfo + self.body
+ + self.body_suffix[:-1])
+ assert not self.context, 'len(context) = %s' % len(self.context)
+
+ def visit_emphasis(self, node):
+ self.body.append(self.starttag(node, 'em', ''))
+
+ def depart_emphasis(self, node):
+ self.body.append('</em>')
+
+ def visit_entry(self, node):
+ atts = {'class': []}
+ if isinstance(node.parent.parent, nodes.thead):
+ atts['class'].append('head')
+ if node.parent.parent.parent.stubs[node.parent.column]:
+ # "stubs" list is an attribute of the tgroup element
+ atts['class'].append('stub')
+ if atts['class']:
+ tagname = 'th'
+ atts['class'] = ' '.join(atts['class'])
+ else:
+ tagname = 'td'
+ del atts['class']
+ node.parent.column += 1
+ if 'morerows' in node:
+ atts['rowspan'] = node['morerows'] + 1
+ if 'morecols' in node:
+ atts['colspan'] = node['morecols'] + 1
+ node.parent.column += node['morecols']
+ self.body.append(self.starttag(node, tagname, '', **atts))
+ self.context.append('</%s>\n' % tagname.lower())
+ # TODO: why does the html4css1 writer insert an NBSP into empty cells?
+ # if len(node) == 0: # empty cell
+ # self.body.append(' ') # no-break space
+
+ def depart_entry(self, node):
+ self.body.append(self.context.pop())
+
+ def visit_enumerated_list(self, node):
+ atts = {}
+ if 'start' in node:
+ atts['start'] = node['start']
+ if 'enumtype' in node:
+ atts['class'] = node['enumtype']
+ if self.is_compactable(node):
+ atts['class'] = (atts.get('class', '') + ' simple').strip()
+ self.body.append(self.starttag(node, 'ol', **atts))
+
+ def depart_enumerated_list(self, node):
+ self.body.append('</ol>\n')
+
+ def visit_field_list(self, node):
+ # Keep simple paragraphs in the field_body to enable CSS
+ # rule to start body on new line if the label is too long
+ classes = 'field-list'
+ if (self.is_compactable(node)):
+ classes += ' simple'
+ self.body.append(self.starttag(node, 'dl', CLASS=classes))
+
+ def depart_field_list(self, node):
+ self.body.append('</dl>\n')
+
+ def visit_field(self, node):
+ pass
+
+ def depart_field(self, node):
+ pass
+
+ # as field is ignored, pass class arguments to field-name and field-body:
+
+ def visit_field_name(self, node):
+ self.body.append(self.starttag(node, 'dt', '',
+ CLASS=''.join(node.parent['classes'])))
+
+ def depart_field_name(self, node):
+ self.body.append('</dt>\n')
+
+ def visit_field_body(self, node):
+ self.body.append(self.starttag(node, 'dd', '',
+ CLASS=''.join(node.parent['classes'])))
+ # prevent misalignment of following content if the field is empty:
+ if not node.children:
+ self.body.append('<p></p>')
+
+ def depart_field_body(self, node):
+ self.body.append('</dd>\n')
+
+ def visit_figure(self, node):
+ atts = {'class': 'figure'}
+ if node.get('width'):
+ atts['style'] = 'width: %s' % node['width']
+ if node.get('align'):
+ atts['class'] += " align-" + node['align']
+ self.body.append(self.starttag(node, 'div', **atts))
+
+ def depart_figure(self, node):
+ self.body.append('</div>\n')
+
+ # use HTML 5 <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, 'div', CLASS='footer'),
+ '<hr class="footer" />\n']
+ footer.extend(self.body[start:])
+ footer.append('\n</div>\n')
+ self.footer.extend(footer)
+ self.body_suffix[:0] = footer
+ del self.body[start:]
+
+ # footnotes
+ # ---------
+ # use definition list instead of table for footnote text
+
+ # TODO: use the new HTML5 element <aside>? (Also for footnote text)
+ def visit_footnote(self, node):
+ if not self.in_footnote_list:
+ classes = 'footnote ' + self.settings.footnote_references
+ self.body.append('<dl class="%s">\n'%classes)
+ self.in_footnote_list = True
+
+ def depart_footnote(self, node):
+ self.body.append('</dd>\n')
+ if not isinstance(node.next_node(descend=False, siblings=True),
+ nodes.footnote):
+ self.body.append('</dl>\n')
+ self.in_footnote_list = False
+
+ def visit_footnote_reference(self, node):
+ href = '#' + node['refid']
+ classes = 'footnote-reference ' + self.settings.footnote_references
+ self.body.append(self.starttag(node, 'a', '', #suffix,
+ CLASS=classes, href=href))
+
+ def depart_footnote_reference(self, node):
+ self.body.append('</a>')
+
+ # Docutils-generated text: put section numbers in a span for CSS styling:
+ def visit_generated(self, node):
+ if 'sectnum' in node['classes']:
+ # get section number (strip trailing no-break-spaces)
+ sectnum = node.astext().rstrip(u' ')
+ self.body.append('<span class="sectnum">%s</span> '
+ % self.encode(sectnum))
+ # Content already processed:
+ raise nodes.SkipNode
+
+ def depart_generated(self, node):
+ pass
+
+ def visit_header(self, node):
+ self.context.append(len(self.body))
+
+ def depart_header(self, node):
+ start = self.context.pop()
+ header = [self.starttag(node, 'div', CLASS='header')]
+ header.extend(self.body[start:])
+ header.append('\n<hr class="header"/>\n</div>\n')
+ self.body_prefix.extend(header)
+ self.header.extend(header)
+ del self.body[start:]
+
+ # Image types to place in an <object> element
+ object_image_types = {'.swf': 'application/x-shockwave-flash'}
+
+ 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 not ('width' in node and 'height' in node)
+ and self.settings.file_insertion_enabled):
+ imagepath = url2pathname(uri)
+ try:
+ img = PIL.Image.open(
+ imagepath.encode(sys.getfilesystemencoding()))
+ except (IOError, UnicodeEncodeError):
+ pass # TODO: warn?
+ 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]
+ del img
+ 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)
+ if (isinstance(node.parent, nodes.TextElement) or
+ (isinstance(node.parent, nodes.reference) and
+ not isinstance(node.parent.parent, nodes.TextElement))):
+ # Inline context or surrounded by <a>...</a>.
+ suffix = ''
+ else:
+ suffix = '\n'
+ 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', suffix, **atts) +
+ node.get('alt', uri) + '</object>' + suffix)
+ else:
+ self.body.append(self.emptytag(node, 'img', suffix, **atts))
+
+ def depart_image(self, node):
+ pass
+
+ def visit_inline(self, node):
+ self.body.append(self.starttag(node, 'span', ''))
+
+ def depart_inline(self, node):
+ self.body.append('</span>')
+
+ # footnote and citation labels:
+ def visit_label(self, node):
+ if (isinstance(node.parent, nodes.footnote)):
+ classes = self.settings.footnote_references
+ else:
+ classes = 'brackets'
+ # pass parent node to get id into starttag:
+ self.body.append(self.starttag(node.parent, 'dt', '', CLASS='label'))
+ self.body.append(self.starttag(node, 'span', '', CLASS=classes))
+ # footnote/citation backrefs:
+ if self.settings.footnote_backlinks:
+ backrefs = node.parent['backrefs']
+ if len(backrefs) == 1:
+ self.body.append('<a class="fn-backref" href="#%s">'
+ % backrefs[0])
+
+ def depart_label(self, node):
+ if self.settings.footnote_backlinks:
+ backrefs = node.parent['backrefs']
+ if len(backrefs) == 1:
+ self.body.append('</a>')
+ self.body.append('</span>')
+ if self.settings.footnote_backlinks and len(backrefs) > 1:
+ backlinks = ['<a href="#%s">%s</a>' % (ref, i)
+ for (i, ref) in enumerate(backrefs, 1)]
+ self.body.append('<span class="fn-backref">(%s)</span>'
+ % ','.join(backlinks))
+ self.body.append('</dt>\n<dd>')
+
+ def visit_legend(self, node):
+ self.body.append(self.starttag(node, 'div', CLASS='legend'))
+
+ def depart_legend(self, node):
+ self.body.append('</div>\n')
+
+ def visit_line(self, node):
+ self.body.append(self.starttag(node, 'div', suffix='', CLASS='line'))
+ if not len(node):
+ self.body.append('<br />')
+
+ def depart_line(self, node):
+ self.body.append('</div>\n')
+
+ def visit_line_block(self, node):
+ self.body.append(self.starttag(node, 'div', CLASS='line-block'))
+
+ def depart_line_block(self, node):
+ self.body.append('</div>\n')
+
+ def visit_list_item(self, node):
+ self.body.append(self.starttag(node, 'li', ''))
+
+ def depart_list_item(self, node):
+ self.body.append('</li>\n')
+
+ # inline literal
+ def visit_literal(self, node):
+ # special case: "code" role
+ classes = node.get('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, 'span', '', 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('<span class="pre">%s</span>'
+ % self.encode(token))
+ else:
+ self.body.append(self.encode(token))
+ self.body.append('</span>')
+ # Content already processed:
+ raise nodes.SkipNode
+
+ def depart_literal(self, node):
+ # skipped unless literal element is from "code" role:
+ self.body.append('</code>')
+
+ def visit_literal_block(self, node):
+ self.body.append(self.starttag(node, 'pre', '', CLASS='literal-block'))
+ if 'code' in node.get('classes', []):
+ self.body.append('<code>')
+
+ def depart_literal_block(self, node):
+ if 'code' in node.get('classes', []):
+ self.body.append('</code>')
+ self.body.append('</pre>\n')
+
+ # Mathematics:
+ # As there is no native HTML math support, we provide alternatives
+ # for the math-output: LaTeX and MathJax simply wrap the content,
+ # HTML and MathML also convert the math_code.
+ # HTML container
+ math_tags = {# math_output: (block, inline, class-arguments)
+ 'mathml': ('div', '', ''),
+ 'html': ('div', 'span', 'formula'),
+ 'mathjax': ('div', 'span', 'math'),
+ 'latex': ('pre', 'tt', 'math'),
+ }
+
+ def visit_math(self, node, math_env=''):
+ # If the method is called from visit_math_block(), math_env != ''.
+
+ if self.math_output not in self.math_tags:
+ self.document.reporter.error(
+ 'math-output format "%s" not supported '
+ 'falling back to "latex"'% self.math_output)
+ self.math_output = 'latex'
+ tag = self.math_tags[self.math_output][math_env == '']
+ clsarg = self.math_tags[self.math_output][2]
+ # LaTeX container
+ wrappers = {# math_mode: (inline, block)
+ 'mathml': ('$%s$', u'\\begin{%s}\n%s\n\\end{%s}'),
+ 'html': ('$%s$', u'\\begin{%s}\n%s\n\\end{%s}'),
+ 'mathjax': (r'\(%s\)', u'\\begin{%s}\n%s\n\\end{%s}'),
+ 'latex': (None, None),
+ }
+ wrapper = wrappers[self.math_output][math_env != '']
+ if self.math_output == 'mathml' and (not self.math_output_options or
+ self.math_output_options[0] == 'blahtexml'):
+ wrapper = None
+ # get and wrap content
+ math_code = node.astext().translate(unichar2tex.uni2tex_table)
+ if wrapper:
+ try: # wrapper with three "%s"
+ math_code = wrapper % (math_env, math_code, math_env)
+ except TypeError: # wrapper with one "%s"
+ math_code = wrapper % math_code
+ # settings and conversion
+ if self.math_output in ('latex', 'mathjax'):
+ math_code = self.encode(math_code)
+ if self.math_output == 'mathjax' and not self.math_header:
+ try:
+ self.mathjax_url = self.math_output_options[0]
+ except IndexError:
+ self.document.reporter.warning('No MathJax URL specified, '
+ 'using local fallback (see config.html)')
+ # append configuration, if not already present in the URL:
+ # input LaTeX with AMS, output common HTML
+ if '?' not in self.mathjax_url:
+ self.mathjax_url += '?config=TeX-AMS_CHTML'
+ self.math_header = [self.mathjax_script % self.mathjax_url]
+ elif self.math_output == 'html':
+ if self.math_output_options and not self.math_header:
+ self.math_header = [self.stylesheet_call(
+ utils.find_file_in_dirs(s, self.settings.stylesheet_dirs))
+ for s in self.math_output_options[0].split(',')]
+ # TODO: fix display mode in matrices and fractions
+ math2html.DocumentParameters.displaymode = (math_env != '')
+ math_code = math2html.math2html(math_code)
+ elif self.math_output == 'mathml':
+ if 'XHTML 1' in self.doctype:
+ self.doctype = self.doctype_mathml
+ self.content_type = self.content_type_mathml
+ converter = ' '.join(self.math_output_options).lower()
+ try:
+ if converter == 'latexml':
+ math_code = tex2mathml_extern.latexml(math_code,
+ self.document.reporter)
+ elif converter == 'ttm':
+ math_code = tex2mathml_extern.ttm(math_code,
+ self.document.reporter)
+ elif converter == 'blahtexml':
+ math_code = tex2mathml_extern.blahtexml(math_code,
+ inline=not(math_env),
+ reporter=self.document.reporter)
+ elif not converter:
+ math_code = latex2mathml.tex2mathml(math_code,
+ inline=not(math_env))
+ else:
+ self.document.reporter.error('option "%s" not supported '
+ 'with math-output "MathML"')
+ except OSError:
+ raise OSError('is "latexmlmath" in your PATH?')
+ except SyntaxError as err:
+ err_node = self.document.reporter.error(err, base_node=node)
+ self.visit_system_message(err_node)
+ self.body.append(self.starttag(node, 'p'))
+ self.body.append(u','.join(err.args))
+ self.body.append('</p>\n')
+ self.body.append(self.starttag(node, 'pre',
+ CLASS='literal-block'))
+ self.body.append(self.encode(math_code))
+ self.body.append('\n</pre>\n')
+ self.depart_system_message(err_node)
+ raise nodes.SkipNode
+ # append to document body
+ if tag:
+ self.body.append(self.starttag(node, tag,
+ suffix='\n'*bool(math_env),
+ CLASS=clsarg))
+ self.body.append(math_code)
+ if math_env: # block mode (equation, display)
+ self.body.append('\n')
+ if tag:
+ self.body.append('</%s>' % tag)
+ if math_env:
+ self.body.append('\n')
+ # Content already processed:
+ raise nodes.SkipNode
+
+ def depart_math(self, node):
+ pass # never reached
+
+ def visit_math_block(self, node):
+ math_env = pick_math_environment(node.astext())
+ self.visit_math(node, math_env=math_env)
+
+ def depart_math_block(self, node):
+ pass # never reached
+
+ # Meta tags: 'lang' attribute replaced by 'xml:lang' in XHTML 1.1
+ # HTML5/polyglot recommends using both
+ def visit_meta(self, node):
+ meta = self.emptytag(node, 'meta', **node.non_default_attributes())
+ self.add_meta(meta)
+
+ def depart_meta(self, node):
+ pass
+
+ def add_meta(self, tag):
+ self.meta.append(tag)
+ self.head.append(tag)
+
+ def visit_option(self, node):
+ self.body.append(self.starttag(node, 'span', '', CLASS='option'))
+
+ def depart_option(self, node):
+ self.body.append('</span>')
+ if isinstance(node.next_node(descend=False, siblings=True),
+ nodes.option):
+ self.body.append(', ')
+
+ def visit_option_argument(self, node):
+ self.body.append(node.get('delimiter', ' '))
+ self.body.append(self.starttag(node, 'var', ''))
+
+ def depart_option_argument(self, node):
+ self.body.append('</var>')
+
+ def visit_option_group(self, node):
+ self.body.append(self.starttag(node, 'dt', ''))
+ self.body.append('<kbd>')
+
+ def depart_option_group(self, node):
+ self.body.append('</kbd></dt>\n')
+
+ def visit_option_list(self, node):
+ self.body.append(
+ self.starttag(node, 'dl', CLASS='option-list'))
+
+ def depart_option_list(self, node):
+ self.body.append('</dl>\n')
+
+ def visit_option_list_item(self, node):
+ pass
+
+ def depart_option_list_item(self, node):
+ pass
+
+ def visit_option_string(self, node):
+ pass
+
+ def depart_option_string(self, node):
+ pass
+
+ def visit_organization(self, node):
+ self.visit_docinfo_item(node, 'organization')
+
+ def depart_organization(self, node):
+ self.depart_docinfo_item()
+
+ # Do not omit <p> tags
+ # --------------------
+ #
+ # The HTML4CSS1 writer does this to "produce
+ # visually compact lists (less vertical whitespace)". This writer
+ # relies on CSS rules for"visual compactness".
+ #
+ # * In XHTML 1.1, e.g. a <blockquote> element may not contain
+ # character data, so you cannot drop the <p> tags.
+ # * Keeping simple paragraphs in the field_body enables a CSS
+ # rule to start the field-body on a new line if the label is too long
+ # * it makes the code simpler.
+ #
+ # TODO: omit paragraph tags in simple table cells?
+
+ def visit_paragraph(self, node):
+ self.body.append(self.starttag(node, 'p', ''))
+
+ def depart_paragraph(self, node):
+ self.body.append('</p>')
+ if not (isinstance(node.parent, (nodes.list_item, nodes.entry)) and
+ (len(node.parent) == 1)):
+ self.body.append('\n')
+
+ def visit_problematic(self, node):
+ if node.hasattr('refid'):
+ self.body.append('<a href="#%s">' % node['refid'])
+ self.context.append('</a>')
+ else:
+ self.context.append('')
+ self.body.append(self.starttag(node, 'span', '', CLASS='problematic'))
+
+ def depart_problematic(self, node):
+ self.body.append('</span>')
+ self.body.append(self.context.pop())
+
+ def visit_raw(self, node):
+ if 'html' in node.get('format', '').split():
+ t = isinstance(node.parent, nodes.TextElement) and 'span' or 'div'
+ if node['classes']:
+ self.body.append(self.starttag(node, t, suffix=''))
+ self.body.append(node.astext())
+ if node['classes']:
+ self.body.append('</%s>' % t)
+ # Keep non-HTML raw text out of output:
+ raise nodes.SkipNode
+
+ def visit_reference(self, node):
+ atts = {'class': 'reference'}
+ if 'refuri' in node:
+ atts['href'] = node['refuri']
+ if ( self.settings.cloak_email_addresses
+ and atts['href'].startswith('mailto:')):
+ atts['href'] = self.cloak_mailto(atts['href'])
+ self.in_mailto = True
+ atts['class'] += ' external'
+ else:
+ assert 'refid' in node, \
+ 'References must have "refuri" or "refid" attribute.'
+ atts['href'] = '#' + node['refid']
+ atts['class'] += ' internal'
+ if not isinstance(node.parent, nodes.TextElement):
+ assert len(node) == 1 and isinstance(node[0], nodes.image)
+ atts['class'] += ' image-reference'
+ self.body.append(self.starttag(node, 'a', '', **atts))
+
+ def depart_reference(self, node):
+ self.body.append('</a>')
+ if not isinstance(node.parent, nodes.TextElement):
+ self.body.append('\n')
+ self.in_mailto = False
+
+ def visit_revision(self, node):
+ self.visit_docinfo_item(node, 'revision', meta=False)
+
+ def depart_revision(self, node):
+ self.depart_docinfo_item()
+
+ def visit_row(self, node):
+ self.body.append(self.starttag(node, 'tr', ''))
+ node.column = 0
+
+ def depart_row(self, node):
+ self.body.append('</tr>\n')
+
+ def visit_rubric(self, node):
+ self.body.append(self.starttag(node, 'p', '', CLASS='rubric'))
+
+ def depart_rubric(self, node):
+ self.body.append('</p>\n')
+
+ # TODO: use the new HTML 5 element <section>?
+ def visit_section(self, node):
+ self.section_level += 1
+ self.body.append(
+ self.starttag(node, 'div', CLASS='section'))
+
+ def depart_section(self, node):
+ self.section_level -= 1
+ self.body.append('</div>\n')
+
+ # TODO: use the new HTML5 element <aside>? (Also for footnote text)
+ def visit_sidebar(self, node):
+ self.body.append(
+ self.starttag(node, 'div', CLASS='sidebar'))
+ self.in_sidebar = True
+
+ def depart_sidebar(self, node):
+ self.body.append('</div>\n')
+ self.in_sidebar = False
+
+ def visit_status(self, node):
+ self.visit_docinfo_item(node, 'status', meta=False)
+
+ def depart_status(self, node):
+ self.depart_docinfo_item()
+
+ def visit_strong(self, node):
+ self.body.append(self.starttag(node, 'strong', ''))
+
+ def depart_strong(self, node):
+ self.body.append('</strong>')
+
+ def visit_subscript(self, node):
+ self.body.append(self.starttag(node, 'sub', ''))
+
+ def depart_subscript(self, node):
+ self.body.append('</sub>')
+
+ def visit_substitution_definition(self, node):
+ """Internal only."""
+ raise nodes.SkipNode
+
+ def visit_substitution_reference(self, node):
+ self.unimplemented_visit(node)
+
+ # h1–h6 elements must not be used to markup subheadings, subtitles,
+ # alternative titles and taglines unless intended to be the heading for a
+ # new section or subsection.
+ # -- http://www.w3.org/TR/html/sections.html#headings-and-sections
+ def visit_subtitle(self, node):
+ if isinstance(node.parent, nodes.sidebar):
+ classes = 'sidebar-subtitle'
+ elif isinstance(node.parent, nodes.document):
+ classes = 'subtitle'
+ self.in_document_title = len(self.body)+1
+ elif isinstance(node.parent, nodes.section):
+ classes = 'section-subtitle'
+ self.body.append(self.starttag(node, 'p', '', CLASS=classes))
+
+ def depart_subtitle(self, node):
+ self.body.append('</p>\n')
+ if isinstance(node.parent, nodes.document):
+ 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[:]
+
+ def visit_superscript(self, node):
+ self.body.append(self.starttag(node, 'sup', ''))
+
+ def depart_superscript(self, node):
+ self.body.append('</sup>')
+
+ 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 '
+ '(<span class="docutils literal">%s</span>%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')
+
+ def visit_table(self, node):
+ atts = {}
+ classes = [cls.strip(u' \t\n')
+ for cls in self.settings.table_style.split(',')]
+ if 'align' in node:
+ classes.append('align-%s' % node['align'])
+ if 'width' in node:
+ atts['style'] = 'width: %s' % node['width']
+ tag = self.starttag(node, 'table', CLASS=' '.join(classes), **atts)
+ self.body.append(tag)
+
+ def depart_table(self, node):
+ self.body.append('</table>\n')
+
+ def visit_target(self, node):
+ if not ('refuri' in node or 'refid' in node
+ or 'refname' in node):
+ self.body.append(self.starttag(node, 'span', '', CLASS='target'))
+ self.context.append('</span>')
+ else:
+ self.context.append('')
+
+ def depart_target(self, node):
+ self.body.append(self.context.pop())
+
+ # no hard-coded vertical alignment in table body
+ def visit_tbody(self, node):
+ self.body.append(self.starttag(node, 'tbody'))
+
+ def depart_tbody(self, node):
+ self.body.append('</tbody>\n')
+
+ def visit_term(self, node):
+ self.body.append(self.starttag(node, 'dt', ''))
+
+ def depart_term(self, node):
+ """
+ Leave the end tag to `self.visit_definition()`, in case there's a
+ classifier.
+ """
+ pass
+
+ def visit_tgroup(self, node):
+ self.colspecs = []
+ node.stubs = []
+
+ def depart_tgroup(self, node):
+ pass
+
+ def visit_thead(self, node):
+ self.body.append(self.starttag(node, 'thead'))
+
+ def depart_thead(self, node):
+ self.body.append('</thead>\n')
+
+ def visit_title(self, node):
+ """Only 6 section levels are supported by HTML."""
+ close_tag = '</p>\n'
+ if isinstance(node.parent, nodes.topic):
+ self.body.append(
+ self.starttag(node, 'p', '', CLASS='topic-title'))
+ elif isinstance(node.parent, nodes.sidebar):
+ self.body.append(
+ self.starttag(node, 'p', '', CLASS='sidebar-title'))
+ elif isinstance(node.parent, nodes.Admonition):
+ self.body.append(
+ self.starttag(node, 'p', '', CLASS='admonition-title'))
+ elif isinstance(node.parent, nodes.table):
+ self.body.append(
+ self.starttag(node, 'caption', ''))
+ close_tag = '</caption>\n'
+ elif isinstance(node.parent, nodes.document):
+ self.body.append(self.starttag(node, 'h1', '', CLASS='title'))
+ close_tag = '</h1>\n'
+ self.in_document_title = len(self.body)
+ else:
+ assert isinstance(node.parent, nodes.section)
+ h_level = self.section_level + self.initial_header_level - 1
+ atts = {}
+ if (len(node.parent) >= 2 and
+ isinstance(node.parent[1], nodes.subtitle)):
+ atts['CLASS'] = 'with-subtitle'
+ self.body.append(
+ self.starttag(node, 'h%s' % h_level, '', **atts))
+ atts = {}
+ if node.hasattr('refid'):
+ atts['class'] = 'toc-backref'
+ atts['href'] = '#' + node['refid']
+ if atts:
+ self.body.append(self.starttag({}, 'a', '', **atts))
+ close_tag = '</a></h%s>\n' % (h_level)
+ else:
+ close_tag = '</h%s>\n' % (h_level)
+ self.context.append(close_tag)
+
+ def depart_title(self, node):
+ self.body.append(self.context.pop())
+ if self.in_document_title:
+ self.title = self.body[self.in_document_title:-1]
+ self.in_document_title = 0
+ self.body_pre_docinfo.extend(self.body)
+ self.html_title.extend(self.body)
+ del self.body[:]
+
+ def visit_title_reference(self, node):
+ self.body.append(self.starttag(node, 'cite', ''))
+
+ def depart_title_reference(self, node):
+ self.body.append('</cite>')
+
+ # TODO: use the new HTML5 element <aside>? (Also for footnote text)
+ def visit_topic(self, node):
+ self.body.append(self.starttag(node, 'div', CLASS='topic'))
+ self.topic_classes = node['classes']
+ # TODO: replace with ::
+ # self.in_contents = 'contents' in node['classes']
+
+ def depart_topic(self, node):
+ self.body.append('</div>\n')
+ self.topic_classes = []
+ # TODO self.in_contents = False
+
+ def visit_transition(self, node):
+ self.body.append(self.emptytag(node, 'hr', CLASS='docutils'))
+
+ def depart_transition(self, node):
+ pass
+
+ def visit_version(self, node):
+ self.visit_docinfo_item(node, 'version', meta=False)
+
+ def depart_version(self, node):
+ self.depart_docinfo_item()
+
+ def unimplemented_visit(self, node):
+ raise NotImplementedError('visiting unimplemented node type: %s'
+ % node.__class__.__name__)
+
+
+class SimpleListChecker(nodes.GenericNodeVisitor):
+
+ """
+ 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.
+
+ This version also checks for simple field lists and docinfo.
+ """
+
+ def default_visit(self, node):
+ raise nodes.NodeFound
+
+ def visit_list_item(self, node):
+ children = [child for child in node.children
+ if not isinstance(child, nodes.Invisible)]
+ if (children and isinstance(children[0], nodes.paragraph)
+ and (isinstance(children[-1], nodes.bullet_list) or
+ isinstance(children[-1], nodes.enumerated_list) or
+ isinstance(children[-1], nodes.field_list))):
+ children.pop()
+ if len(children) <= 1:
+ return
+ else:
+ raise nodes.NodeFound
+
+ def pass_node(self, node):
+ pass
+
+ def ignore_node(self, node):
+ # ignore nodes that are never complex (can contain only inline nodes)
+ raise nodes.SkipNode
+
+ # Paragraphs and text
+ visit_Text = ignore_node
+ visit_paragraph = ignore_node
+
+ # Lists
+ visit_bullet_list = pass_node
+ visit_enumerated_list = pass_node
+ visit_docinfo = pass_node
+
+ # Docinfo nodes:
+ visit_author = ignore_node
+ visit_authors = visit_list_item
+ visit_address = visit_list_item
+ visit_contact = pass_node
+ visit_copyright = ignore_node
+ visit_date = ignore_node
+ visit_organization = ignore_node
+ visit_status = ignore_node
+ visit_version = visit_list_item
+
+ # Definition list:
+ visit_definition_list = pass_node
+ visit_definition_list_item = pass_node
+ visit_term = ignore_node
+ visit_classifier = pass_node
+ visit_definition = visit_list_item
+
+ # Field list:
+ visit_field_list = pass_node
+ visit_field = pass_node
+ # the field body corresponds to a list item
+ visit_field_body = visit_list_item
+ visit_field_name = ignore_node
+
+ # Invisible nodes should be ignored.
+ visit_comment = ignore_node
+ visit_substitution_definition = ignore_node
+ visit_target = ignore_node
+ visit_pending = ignore_node
--- /dev/null
+# $Id: docutils_xml.py 8368 2019-08-27 12:10:14Z 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
+http://docutils.sourceforge.net/docs/ref/docutils.dtd.
+"""
+
+__docformat__ = 'reStructuredText'
+
+import sys
+import xml.sax.saxutils
+
+import docutils
+from docutils import frontend, writers, nodes
+
+if sys.version_info >= (3, 0):
+ from io import StringIO # noqa
+else:
+ from StringIO import StringIO # noqa
+
+
+if sys.version_info >= (3, 0):
+ unicode = str # noqa
+
+
+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):
+
+ xml_declaration = '<?xml version="1.0" encoding="%s"?>\n'
+ # 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/exctract 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(
+ self.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.image, nodes.colspec, nodes.transition) # empty elements
+
+ 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
+ # @@ make nodes.literal an instance of FixedTextElement?
+ 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:
+ if isinstance(xml_string, unicode) and sys.version_info < (3, 0):
+ xml_string = xml_string.encode('utf8')
+ try:
+ self.xmlparser.parse(StringIO(xml_string))
+ except xml.sax._exceptions.SAXParseException as error:
+ 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
--- /dev/null
+# $Id: __init__.py 8242 2018-11-29 08:11:18Z 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 docutils
+from docutils import frontend, nodes, writers, io
+from docutils.transforms import writer_aux
+from docutils.writers import _html_base
+
+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__)),
+ # for math.css
+ os.path.abspath(os.path.join(
+ os.path.dirname(os.path.dirname(__file__)), 'html5_polyglot'))
+ ]
+
+ default_template = 'template.txt'
+ default_template_path = os.path.join(
+ os.path.dirname(os.path.abspath(__file__)), default_template)
+
+ settings_spec = (
+ 'HTML-Specific Options',
+ None,
+ (('Specify the template file (UTF-8 encoded). Default is "%s".'
+ % default_template_path,
+ ['--template'],
+ {'default': default_template_path, 'metavar': '<file>'}),
+ ('Comma separated list of stylesheet URLs. '
+ 'Overrides previous --stylesheet and --stylesheet-path settings.',
+ ['--stylesheet'],
+ {'metavar': '<URL[,URL,...]>', 'overrides': 'stylesheet_path',
+ 'validator': frontend.validate_comma_separated_list}),
+ ('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}),
+ ('Embed the stylesheet(s) in the output HTML file. The stylesheet '
+ 'files must be accessible during processing. This is the default.',
+ ['--embed-stylesheet'],
+ {'default': 1, 'action': 'store_true',
+ 'validator': frontend.validate_boolean}),
+ ('Link to the stylesheet(s) in the output HTML file. '
+ 'Default: embed stylesheets.',
+ ['--link-stylesheet'],
+ {'dest': 'embed_stylesheet', 'action': 'store_false'}),
+ ('Comma-separated list of directories where stylesheets are found. '
+ 'Used by --stylesheet-path when expanding relative path arguments. '
+ 'Default: "%s"' % default_stylesheet_dirs,
+ ['--stylesheet-dirs'],
+ {'metavar': '<dir[,dir,...]>',
+ 'validator': frontend.validate_comma_separated_list,
+ 'default': default_stylesheet_dirs}),
+ ('Specify the initial header level. Default is 1 for "<h1>". '
+ 'Does not affect document title & subtitle (see --no-doc-title).',
+ ['--initial-header-level'],
+ {'choices': '1 2 3 4 5 6'.split(), 'default': '1',
+ 'metavar': '<level>'}),
+ ('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}),
+ ('Format for footnote references: one of "superscript" or '
+ '"brackets". Default is "brackets".',
+ ['--footnote-references'],
+ {'choices': ['superscript', 'brackets'], 'default': 'brackets',
+ 'metavar': '<format>',
+ 'overrides': 'trim_footnote_reference_space'}),
+ ('Format for block quote attributions: one of "dash" (em-dash '
+ 'prefix), "parentheses"/"parens", or "none". Default is "dash".',
+ ['--attribution'],
+ {'choices': ['dash', 'parentheses', 'parens', 'none'],
+ 'default': 'dash', 'metavar': '<format>'}),
+ ('Remove extra vertical whitespace between items of "simple" bullet '
+ 'lists and enumerated lists. Default: enabled.',
+ ['--compact-lists'],
+ {'default': 1, 'action': 'store_true',
+ 'validator': frontend.validate_boolean}),
+ ('Disable compact simple bullet and enumerated lists.',
+ ['--no-compact-lists'],
+ {'dest': 'compact_lists', 'action': 'store_false'}),
+ ('Remove extra vertical whitespace between items of simple field '
+ 'lists. Default: enabled.',
+ ['--compact-field-lists'],
+ {'default': 1, 'action': 'store_true',
+ 'validator': frontend.validate_boolean}),
+ ('Disable compact simple field lists.',
+ ['--no-compact-field-lists'],
+ {'dest': 'compact_field_lists', 'action': 'store_false'}),
+ ('Added to standard table classes. '
+ 'Defined styles: "borderless". Default: ""',
+ ['--table-style'],
+ {'default': ''}),
+ ('Math output format, one of "MathML", "HTML", "MathJax" '
+ 'or "LaTeX". Default: "HTML math.css"',
+ ['--math-output'],
+ {'default': 'HTML math.css'}),
+ ('Omit the XML declaration. Use with caution.',
+ ['--no-xml-declaration'],
+ {'dest': 'xml_declaration', 'default': 1, 'action': 'store_false',
+ 'validator': frontend.validate_boolean}),
+ ('Obfuscate email addresses to confuse harvesters while still '
+ 'keeping email links usable with standards-compliant browsers.',
+ ['--cloak-email-addresses'],
+ {'action': 'store_true', 'validator': frontend.validate_boolean}),))
+
+ 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 = dict(_html_base.HTMLTranslator.special_characters)
+ special_characters[0xa0] = u' '
+
+ # use character reference for dash (not valid in HTML5)
+ attribution_formats = {'dash': ('—', ''),
+ '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'))
+
+
+ # 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)
+
+ # 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 insted 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 self.topic_classes == ['contents']
+ # 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')
+
+ # 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'))
+
+ # ersatz for first/last pseudo-classes
+ def visit_definition(self, node):
+ self.body.append('</dt>\n')
+ self.body.append(self.starttag(node, 'dd', ''))
+ self.set_first_last(node)
+
+ # don't add "simple" class value
+ def visit_definition_list(self, node):
+ self.body.append(self.starttag(node, 'dl', CLASS='docutils'))
+
+ # 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.add_meta(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'))
+
+ # 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(' ')
+ self.set_first_last(node)
+
+ # 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> </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 as 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
+
+ # Image types to place in an <object> element
+ # 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'}
+
+ # 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(']%s</td><td>%s' % (self.context.pop(), 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')
+
+ # 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.get('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(' ' * (len(token) - 1) + ' ')
+ self.body.append('</tt>')
+ # Content already processed:
+ raise nodes.SkipNode
+
+ # add newline after opening tag, don't use <code> for code
+ def visit_literal_block(self, node):
+ self.body.append(self.starttag(node, 'pre', CLASS='literal-block'))
+
+ # add newline
+ 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> </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())
+
+ # 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
+
+ # <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))
+
+ # "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')
+
+ # 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')
+
+
+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
--- /dev/null
+/*
+:Author: David Goodger (goodger@python.org)
+:Id: $Id: html4css1.css 7952 2016-07-26 18:15:59Z milde $
+:Copyright: This stylesheet has been placed in the public domain.
+
+Default cascading style sheet for the HTML output of Docutils.
+
+See http://docutils.sf.net/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: grey; } /* 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 {
+ 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 }
--- /dev/null
+%(head_prefix)s
+%(head)s
+%(stylesheet)s
+%(body_prefix)s
+%(body_pre_docinfo)s
+%(docinfo)s
+%(body)s
+%(body_suffix)s
--- /dev/null
+# .. coding: utf-8
+# $Id: __init__.py 8410 2019-11-04 21:14:43Z 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: http://www.spdx.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'
+
+import os.path
+import docutils
+from docutils import frontend, nodes, writers, io
+from docutils.transforms import writer_aux
+from docutils.writers import _html_base
+
+class Writer(writers._html_base.Writer):
+
+ supported = ('html', 'html5', 'html4', 'xhtml', 'xhtml10')
+ """Formats this writer supports."""
+
+ default_stylesheets = ['minimal.css', 'plain.css']
+ default_stylesheet_dirs = ['.', os.path.abspath(os.path.dirname(__file__))]
+
+ default_template = 'template.txt'
+ default_template_path = os.path.join(
+ os.path.dirname(os.path.abspath(__file__)), default_template)
+
+ settings_spec = (
+ 'HTML-Specific Options',
+ None,
+ (('Specify the template file (UTF-8 encoded). Default is "%s".'
+ % default_template_path,
+ ['--template'],
+ {'default': default_template_path, 'metavar': '<file>'}),
+ ('Comma separated list of stylesheet URLs. '
+ 'Overrides previous --stylesheet and --stylesheet-path settings.',
+ ['--stylesheet'],
+ {'metavar': '<URL[,URL,...]>', 'overrides': 'stylesheet_path',
+ 'validator': frontend.validate_comma_separated_list}),
+ ('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}),
+ ('Embed the stylesheet(s) in the output HTML file. The stylesheet '
+ 'files must be accessible during processing. This is the default.',
+ ['--embed-stylesheet'],
+ {'default': 1, 'action': 'store_true',
+ 'validator': frontend.validate_boolean}),
+ ('Link to the stylesheet(s) in the output HTML file. '
+ 'Default: embed stylesheets.',
+ ['--link-stylesheet'],
+ {'dest': 'embed_stylesheet', 'action': 'store_false'}),
+ ('Comma-separated list of directories where stylesheets are found. '
+ 'Used by --stylesheet-path when expanding relative path arguments. '
+ 'Default: "%s"' % default_stylesheet_dirs,
+ ['--stylesheet-dirs'],
+ {'metavar': '<dir[,dir,...]>',
+ 'validator': frontend.validate_comma_separated_list,
+ 'default': default_stylesheet_dirs}),
+ ('Specify the initial header level. Default is 1 for "<h1>". '
+ 'Does not affect document title & subtitle (see --no-doc-title).',
+ ['--initial-header-level'],
+ {'choices': '1 2 3 4 5 6'.split(), 'default': '1',
+ 'metavar': '<level>'}),
+ ('Format for footnote references: one of "superscript" or '
+ '"brackets". Default is "brackets".',
+ ['--footnote-references'],
+ {'choices': ['superscript', 'brackets'], 'default': 'brackets',
+ 'metavar': '<format>',
+ 'overrides': 'trim_footnote_reference_space'}),
+ ('Format for block quote attributions: one of "dash" (em-dash '
+ 'prefix), "parentheses"/"parens", or "none". Default is "dash".',
+ ['--attribution'],
+ {'choices': ['dash', 'parentheses', 'parens', 'none'],
+ 'default': 'dash', 'metavar': '<format>'}),
+ ('Remove extra vertical whitespace between items of "simple" bullet '
+ 'lists and enumerated lists. Default: enabled.',
+ ['--compact-lists'],
+ {'default': True, 'action': 'store_true',
+ 'validator': frontend.validate_boolean}),
+ ('Disable compact simple bullet and enumerated lists.',
+ ['--no-compact-lists'],
+ {'dest': 'compact_lists', 'action': 'store_false'}),
+ ('Remove extra vertical whitespace between items of simple field '
+ 'lists. Default: enabled.',
+ ['--compact-field-lists'],
+ {'default': True, 'action': 'store_true',
+ 'validator': frontend.validate_boolean}),
+ ('Disable compact simple field lists.',
+ ['--no-compact-field-lists'],
+ {'dest': 'compact_field_lists', 'action': 'store_false'}),
+ ('Added to standard table classes. '
+ 'Defined styles: borderless, booktabs, '
+ 'align-left, align-center, align-right, colwidths-auto. '
+ 'Default: ""',
+ ['--table-style'],
+ {'default': ''}),
+ ('Math output format (one of "MathML", "HTML", "MathJax", '
+ 'or "LaTeX") and option(s). '
+ 'Default: "HTML math.css"',
+ ['--math-output'],
+ {'default': 'HTML math.css'}),
+ ('Prepend an XML declaration. (Thwarts HTML5 conformance.) '
+ 'Default: False',
+ ['--xml-declaration'],
+ {'default': False, 'action': 'store_true',
+ 'validator': frontend.validate_boolean}),
+ ('Omit the XML declaration.',
+ ['--no-xml-declaration'],
+ {'dest': 'xml_declaration', 'action': 'store_false'}),
+ ('Obfuscate email addresses to confuse harvesters while still '
+ 'keeping email links usable with standards-compliant browsers.',
+ ['--cloak-email-addresses'],
+ {'action': 'store_true', 'validator': frontend.validate_boolean}),))
+
+ config_section = 'html5 writer'
+
+ def __init__(self):
+ self.parts = {}
+ self.translator_class = HTMLTranslator
+
+
+class HTMLTranslator(writers._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.
+ """
+
+ # <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.add_meta('<meta name="author" content="%s" />\n' %
+ self.attval(subnode.astext()))
+ def depart_authors(self, node):
+ self.depart_docinfo_item()
+
+ # 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.add_meta('<meta name="dcterms.rights" content="%s" />\n'
+ % self.attval(node.astext()))
+ 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.add_meta('<meta name="dcterms.date" content="%s" />\n'
+ % self.attval(node.astext()))
+ def depart_date(self, node):
+ self.depart_docinfo_item()
+
+ # TODO: use HTML5 <footer> element?
+ # def visit_footer(self, node):
+ # def depart_footer(self, node):
+
+ # TODO: use the new HTML5 element <aside>? (Also for footnote text)
+ # def visit_footnote(self, node):
+ # def depart_footnote(self, 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']
+ # del(node['lang'])
+ meta = self.emptytag(node, 'meta', **node.non_default_attributes())
+ self.add_meta(meta)
+ 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()
+
+ # TODO: use the new HTML5 element <section>?
+ # def visit_section(self, node):
+ # def depart_section(self, node):
--- /dev/null
+/*
+* math2html: convert LaTeX equations to HTML output.
+*
+* Copyright (C) 2009,2010 Alex Fernández
+*
+* 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/
+*/
+/* --end--
+* CSS file for LaTeX formulas.
+*/
+
+/* Formulas */
+.formula {
+ text-align: center;
+ font-family: "Droid Serif", "DejaVu Serif", "STIX", serif;
+ margin: 1.2em 0;
+}
+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;
+}
+.formula i {
+ letter-spacing: 0.1ex;
+}
+
+/* Alignment */
+.align-left, .align-l {
+ text-align: left;
+}
+.align-right, .align-r {
+ text-align: right;
+}
+.align-center, .align-c {
+ text-align: center;
+}
+
+/* Structures */
+span.overline, span.bar {
+ text-decoration: overline;
+}
+.fraction, .fullfraction {
+ display: inline-block;
+ vertical-align: middle;
+ text-align: center;
+}
+.fraction .fraction {
+ font-size: 80%;
+ line-height: 100%;
+}
+span.numerator {
+ display: block;
+}
+span.denominator {
+ display: block;
+ padding: 0ex;
+ border-top: thin solid;
+}
+sup.numerator, sup.unit {
+ font-size: 70%;
+ vertical-align: 80%;
+}
+sub.denominator, sub.unit {
+ font-size: 70%;
+ vertical-align: -20%;
+}
+span.sqrt {
+ display: inline-block;
+ vertical-align: middle;
+ padding: 0.1ex;
+}
+sup.root {
+ font-size: 70%;
+ position: relative;
+ left: 1.4ex;
+}
+span.radical {
+ display: inline-block;
+ padding: 0ex;
+ font-size: 150%;
+ vertical-align: top;
+}
+span.root {
+ display: inline-block;
+ border-top: thin solid;
+ padding: 0ex;
+ vertical-align: middle;
+}
+span.symbol {
+ line-height: 125%;
+ font-size: 125%;
+}
+span.bigsymbol {
+ line-height: 150%;
+ font-size: 150%;
+}
+span.largesymbol {
+ font-size: 175%;
+}
+span.hugesymbol {
+ font-size: 200%;
+}
+span.scripts {
+ display: inline-table;
+ vertical-align: middle;
+}
+.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.symbolover {
+ display: inline-block;
+ text-align: center;
+ position: relative;
+ float: right;
+ right: 100%;
+ bottom: 0.5em;
+ width: 0px;
+}
+span.withsymbol {
+ display: inline-block;
+}
+span.symbolunder {
+ display: inline-block;
+ text-align: center;
+ position: relative;
+ float: right;
+ right: 80%;
+ top: 0.3em;
+ width: 0px;
+}
+
+/* Environments */
+span.array, span.bracketcases, span.binomial, span.environment {
+ display: inline-table;
+ text-align: center;
+ border-collapse: collapse;
+ margin: 0em;
+ vertical-align: middle;
+}
+span.arrayrow, span.binomrow {
+ display: table-row;
+ padding: 0ex;
+ border: 0ex;
+}
+span.arraycell, span.bracket, span.case, span.binomcell, span.environmentcell {
+ display: table-cell;
+ padding: 0ex 0.2ex;
+ line-height: 99%;
+ border: 0ex;
+}
+/*
+* CSS file for LaTeX formulas, extra stuff:
+* binomials, vertical braces, stackrel, fonts and colors.
+*/
+
+/* 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 */
+span.mathsf, span.textsf {
+ font-style: normal;
+ font-family: sans-serif;
+}
+span.mathrm, span.textrm {
+ font-style: normal;
+ font-family: serif;
+}
+span.text, span.textnormal {
+ font-style: normal;
+}
+span.textipa {
+ color: #008080;
+}
+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;
+}
+
+/* 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;
+}
+
--- /dev/null
+/* Minimal style sheet for the HTML output of Docutils. */
+/* */
+/* :Author: Günter Milde, based on html4css1.css by David Goodger */
+/* :Id: $Id: minimal.css 8397 2019-09-20 11:09:34Z 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 */
+
+/* This CSS2.1_ stylesheet defines rules for Docutils elements without */
+/* HTML equivalent. It is required to make the document semantic visible. */
+/* */
+/* .. _CSS2.1: http://www.w3.org/TR/CSS2 */
+/* .. _validates: http://jigsaw.w3.org/css-validator/validator$link */
+
+/* alignment of text and inline objects inside block objects*/
+.align-left { text-align: left; }
+.align-right { text-align: right; }
+.align-center { clear: both; text-align: center; }
+.align-top { vertical-align: top; }
+.align-middle { vertical-align: middle; }
+.align-bottom { vertical-align: bottom; }
+
+/* titles */
+h1.title, p.subtitle {
+ text-align: center;
+}
+p.topic-title,
+p.sidebar-title,
+p.rubric,
+p.admonition-title,
+p.system-message-title {
+ font-weight: bold;
+}
+h1 + p.subtitle,
+h1 + p.section-subtitle {
+ font-size: 1.6em;
+}
+h2 + p.section-subtitle { font-size: 1.28em; }
+p.subtitle,
+p.section-subtitle,
+p.sidebar-subtitle {
+ font-weight: bold;
+ margin-top: -0.5em;
+}
+p.sidebar-title,
+p.rubric {
+ font-size: larger;
+}
+p.rubric { color: maroon; }
+a.toc-backref {
+ color: black;
+ text-decoration: none; }
+
+/* Warnings, Errors */
+div.caution p.admonition-title,
+div.attention p.admonition-title,
+div.danger p.admonition-title,
+div.error p.admonition-title,
+div.warning p.admonition-title,
+div.system-messages h1,
+div.error,
+span.problematic,
+p.system-message-title {
+ color: red;
+}
+
+/* inline literals */
+span.docutils.literal {
+ font-family: monospace;
+ white-space: pre-wrap;
+}
+/* do not wraph at hyphens and similar: */
+.literal > span.pre { white-space: nowrap; }
+
+/* Lists */
+
+/* compact and simple lists: no margin between items */
+.simple li, .compact li,
+.simple ul, .compact ul,
+.simple ol, .compact ol,
+.simple > li p, .compact > li p,
+dl.simple > dd, dl.compact > dd {
+ margin-top: 0;
+ margin-bottom: 0;
+}
+
+/* Table of Contents */
+div.topic.contents { margin: 0.5em 0; }
+div.topic.contents ul {
+ list-style-type: none;
+ padding-left: 1.5em;
+}
+
+/* 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 }
+
+dt span.classifier { font-style: italic }
+dt span.classifier:before {
+ font-style: normal;
+ margin: 0.5em;
+ content: ":";
+}
+
+/* Field Lists and drivatives */
+/* bold field name, content starts on the same line */
+dl.field-list > dt,
+dl.option-list > dt,
+dl.docinfo > dt,
+dl.footnote > dt,
+dl.citation > dt {
+ font-weight: bold;
+ clear: left;
+ float: left;
+ margin: 0;
+ padding: 0;
+ padding-right: 0.5em;
+}
+/* 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 */
+}
+/* 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;
+}
+/* field names followed by a colon */
+dl.field-list > dt:after,
+dl.docinfo > dt:after {
+ content: ":";
+}
+
+/* Bibliographic Fields (docinfo) */
+pre.address { font: inherit; }
+dd.authors > p { margin: 0; }
+
+/* Option Lists */
+dl.option-list { margin-left: 1.5em; }
+dl.option-list > dt { font-weight: normal; }
+span.option { white-space: nowrap; }
+
+/* Footnotes and Citations */
+dl.footnote.superscript > dd {margin-left: 1em; }
+dl.footnote.brackets > dd {margin-left: 2em; }
+dl > dt.label { font-weight: normal; }
+a.footnote-reference.brackets:before,
+dt.label > span.brackets:before { content: "["; }
+a.footnote-reference.brackets:after,
+dt.label > span.brackets:after { content: "]"; }
+a.footnote-reference.superscript,
+dl.footnote.superscript > dt.label {
+ vertical-align: super;
+ font-size: smaller;
+}
+dt.label > span.fn-backref { margin-left: 0.2em; }
+dt.label > span.fn-backref > a { font-style: italic; }
+
+/* Line Blocks */
+div.line-block { display: block; }
+div.line-block div.line-block {
+ margin-top: 0;
+ margin-bottom: 0;
+ margin-left: 40px;
+}
+
+/* Figures, Images, and Tables */
+.figure.align-left,
+figure.align-left,
+img.align-left,
+object.align-left,
+table.align-left {
+ margin-right: auto;
+}
+.figure.align-center,
+figure.align-center,
+img.align-center,
+object.align-center,
+table.align-center {
+ margin-left: auto;
+ margin-right: auto;
+}
+.figure.align-right,
+figure.align-right,
+img.align-right,
+object.align-right,
+table.align-right {
+ margin-left: auto;
+}
+.figure.align-center, .figure.align-right,
+figure.align-center, figure.align-right,
+img.align-center, img.align-right,
+object.align-center, object.align-right {
+ display: block;
+}
+/* reset inner alignment in figures and tables */
+.figure.align-left, .figure.align-right,
+figure.align-left, figure.align-right,
+table.align-left, table.align-center, table.align-right {
+ text-align: inherit;
+}
+
+/* Admonitions and System Messages */
+div.admonition,
+div.system-message,
+div.sidebar,
+aside.sidebar {
+ margin: 1em 1.5em;
+ border: medium outset;
+ padding-top: 0.5em;
+ padding-bottom: 0.5em;
+ padding-right: 1em;
+ padding-left: 1em;
+}
+
+/* Sidebar */
+div.sidebar,
+aside.sidebar {
+ width: 30%;
+ max-width: 26em;
+ float: right;
+ clear: right;
+}
+
+/* Text Blocks */
+blockquote,
+div.topic,
+pre.literal-block,
+pre.doctest-block,
+pre.math,
+pre.code {
+ margin-left: 1.5em;
+ margin-right: 1.5em;
+}
+pre.code .ln { color: gray; } /* line numbers */
+
+/* Tables */
+table { border-collapse: collapse; }
+td, th {
+ border-style: solid;
+ border-color: silver;
+ padding: 0 1ex;
+ border-width: thin;
+}
+td > p:first-child, th > p:first-child { margin-top: 0; }
+td > p, th > p { margin-bottom: 0; }
+
+table > caption {
+ text-align: left;
+ margin-bottom: 0.25em
+}
+
+table.borderless td, table.borderless th {
+ border: 0;
+ padding: 0;
+ padding-right: 0.5em /* separate table cells */
+}
+
+/* Document Header and Footer */
+/* div.header, */
+/* header { border-bottom: 1px solid black; } */
+/* div.footer, */
+/* footer { border-top: 1px solid black; } */
+
+/* new HTML5 block elements: set display for older browsers */
+header, section, footer, aside, nav, main, article, figure {
+ display: block;
+}
--- /dev/null
+/* 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 8397 2019-09-20 11:09:34Z 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: http://www.w3.org/TR/CSS3 */
+
+
+/* Document Structure */
+/* ****************** */
+
+/* "page layout" */
+body {
+ margin: 0;
+ background-color: #dbdbdb;
+}
+div.document,
+main {
+ line-height:1.3;
+ counter-reset: table;
+ /* counter-reset: figure; */
+ /* avoid long lines --> better reading */
+ /* OTOH: lines should not be too short because of missing hyphenation, */
+ max-width: 50em;
+ padding: 1px 2%; /* 1px on top avoids grey bar above title (mozilla) */
+ margin: auto;
+ background-color: white;
+}
+
+/* Sections */
+
+/* Transitions */
+
+hr.docutils {
+ width: 80%;
+ margin-top: 1em;
+ margin-bottom: 1em;
+ clear: both;
+}
+
+/* Paragraphs */
+/* ========== */
+
+/* vertical space (parskip) */
+p, ol, ul, dl,
+div.line-block,
+div.topic,
+table {
+ margin-top: 0.5em;
+ margin-bottom: 0.5em;
+}
+p:first-child { margin-top: 0; }
+/* (:last-child is new in CSS 3) */
+p:last-child { margin-bottom: 0; }
+
+h1, h2, h3, h4, h5, h6,
+dl > dd {
+ margin-bottom: 0.5em;
+}
+
+/* Lists */
+/* ===== */
+
+/* Definition Lists */
+
+/* lists nested in definition lists */
+/* (:only-child is new in CSS 3) */
+dd > ul:only-child, dd > ol:only-child { padding-left: 1em; }
+
+/* Description Lists */
+/* styled like in most dictionaries, encyclopedias etc. */
+dl.description > dt {
+ font-weight: bold;
+ clear: left;
+ float: left;
+ margin: 0;
+ padding: 0;
+ padding-right: 0.5em;
+}
+
+/* Field Lists */
+
+/* example for custom field-name width */
+dl.field-list.narrow > dd {
+ margin-left: 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 special definition list dl.docinfo */
+/* but dedication and abstract are placed into "topic" 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;
+}
+
+/* Citations */
+dl.citation dt.label {
+ font-weight: bold;
+}
+span.fn-backref {
+ font-weight: normal;
+}
+
+/* Text Blocks */
+/* =========== */
+
+/* Literal Blocks */
+
+pre.literal-block,
+pre.doctest-block,
+pre.math,
+pre.code {
+ font-family: monospace;
+}
+
+/* Block Quotes */
+
+blockquote > table,
+div.topic > table {
+ margin-top: 0;
+ margin-bottom: 0;
+}
+blockquote p.attribution,
+div.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 */
+dl.footnote {
+ padding-left: 1ex;
+ border-left: solid;
+ border-left-width: thin;
+}
+
+/* Directives */
+/* ---------- */
+
+/* Body Elements */
+/* ~~~~~~~~~~~~~ */
+
+/* Images and Figures */
+
+/* let content flow to the side of aligned images and figures */
+.figure.align-left,
+figure.align-left,
+img.align-left,
+object.align-left {
+ display: block;
+ clear: left;
+ float: left;
+ margin-right: 1em;
+}
+.figure.align-right,
+figure.align-right,
+img.align-right,
+object.align-right {
+ display: block;
+ clear: right;
+ float: right;
+ margin-left: 1em;
+}
+/* Stop floating sidebars, images and figures at section level 1,2,3 */
+h1, h2, h3 { clear: both; }
+
+/* Sidebar */
+
+/* Move right. In a layout with fixed margins, */
+/* it can be moved into the margin. */
+div.sidebar,
+aside.sidebar {
+ width: 30%;
+ max-width: 26em;
+ margin-left: 1em;
+ margin-right: -2%;
+ background-color: #ffffee;
+}
+
+/* Code */
+
+pre.code { padding: 0.7ex }
+pre.code, code { background-color: #eeeeee }
+pre.code .ln { color: gray; } /* line numbers */
+/* basic highlighting: for a complete scheme, see */
+/* http://docutils.sourceforge.net/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}
+
+/* Math */
+/* styled separately (see math.css for math-output=HTML) */
+
+/* Epigraph */
+/* Highlights */
+/* Pull-Quote */
+/* Compound Paragraph */
+/* Container */
+
+/* can be styled in a custom stylesheet */
+
+/* Document Header and Footer */
+
+footer, header,
+div.footer, div.header {
+ font-size: smaller;
+ clear: both;
+ padding: 0.5em 2%;
+ background-color: #ebebee;
+ border: none;
+}
+
+/* Inline Markup */
+/* ============= */
+
+/* Emphasis */
+/* em */
+/* Strong Emphasis */
+/* strong */
+/* Interpreted Text */
+/* span.interpreted */
+/* Title Reference */
+/* cite */
+
+/* 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.footnote-reference */
+/* Citation References */
+/* a.citation-reference */
--- /dev/null
+%(head_prefix)s
+%(head)s
+%(stylesheet)s
+%(body_prefix)s
+%(body_pre_docinfo)s
+%(docinfo)s
+%(body)s
+%(body_suffix)s
--- /dev/null
+# .. coding: utf-8
+# $Id: __init__.py 8413 2019-11-13 13:45:43Z milde $
+# Author: Engelbert Gruber, Günter Milde
+# Maintainer: docutils-develop@lists.sourceforge.net
+# Copyright: This module has been placed in the public domain.
+
+"""LaTeX2e document tree Writer."""
+
+__docformat__ = 'reStructuredText'
+
+# code contributions from several people included, thanks to all.
+# some named: David Abrahams, Julien Letessier, Lele Gaifax, and others.
+#
+# convention deactivate code by two # i.e. ##.
+
+import sys
+import os
+import re
+import string
+
+try:
+ import roman
+except ImportError:
+ import docutils.utils.roman as roman
+
+from docutils import frontend, nodes, languages, writers, utils, io
+from docutils.utils.error_reporting import SafeString
+from docutils.transforms import writer_aux
+from docutils.utils.math import pick_math_environment, unichar2tex
+
+if sys.version_info >= (3, 0):
+ from urllib.request import url2pathname
+else:
+ from urllib import url2pathname
+
+if sys.version_info >= (3, 0):
+ unicode = str # noqa
+
+
+class Writer(writers.Writer):
+
+ supported = ('latex', 'latex2e')
+ """Formats this writer supports."""
+
+ default_template = 'default.tex'
+ default_template_path = os.path.dirname(os.path.abspath(__file__))
+ default_preamble = '\n'.join([r'% PDF Standard Fonts',
+ r'\usepackage{mathptmx} % Times',
+ r'\usepackage[scaled=.90]{helvet}',
+ r'\usepackage{courier}'])
+ table_style_values = ('standard', 'booktabs', 'nolines', 'borderless',
+ 'colwidths-auto', 'colwidths-given')
+
+ settings_spec = (
+ 'LaTeX-Specific Options',
+ None,
+ (('Specify LaTeX documentclass. Default: "article".',
+ ['--documentclass'],
+ {'default': 'article', }),
+ ('Specify document options. Multiple options can be given, '
+ 'separated by commas. Default: "a4paper".',
+ ['--documentoptions'],
+ {'default': 'a4paper', }),
+ ('Format for footnote references: one of "superscript" or '
+ '"brackets". Default: "superscript".',
+ ['--footnote-references'],
+ {'choices': ['superscript', 'brackets'], 'default': 'superscript',
+ 'metavar': '<format>',
+ 'overrides': 'trim_footnote_reference_space'}),
+ ('Use \\cite command for citations. (future default)',
+ ['--use-latex-citations'],
+ {'default': False, 'action': 'store_true',
+ 'validator': frontend.validate_boolean}),
+ ('Use figure floats for citations '
+ '(might get mixed with real figures). (current default)',
+ ['--figure-citations'],
+ {'dest': 'use_latex_citations', 'action': 'store_false',
+ 'validator': frontend.validate_boolean}),
+ ('Format for block quote attributions: one of "dash" (em-dash '
+ 'prefix), "parentheses"/"parens", or "none". Default: "dash".',
+ ['--attribution'],
+ {'choices': ['dash', 'parentheses', 'parens', 'none'],
+ 'default': 'dash', 'metavar': '<format>'}),
+ ('Specify LaTeX packages/stylesheets. '
+ 'A style is referenced with "\\usepackage" if extension is '
+ '".sty" or omitted and with "\\input" else. '
+ ' Overrides previous --stylesheet and --stylesheet-path settings.',
+ ['--stylesheet'],
+ {'default': '', 'metavar': '<file[,file,...]>',
+ 'overrides': 'stylesheet_path',
+ 'validator': frontend.validate_comma_separated_list}),
+ ('Comma separated list of LaTeX packages/stylesheets. '
+ '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 *.tex file. ',
+ ['--stylesheet-path'],
+ {'metavar': '<file[,file,...]>', 'overrides': 'stylesheet',
+ 'validator': frontend.validate_comma_separated_list}),
+ ('Link to the stylesheet(s) in the output file. (default)',
+ ['--link-stylesheet'],
+ {'dest': 'embed_stylesheet', 'action': 'store_false'}),
+ ('Embed the stylesheet(s) in the output file. '
+ 'Stylesheets must be accessible during processing. ',
+ ['--embed-stylesheet'],
+ {'default': False, 'action': 'store_true',
+ 'validator': frontend.validate_boolean}),
+ ('Comma-separated list of directories where stylesheets are found. '
+ 'Used by --stylesheet-path when expanding relative path arguments. '
+ 'Default: ".".',
+ ['--stylesheet-dirs'],
+ {'metavar': '<dir[,dir,...]>',
+ 'validator': frontend.validate_comma_separated_list,
+ 'default': ['.']}),
+ ('Customization by LaTeX code in the preamble. '
+ 'Default: select PDF standard fonts (Times, Helvetica, Courier).',
+ ['--latex-preamble'],
+ {'default': default_preamble}),
+ ('Specify the template file. Default: "%s".' % default_template,
+ ['--template'],
+ {'default': default_template, 'metavar': '<file>'}),
+ ('Table of contents by LaTeX. (default)',
+ ['--use-latex-toc'],
+ {'default': True, 'action': 'store_true',
+ 'validator': frontend.validate_boolean}),
+ ('Table of contents by Docutils (without page numbers).',
+ ['--use-docutils-toc'],
+ {'dest': 'use_latex_toc', 'action': 'store_false',
+ 'validator': frontend.validate_boolean}),
+ ('Add parts on top of the section hierarchy.',
+ ['--use-part-section'],
+ {'default': False, 'action': 'store_true',
+ 'validator': frontend.validate_boolean}),
+ ('Attach author and date to the document info table. (default)',
+ ['--use-docutils-docinfo'],
+ {'dest': 'use_latex_docinfo', 'action': 'store_false',
+ 'validator': frontend.validate_boolean}),
+ ('Attach author and date to the document title.',
+ ['--use-latex-docinfo'],
+ {'default': False, 'action': 'store_true',
+ 'validator': frontend.validate_boolean}),
+ ("Typeset abstract as topic. (default)",
+ ['--topic-abstract'],
+ {'dest': 'use_latex_abstract', 'action': 'store_false',
+ 'validator': frontend.validate_boolean}),
+ ("Use LaTeX abstract environment for the document's abstract.",
+ ['--use-latex-abstract'],
+ {'default': False, 'action': 'store_true',
+ 'validator': frontend.validate_boolean}),
+ ('Color of any hyperlinks embedded in text. '
+ 'Default: "blue" (use "false" to disable).',
+ ['--hyperlink-color'], {'default': 'blue'}),
+ ('Additional options to the "hyperref" package.',
+ ['--hyperref-options'], {'default': ''}),
+ ('Enable compound enumerators for nested enumerated lists '
+ '(e.g. "1.2.a.ii").',
+ ['--compound-enumerators'],
+ {'default': False, 'action': 'store_true',
+ 'validator': frontend.validate_boolean}),
+ ('Disable compound enumerators for nested enumerated lists. '
+ '(default)',
+ ['--no-compound-enumerators'],
+ {'action': 'store_false', 'dest': 'compound_enumerators'}),
+ ('Enable section ("." subsection ...) prefixes for compound '
+ 'enumerators. This has no effect without --compound-enumerators.',
+ ['--section-prefix-for-enumerators'],
+ {'default': None, 'action': 'store_true',
+ 'validator': frontend.validate_boolean}),
+ ('Disable section prefixes for compound enumerators. (default)',
+ ['--no-section-prefix-for-enumerators'],
+ {'action': 'store_false', 'dest': 'section_prefix_for_enumerators'}),
+ ('Set the separator between section number and enumerator '
+ 'for compound enumerated lists. Default: "-".',
+ ['--section-enumerator-separator'],
+ {'default': '-', 'metavar': '<char>'}),
+ ('When possible, use the specified environment for literal-blocks. '
+ 'Default: "" (fall back to "alltt").',
+ ['--literal-block-env'],
+ {'default': ''}),
+ ('When possible, use "verbatim" for literal-blocks. '
+ 'Compatibility alias for "--literal-block-env=verbatim".',
+ ['--use-verbatim-when-possible'],
+ {'default': False, 'action': 'store_true',
+ 'validator': frontend.validate_boolean}),
+ ('Table style. "standard" with horizontal and vertical lines, '
+ '"booktabs" (LaTeX booktabs style) only horizontal lines '
+ 'above and below the table and below the header, or "borderless". '
+ 'Default: "standard"',
+ ['--table-style'],
+ {'default': ['standard'],
+ 'metavar': '<format>',
+ 'action': 'append',
+ 'validator': frontend.validate_comma_separated_list,
+ 'choices': table_style_values}),
+ ('LaTeX graphicx package option. '
+ 'Possible values are "dvips", "pdftex". "auto" includes LaTeX code '
+ 'to use "pdftex" if processing with pdf(la)tex and dvips otherwise. '
+ 'Default: "".',
+ ['--graphicx-option'],
+ {'default': ''}),
+ ('LaTeX font encoding. '
+ 'Possible values are "", "T1" (default), "OT1", "LGR,T1" or '
+ 'any other combination of options to the `fontenc` package. ',
+ ['--font-encoding'],
+ {'default': 'T1'}),
+ ('Per default the latex-writer puts the reference title into '
+ 'hyperreferences. Specify "ref*" or "pageref*" to get the section '
+ 'number or the page number.',
+ ['--reference-label'],
+ {'default': ''}),
+ ('Specify style and database for bibtex, for example '
+ '"--use-bibtex=mystyle,mydb1,mydb2".',
+ ['--use-bibtex'],
+ {'default': ''}),
+ # TODO: implement "latex footnotes" alternative
+ ('Footnotes with numbers/symbols by Docutils. (default) '
+ '(The alternative, --latex-footnotes, is not implemented yet.)',
+ ['--docutils-footnotes'],
+ {'default': True,
+ 'action': 'store_true',
+ 'validator': frontend.validate_boolean}),
+ ),)
+
+ settings_defaults = {'sectnum_depth': 0 # updated by SectNum transform
+ }
+ config_section = 'latex2e writer'
+ config_section_dependencies = ('writers', 'latex writers')
+
+ head_parts = ('head_prefix', 'requirements', 'latex_preamble',
+ 'stylesheet', 'fallbacks', 'pdfsetup', 'titledata')
+ visitor_attributes = head_parts + ('title', 'subtitle',
+ 'body_pre_docinfo', 'docinfo',
+ 'dedication', 'abstract', 'body')
+
+ output = None
+ """Final translated form of `document`."""
+
+ def __init__(self):
+ writers.Writer.__init__(self)
+ self.translator_class = LaTeXTranslator
+
+ # Override parent method to add latex-specific transforms
+ def get_transforms(self):
+ return writers.Writer.get_transforms(self) + [
+ # Convert specific admonitions to generic one
+ writer_aux.Admonitions,
+ # TODO: footnote collection transform
+ ]
+
+ def translate(self):
+ visitor = self.translator_class(self.document)
+ self.document.walkabout(visitor)
+ # copy parts
+ for part in self.visitor_attributes:
+ setattr(self, part, getattr(visitor, part))
+ # get template string from file
+ try:
+ template_file = open(self.document.settings.template, 'rb')
+ except IOError:
+ template_file = open(os.path.join(self.default_template_path,
+ self.document.settings.template), 'rb')
+ template = string.Template(unicode(template_file.read(), 'utf-8'))
+ template_file.close()
+ # fill template
+ self.assemble_parts() # create dictionary of parts
+ self.output = template.substitute(self.parts)
+
+ def assemble_parts(self):
+ """Assemble the `self.parts` dictionary of output fragments."""
+ writers.Writer.assemble_parts(self)
+ for part in self.visitor_attributes:
+ lines = getattr(self, part)
+ if part in self.head_parts:
+ if lines:
+ lines.append('') # to get a trailing newline
+ self.parts[part] = '\n'.join(lines)
+ else:
+ # body contains inline elements, so join without newline
+ self.parts[part] = ''.join(lines)
+
+
+class Babel(object):
+ """Language specifics for LaTeX."""
+
+ # TeX (babel) language names:
+ # ! not all of these are supported by Docutils!
+ #
+ # based on LyX' languages file with adaptions to `BCP 47`_
+ # (http://www.rfc-editor.org/rfc/bcp/bcp47.txt) and
+ # http://www.tug.org/TUGboat/Articles/tb29-3/tb93miklavec.pdf
+ # * the key without subtags is the default
+ # * case is ignored
+ # cf. http://docutils.sourceforge.net/docs/howto/i18n.html
+ # http://www.w3.org/International/articles/language-tags/
+ # and http://www.iana.org/assignments/language-subtag-registry
+ language_codes = {
+ # code TeX/Babel-name comment
+ 'af': 'afrikaans',
+ 'ar': 'arabic',
+ # 'be': 'belarusian',
+ 'bg': 'bulgarian',
+ 'br': 'breton',
+ 'ca': 'catalan',
+ # 'cop': 'coptic',
+ 'cs': 'czech',
+ 'cy': 'welsh',
+ 'da': 'danish',
+ 'de': 'ngerman', # new spelling (de_1996)
+ 'de-1901': 'german', # old spelling
+ 'de-AT': 'naustrian',
+ 'de-AT-1901': 'austrian',
+ 'dsb': 'lowersorbian',
+ 'el': 'greek', # monotonic (el-monoton)
+ 'el-polyton': 'polutonikogreek',
+ 'en': 'english', # TeX' default language
+ 'en-AU': 'australian',
+ 'en-CA': 'canadian',
+ 'en-GB': 'british',
+ 'en-NZ': 'newzealand',
+ 'en-US': 'american',
+ 'eo': 'esperanto',
+ 'es': 'spanish',
+ 'et': 'estonian',
+ 'eu': 'basque',
+ # 'fa': 'farsi',
+ 'fi': 'finnish',
+ 'fr': 'french',
+ 'fr-CA': 'canadien',
+ 'ga': 'irish', # Irish Gaelic
+ # 'grc': # Ancient Greek
+ 'grc-ibycus': 'ibycus', # Ibycus encoding
+ 'gl': 'galician',
+ 'he': 'hebrew',
+ 'hr': 'croatian',
+ 'hsb': 'uppersorbian',
+ 'hu': 'magyar',
+ 'ia': 'interlingua',
+ 'id': 'bahasai', # Bahasa (Indonesian)
+ 'is': 'icelandic',
+ 'it': 'italian',
+ 'ja': 'japanese',
+ 'kk': 'kazakh',
+ 'la': 'latin',
+ 'lt': 'lithuanian',
+ 'lv': 'latvian',
+ 'mn': 'mongolian', # Mongolian, Cyrillic script (mn-cyrl)
+ 'ms': 'bahasam', # Bahasa (Malay)
+ 'nb': 'norsk', # Norwegian Bokmal
+ 'nl': 'dutch',
+ 'nn': 'nynorsk', # Norwegian Nynorsk
+ 'no': 'norsk', # Norwegian (Bokmal)
+ 'pl': 'polish',
+ 'pt': 'portuges',
+ 'pt-BR': 'brazil',
+ 'ro': 'romanian',
+ 'ru': 'russian',
+ 'se': 'samin', # North Sami
+ 'sh-Cyrl': 'serbianc', # Serbo-Croatian, Cyrillic script
+ 'sh-Latn': 'serbian', # Serbo-Croatian, Latin script see also 'hr'
+ 'sk': 'slovak',
+ 'sl': 'slovene',
+ 'sq': 'albanian',
+ 'sr': 'serbianc', # Serbian, Cyrillic script (contributed)
+ 'sr-Latn': 'serbian', # Serbian, Latin script
+ 'sv': 'swedish',
+ # 'th': 'thai',
+ 'tr': 'turkish',
+ 'uk': 'ukrainian',
+ 'vi': 'vietnam',
+ # zh-Latn: Chinese Pinyin
+ }
+ # normalize (downcase) keys
+ language_codes = dict([(k.lower(), v) for (k, v) in language_codes.items()])
+
+ warn_msg = 'Language "%s" not supported by LaTeX (babel)'
+
+ # "Active characters" are shortcuts that start a LaTeX macro and may need
+ # escaping for literals use. Characters that prevent literal use (e.g.
+ # starting accent macros like "a -> ä) will be deactivated if one of the
+ # defining languages is used in the document.
+ # Special cases:
+ # ~ (tilde) -- used in estonian, basque, galician, and old versions of
+ # spanish -- cannot be deactivated as it denotes a no-break space macro,
+ # " (straight quote) -- used in albanian, austrian, basque
+ # brazil, bulgarian, catalan, czech, danish, dutch, estonian,
+ # finnish, galician, german, icelandic, italian, latin, naustrian,
+ # ngerman, norsk, nynorsk, polish, portuges, russian, serbian, slovak,
+ # slovene, spanish, swedish, ukrainian, and uppersorbian --
+ # is escaped as ``\textquotedbl``.
+ active_chars = {# TeX/Babel-name: active characters to deactivate
+ # 'breton': ':;!?' # ensure whitespace
+ # 'esperanto': '^',
+ # 'estonian': '~"`',
+ # 'french': ':;!?' # ensure whitespace
+ 'galician': '.<>', # also '~"'
+ # 'magyar': '`', # for special hyphenation cases
+ 'spanish': '.<>', # old versions also '~'
+ # 'turkish': ':!=' # ensure whitespace
+ }
+
+ def __init__(self, language_code, reporter=None):
+ self.reporter = reporter
+ self.language = self.language_name(language_code)
+ self.otherlanguages = {}
+
+ def __call__(self):
+ """Return the babel call with correct options and settings"""
+ languages = sorted(self.otherlanguages.keys())
+ languages.append(self.language or 'english')
+ self.setup = [r'\usepackage[%s]{babel}' % ','.join(languages)]
+ # Deactivate "active characters"
+ shorthands = []
+ for c in ''.join([self.active_chars.get(l, '') for l in languages]):
+ if c not in shorthands:
+ shorthands.append(c)
+ if shorthands:
+ self.setup.append(r'\AtBeginDocument{\shorthandoff{%s}}'
+ % ''.join(shorthands))
+ # Including '~' in shorthandoff prevents its use as no-break space
+ if 'galician' in languages:
+ self.setup.append(r'\deactivatetilden % restore ~ in Galician')
+ if 'estonian' in languages:
+ self.setup.extend([r'\makeatletter',
+ r' \addto\extrasestonian{\bbl@deactivate{~}}',
+ r'\makeatother'])
+ if 'basque' in languages:
+ self.setup.extend([r'\makeatletter',
+ r' \addto\extrasbasque{\bbl@deactivate{~}}',
+ r'\makeatother'])
+ if (languages[-1] == 'english' and
+ 'french' in self.otherlanguages.keys()):
+ self.setup += ['% Prevent side-effects if French hyphenation '
+ 'patterns are not loaded:',
+ r'\frenchbsetup{StandardLayout}',
+ r'\AtBeginDocument{\selectlanguage{%s}'
+ r'\noextrasfrench}' % self.language]
+ return '\n'.join(self.setup)
+
+ def language_name(self, language_code):
+ """Return TeX language name for `language_code`"""
+ for tag in utils.normalize_language_tag(language_code):
+ try:
+ return self.language_codes[tag]
+ except KeyError:
+ pass
+ if self.reporter is not None:
+ self.reporter.warning(self.warn_msg % language_code)
+ return ''
+
+ def get_language(self):
+ # Obsolete, kept for backwards compatibility with Sphinx
+ return self.language
+
+
+# Building blocks for the latex preamble
+# --------------------------------------
+
+class SortableDict(dict):
+ """Dictionary with additional sorting methods
+
+ Tip: use key starting with with '_' for sorting before small letters
+ and with '~' for sorting after small letters.
+ """
+ def sortedkeys(self):
+ """Return sorted list of keys"""
+ keys = sorted(self.keys())
+ return keys
+
+ def sortedvalues(self):
+ """Return list of values sorted by keys"""
+ return [self[key] for key in self.sortedkeys()]
+
+
+# PreambleCmds
+# `````````````
+# A container for LaTeX code snippets that can be
+# inserted into the preamble if required in the document.
+#
+# .. The package 'makecmds' would enable shorter definitions using the
+# \providelength and \provideenvironment commands.
+# However, it is pretty non-standard (texlive-latex-extra).
+
+class PreambleCmds(object):
+ """Building blocks for the latex preamble."""
+
+PreambleCmds.abstract = r"""
+% abstract title
+\providecommand*{\DUtitleabstract}[1]{\centerline{\textbf{#1}}}"""
+
+PreambleCmds.admonition = r"""
+% admonition (specially marked topic)
+\providecommand{\DUadmonition}[2][class-arg]{%
+ % try \DUadmonition#1{#2}:
+ \ifcsname DUadmonition#1\endcsname%
+ \csname DUadmonition#1\endcsname{#2}%
+ \else
+ \begin{center}
+ \fbox{\parbox{0.9\linewidth}{#2}}
+ \end{center}
+ \fi
+}"""
+
+## PreambleCmds.caption = r"""% configure caption layout
+## \usepackage{caption}
+## \captionsetup{singlelinecheck=false}% no exceptions for one-liners"""
+
+PreambleCmds.color = r"""\usepackage{color}"""
+
+PreambleCmds.docinfo = r"""
+% docinfo (width of docinfo table)
+\DUprovidelength{\DUdocinfowidth}{0.9\linewidth}"""
+# PreambleCmds.docinfo._depends = 'providelength'
+
+PreambleCmds.dedication = r"""
+% dedication topic
+\providecommand*{\DUCLASSdedication}{%
+ \renewenvironment{quote}{\begin{center}}{\end{center}}%
+}"""
+
+PreambleCmds.duclass = r"""
+% 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]%
+ {\def\DocutilsClassFunctionName{DUCLASS#1}% arg cannot be used in end-part of environment.
+ \csname \DocutilsClassFunctionName \endcsname}%
+ {\csname end\DocutilsClassFunctionName \endcsname}%
+\fi"""
+
+PreambleCmds.error = r"""
+% error admonition title
+\providecommand*{\DUtitleerror}[1]{\DUtitle{\color{red}#1}}"""
+
+PreambleCmds.fieldlist = r"""
+% fieldlist environment
+\ifthenelse{\isundefined{\DUfieldlist}}{
+ \newenvironment{DUfieldlist}%
+ {\quote\description}
+ {\enddescription\endquote}
+}{}"""
+
+PreambleCmds.float_settings = r"""\usepackage{float} % float configuration
+\floatplacement{figure}{H} % place figures here definitely"""
+
+PreambleCmds.footnotes = r"""% numeric or symbol footnotes with hyperlinks
+\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%
+}"""
+
+PreambleCmds.graphicx_auto = r"""% Check output format
+\ifx\pdftexversion\undefined
+ \usepackage{graphicx}
+\else
+ \usepackage[pdftex]{graphicx}
+\fi"""
+
+PreambleCmds.highlight_rules = r"""% 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}}"""
+
+PreambleCmds.inline = r"""
+% inline markup (custom roles)
+% \DUrole{#1}{#2} tries \DUrole#1{#2}
+\providecommand*{\DUrole}[2]{%
+ \ifcsname DUrole#1\endcsname%
+ \csname DUrole#1\endcsname{#2}%
+ \else
+ % backwards compatibility: try \docutilsrole#1{#2}
+ \ifcsname docutilsrole#1\endcsname%
+ \PackageWarningNoLine{docutils}{Command prefix "docutilsrole" is
+ deprecated, \MessageBreak use `\protect\DUrole #1`}
+ \csname docutilsrole#1\endcsname{#2}%
+ \else%
+ #2%
+ \fi%
+ \fi%
+}"""
+
+PreambleCmds.legend = r"""
+% legend environment
+\ifthenelse{\isundefined{\DUlegend}}{
+ \newenvironment{DUlegend}{\small}{}
+}{}"""
+
+PreambleCmds.lineblock = r"""
+% lineblock 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}
+}{}"""
+# PreambleCmds.lineblock._depends = 'providelength'
+
+PreambleCmds.linking = r"""%% hyperlinks:
+\ifthenelse{\isundefined{\hypersetup}}{
+ \usepackage[%s]{hyperref}
+ \usepackage{bookmark}
+ \urlstyle{same} %% normal text font (alternatives: tt, rm, sf)
+}{}"""
+
+PreambleCmds.minitoc = r"""%% local table of contents
+\usepackage{minitoc}"""
+
+PreambleCmds.optionlist = r"""
+% optionlist environment
+\providecommand*{\DUoptionlistlabel}[1]{\bf #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}
+}{}"""
+# PreambleCmds.optionlist._depends = 'providelength'
+
+PreambleCmds.providelength = r"""
+% providelength (provide a length variable and set default, if it is new)
+\providecommand*{\DUprovidelength}[2]{
+ \ifthenelse{\isundefined{#1}}{\newlength{#1}\setlength{#1}{#2}}{}
+}"""
+
+PreambleCmds.rubric = r"""
+% rubric (informal heading)
+\providecommand*{\DUrubric}[1]{\subsubsection*{\emph{#1}}}"""
+
+PreambleCmds.sidebar = r"""
+% sidebar (text outside the main text flow)
+\providecommand{\DUsidebar}[1]{%
+ \begin{center}
+ \colorbox[gray]{0.80}{\parbox{0.9\linewidth}{#1}}
+ \end{center}
+}"""
+
+PreambleCmds.subtitle = r"""
+% subtitle (for sidebar)
+\providecommand*{\DUsubtitle}[1]{\par\emph{#1}\smallskip}"""
+
+PreambleCmds.documentsubtitle = r"""
+% subtitle (in document title)
+\providecommand*{\DUdocumentsubtitle}[1]{{\large #1}}"""
+
+PreambleCmds.table = r"""\usepackage{longtable,ltcaption,array}
+\setlength{\extrarowheight}{2pt}
+\newlength{\DUtablewidth} % internal use in tables"""
+
+# Options [force,almostfull] prevent spurious error messages, see
+# de.comp.text.tex/2005-12/msg01855
+PreambleCmds.textcomp = """\
+\\usepackage{textcomp} % text symbol macros"""
+
+PreambleCmds.textsubscript = r"""
+% text mode subscript
+\ifx\textsubscript\undefined
+ \usepackage{fixltx2e} % since 2015 loaded by default
+\fi"""
+
+PreambleCmds.titlereference = r"""
+% titlereference role
+\providecommand*{\DUroletitlereference}[1]{\textsl{#1}}"""
+
+PreambleCmds.title = r"""
+% title for topics, admonitions, unsupported section levels, and sidebar
+\providecommand*{\DUtitle}[2][class-arg]{%
+ % call \DUtitle#1{#2} if it exists:
+ \ifcsname DUtitle#1\endcsname%
+ \csname DUtitle#1\endcsname{#2}%
+ \else
+ \smallskip\noindent\textbf{#2}\smallskip%
+ \fi
+}"""
+
+PreambleCmds.transition = r"""
+% transition (break, fancybreak, anonymous section)
+\providecommand*{\DUtransition}{%
+ \hspace*{\fill}\hrulefill\hspace*{\fill}
+ \vskip 0.5\baselineskip
+}"""
+
+
+# LaTeX encoding maps
+# -------------------
+# ::
+
+class CharMaps(object):
+ """LaTeX representations for active and Unicode characters."""
+
+ # characters that need escaping even in `alltt` environments:
+ alltt = {
+ ord('\\'): u'\\textbackslash{}',
+ ord('{'): u'\\{',
+ ord('}'): u'\\}',
+ }
+ # characters that normally need escaping:
+ special = {
+ ord('#'): u'\\#',
+ ord('$'): u'\\$',
+ ord('%'): u'\\%',
+ ord('&'): u'\\&',
+ ord('~'): u'\\textasciitilde{}',
+ ord('_'): u'\\_',
+ ord('^'): u'\\textasciicircum{}',
+ # straight double quotes are 'active' in many languages
+ ord('"'): u'\\textquotedbl{}',
+ # Square brackets are ordinary chars and cannot be escaped with '\',
+ # so we put them in a group '{[}'. (Alternative: ensure that all
+ # macros with optional arguments are terminated with {} and text
+ # inside any optional argument is put in a group ``[{text}]``).
+ # Commands with optional args inside an optional arg must be put in a
+ # group, e.g. ``\item[{\hyperref[label]{text}}]``.
+ ord('['): u'{[}',
+ ord(']'): u'{]}',
+ # the soft hyphen is unknown in 8-bit text
+ # and not properly handled by XeTeX
+ 0x00AD: u'\\-', # SOFT HYPHEN
+ }
+ # Unicode chars that are not recognized by LaTeX's utf8 encoding
+ unsupported_unicode = {
+ # TODO: ensure white space also at the beginning of a line?
+ # 0x00A0: u'\\leavevmode\\nobreak\\vadjust{}~'
+ 0x2000: u'\\enskip', # EN QUAD
+ 0x2001: u'\\quad', # EM QUAD
+ 0x2002: u'\\enskip', # EN SPACE
+ 0x2003: u'\\quad', # EM SPACE
+ 0x2008: u'\\,', # PUNCTUATION SPACE
+ 0x200b: u'\\hspace{0pt}', # ZERO WIDTH SPACE
+ 0x202F: u'\\,', # NARROW NO-BREAK SPACE
+ # 0x02d8: u'\\\u{ }', # BREVE
+ 0x2011: u'\\hbox{-}', # NON-BREAKING HYPHEN
+ 0x212b: u'\\AA', # ANGSTROM SIGN
+ 0x21d4: u'\\ensuremath{\\Leftrightarrow}',
+ # Docutils footnote symbols:
+ 0x2660: u'\\ensuremath{\\spadesuit}',
+ 0x2663: u'\\ensuremath{\\clubsuit}',
+ 0xfb00: u'ff', # LATIN SMALL LIGATURE FF
+ 0xfb01: u'fi', # LATIN SMALL LIGATURE FI
+ 0xfb02: u'fl', # LATIN SMALL LIGATURE FL
+ 0xfb03: u'ffi', # LATIN SMALL LIGATURE FFI
+ 0xfb04: u'ffl', # LATIN SMALL LIGATURE FFL
+ }
+ # Unicode chars that are recognized by LaTeX's utf8 encoding
+ utf8_supported_unicode = {
+ 0x00A0: u'~', # NO-BREAK SPACE
+ 0x00AB: u'\\guillemotleft{}', # LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
+ 0x00bb: u'\\guillemotright{}', # RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
+ 0x200C: u'\\textcompwordmark{}', # ZERO WIDTH NON-JOINER
+ 0x2013: u'\\textendash{}',
+ 0x2014: u'\\textemdash{}',
+ 0x2018: u'\\textquoteleft{}',
+ 0x2019: u'\\textquoteright{}',
+ 0x201A: u'\\quotesinglbase{}', # SINGLE LOW-9 QUOTATION MARK
+ 0x201C: u'\\textquotedblleft{}',
+ 0x201D: u'\\textquotedblright{}',
+ 0x201E: u'\\quotedblbase{}', # DOUBLE LOW-9 QUOTATION MARK
+ 0x2030: u'\\textperthousand{}', # PER MILLE SIGN
+ 0x2031: u'\\textpertenthousand{}', # PER TEN THOUSAND SIGN
+ 0x2039: u'\\guilsinglleft{}',
+ 0x203A: u'\\guilsinglright{}',
+ 0x2423: u'\\textvisiblespace{}', # OPEN BOX
+ 0x2020: u'\\dag{}',
+ 0x2021: u'\\ddag{}',
+ 0x2026: u'\\dots{}',
+ 0x2122: u'\\texttrademark{}',
+ }
+ # recognized with 'utf8', if textcomp is loaded
+ textcomp = {
+ # Latin-1 Supplement
+ 0x00a2: u'\\textcent{}', # ¢ CENT SIGN
+ 0x00a4: u'\\textcurrency{}', # ¤ CURRENCY SYMBOL
+ 0x00a5: u'\\textyen{}', # ¥ YEN SIGN
+ 0x00a6: u'\\textbrokenbar{}', # ¦ BROKEN BAR
+ 0x00a7: u'\\textsection{}', # § SECTION SIGN
+ 0x00a8: u'\\textasciidieresis{}', # ¨ DIAERESIS
+ 0x00a9: u'\\textcopyright{}', # © COPYRIGHT SIGN
+ 0x00aa: u'\\textordfeminine{}', # ª FEMININE ORDINAL INDICATOR
+ 0x00ac: u'\\textlnot{}', # ¬ NOT SIGN
+ 0x00ae: u'\\textregistered{}', # ® REGISTERED SIGN
+ 0x00af: u'\\textasciimacron{}', # ¯ MACRON
+ 0x00b0: u'\\textdegree{}', # ° DEGREE SIGN
+ 0x00b1: u'\\textpm{}', # ± PLUS-MINUS SIGN
+ 0x00b2: u'\\texttwosuperior{}', # ² SUPERSCRIPT TWO
+ 0x00b3: u'\\textthreesuperior{}', # ³ SUPERSCRIPT THREE
+ 0x00b4: u'\\textasciiacute{}', # ´ ACUTE ACCENT
+ 0x00b5: u'\\textmu{}', # µ MICRO SIGN
+ 0x00b6: u'\\textparagraph{}', # ¶ PILCROW SIGN # != \textpilcrow
+ 0x00b9: u'\\textonesuperior{}', # ¹ SUPERSCRIPT ONE
+ 0x00ba: u'\\textordmasculine{}', # º MASCULINE ORDINAL INDICATOR
+ 0x00bc: u'\\textonequarter{}', # 1/4 FRACTION
+ 0x00bd: u'\\textonehalf{}', # 1/2 FRACTION
+ 0x00be: u'\\textthreequarters{}', # 3/4 FRACTION
+ 0x00d7: u'\\texttimes{}', # × MULTIPLICATION SIGN
+ 0x00f7: u'\\textdiv{}', # ÷ DIVISION SIGN
+ # others
+ 0x0192: u'\\textflorin{}', # LATIN SMALL LETTER F WITH HOOK
+ 0x02b9: u'\\textasciiacute{}', # MODIFIER LETTER PRIME
+ 0x02ba: u'\\textacutedbl{}', # MODIFIER LETTER DOUBLE PRIME
+ 0x2016: u'\\textbardbl{}', # DOUBLE VERTICAL LINE
+ 0x2022: u'\\textbullet{}', # BULLET
+ 0x2032: u'\\textasciiacute{}', # PRIME
+ 0x2033: u'\\textacutedbl{}', # DOUBLE PRIME
+ 0x2035: u'\\textasciigrave{}', # REVERSED PRIME
+ 0x2036: u'\\textgravedbl{}', # REVERSED DOUBLE PRIME
+ 0x203b: u'\\textreferencemark{}', # REFERENCE MARK
+ 0x203d: u'\\textinterrobang{}', # INTERROBANG
+ 0x2044: u'\\textfractionsolidus{}', # FRACTION SLASH
+ 0x2045: u'\\textlquill{}', # LEFT SQUARE BRACKET WITH QUILL
+ 0x2046: u'\\textrquill{}', # RIGHT SQUARE BRACKET WITH QUILL
+ 0x2052: u'\\textdiscount{}', # COMMERCIAL MINUS SIGN
+ 0x20a1: u'\\textcolonmonetary{}', # COLON SIGN
+ 0x20a3: u'\\textfrenchfranc{}', # FRENCH FRANC SIGN
+ 0x20a4: u'\\textlira{}', # LIRA SIGN
+ 0x20a6: u'\\textnaira{}', # NAIRA SIGN
+ 0x20a9: u'\\textwon{}', # WON SIGN
+ 0x20ab: u'\\textdong{}', # DONG SIGN
+ 0x20ac: u'\\texteuro{}', # EURO SIGN
+ 0x20b1: u'\\textpeso{}', # PESO SIGN
+ 0x20b2: u'\\textguarani{}', # GUARANI SIGN
+ 0x2103: u'\\textcelsius{}', # DEGREE CELSIUS
+ 0x2116: u'\\textnumero{}', # NUMERO SIGN
+ 0x2117: u'\\textcircledP{}', # SOUND RECORDING COYRIGHT
+ 0x211e: u'\\textrecipe{}', # PRESCRIPTION TAKE
+ 0x2120: u'\\textservicemark{}', # SERVICE MARK
+ 0x2122: u'\\texttrademark{}', # TRADE MARK SIGN
+ 0x2126: u'\\textohm{}', # OHM SIGN
+ 0x2127: u'\\textmho{}', # INVERTED OHM SIGN
+ 0x212e: u'\\textestimated{}', # ESTIMATED SYMBOL
+ 0x2190: u'\\textleftarrow{}', # LEFTWARDS ARROW
+ 0x2191: u'\\textuparrow{}', # UPWARDS ARROW
+ 0x2192: u'\\textrightarrow{}', # RIGHTWARDS ARROW
+ 0x2193: u'\\textdownarrow{}', # DOWNWARDS ARROW
+ 0x2212: u'\\textminus{}', # MINUS SIGN
+ 0x2217: u'\\textasteriskcentered{}', # ASTERISK OPERATOR
+ 0x221a: u'\\textsurd{}', # SQUARE ROOT
+ 0x2422: u'\\textblank{}', # BLANK SYMBOL
+ 0x25e6: u'\\textopenbullet{}', # WHITE BULLET
+ 0x25ef: u'\\textbigcircle{}', # LARGE CIRCLE
+ 0x266a: u'\\textmusicalnote{}', # EIGHTH NOTE
+ 0x26ad: u'\\textmarried{}', # MARRIAGE SYMBOL
+ 0x26ae: u'\\textdivorced{}', # DIVORCE SYMBOL
+ 0x27e8: u'\\textlangle{}', # MATHEMATICAL LEFT ANGLE BRACKET
+ 0x27e9: u'\\textrangle{}', # MATHEMATICAL RIGHT ANGLE BRACKET
+ }
+ # Unicode chars that require a feature/package to render
+ pifont = {
+ 0x2665: u'\\ding{170}', # black heartsuit
+ 0x2666: u'\\ding{169}', # black diamondsuit
+ 0x2713: u'\\ding{51}', # check mark
+ 0x2717: u'\\ding{55}', # check mark
+ }
+ # TODO: greek alphabet ... ?
+ # see also LaTeX codec
+ # http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/252124
+ # and unimap.py from TeXML
+
+
+class DocumentClass(object):
+ """Details of a LaTeX document class."""
+
+ def __init__(self, document_class, with_part=False):
+ self.document_class = document_class
+ self._with_part = with_part
+ self.sections = ['section', 'subsection', 'subsubsection',
+ 'paragraph', 'subparagraph']
+ if self.document_class in ('book', 'memoir', 'report',
+ 'scrbook', 'scrreprt'):
+ self.sections.insert(0, 'chapter')
+ if self._with_part:
+ self.sections.insert(0, 'part')
+
+ def section(self, level):
+ """Return the LaTeX section name for section `level`.
+
+ The name depends on the specific document class.
+ Level is 1,2,3..., as level 0 is the title.
+ """
+ if level <= len(self.sections):
+ return self.sections[level-1]
+ else: # unsupported levels
+ return 'DUtitle[section%s]' % roman.toRoman(level)
+
+class Table(object):
+ """Manage a table while traversing.
+
+ Maybe change to a mixin defining the visit/departs, but then
+ class Table internal variables are in the Translator.
+
+ Table style might be
+
+ :standard: horizontal and vertical lines
+ :booktabs: only horizontal lines (requires "booktabs" LaTeX package)
+ :borderless: no borders around table cells
+ :nolines: alias for borderless
+
+ :colwidths-auto: column widths determined by LaTeX
+ :colwidths-given: use colum widths from rST source
+ """
+ def __init__(self, translator, latex_type):
+ self._translator = translator
+ self._latex_type = latex_type
+ self._open = False
+ # miscellaneous attributes
+ self._attrs = {}
+ self._col_width = []
+ self._rowspan = []
+ self.stubs = []
+ self.colwidths_auto = False
+ self._in_thead = 0
+
+ def open(self):
+ self._open = True
+ self._col_specs = []
+ self.caption = []
+ self._attrs = {}
+ self._in_head = False # maybe context with search
+ def close(self):
+ self._open = False
+ self._col_specs = None
+ self.caption = []
+ self._attrs = {}
+ self.stubs = []
+ self.colwidths_auto = False
+
+ def is_open(self):
+ return self._open
+
+ def set_table_style(self, table_style, classes):
+ borders = [cls.replace('nolines', 'borderless')
+ for cls in table_style+classes
+ if cls in ('standard', 'booktabs', 'borderless', 'nolines')]
+ try:
+ self.borders = borders[-1]
+ except IndexError:
+ self.borders = 'standard'
+ self.colwidths_auto = (('colwidths-auto' in classes
+ and 'colwidths-given' not in table_style)
+ or ('colwidths-auto' in table_style
+ and ('colwidths-given' not in classes)))
+
+ def get_latex_type(self):
+ if self._latex_type == 'longtable' and not self.caption:
+ # do not advance the "table" counter (requires "ltcaption" package)
+ return('longtable*')
+ return self._latex_type
+
+ def set(self, attr, value):
+ self._attrs[attr] = value
+ def get(self, attr):
+ if attr in self._attrs:
+ return self._attrs[attr]
+ return None
+
+ def get_vertical_bar(self):
+ if self.borders == 'standard':
+ return '|'
+ return ''
+
+ # horizontal lines are drawn below a row,
+ def get_opening(self, width=r'\linewidth'):
+ align_map = {'left': 'l',
+ 'center': 'c',
+ 'right': 'r'}
+ align = align_map.get(self.get('align') or 'center')
+ opening = [r'\begin{%s}[%s]' % (self.get_latex_type(), align)]
+ if not self.colwidths_auto:
+ opening.insert(0, r'\setlength{\DUtablewidth}{%s}'%width)
+ return '\n'.join(opening)
+
+ def get_closing(self):
+ closing = []
+ if self.borders == 'booktabs':
+ closing.append(r'\bottomrule')
+ # elif self.borders == 'standard':
+ # closing.append(r'\hline')
+ closing.append(r'\end{%s}' % self.get_latex_type())
+ return '\n'.join(closing)
+
+ def visit_colspec(self, node):
+ self._col_specs.append(node)
+ # "stubs" list is an attribute of the tgroup element:
+ self.stubs.append(node.attributes.get('stub'))
+
+ def get_colspecs(self, node):
+ """Return column specification for longtable.
+
+ Assumes reST line length being 80 characters.
+ Table width is hairy.
+
+ === ===
+ ABC DEF
+ === ===
+
+ usually gets to narrow, therefore we add 1 (fiddlefactor).
+ """
+ bar = self.get_vertical_bar()
+ self._rowspan= [0] * len(self._col_specs)
+ self._col_width = []
+ if self.colwidths_auto:
+ latex_table_spec = (bar+'l')*len(self._col_specs)
+ return latex_table_spec+bar
+ width = 80
+ total_width = 0.0
+ # first see if we get too wide.
+ for node in self._col_specs:
+ colwidth = float(node['colwidth']+1) / width
+ total_width += colwidth
+ # donot make it full linewidth
+ factor = 0.93
+ if total_width > 1.0:
+ factor /= total_width
+ latex_table_spec = ''
+ for node in self._col_specs:
+ colwidth = factor * float(node['colwidth']+1) / width
+ self._col_width.append(colwidth+0.005)
+ latex_table_spec += '%sp{%.3f\\DUtablewidth}' % (bar, colwidth+0.005)
+ return latex_table_spec+bar
+
+ def get_column_width(self):
+ """Return columnwidth for current cell (not multicell)."""
+ try:
+ return '%.2f\\DUtablewidth' % self._col_width[self._cell_in_row]
+ except IndexError:
+ return '*'
+
+ def get_multicolumn_width(self, start, len_):
+ """Return sum of columnwidths for multicell."""
+ try:
+ mc_width = sum([width
+ for width in ([self._col_width[start + co]
+ for co in range (len_)])])
+ return 'p{%.2f\\DUtablewidth}' % mc_width
+ except IndexError:
+ return 'l'
+
+ def get_caption(self):
+ if not self.caption:
+ return ''
+ caption = ''.join(self.caption)
+ if 1 == self._translator.thead_depth():
+ return r'\caption{%s}\\' '\n' % caption
+ return r'\caption[]{%s (... continued)}\\' '\n' % caption
+
+ def need_recurse(self):
+ if self._latex_type == 'longtable':
+ return 1 == self._translator.thead_depth()
+ return 0
+
+ def visit_thead(self):
+ self._in_thead += 1
+ if self.borders == 'standard':
+ return ['\\hline\n']
+ elif self.borders == 'booktabs':
+ return ['\\toprule\n']
+ return []
+
+ def depart_thead(self):
+ a = []
+ #if self.borders == 'standard':
+ # a.append('\\hline\n')
+ if self.borders == 'booktabs':
+ a.append('\\midrule\n')
+ if self._latex_type == 'longtable':
+ if 1 == self._translator.thead_depth():
+ a.append('\\endfirsthead\n')
+ else:
+ a.append('\\endhead\n')
+ a.append(r'\multicolumn{%d}{c}' % len(self._col_specs) +
+ r'{\hfill ... continued on next page} \\')
+ a.append('\n\\endfoot\n\\endlastfoot\n')
+ # for longtable one could add firsthead, foot and lastfoot
+ self._in_thead -= 1
+ return a
+
+ def visit_row(self):
+ self._cell_in_row = 0
+
+ def depart_row(self):
+ res = [' \\\\\n']
+ self._cell_in_row = None # remove cell counter
+ for i in range(len(self._rowspan)):
+ if (self._rowspan[i]>0):
+ self._rowspan[i] -= 1
+
+ if self.borders == 'standard':
+ rowspans = [i+1 for i in range(len(self._rowspan))
+ if (self._rowspan[i]<=0)]
+ if len(rowspans)==len(self._rowspan):
+ res.append('\\hline\n')
+ else:
+ cline = ''
+ rowspans.reverse()
+ # TODO merge clines
+ while True:
+ try:
+ c_start = rowspans.pop()
+ except:
+ break
+ cline += '\\cline{%d-%d}\n' % (c_start, c_start)
+ res.append(cline)
+ return res
+
+ def set_rowspan(self, cell, value):
+ try:
+ self._rowspan[cell] = value
+ except:
+ pass
+
+ def get_rowspan(self, cell):
+ try:
+ return self._rowspan[cell]
+ except:
+ return 0
+
+ def get_entry_number(self):
+ return self._cell_in_row
+
+ def visit_entry(self):
+ self._cell_in_row += 1
+
+ def is_stub_column(self):
+ if len(self.stubs) >= self._cell_in_row:
+ return self.stubs[self._cell_in_row]
+ return False
+
+
+class LaTeXTranslator(nodes.NodeVisitor):
+ """
+ Generate code for 8-bit LaTeX from a Docutils document tree.
+
+ See the docstring of docutils.writers._html_base.HTMLTranslator for
+ notes on and examples of safe subclassing.
+ """
+
+ # When options are given to the documentclass, latex will pass them
+ # to other packages, as done with babel.
+ # Dummy settings might be taken from document settings
+
+ # Generate code for typesetting with 8-bit latex/pdflatex vs.
+ # xelatex/lualatex engine. Overwritten by the XeTeX writer
+ is_xetex = False
+
+ # Config setting defaults
+ # -----------------------
+
+ # TODO: use mixins for different implementations.
+ # list environment for docinfo. else tabularx
+ ## use_optionlist_for_docinfo = False # TODO: NOT YET IN USE
+
+ # Use compound enumerations (1.A.1.)
+ compound_enumerators = False
+
+ # If using compound enumerations, include section information.
+ section_prefix_for_enumerators = False
+
+ # This is the character that separates the section ("." subsection ...)
+ # prefix from the regular list enumerator.
+ section_enumerator_separator = '-'
+
+ # Auxiliary variables
+ # -------------------
+
+ has_latex_toc = False # is there a toc in the doc? (needed by minitoc)
+ is_toc_list = False # is the current bullet_list a ToC?
+ section_level = 0
+
+ # Flags to encode():
+ # inside citation reference labels underscores dont need to be escaped
+ inside_citation_reference_label = False
+ verbatim = False # do not encode
+ insert_non_breaking_blanks = False # replace blanks by "~"
+ insert_newline = False # add latex newline commands
+ literal = False # literal text (block or inline)
+ alltt = False # inside `alltt` environment
+
+ def __init__(self, document, babel_class=Babel):
+ 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.latex_encoding = self.to_latex_encoding(settings.output_encoding)
+ self.use_latex_toc = settings.use_latex_toc
+ self.use_latex_docinfo = settings.use_latex_docinfo
+ self._use_latex_citations = settings.use_latex_citations
+ self._reference_label = settings.reference_label
+ self.hyperlink_color = settings.hyperlink_color
+ self.compound_enumerators = settings.compound_enumerators
+ self.font_encoding = getattr(settings, 'font_encoding', '')
+ self.section_prefix_for_enumerators = (
+ settings.section_prefix_for_enumerators)
+ self.section_enumerator_separator = (
+ settings.section_enumerator_separator.replace('_', r'\_'))
+ # literal blocks:
+ self.literal_block_env = ''
+ self.literal_block_options = ''
+ if settings.literal_block_env:
+ (none,
+ self.literal_block_env,
+ self.literal_block_options,
+ none ) = re.split(r'(\w+)(.*)', settings.literal_block_env)
+ elif settings.use_verbatim_when_possible:
+ self.literal_block_env = 'verbatim'
+ #
+ if self.settings.use_bibtex:
+ self.bibtex = self.settings.use_bibtex.split(',', 1)
+ # TODO avoid errors on not declared citations.
+ else:
+ self.bibtex = None
+ # language module for Docutils-generated text
+ # (labels, bibliographic_fields, and author_separators)
+ self.language_module = languages.get_language(settings.language_code,
+ document.reporter)
+ self.babel = babel_class(settings.language_code, document.reporter)
+ self.author_separator = self.language_module.author_separators[0]
+ d_options = [self.settings.documentoptions]
+ if self.babel.language not in ('english', ''):
+ d_options.append(self.babel.language)
+ self.documentoptions = ','.join(filter(None, d_options))
+ self.d_class = DocumentClass(settings.documentclass,
+ settings.use_part_section)
+ # graphic package options:
+ if self.settings.graphicx_option == '':
+ self.graphicx_package = r'\usepackage{graphicx}'
+ elif self.settings.graphicx_option.lower() == 'auto':
+ self.graphicx_package = PreambleCmds.graphicx_auto
+ else:
+ self.graphicx_package = (r'\usepackage[%s]{graphicx}' %
+ self.settings.graphicx_option)
+ # footnotes: TODO: implement LaTeX footnotes
+ self.docutils_footnotes = settings.docutils_footnotes
+ # @@ table_style: list of values from fixed set: warn?
+ # for s in self.settings.table_style:
+ # if s not in Writer.table_style_values:
+ # self.warn('Ignoring value "%s" in "table-style" setting.' %s)
+
+ # Output collection stacks
+ # ~~~~~~~~~~~~~~~~~~~~~~~~
+
+ # Document parts
+ self.head_prefix = [r'\documentclass[%s]{%s}' %
+ (self.documentoptions, self.settings.documentclass)]
+ self.requirements = SortableDict() # made a list in depart_document()
+ self.requirements['__static'] = r'\usepackage{ifthen}'
+ self.latex_preamble = [settings.latex_preamble]
+ self.fallbacks = SortableDict() # made a list in depart_document()
+ self.pdfsetup = [] # PDF properties (hyperref package)
+ self.title = []
+ self.subtitle = []
+ self.titledata = [] # \title, \author, \date
+ ## self.body_prefix = ['\\begin{document}\n']
+ self.body_pre_docinfo = [] # \maketitle
+ self.docinfo = []
+ self.dedication = []
+ self.abstract = []
+ self.body = []
+ ## self.body_suffix = ['\\end{document}\n']
+
+ self.context = []
+ """Heterogeneous stack.
+
+ Used by visit_* and depart_* functions in conjunction with the tree
+ traversal. Make sure that the pops correspond to the pushes."""
+
+ # Title metadata:
+ self.title_labels = []
+ self.subtitle_labels = []
+ # (if use_latex_docinfo: collects lists of
+ # author/organization/contact/address lines)
+ self.author_stack = []
+ self.date = []
+
+ # PDF properties: pdftitle, pdfauthor
+ # TODO?: pdfcreator, pdfproducer, pdfsubject, pdfkeywords
+ self.pdfinfo = []
+ self.pdfauthor = []
+
+ # Stack of section counters so that we don't have to use_latex_toc.
+ # This will grow and shrink as processing occurs.
+ # Initialized for potential first-level sections.
+ self._section_number = [0]
+
+ # The current stack of enumerations so that we can expand
+ # them into a compound enumeration.
+ self._enumeration_counters = []
+ # The maximum number of enumeration counters we've used.
+ # If we go beyond this number, we need to create a new
+ # counter; otherwise, just reuse an old one.
+ self._max_enumeration_counters = 0
+
+ self._bibitems = []
+
+ # object for a table while proccessing.
+ self.table_stack = []
+ self.active_table = Table(self, 'longtable')
+
+ # Where to collect the output of visitor methods (default: body)
+ self.out = self.body
+ self.out_stack = [] # stack of output collectors
+
+ # Process settings
+ # ~~~~~~~~~~~~~~~~
+ # Encodings:
+ # Docutils' output-encoding => TeX input encoding
+ if self.latex_encoding != 'ascii':
+ self.requirements['_inputenc'] = (r'\usepackage[%s]{inputenc}'
+ % self.latex_encoding)
+ # TeX font encoding
+ if not self.is_xetex:
+ if self.font_encoding:
+ self.requirements['_fontenc'] = (r'\usepackage[%s]{fontenc}' %
+ self.font_encoding)
+ # ensure \textquotedbl is defined:
+ for enc in self.font_encoding.split(','):
+ enc = enc.strip()
+ if enc == 'OT1':
+ self.requirements['_textquotedblOT1'] = (
+ r'\DeclareTextSymbol{\textquotedbl}{OT1}{`\"}')
+ elif enc not in ('T1', 'T2A', 'T2B', 'T2C', 'T4', 'T5'):
+ self.requirements['_textquotedbl'] = (
+ r'\DeclareTextSymbolDefault{\textquotedbl}{T1}')
+ # page layout with typearea (if there are relevant document options)
+ if (settings.documentclass.find('scr') == -1 and
+ (self.documentoptions.find('DIV') != -1 or
+ self.documentoptions.find('BCOR') != -1)):
+ self.requirements['typearea'] = r'\usepackage{typearea}'
+
+ # Stylesheets
+ # (the name `self.stylesheet` is singular because only one
+ # stylesheet was supported before Docutils 0.6).
+ self.stylesheet = [self.stylesheet_call(path)
+ for path in utils.get_stylesheet_list(settings)]
+
+ # PDF setup
+ if self.hyperlink_color in ('0', 'false', 'False', ''):
+ self.hyperref_options = ''
+ else:
+ self.hyperref_options = 'colorlinks=true,linkcolor=%s,urlcolor=%s' % (
+ self.hyperlink_color, self.hyperlink_color)
+ if settings.hyperref_options:
+ self.hyperref_options += ',' + settings.hyperref_options
+
+ # LaTeX Toc
+ # include all supported sections in toc and PDF bookmarks
+ # (or use documentclass-default (as currently))?
+ ## if self.use_latex_toc:
+ ## self.requirements['tocdepth'] = (r'\setcounter{tocdepth}{%d}' %
+ ## len(self.d_class.sections))
+
+ # Section numbering
+ if settings.sectnum_xform: # section numbering by Docutils
+ PreambleCmds.secnumdepth = r'\setcounter{secnumdepth}{0}'
+ else: # section numbering by LaTeX:
+ secnumdepth = settings.sectnum_depth
+ # Possible values of settings.sectnum_depth:
+ # None "sectnum" directive without depth arg -> LaTeX default
+ # 0 no "sectnum" directive -> no section numbers
+ # >0 value of "depth" argument -> translate to LaTeX levels:
+ # -1 part (0 with "article" document class)
+ # 0 chapter (missing in "article" document class)
+ # 1 section
+ # 2 subsection
+ # 3 subsubsection
+ # 4 paragraph
+ # 5 subparagraph
+ if secnumdepth is not None:
+ # limit to supported levels
+ secnumdepth = min(secnumdepth, len(self.d_class.sections))
+ # adjust to document class and use_part_section settings
+ if 'chapter' in self.d_class.sections:
+ secnumdepth -= 1
+ if self.d_class.sections[0] == 'part':
+ secnumdepth -= 1
+ PreambleCmds.secnumdepth = \
+ r'\setcounter{secnumdepth}{%d}' % secnumdepth
+
+ # start with specified number:
+ if (hasattr(settings, 'sectnum_start') and
+ settings.sectnum_start != 1):
+ self.requirements['sectnum_start'] = (
+ r'\setcounter{%s}{%d}' % (self.d_class.sections[0],
+ settings.sectnum_start-1))
+ # TODO: currently ignored (configure in a stylesheet):
+ ## settings.sectnum_prefix
+ ## settings.sectnum_suffix
+
+ # Auxiliary Methods
+ # -----------------
+
+ def stylesheet_call(self, path):
+ """Return code to reference or embed stylesheet file `path`"""
+ # is it a package (no extension or *.sty) or "normal" tex code:
+ (base, ext) = os.path.splitext(path)
+ is_package = ext in ['.sty', '']
+ # Embed content of style file:
+ if self.settings.embed_stylesheet:
+ if is_package:
+ path = base + '.sty' # ensure extension
+ try:
+ content = io.FileInput(source_path=path,
+ encoding='utf-8').read()
+ self.settings.record_dependencies.add(path)
+ except IOError as err:
+ msg = u"Cannot embed stylesheet '%s':\n %s." % (
+ path, SafeString(err.strerror))
+ self.document.reporter.error(msg)
+ return '% ' + msg.replace('\n', '\n% ')
+ if is_package:
+ content = '\n'.join([r'\makeatletter',
+ content,
+ r'\makeatother'])
+ return '%% embedded stylesheet: %s\n%s' % (path, content)
+ # Link to style file:
+ if is_package:
+ path = base # drop extension
+ cmd = r'\usepackage{%s}'
+ else:
+ cmd = r'\input{%s}'
+ if self.settings.stylesheet_path:
+ # adapt path relative to output (cf. config.html#stylesheet-path)
+ path = utils.relative_path(self.settings._destination, path)
+ return cmd % path
+
+ def to_latex_encoding(self, docutils_encoding):
+ """Translate docutils encoding name into LaTeX's.
+
+ Default method is remove "-" and "_" chars from docutils_encoding.
+ """
+ tr = { 'iso-8859-1': 'latin1', # west european
+ 'iso-8859-2': 'latin2', # east european
+ 'iso-8859-3': 'latin3', # esperanto, maltese
+ 'iso-8859-4': 'latin4', # north european, scandinavian, baltic
+ 'iso-8859-5': 'iso88595', # cyrillic (ISO)
+ 'iso-8859-9': 'latin5', # turkish
+ 'iso-8859-15': 'latin9', # latin9, update to latin1.
+ 'mac_cyrillic': 'maccyr', # cyrillic (on Mac)
+ 'windows-1251': 'cp1251', # cyrillic (on Windows)
+ 'koi8-r': 'koi8-r', # cyrillic (Russian)
+ 'koi8-u': 'koi8-u', # cyrillic (Ukrainian)
+ 'windows-1250': 'cp1250', #
+ 'windows-1252': 'cp1252', #
+ 'us-ascii': 'ascii', # ASCII (US)
+ # unmatched encodings
+ #'': 'applemac',
+ #'': 'ansinew', # windows 3.1 ansi
+ #'': 'ascii', # ASCII encoding for the range 32--127.
+ #'': 'cp437', # dos latin us
+ #'': 'cp850', # dos latin 1
+ #'': 'cp852', # dos latin 2
+ #'': 'decmulti',
+ #'': 'latin10',
+ #'iso-8859-6': '' # arabic
+ #'iso-8859-7': '' # greek
+ #'iso-8859-8': '' # hebrew
+ #'iso-8859-10': '' # latin6, more complete iso-8859-4
+ }
+ encoding = docutils_encoding.lower()
+ if encoding in tr:
+ return tr[encoding]
+ # drop hyphen or low-line from "latin-1", "latin_1", "utf-8" and similar
+ encoding = encoding.replace('_', '').replace('-', '')
+ # strip the error handler
+ return encoding.split(':')[0]
+
+ def language_label(self, docutil_label):
+ return self.language_module.labels[docutil_label]
+
+ def encode(self, text):
+ """Return text with 'problematic' characters escaped.
+
+ * Escape the special printing characters ``# $ % & ~ _ ^ \\ { }``,
+ square brackets ``[ ]``, double quotes and (in OT1) ``< | >``.
+ * Translate non-supported Unicode characters.
+ * Separate ``-`` (and more in literal text) to prevent input ligatures.
+ """
+ if self.verbatim:
+ return text
+ # Set up the translation table:
+ table = CharMaps.alltt.copy()
+ if not self.alltt:
+ table.update(CharMaps.special)
+ # keep the underscore in citation references
+ if self.inside_citation_reference_label and not self.alltt:
+ del(table[ord('_')])
+ # Workarounds for OT1 font-encoding
+ if self.font_encoding in ['OT1', ''] and not self.is_xetex:
+ # * out-of-order characters in cmtt
+ if self.literal:
+ # replace underscore by underlined blank,
+ # because this has correct width.
+ table[ord('_')] = u'\\underline{~}'
+ # the backslash doesn't work, so we use a mirrored slash.
+ # \reflectbox is provided by graphicx:
+ self.requirements['graphicx'] = self.graphicx_package
+ table[ord('\\')] = u'\\reflectbox{/}'
+ # * ``< | >`` come out as different chars (except for cmtt):
+ else:
+ table[ord('|')] = u'\\textbar{}'
+ table[ord('<')] = u'\\textless{}'
+ table[ord('>')] = u'\\textgreater{}'
+ if self.insert_non_breaking_blanks:
+ table[ord(' ')] = u'~'
+ # tab chars may occur in included files (literal or code)
+ # quick-and-dirty replacement with spaces
+ # (for better results use `--literal-block-env=lstlisting`)
+ table[ord('\t')] = u'~' * self.settings.tab_width
+ # Unicode replacements for 8-bit tex engines (not required with XeTeX/LuaTeX):
+ if not self.is_xetex:
+ if not self.latex_encoding.startswith('utf8'):
+ table.update(CharMaps.unsupported_unicode)
+ table.update(CharMaps.utf8_supported_unicode)
+ table.update(CharMaps.textcomp)
+ table.update(CharMaps.pifont)
+ # Characters that require a feature/package to render
+ for ch in text:
+ cp = ord(ch)
+ if cp in CharMaps.textcomp:
+ self.requirements['textcomp'] = PreambleCmds.textcomp
+ elif cp in CharMaps.pifont:
+ self.requirements['pifont'] = '\\usepackage{pifont}'
+ # preamble-definitions for unsupported Unicode characters
+ elif (self.latex_encoding == 'utf8'
+ and cp in CharMaps.unsupported_unicode):
+ self.requirements['_inputenc'+str(cp)] = (
+ '\\DeclareUnicodeCharacter{%04X}{%s}'
+ % (cp, CharMaps.unsupported_unicode[cp]))
+ text = text.translate(table)
+
+ # Break up input ligatures e.g. '--' to '-{}-'.
+ if not self.is_xetex: # Not required with xetex/luatex
+ separate_chars = '-'
+ # In monospace-font, we also separate ',,', '``' and "''" and some
+ # other characters which can't occur in non-literal text.
+ if self.literal:
+ separate_chars += ',`\'"<>'
+ for char in separate_chars * 2:
+ # Do it twice ("* 2") because otherwise we would replace
+ # '---' by '-{}--'.
+ text = text.replace(char + char, char + '{}' + char)
+
+ # Literal line breaks (in address or literal blocks):
+ if self.insert_newline:
+ lines = text.split('\n')
+ # Add a protected space to blank lines (except the last)
+ # to avoid ``! LaTeX Error: There's no line here to end.``
+ for i, line in enumerate(lines[:-1]):
+ if not line.lstrip():
+ lines[i] += '~'
+ text = (r'\\' + '\n').join(lines)
+ if self.literal and not self.insert_non_breaking_blanks:
+ # preserve runs of spaces but allow wrapping
+ text = text.replace(' ', ' ~')
+ return text
+
+ def attval(self, text,
+ whitespace=re.compile('[\n\r\t\v\f]')):
+ """Cleanse, encode, and return attribute value text."""
+ return self.encode(whitespace.sub(' ', text))
+
+ # TODO: is this used anywhere? -> update (use template) or delete
+ ## def astext(self):
+ ## """Assemble document parts and return as string."""
+ ## head = '\n'.join(self.head_prefix + self.stylesheet + self.head)
+ ## body = ''.join(self.body_prefix + self.body + self.body_suffix)
+ ## return head + '\n' + body
+
+ def is_inline(self, node):
+ """Check whether a node represents an inline or block-level element"""
+ return isinstance(node.parent, nodes.TextElement)
+
+ def append_hypertargets(self, node):
+ """Append hypertargets for all ids of `node`"""
+ # hypertarget places the anchor at the target's baseline,
+ # so we raise it explicitely
+ self.out.append('%\n'.join(['\\raisebox{1em}{\\hypertarget{%s}{}}' %
+ id for id in node['ids']]))
+
+ def ids_to_labels(self, node, set_anchor=True):
+ """Return list of label definitions for all ids of `node`
+
+ If `set_anchor` is True, an anchor is set with \\phantomsection.
+ """
+ labels = ['\\label{%s}' % id for id in node.get('ids', [])]
+ if set_anchor and labels:
+ labels.insert(0, '\\phantomsection')
+ return labels
+
+ def set_align_from_classes(self, node):
+ """Convert ``align-*`` class arguments into alignment args."""
+ # separate:
+ align = [cls for cls in node['classes'] if cls.startswith('align-')]
+ if align:
+ node['align'] = align[-1].replace('align-', '')
+ node['classes'] = [cls for cls in node['classes']
+ if not cls.startswith('align-')]
+
+ def insert_align_declaration(self, node, default=None):
+ align = node.get('align', default)
+ if align == 'left':
+ self.out.append('\\raggedright\n')
+ elif align == 'center':
+ self.out.append('\\centering\n')
+ elif align == 'right':
+ self.out.append('\\raggedleft\n')
+
+ def duclass_open(self, node):
+ """Open a group and insert declarations for class values."""
+ if not isinstance(node.parent, nodes.compound):
+ self.out.append('\n')
+ for cls in node['classes']:
+ if cls.startswith('language-'):
+ language = self.babel.language_name(cls[9:])
+ if language:
+ self.babel.otherlanguages[language] = True
+ self.out.append('\\begin{selectlanguage}{%s}\n' % language)
+ else:
+ self.fallbacks['DUclass'] = PreambleCmds.duclass
+ self.out.append('\\begin{DUclass}{%s}\n' % cls)
+
+ def duclass_close(self, node):
+ """Close a group of class declarations."""
+ for cls in reversed(node['classes']):
+ if cls.startswith('language-'):
+ language = self.babel.language_name(cls[9:])
+ if language:
+ self.babel.otherlanguages[language] = True
+ self.out.append('\\end{selectlanguage}\n')
+ else:
+ self.fallbacks['DUclass'] = PreambleCmds.duclass
+ self.out.append('\\end{DUclass}\n')
+
+ def push_output_collector(self, new_out):
+ self.out_stack.append(self.out)
+ self.out = new_out
+
+ def pop_output_collector(self):
+ self.out = self.out_stack.pop()
+
+ # Visitor methods
+ # ---------------
+
+ def visit_Text(self, node):
+ self.out.append(self.encode(node.astext()))
+
+ def depart_Text(self, node):
+ pass
+
+ def visit_abbreviation(self, node):
+ node['classes'].insert(0, 'abbreviation')
+ self.visit_inline(node)
+
+ def depart_abbreviation(self, node):
+ self.depart_inline(node)
+
+ def visit_acronym(self, node):
+ node['classes'].insert(0, 'acronym')
+ self.visit_inline(node)
+
+ def depart_acronym(self, node):
+ self.depart_inline(node)
+
+ def visit_address(self, node):
+ self.visit_docinfo_item(node, 'address')
+
+ def depart_address(self, node):
+ self.depart_docinfo_item(node)
+
+ def visit_admonition(self, node):
+ self.fallbacks['admonition'] = PreambleCmds.admonition
+ if 'error' in node['classes']:
+ self.fallbacks['error'] = PreambleCmds.error
+ # strip the generic 'admonition' from the list of classes
+ node['classes'] = [cls for cls in node['classes']
+ if cls != 'admonition']
+ self.out.append('\n\\DUadmonition[%s]{' % ','.join(node['classes']))
+
+ def depart_admonition(self, node):
+ self.out.append('}\n')
+
+ def visit_author(self, node):
+ self.pdfauthor.append(self.attval(node.astext()))
+ self.visit_docinfo_item(node, 'author')
+
+ def depart_author(self, node):
+ self.depart_docinfo_item(node)
+
+ def visit_authors(self, node):
+ # not used: visit_author is called anyway for each author.
+ pass
+
+ def depart_authors(self, node):
+ pass
+
+ def visit_block_quote(self, node):
+ self.duclass_open(node)
+ self.out.append( '\\begin{quote}')
+
+ def depart_block_quote(self, node):
+ self.out.append( '\\end{quote}\n')
+ self.duclass_close(node)
+
+ def visit_bullet_list(self, node):
+ self.duclass_open(node)
+ if self.is_toc_list:
+ self.out.append( '\\begin{list}{}{}' )
+ else:
+ self.out.append( '\\begin{itemize}' )
+
+ def depart_bullet_list(self, node):
+ if self.is_toc_list:
+ self.out.append( '\\end{list}\n' )
+ else:
+ self.out.append( '\\end{itemize}\n' )
+ self.duclass_close(node)
+
+ def visit_superscript(self, node):
+ self.out.append(r'\textsuperscript{')
+ if node['classes']:
+ self.visit_inline(node)
+
+ def depart_superscript(self, node):
+ if node['classes']:
+ self.depart_inline(node)
+ self.out.append('}')
+
+ def visit_subscript(self, node):
+ self.fallbacks['textsubscript'] = PreambleCmds.textsubscript
+ self.out.append(r'\textsubscript{')
+ if node['classes']:
+ self.visit_inline(node)
+
+ def depart_subscript(self, node):
+ if node['classes']:
+ self.depart_inline(node)
+ self.out.append('}')
+
+ def visit_caption(self, node):
+ self.out.append('\n\\caption{')
+
+ def depart_caption(self, node):
+ self.out.append('}\n')
+
+ def visit_title_reference(self, node):
+ self.fallbacks['titlereference'] = PreambleCmds.titlereference
+ self.out.append(r'\DUroletitlereference{')
+ if node['classes']:
+ self.visit_inline(node)
+
+ def depart_title_reference(self, node):
+ if node['classes']:
+ self.depart_inline(node)
+ self.out.append( '}' )
+
+ def visit_citation(self, node):
+ if self._use_latex_citations:
+ self.push_output_collector([])
+ else:
+ # TODO: do we need these?
+ ## self.requirements['~fnt_floats'] = PreambleCmds.footnote_floats
+ self.out.append(r'\begin{figure}[b]')
+ self.append_hypertargets(node)
+
+ def depart_citation(self, node):
+ if self._use_latex_citations:
+ # TODO: normalize label
+ label = self.out[0]
+ text = ''.join(self.out[1:])
+ self._bibitems.append([label, text])
+ self.pop_output_collector()
+ else:
+ self.out.append('\\end{figure}\n')
+
+ def visit_citation_reference(self, node):
+ if self._use_latex_citations:
+ if not self.inside_citation_reference_label:
+ self.out.append(r'\cite{')
+ self.inside_citation_reference_label = 1
+ else:
+ assert self.body[-1] in (' ', '\n'),\
+ 'unexpected non-whitespace while in reference label'
+ del self.body[-1]
+ else:
+ href = ''
+ if 'refid' in node:
+ href = node['refid']
+ elif 'refname' in node:
+ href = self.document.nameids[node['refname']]
+ self.out.append('\\hyperlink{%s}{[' % href)
+
+ def depart_citation_reference(self, node):
+ if self._use_latex_citations:
+ followup_citation = False
+ # check for a following citation separated by a space or newline
+ sibling = node.next_node(descend=False, siblings=True)
+ if (isinstance(sibling, nodes.Text)
+ and sibling.astext() in (' ', '\n')):
+ sibling2 = sibling.next_node(descend=False, siblings=True)
+ if isinstance(sibling2, nodes.citation_reference):
+ followup_citation = True
+ if followup_citation:
+ self.out.append(',')
+ else:
+ self.out.append('}')
+ self.inside_citation_reference_label = False
+ else:
+ self.out.append(']}')
+
+ def visit_classifier(self, node):
+ self.out.append( '(\\textbf{' )
+
+ def depart_classifier(self, node):
+ self.out.append( '})' )
+
+ def visit_colspec(self, node):
+ self.active_table.visit_colspec(node)
+
+ def depart_colspec(self, node):
+ pass
+
+ def visit_comment(self, node):
+ if not isinstance(node.parent, nodes.compound):
+ self.out.append('\n')
+ # Precede every line with a comment sign, wrap in newlines
+ self.out.append('%% %s\n' % node.astext().replace('\n', '\n% '))
+ raise nodes.SkipNode
+
+ def depart_comment(self, node):
+ pass
+
+ def visit_compound(self, node):
+ if isinstance(node.parent, nodes.compound):
+ self.out.append('\n')
+ node['classes'].insert(0, 'compound')
+ self.duclass_open(node)
+
+ def depart_compound(self, node):
+ self.duclass_close(node)
+
+ def visit_contact(self, node):
+ self.visit_docinfo_item(node, 'contact')
+
+ def depart_contact(self, node):
+ self.depart_docinfo_item(node)
+
+ def visit_container(self, node):
+ self.duclass_open(node)
+
+ def depart_container(self, node):
+ self.duclass_close(node)
+
+ def visit_copyright(self, node):
+ self.visit_docinfo_item(node, 'copyright')
+
+ def depart_copyright(self, node):
+ self.depart_docinfo_item(node)
+
+ def visit_date(self, node):
+ self.visit_docinfo_item(node, 'date')
+
+ def depart_date(self, node):
+ self.depart_docinfo_item(node)
+
+ def visit_decoration(self, node):
+ # header and footer
+ pass
+
+ def depart_decoration(self, node):
+ pass
+
+ def visit_definition(self, node):
+ pass
+
+ def depart_definition(self, node):
+ self.out.append('\n') # TODO: just pass?
+
+ def visit_definition_list(self, node):
+ self.duclass_open(node)
+ self.out.append( '\\begin{description}\n' )
+
+ def depart_definition_list(self, node):
+ self.out.append( '\\end{description}\n' )
+ self.duclass_close(node)
+
+ def visit_definition_list_item(self, node):
+ pass
+
+ def depart_definition_list_item(self, node):
+ pass
+
+ def visit_description(self, node):
+ self.out.append(' ')
+
+ def depart_description(self, node):
+ pass
+
+ def visit_docinfo(self, node):
+ self.push_output_collector(self.docinfo)
+
+ def depart_docinfo(self, node):
+ self.pop_output_collector()
+ # Some itmes (e.g. author) end up at other places
+ if self.docinfo:
+ # tabularx: automatic width of columns, no page breaks allowed.
+ self.requirements['tabularx'] = r'\usepackage{tabularx}'
+ self.fallbacks['_providelength'] = PreambleCmds.providelength
+ self.fallbacks['docinfo'] = PreambleCmds.docinfo
+ #
+ self.docinfo.insert(0, '\n% Docinfo\n'
+ '\\begin{center}\n'
+ '\\begin{tabularx}{\\DUdocinfowidth}{lX}\n')
+ self.docinfo.append('\\end{tabularx}\n'
+ '\\end{center}\n')
+
+ def visit_docinfo_item(self, node, name):
+ if self.use_latex_docinfo:
+ if name in ('author', 'organization', 'contact', 'address'):
+ # We attach these to the last author. If any of them precedes
+ # the first author, put them in a separate "author" group
+ # (in lack of better semantics).
+ if name == 'author' or not self.author_stack:
+ self.author_stack.append([])
+ if name == 'address': # newlines are meaningful
+ self.insert_newline = True
+ text = self.encode(node.astext())
+ self.insert_newline = False
+ else:
+ text = self.attval(node.astext())
+ self.author_stack[-1].append(text)
+ raise nodes.SkipNode
+ elif name == 'date':
+ self.date.append(self.attval(node.astext()))
+ raise nodes.SkipNode
+ self.out.append('\\textbf{%s}: &\n\t' % self.language_label(name))
+ if name == 'address':
+ self.insert_newline = True
+ self.out.append('{\\raggedright\n')
+ self.context.append(' } \\\\\n')
+ else:
+ self.context.append(' \\\\\n')
+
+ def depart_docinfo_item(self, node):
+ self.out.append(self.context.pop())
+ # for address we did set insert_newline
+ self.insert_newline = False
+
+ def visit_doctest_block(self, node):
+ self.visit_literal_block(node)
+
+ def depart_doctest_block(self, node):
+ self.depart_literal_block(node)
+
+ def visit_document(self, node):
+ # titled document?
+ if (self.use_latex_docinfo or len(node) and
+ isinstance(node[0], nodes.title)):
+ self.title_labels += self.ids_to_labels(node, set_anchor=False)
+
+ def depart_document(self, node):
+ # Complete header with information gained from walkabout
+ # * language setup
+ if (self.babel.otherlanguages or
+ self.babel.language not in ('', 'english')):
+ self.requirements['babel'] = self.babel()
+ # * conditional requirements (before style sheet)
+ self.requirements = self.requirements.sortedvalues()
+ # * coditional fallback definitions (after style sheet)
+ self.fallbacks = self.fallbacks.sortedvalues()
+ # * PDF properties
+ self.pdfsetup.append(PreambleCmds.linking % self.hyperref_options)
+ if self.pdfauthor:
+ authors = self.author_separator.join(self.pdfauthor)
+ self.pdfinfo.append(' pdfauthor={%s}' % authors)
+ if self.pdfinfo:
+ self.pdfsetup += [r'\hypersetup{'] + self.pdfinfo + ['}']
+ # Complete body
+ # * document title (with "use_latex_docinfo" also
+ # 'author', 'organization', 'contact', 'address' and 'date')
+ if self.title or (
+ self.use_latex_docinfo and (self.author_stack or self.date)):
+ # \title (empty \title prevents error with \maketitle)
+ title = [''.join(self.title)]
+ if self.title:
+ title += self.title_labels
+ if self.subtitle:
+ title += [r'\\',
+ r'\DUdocumentsubtitle{%s}' % ''.join(self.subtitle)
+ ] + self.subtitle_labels
+ self.titledata.append(r'\title{%s}' % '%\n '.join(title))
+ # \author (empty \author prevents warning with \maketitle)
+ authors = ['\\\\\n'.join(author_entry)
+ for author_entry in self.author_stack]
+ self.titledata.append(r'\author{%s}' %
+ ' \\and\n'.join(authors))
+ # \date (empty \date prevents defaulting to \today)
+ self.titledata.append(r'\date{%s}' % ', '.join(self.date))
+ # \maketitle in the body formats title with LaTeX
+ self.body_pre_docinfo.append('\\maketitle\n')
+
+ # * bibliography
+ # TODO insertion point of bibliography should be configurable.
+ if self._use_latex_citations and len(self._bibitems)>0:
+ if not self.bibtex:
+ widest_label = ''
+ for bi in self._bibitems:
+ if len(widest_label)<len(bi[0]):
+ widest_label = bi[0]
+ self.out.append('\n\\begin{thebibliography}{%s}\n' %
+ widest_label)
+ for bi in self._bibitems:
+ # cite_key: underscores must not be escaped
+ cite_key = bi[0].replace(r'\_', '_')
+ self.out.append('\\bibitem[%s]{%s}{%s}\n' %
+ (bi[0], cite_key, bi[1]))
+ self.out.append('\\end{thebibliography}\n')
+ else:
+ self.out.append('\n\\bibliographystyle{%s}\n' %
+ self.bibtex[0])
+ self.out.append('\\bibliography{%s}\n' % self.bibtex[1])
+ # * make sure to generate a toc file if needed for local contents:
+ if 'minitoc' in self.requirements and not self.has_latex_toc:
+ self.out.append('\n\\faketableofcontents % for local ToCs\n')
+
+ def visit_emphasis(self, node):
+ self.out.append('\\emph{')
+ if node['classes']:
+ self.visit_inline(node)
+
+ def depart_emphasis(self, node):
+ if node['classes']:
+ self.depart_inline(node)
+ self.out.append('}')
+
+ # Append column delimiters and advance column counter,
+ # if the current cell is a multi-row continuation."""
+ def insert_additional_table_colum_delimiters(self):
+ while self.active_table.get_rowspan(
+ self.active_table.get_entry_number()):
+ self.out.append(' & ')
+ self.active_table.visit_entry() # increment cell count
+
+ def visit_entry(self, node):
+ # cell separation
+ if self.active_table.get_entry_number() == 0:
+ self.insert_additional_table_colum_delimiters()
+ else:
+ self.out.append(' & ')
+
+ # multirow, multicolumn
+ if 'morerows' in node and 'morecols' in node:
+ raise NotImplementedError('Cells that '
+ 'span multiple rows *and* columns currently not supported, sorry.')
+ # TODO: should be possible with LaTeX, see e.g.
+ # http://texblog.org/2012/12/21/multi-column-and-multi-row-cells-in-latex-tables/
+ # multirow in LaTeX simply will enlarge the cell over several rows
+ # (the following n if n is positive, the former if negative).
+ if 'morerows' in node:
+ self.requirements['multirow'] = r'\usepackage{multirow}'
+ mrows = node['morerows'] + 1
+ self.active_table.set_rowspan(
+ self.active_table.get_entry_number(), mrows)
+ self.out.append('\\multirow{%d}{%s}{' %
+ (mrows, self.active_table.get_column_width()))
+ self.context.append('}')
+ elif 'morecols' in node:
+ # the vertical bar before column is missing if it is the first
+ # column. the one after always.
+ if self.active_table.get_entry_number() == 0:
+ bar1 = self.active_table.get_vertical_bar()
+ else:
+ bar1 = ''
+ mcols = node['morecols'] + 1
+ self.out.append('\\multicolumn{%d}{%s%s%s}{' %
+ (mcols, bar1,
+ self.active_table.get_multicolumn_width(
+ self.active_table.get_entry_number(),
+ mcols),
+ self.active_table.get_vertical_bar()))
+ self.context.append('}')
+ else:
+ self.context.append('')
+
+ # bold header/stub-column
+ if len(node) and (isinstance(node.parent.parent, nodes.thead)
+ or self.active_table.is_stub_column()):
+ self.out.append('\\textbf{')
+ self.context.append('}')
+ else:
+ self.context.append('')
+
+ # if line ends with '{', mask line break to prevent spurious whitespace
+ if (not self.active_table.colwidths_auto
+ and self.out[-1].endswith("{")
+ and node.astext()):
+ self.out.append("%")
+
+ self.active_table.visit_entry() # increment cell count
+
+ def depart_entry(self, node):
+ self.out.append(self.context.pop()) # header / not header
+ self.out.append(self.context.pop()) # multirow/column
+ # insert extra "&"s, if following rows are spanned from above:
+ self.insert_additional_table_colum_delimiters()
+
+ def visit_row(self, node):
+ self.active_table.visit_row()
+
+ def depart_row(self, node):
+ self.out.extend(self.active_table.depart_row())
+
+ def visit_enumerated_list(self, node):
+ # enumeration styles:
+ types = {'': '',
+ 'arabic':'arabic',
+ 'loweralpha':'alph',
+ 'upperalpha':'Alph',
+ 'lowerroman':'roman',
+ 'upperroman':'Roman'}
+ # the 4 default LaTeX enumeration labels: präfix, enumtype, suffix,
+ labels = [('', 'arabic', '.'), # 1.
+ ('(', 'alph', ')'), # (a)
+ ('', 'roman', '.'), # i.
+ ('', 'Alph', '.')] # A.
+
+ prefix = ''
+ if self.compound_enumerators:
+ if (self.section_prefix_for_enumerators and self.section_level
+ and not self._enumeration_counters):
+ prefix = '.'.join([str(n) for n in
+ self._section_number[:self.section_level]]
+ ) + self.section_enumerator_separator
+ if self._enumeration_counters:
+ prefix += self._enumeration_counters[-1]
+ # TODO: use LaTeX default for unspecified label-type?
+ # (needs change of parser)
+ prefix += node.get('prefix', '')
+ enumtype = types[node.get('enumtype' '')]
+ suffix = node.get('suffix', '')
+
+ enumeration_level = len(self._enumeration_counters)+1
+ counter_name = 'enum' + roman.toRoman(enumeration_level).lower()
+ label = r'%s\%s{%s}%s' % (prefix, enumtype, counter_name, suffix)
+ self._enumeration_counters.append(label)
+
+ self.duclass_open(node)
+ if enumeration_level <= 4:
+ self.out.append('\\begin{enumerate}')
+ if (prefix, enumtype, suffix
+ ) != labels[enumeration_level-1]:
+ self.out.append('\n\\renewcommand{\\label%s}{%s}' %
+ (counter_name, label))
+ else:
+ self.fallbacks[counter_name] = '\\newcounter{%s}' % counter_name
+ self.out.append('\\begin{list}')
+ self.out.append('{%s}' % label)
+ self.out.append('{\\usecounter{%s}}' % counter_name)
+ if 'start' in node:
+ self.out.append('\n\\setcounter{%s}{%d}' %
+ (counter_name, node['start']-1))
+
+
+ def depart_enumerated_list(self, node):
+ if len(self._enumeration_counters) <= 4:
+ self.out.append('\\end{enumerate}\n')
+ else:
+ self.out.append('\\end{list}\n')
+ self.duclass_close(node)
+ self._enumeration_counters.pop()
+
+ def visit_field(self, node):
+ # output is done in field_argument, field_body, field_name
+ pass
+
+ def depart_field(self, node):
+ pass
+
+ def visit_field_body(self, node):
+ pass
+
+ def depart_field_body(self, node):
+ if self.out is self.docinfo:
+ self.out.append(r'\\'+'\n')
+
+ def visit_field_list(self, node):
+ self.duclass_open(node)
+ if self.out is not self.docinfo:
+ self.fallbacks['fieldlist'] = PreambleCmds.fieldlist
+ self.out.append('\\begin{DUfieldlist}')
+
+ def depart_field_list(self, node):
+ if self.out is not self.docinfo:
+ self.out.append('\\end{DUfieldlist}\n')
+ self.duclass_close(node)
+
+ def visit_field_name(self, node):
+ if self.out is self.docinfo:
+ self.out.append('\\textbf{')
+ else:
+ # Commands with optional args inside an optional arg must be put
+ # in a group, e.g. ``\item[{\hyperref[label]{text}}]``.
+ self.out.append('\n\\item[{')
+
+ def depart_field_name(self, node):
+ if self.out is self.docinfo:
+ self.out.append('}: &')
+ else:
+ self.out.append(':}]')
+
+ def visit_figure(self, node):
+ self.requirements['float_settings'] = PreambleCmds.float_settings
+ self.duclass_open(node)
+ # The 'align' attribute sets the "outer alignment",
+ # for "inner alignment" use LaTeX default alignment (similar to HTML)
+ alignment = node.attributes.get('align', 'center')
+ if alignment != 'center':
+ # The LaTeX "figure" environment always uses the full linewidth,
+ # so "outer alignment" is ignored. Just write a comment.
+ # TODO: use the wrapfigure environment?
+ self.out.append('\\begin{figure} %% align = "%s"\n' % alignment)
+ else:
+ self.out.append('\\begin{figure}\n')
+ if node.get('ids'):
+ self.out += self.ids_to_labels(node) + ['\n']
+
+ def depart_figure(self, node):
+ self.out.append('\\end{figure}\n')
+ self.duclass_close(node)
+
+ def visit_footer(self, node):
+ self.push_output_collector([])
+ self.out.append(r'\newcommand{\DUfooter}{')
+
+ def depart_footer(self, node):
+ self.out.append('}')
+ self.requirements['~footer'] = ''.join(self.out)
+ self.pop_output_collector()
+
+ def visit_footnote(self, node):
+ try:
+ backref = node['backrefs'][0]
+ except IndexError:
+ backref = node['ids'][0] # no backref, use self-ref instead
+ if self.docutils_footnotes:
+ self.fallbacks['footnotes'] = PreambleCmds.footnotes
+ num = node[0].astext()
+ if self.settings.footnote_references == 'brackets':
+ num = '[%s]' % num
+ self.out.append('%%\n\\DUfootnotetext{%s}{%s}{%s}{' %
+ (node['ids'][0], backref, self.encode(num)))
+ if node['ids'] == node['names']:
+ self.out += self.ids_to_labels(node)
+ # mask newline to prevent spurious whitespace if paragraph follows:
+ if node[1:] and isinstance(node[1], nodes.paragraph):
+ self.out.append('%')
+ # TODO: "real" LaTeX \footnote{}s (see visit_footnotes_reference())
+
+ def depart_footnote(self, node):
+ self.out.append('}\n')
+
+ def visit_footnote_reference(self, node):
+ href = ''
+ if 'refid' in node:
+ href = node['refid']
+ elif 'refname' in node:
+ href = self.document.nameids[node['refname']]
+ # if not self.docutils_footnotes:
+ # TODO: insert footnote content at (or near) this place
+ # print("footnote-ref to", node['refid'])
+ # footnotes = (self.document.footnotes +
+ # self.document.autofootnotes +
+ # self.document.symbol_footnotes)
+ # for footnote in footnotes:
+ # # print(footnote['ids'])
+ # if node.get('refid', '') in footnote['ids']:
+ # print('matches', footnote['ids'])
+ format = self.settings.footnote_references
+ if format == 'brackets':
+ self.append_hypertargets(node)
+ self.out.append('\\hyperlink{%s}{[' % href)
+ self.context.append(']}')
+ else:
+ self.fallbacks['footnotes'] = PreambleCmds.footnotes
+ self.out.append(r'\DUfootnotemark{%s}{%s}{' %
+ (node['ids'][0], href))
+ self.context.append('}')
+
+ def depart_footnote_reference(self, node):
+ self.out.append(self.context.pop())
+
+ # footnote/citation label
+ def label_delim(self, node, bracket, superscript):
+ if isinstance(node.parent, nodes.footnote):
+ raise nodes.SkipNode
+ else:
+ assert isinstance(node.parent, nodes.citation)
+ if not self._use_latex_citations:
+ self.out.append(bracket)
+
+ def visit_label(self, node):
+ """footnote or citation label: in brackets or as superscript"""
+ self.label_delim(node, '[', '\\textsuperscript{')
+
+ def depart_label(self, node):
+ self.label_delim(node, ']', '}')
+
+ # elements generated by the framework e.g. section numbers.
+ def visit_generated(self, node):
+ pass
+
+ def depart_generated(self, node):
+ pass
+
+ def visit_header(self, node):
+ self.push_output_collector([])
+ self.out.append(r'\newcommand{\DUheader}{')
+
+ def depart_header(self, node):
+ self.out.append('}')
+ self.requirements['~header'] = ''.join(self.out)
+ self.pop_output_collector()
+
+ def to_latex_length(self, length_str, pxunit=None):
+ """Convert `length_str` with rst lenght to LaTeX length
+ """
+ if pxunit is not None:
+ sys.stderr.write('deprecation warning: LaTeXTranslator.to_latex_length()'
+ ' option `pxunit` will be removed.')
+ match = re.match(r'(\d*\.?\d*)\s*(\S*)', length_str)
+ if not match:
+ return length_str
+ value, unit = match.groups()[:2]
+ # no unit or "DTP" points (called 'bp' in TeX):
+ if unit in ('', 'pt'):
+ length_str = '%sbp' % value
+ # percentage: relate to current line width
+ elif unit == '%':
+ length_str = '%.3f\\linewidth' % (float(value)/100.0)
+ elif self.is_xetex and unit == 'px':
+ # XeTeX does not know the length unit px.
+ # Use \pdfpxdimen, the macro to set the value of 1 px in pdftex.
+ # This way, configuring works the same for pdftex and xetex.
+ self.fallbacks['_providelength'] = PreambleCmds.providelength
+ self.fallbacks['px'] = '\n\\DUprovidelength{\\pdfpxdimen}{1bp}\n'
+ length_str = r'%s\pdfpxdimen' % value
+ return length_str
+
+ def visit_image(self, node):
+ self.requirements['graphicx'] = self.graphicx_package
+ attrs = node.attributes
+ # Convert image URI to a local file path
+ imagepath = url2pathname(attrs['uri']).replace('\\', '/')
+ # alignment defaults:
+ if not 'align' in attrs:
+ # Set default align of image in a figure to 'center'
+ if isinstance(node.parent, nodes.figure):
+ attrs['align'] = 'center'
+ self.set_align_from_classes(node)
+ # pre- and postfix (prefix inserted in reverse order)
+ pre = []
+ post = []
+ include_graphics_options = []
+ align_codes = {
+ # inline images: by default latex aligns the bottom.
+ 'bottom': ('', ''),
+ 'middle': (r'\raisebox{-0.5\height}{', '}'),
+ 'top': (r'\raisebox{-\height}{', '}'),
+ # block level images:
+ 'center': (r'\noindent\makebox[\linewidth][c]{', '}'),
+ 'left': (r'\noindent{', r'\hfill}'),
+ 'right': (r'\noindent{\hfill', '}'),}
+ if 'align' in attrs:
+ # TODO: warn or ignore non-applicable alignment settings?
+ try:
+ align_code = align_codes[attrs['align']]
+ pre.append(align_code[0])
+ post.append(align_code[1])
+ except KeyError:
+ pass # TODO: warn?
+ if 'height' in attrs:
+ include_graphics_options.append('height=%s' %
+ self.to_latex_length(attrs['height']))
+ if 'scale' in attrs:
+ include_graphics_options.append('scale=%f' %
+ (attrs['scale'] / 100.0))
+ if 'width' in attrs:
+ include_graphics_options.append('width=%s' %
+ self.to_latex_length(attrs['width']))
+ if not (self.is_inline(node) or
+ isinstance(node.parent, (nodes.figure, nodes.compound))):
+ pre.append('\n')
+ if not (self.is_inline(node) or
+ isinstance(node.parent, nodes.figure)):
+ post.append('\n')
+ pre.reverse()
+ self.out.extend(pre)
+ options = ''
+ if include_graphics_options:
+ options = '[%s]' % (','.join(include_graphics_options))
+ self.out.append('\\includegraphics%s{%s}' % (options, imagepath))
+ self.out.extend(post)
+
+ def depart_image(self, node):
+ if node.get('ids'):
+ self.out += self.ids_to_labels(node) + ['\n']
+
+ def visit_inline(self, node): # <span>, i.e. custom roles
+ for cls in node['classes']:
+ if cls.startswith('language-'):
+ language = self.babel.language_name(cls[9:])
+ if language:
+ self.babel.otherlanguages[language] = True
+ self.out.append(r'\foreignlanguage{%s}{' % language)
+ else:
+ self.fallbacks['inline'] = PreambleCmds.inline
+ self.out.append(r'\DUrole{%s}{' % cls)
+
+ def depart_inline(self, node):
+ self.out.append('}' * len(node['classes']))
+
+ def visit_legend(self, node):
+ self.fallbacks['legend'] = PreambleCmds.legend
+ self.out.append('\\begin{DUlegend}')
+
+ def depart_legend(self, node):
+ self.out.append('\\end{DUlegend}\n')
+
+ def visit_line(self, node):
+ self.out.append(r'\item[] ')
+
+ def depart_line(self, node):
+ self.out.append('\n')
+
+ def visit_line_block(self, node):
+ self.fallbacks['_providelength'] = PreambleCmds.providelength
+ self.fallbacks['lineblock'] = PreambleCmds.lineblock
+ self.set_align_from_classes(node)
+ if isinstance(node.parent, nodes.line_block):
+ self.out.append('\\item[]\n'
+ '\\begin{DUlineblock}{\\DUlineblockindent}\n')
+ # nested line-blocks cannot be given class arguments
+ else:
+ self.duclass_open(node)
+ self.out.append('\\begin{DUlineblock}{0em}\n')
+ self.insert_align_declaration(node)
+
+ def depart_line_block(self, node):
+ self.out.append('\\end{DUlineblock}\n')
+ self.duclass_close(node)
+
+ def visit_list_item(self, node):
+ self.out.append('\n\\item ')
+
+ def depart_list_item(self, node):
+ pass
+
+ def visit_literal(self, node):
+ self.literal = True
+ if 'code' in node['classes'] and (
+ self.settings.syntax_highlight != 'none'):
+ self.requirements['color'] = PreambleCmds.color
+ self.fallbacks['code'] = PreambleCmds.highlight_rules
+ self.out.append('\\texttt{')
+ if node['classes']:
+ self.visit_inline(node)
+
+ def depart_literal(self, node):
+ self.literal = False
+ if node['classes']:
+ self.depart_inline(node)
+ self.out.append('}')
+
+ # Literal blocks are used for '::'-prefixed literal-indented
+ # blocks of text, where the inline markup is not recognized,
+ # but are also the product of the "parsed-literal" directive,
+ # where the markup is respected.
+ #
+ # In both cases, we want to use a typewriter/monospaced typeface.
+ # For "real" literal-blocks, we can use \verbatim, while for all
+ # the others we must use \ttfamily and \raggedright.
+ #
+ # We can distinguish between the two kinds by the number of
+ # siblings that compose this node: if it is composed by a
+ # single element, it's either
+ # * a real one,
+ # * a parsed-literal that does not contain any markup, or
+ # * a parsed-literal containing just one markup construct.
+ def is_plaintext(self, node):
+ """Check whether a node can be typeset verbatim"""
+ return (len(node) == 1) and isinstance(node[0], nodes.Text)
+
+ def visit_literal_block(self, node):
+ """Render a literal block.
+
+ Corresponding rST elements: literal block, parsed-literal, code.
+ """
+ packages = {'lstlisting': r'\usepackage{listings}' '\n'
+ r'\lstset{xleftmargin=\leftmargin}',
+ 'listing': r'\usepackage{moreverb}',
+ 'Verbatim': r'\usepackage{fancyvrb}',
+ 'verbatimtab': r'\usepackage{moreverb}'}
+
+ literal_env = self.literal_block_env
+
+ # Check, if it is possible to use a literal-block environment
+ _plaintext = self.is_plaintext(node)
+ _in_table = self.active_table.is_open()
+ # TODO: fails if normal text precedes the literal block.
+ # Check parent node instead?
+ _autowidth_table = _in_table and self.active_table.colwidths_auto
+ _use_env = _plaintext and not isinstance(node.parent,
+ (nodes.footnote, nodes.admonition))
+ _use_listings = (literal_env == 'lstlisting') and _use_env
+
+ # Labels and classes:
+ if node.get('ids'):
+ self.out += ['\n'] + self.ids_to_labels(node)
+ self.duclass_open(node)
+ # Highlight code?
+ if (not _plaintext and 'code' in node['classes']
+ and self.settings.syntax_highlight != 'none'):
+ self.requirements['color'] = PreambleCmds.color
+ self.fallbacks['code'] = PreambleCmds.highlight_rules
+ # Wrap?
+ if _in_table and _use_env and not _autowidth_table:
+ # Wrap in minipage to prevent extra vertical space
+ # with alltt and verbatim-like environments:
+ self.fallbacks['ttem'] = '\n'.join(['',
+ r'% character width in monospaced font',
+ r'\newlength{\ttemwidth}',
+ r'\settowidth{\ttemwidth}{\ttfamily M}'])
+ self.out.append('\\begin{minipage}{%d\\ttemwidth}\n' %
+ (max(len(line) for line in node.astext().split('\n'))))
+ self.context.append('\n\\end{minipage}\n')
+ elif not _in_table and not _use_listings:
+ # Wrap in quote to set off vertically and indent
+ self.out.append('\\begin{quote}\n')
+ self.context.append('\n\\end{quote}\n')
+ else:
+ self.context.append('\n')
+
+ # Use verbatim-like environment, if defined and possible
+ # (in an auto-width table, only listings works):
+ if literal_env and _use_env and (not _autowidth_table
+ or _use_listings):
+ try:
+ self.requirements['literal_block'] = packages[literal_env]
+ except KeyError:
+ pass
+ self.verbatim = True
+ if _in_table and _use_listings:
+ self.out.append('\\lstset{xleftmargin=0pt}\n')
+ self.out.append('\\begin{%s}%s\n' %
+ (literal_env, self.literal_block_options))
+ self.context.append('\n\\end{%s}' % literal_env)
+ elif _use_env and not _autowidth_table:
+ self.alltt = True
+ self.requirements['alltt'] = r'\usepackage{alltt}'
+ self.out.append('\\begin{alltt}\n')
+ self.context.append('\n\\end{alltt}')
+ else:
+ self.literal = True
+ self.insert_newline = True
+ self.insert_non_breaking_blanks = True
+ # \raggedright ensures leading blanks are respected but
+ # leads to additional leading vspace if the first line
+ # of the block is overfull :-(
+ self.out.append('\\ttfamily\\raggedright\n')
+ self.context.append('')
+
+ def depart_literal_block(self, node):
+ self.insert_non_breaking_blanks = False
+ self.insert_newline = False
+ self.literal = False
+ self.verbatim = False
+ self.alltt = False
+ self.out.append(self.context.pop())
+ self.out.append(self.context.pop())
+ self.duclass_close(node)
+
+ ## def visit_meta(self, node):
+ ## self.out.append('[visit_meta]\n')
+ # TODO: set keywords for pdf?
+ # But:
+ # The reStructuredText "meta" directive creates a "pending" node,
+ # which contains knowledge that the embedded "meta" node can only
+ # be handled by HTML-compatible writers. The "pending" node is
+ # resolved by the docutils.transforms.components.Filter transform,
+ # which checks that the calling writer supports HTML; if it doesn't,
+ # the "pending" node (and enclosed "meta" node) is removed from the
+ # document.
+ # --- docutils/docs/peps/pep-0258.html#transformer
+
+ ## def depart_meta(self, node):
+ ## self.out.append('[depart_meta]\n')
+
+ def visit_math(self, node, math_env='$'):
+ """math role"""
+ if node['classes']:
+ self.visit_inline(node)
+ self.requirements['amsmath'] = r'\usepackage{amsmath}'
+ math_code = node.astext().translate(unichar2tex.uni2tex_table)
+ if node.get('ids'):
+ math_code = '\n'.join([math_code] + self.ids_to_labels(node))
+ if math_env == '$':
+ if self.alltt:
+ wrapper = u'\\(%s\\)'
+ else:
+ wrapper = u'$%s$'
+ else:
+ wrapper = u'\n'.join(['%%',
+ r'\begin{%s}' % math_env,
+ '%s',
+ r'\end{%s}' % math_env])
+ self.out.append(wrapper % math_code)
+ if node['classes']:
+ self.depart_inline(node)
+ # Content already processed:
+ raise nodes.SkipNode
+
+ def depart_math(self, node):
+ pass # never reached
+
+ def visit_math_block(self, node):
+ math_env = pick_math_environment(node.astext())
+ self.visit_math(node, math_env=math_env)
+
+ def depart_math_block(self, node):
+ pass # never reached
+
+ def visit_option(self, node):
+ if self.context[-1]:
+ # this is not the first option
+ self.out.append(', ')
+
+ def depart_option(self, node):
+ # flag that the first option is done.
+ self.context[-1] += 1
+
+ def visit_option_argument(self, node):
+ """Append the delimiter betweeen an option and its argument to body."""
+ self.out.append(node.get('delimiter', ' '))
+
+ def depart_option_argument(self, node):
+ pass
+
+ def visit_option_group(self, node):
+ self.out.append('\n\\item[')
+ # flag for first option
+ self.context.append(0)
+
+ def depart_option_group(self, node):
+ self.context.pop() # the flag
+ self.out.append('] ')
+
+ def visit_option_list(self, node):
+ self.fallbacks['_providelength'] = PreambleCmds.providelength
+ self.fallbacks['optionlist'] = PreambleCmds.optionlist
+ self.duclass_open(node)
+ self.out.append('\\begin{DUoptionlist}')
+
+ def depart_option_list(self, node):
+ self.out.append('\\end{DUoptionlist}\n')
+ self.duclass_close(node)
+
+ def visit_option_list_item(self, node):
+ pass
+
+ def depart_option_list_item(self, node):
+ pass
+
+ def visit_option_string(self, node):
+ ##self.out.append(self.starttag(node, 'span', '', CLASS='option'))
+ pass
+
+ def depart_option_string(self, node):
+ ##self.out.append('</span>')
+ pass
+
+ def visit_organization(self, node):
+ self.visit_docinfo_item(node, 'organization')
+
+ def depart_organization(self, node):
+ self.depart_docinfo_item(node)
+
+ def visit_paragraph(self, node):
+ # insert blank line, unless
+ # * the paragraph is first in a list item or compound,
+ # * follows a non-paragraph node in a compound,
+ # * is in a table with auto-width columns
+ index = node.parent.index(node)
+ if index == 0 and isinstance(node.parent,
+ (nodes.list_item, nodes.description, nodes.compound)):
+ pass
+ elif (index > 0 and isinstance(node.parent, nodes.compound) and
+ not isinstance(node.parent[index - 1], nodes.paragraph) and
+ not isinstance(node.parent[index - 1], nodes.compound)):
+ pass
+ elif self.active_table.colwidths_auto:
+ if index == 1: # second paragraph
+ self.warn('LaTeX merges paragraphs in tables '
+ 'with auto-sized columns!', base_node=node)
+ if index > 0:
+ self.out.append('\n')
+ else:
+ self.out.append('\n')
+ if node.get('ids'):
+ self.out += self.ids_to_labels(node) + ['\n']
+ if node['classes']:
+ self.visit_inline(node)
+
+ def depart_paragraph(self, node):
+ if node['classes']:
+ self.depart_inline(node)
+ if not self.active_table.colwidths_auto:
+ self.out.append('\n')
+
+ def visit_problematic(self, node):
+ self.requirements['color'] = PreambleCmds.color
+ self.out.append('%\n')
+ self.append_hypertargets(node)
+ self.out.append(r'\hyperlink{%s}{\textbf{\color{red}' % node['refid'])
+
+ def depart_problematic(self, node):
+ self.out.append('}}')
+
+ def visit_raw(self, node):
+ if not 'latex' in node.get('format', '').split():
+ raise nodes.SkipNode
+ if not self.is_inline(node):
+ self.out.append('\n')
+ if node['classes']:
+ self.visit_inline(node)
+ # append "as-is" skipping any LaTeX-encoding
+ self.verbatim = True
+
+ def depart_raw(self, node):
+ self.verbatim = False
+ if node['classes']:
+ self.depart_inline(node)
+ if not self.is_inline(node):
+ self.out.append('\n')
+
+ def has_unbalanced_braces(self, string):
+ """Test whether there are unmatched '{' or '}' characters."""
+ level = 0
+ for ch in string:
+ if ch == '{':
+ level += 1
+ if ch == '}':
+ level -= 1
+ if level < 0:
+ return True
+ return level != 0
+
+ def visit_reference(self, node):
+ # We need to escape #, \, and % if we use the URL in a command.
+ special_chars = {ord('#'): u'\\#',
+ ord('%'): u'\\%',
+ ord('\\'): u'\\\\',
+ }
+ # external reference (URL)
+ if 'refuri' in node:
+ href = unicode(node['refuri']).translate(special_chars)
+ # problematic chars double caret and unbalanced braces:
+ if href.find('^^') != -1 or self.has_unbalanced_braces(href):
+ self.error(
+ 'External link "%s" not supported by LaTeX.\n'
+ ' (Must not contain "^^" or unbalanced braces.)' % href)
+ if node['refuri'] == node.astext():
+ self.out.append(r'\url{%s}' % href)
+ raise nodes.SkipNode
+ self.out.append(r'\href{%s}{' % href)
+ return
+ # internal reference
+ if 'refid' in node:
+ href = node['refid']
+ elif 'refname' in node:
+ href = self.document.nameids[node['refname']]
+ else:
+ raise AssertionError('Unknown reference.')
+ if not self.is_inline(node):
+ self.out.append('\n')
+ self.out.append('\\hyperref[%s]{' % href)
+ if self._reference_label:
+ self.out.append('\\%s{%s}}' %
+ (self._reference_label, href.replace('#', '')))
+ raise nodes.SkipNode
+
+ def depart_reference(self, node):
+ self.out.append('}')
+ if not self.is_inline(node):
+ self.out.append('\n')
+
+ def visit_revision(self, node):
+ self.visit_docinfo_item(node, 'revision')
+
+ def depart_revision(self, node):
+ self.depart_docinfo_item(node)
+
+ def visit_rubric(self, node):
+ self.fallbacks['rubric'] = PreambleCmds.rubric
+ # class wrapper would interfere with ``\section*"`` type commands
+ # (spacing/indent of first paragraph)
+ self.out.append('\n\\DUrubric{')
+
+ def depart_rubric(self, node):
+ self.out.append('}\n')
+
+ def visit_section(self, node):
+ self.section_level += 1
+ # Initialize counter for potential subsections:
+ self._section_number.append(0)
+ # Counter for this section's level (initialized by parent section):
+ self._section_number[self.section_level - 1] += 1
+
+ def depart_section(self, node):
+ # Remove counter for potential subsections:
+ self._section_number.pop()
+ self.section_level -= 1
+
+ def visit_sidebar(self, node):
+ self.duclass_open(node)
+ self.requirements['color'] = PreambleCmds.color
+ self.fallbacks['sidebar'] = PreambleCmds.sidebar
+ self.out.append('\\DUsidebar{')
+
+ def depart_sidebar(self, node):
+ self.out.append('}\n')
+ self.duclass_close(node)
+
+ attribution_formats = {'dash': (u'—', ''), # EM DASH
+ 'parentheses': ('(', ')'),
+ 'parens': ('(', ')'),
+ 'none': ('', '')}
+
+ def visit_attribution(self, node):
+ prefix, suffix = self.attribution_formats[self.settings.attribution]
+ self.out.append('\\nopagebreak\n\n\\raggedleft ')
+ self.out.append(prefix)
+ self.context.append(suffix)
+
+ def depart_attribution(self, node):
+ self.out.append(self.context.pop() + '\n')
+
+ def visit_status(self, node):
+ self.visit_docinfo_item(node, 'status')
+
+ def depart_status(self, node):
+ self.depart_docinfo_item(node)
+
+ def visit_strong(self, node):
+ self.out.append('\\textbf{')
+ if node['classes']:
+ self.visit_inline(node)
+
+ def depart_strong(self, node):
+ if node['classes']:
+ self.depart_inline(node)
+ self.out.append('}')
+
+ def visit_substitution_definition(self, node):
+ raise nodes.SkipNode
+
+ def visit_substitution_reference(self, node):
+ self.unimplemented_visit(node)
+
+ def visit_subtitle(self, node):
+ if isinstance(node.parent, nodes.document):
+ self.push_output_collector(self.subtitle)
+ self.fallbacks['documentsubtitle'] = PreambleCmds.documentsubtitle
+ self.subtitle_labels += self.ids_to_labels(node, set_anchor=False)
+ # section subtitle: "starred" (no number, not in ToC)
+ elif isinstance(node.parent, nodes.section):
+ self.out.append(r'\%s*{' %
+ self.d_class.section(self.section_level + 1))
+ else:
+ self.fallbacks['subtitle'] = PreambleCmds.subtitle
+ self.out.append('\n\\DUsubtitle{')
+
+ def depart_subtitle(self, node):
+ if isinstance(node.parent, nodes.document):
+ self.pop_output_collector()
+ else:
+ self.out.append('}\n')
+
+ def visit_system_message(self, node):
+ self.requirements['color'] = PreambleCmds.color
+ self.fallbacks['title'] = PreambleCmds.title
+ node['classes'] = ['system-message']
+ self.visit_admonition(node)
+ self.out.append('\n\\DUtitle[system-message]{system-message}\n')
+ self.append_hypertargets(node)
+ try:
+ line = ', line~%s' % node['line']
+ except KeyError:
+ line = ''
+ self.out.append('\n\n{\\color{red}%s/%s} in \\texttt{%s}%s\n' %
+ (node['type'], node['level'],
+ self.encode(node['source']), line))
+ if len(node['backrefs']) == 1:
+ self.out.append('\n\\hyperlink{%s}{' % node['backrefs'][0])
+ self.context.append('}')
+ else:
+ backrefs = ['\\hyperlink{%s}{%d}' % (href, i+1)
+ for (i, href) in enumerate(node['backrefs'])]
+ self.context.append('backrefs: ' + ' '.join(backrefs))
+
+ def depart_system_message(self, node):
+ self.out.append(self.context.pop())
+ self.depart_admonition(node)
+
+ def visit_table(self, node):
+ self.requirements['table'] = PreambleCmds.table
+ if self.active_table.is_open():
+ self.table_stack.append(self.active_table)
+ # nesting longtable does not work (e.g. 2007-04-18)
+ self.active_table = Table(self, 'tabular')
+ # A longtable moves before \paragraph and \subparagraph
+ # section titles if it immediately follows them:
+ if (self.active_table._latex_type == 'longtable' and
+ isinstance(node.parent, nodes.section) and
+ node.parent.index(node) == 1 and
+ self.d_class.section(self.section_level).find('paragraph') != -1):
+ self.out.append('\\leavevmode')
+ self.active_table.open()
+ self.active_table.set_table_style(self.settings.table_style,
+ node['classes'])
+ if 'align' in node:
+ self.active_table.set('align', node['align'])
+ if self.active_table.borders == 'booktabs':
+ self.requirements['booktabs'] = r'\usepackage{booktabs}'
+ self.push_output_collector([])
+
+ def depart_table(self, node):
+ # wrap content in the right environment:
+ content = self.out
+ self.pop_output_collector()
+ try:
+ width = self.to_latex_length(node.attributes['width'])
+ except KeyError:
+ width = r'\linewidth'
+ self.out.append('\n' + self.active_table.get_opening(width))
+ self.out += content
+ self.out.append(self.active_table.get_closing() + '\n')
+ self.active_table.close()
+ if len(self.table_stack)>0:
+ self.active_table = self.table_stack.pop()
+ # Insert hyperlabel after (long)table, as
+ # other places (beginning, caption) result in LaTeX errors.
+ if node.get('ids'):
+ self.out += self.ids_to_labels(node, set_anchor=False) + ['\n']
+
+ def visit_target(self, node):
+ # Skip indirect targets:
+ if ('refuri' in node # external hyperlink
+ or 'refid' in node # resolved internal link
+ or 'refname' in node): # unresolved internal link
+ ## self.out.append('%% %s\n' % node) # for debugging
+ return
+ self.out.append('%\n')
+ # do we need an anchor (\phantomsection)?
+ set_anchor = not isinstance(node.parent, (nodes.caption, nodes.title))
+ # TODO: where else can/must we omit the \phantomsection?
+ self.out += self.ids_to_labels(node, set_anchor)
+
+ def depart_target(self, node):
+ pass
+
+ def visit_tbody(self, node):
+ # BUG write preamble if not yet done (colspecs not [])
+ # for tables without heads.
+ if not self.active_table.get('preamble written'):
+ self.visit_thead(node)
+ self.depart_thead(None)
+
+ def depart_tbody(self, node):
+ pass
+
+ def visit_term(self, node):
+ """definition list term"""
+ # Commands with optional args inside an optional arg must be put
+ # in a group, e.g. ``\item[{\hyperref[label]{text}}]``.
+ self.out.append('\\item[{')
+
+ def depart_term(self, node):
+ # \leavevmode results in a line break if the
+ # term is followed by an item list.
+ self.out.append('}] \\leavevmode ')
+
+ def visit_tgroup(self, node):
+ #self.out.append(self.starttag(node, 'colgroup'))
+ #self.context.append('</colgroup>\n')
+ pass
+
+ def depart_tgroup(self, node):
+ pass
+
+ _thead_depth = 0
+ def thead_depth (self):
+ return self._thead_depth
+
+ def visit_thead(self, node):
+ self._thead_depth += 1
+ if 1 == self.thead_depth():
+ self.out.append('{%s}\n' % self.active_table.get_colspecs(node))
+ self.active_table.set('preamble written', 1)
+ self.out.append(self.active_table.get_caption())
+ self.out.extend(self.active_table.visit_thead())
+
+ def depart_thead(self, node):
+ if node is not None:
+ self.out.extend(self.active_table.depart_thead())
+ if self.active_table.need_recurse():
+ node.walkabout(self)
+ self._thead_depth -= 1
+
+ def visit_title(self, node):
+ """Append section and other titles."""
+ # Document title
+ if node.parent.tagname == 'document':
+ self.push_output_collector(self.title)
+ self.context.append('')
+ self.pdfinfo.append(' pdftitle={%s},' %
+ self.encode(node.astext()))
+ # Topic titles (topic, admonition, sidebar)
+ elif (isinstance(node.parent, nodes.topic) or
+ isinstance(node.parent, nodes.admonition) or
+ isinstance(node.parent, nodes.sidebar)):
+ self.fallbacks['title'] = PreambleCmds.title
+ classes = ','.join(node.parent['classes'])
+ if not classes:
+ classes = node.parent.tagname
+ self.out.append('\n\\DUtitle[%s]{' % classes)
+ self.context.append('}\n')
+ # Table caption
+ elif isinstance(node.parent, nodes.table):
+ self.push_output_collector(self.active_table.caption)
+ self.context.append('')
+ # Section title
+ else:
+ if hasattr(PreambleCmds, 'secnumdepth'):
+ self.requirements['secnumdepth'] = PreambleCmds.secnumdepth
+ section_name = self.d_class.section(self.section_level)
+ self.out.append('\n\n')
+ # System messages heading in red:
+ if ('system-messages' in node.parent['classes']):
+ self.requirements['color'] = PreambleCmds.color
+ section_title = self.encode(node.astext())
+ self.out.append(r'\%s[%s]{\color{red}' % (
+ section_name, section_title))
+ else:
+ self.out.append(r'\%s{' % section_name)
+ if self.section_level > len(self.d_class.sections):
+ # section level not supported by LaTeX
+ self.fallbacks['title'] = PreambleCmds.title
+ # self.out.append('\\phantomsection%\n ')
+ # label and ToC entry:
+ bookmark = ['']
+ # add sections with unsupported level to toc and pdfbookmarks?
+ ## if self.section_level > len(self.d_class.sections):
+ ## section_title = self.encode(node.astext())
+ ## bookmark.append(r'\addcontentsline{toc}{%s}{%s}' %
+ ## (section_name, section_title))
+ bookmark += self.ids_to_labels(node.parent, set_anchor=False)
+ self.context.append('%\n '.join(bookmark) + '%\n}\n')
+
+ # MAYBE postfix paragraph and subparagraph with \leavemode to
+ # ensure floats stay in the section and text starts on a new line.
+
+ def depart_title(self, node):
+ self.out.append(self.context.pop())
+ if (isinstance(node.parent, nodes.table) or
+ node.parent.tagname == 'document'):
+ self.pop_output_collector()
+
+ def minitoc(self, node, title, depth):
+ """Generate a local table of contents with LaTeX package minitoc"""
+ section_name = self.d_class.section(self.section_level)
+ # name-prefix for current section level
+ minitoc_names = {'part': 'part', 'chapter': 'mini'}
+ if 'chapter' not in self.d_class.sections:
+ minitoc_names['section'] = 'sect'
+ try:
+ minitoc_name = minitoc_names[section_name]
+ except KeyError: # minitoc only supports part- and toplevel
+ self.warn('Skipping local ToC at %s level.\n' % section_name +
+ ' Feature not supported with option "use-latex-toc"',
+ base_node=node)
+ return
+ # Requirements/Setup
+ self.requirements['minitoc'] = PreambleCmds.minitoc
+ self.requirements['minitoc-'+minitoc_name] = (r'\do%stoc' %
+ minitoc_name)
+ # depth: (Docutils defaults to unlimited depth)
+ maxdepth = len(self.d_class.sections)
+ self.requirements['minitoc-%s-depth' % minitoc_name] = (
+ r'\mtcsetdepth{%stoc}{%d}' % (minitoc_name, maxdepth))
+ # Process 'depth' argument (!Docutils stores a relative depth while
+ # minitoc expects an absolute depth!):
+ offset = {'sect': 1, 'mini': 0, 'part': 0}
+ if 'chapter' in self.d_class.sections:
+ offset['part'] = -1
+ if depth:
+ self.out.append('\\setcounter{%stocdepth}{%d}' %
+ (minitoc_name, depth + offset[minitoc_name]))
+ # title:
+ self.out.append('\\mtcsettitle{%stoc}{%s}\n' % (minitoc_name, title))
+ # the toc-generating command:
+ self.out.append('\\%stoc\n' % minitoc_name)
+
+ def visit_topic(self, node):
+ # Topic nodes can be generic topic, abstract, dedication, or ToC.
+ # table of contents:
+ if 'contents' in node['classes']:
+ self.out.append('\n')
+ self.out += self.ids_to_labels(node)
+ # add contents to PDF bookmarks sidebar
+ if isinstance(node.next_node(), nodes.title):
+ self.out.append('\n\\pdfbookmark[%d]{%s}{%s}' %
+ (self.section_level+1,
+ node.next_node().astext(),
+ node.get('ids', ['contents'])[0]
+ ))
+ if self.use_latex_toc:
+ title = ''
+ if isinstance(node.next_node(), nodes.title):
+ title = self.encode(node.pop(0).astext())
+ depth = node.get('depth', 0)
+ if 'local' in node['classes']:
+ self.minitoc(node, title, depth)
+ return
+ if depth:
+ self.out.append('\\setcounter{tocdepth}{%d}\n' % depth)
+ if title != 'Contents':
+ self.out.append('\n\\renewcommand{\\contentsname}{%s}' %
+ title)
+ self.out.append('\n\\tableofcontents\n')
+ self.has_latex_toc = True
+ else: # Docutils generated contents list
+ # set flag for visit_bullet_list() and visit_title()
+ self.is_toc_list = True
+ elif ('abstract' in node['classes'] and
+ self.settings.use_latex_abstract):
+ self.push_output_collector(self.abstract)
+ self.out.append('\\begin{abstract}')
+ if isinstance(node.next_node(), nodes.title):
+ node.pop(0) # LaTeX provides its own title
+ else:
+ # special topics:
+ if 'abstract' in node['classes']:
+ self.fallbacks['abstract'] = PreambleCmds.abstract
+ self.push_output_collector(self.abstract)
+ elif 'dedication' in node['classes']:
+ self.fallbacks['dedication'] = PreambleCmds.dedication
+ self.push_output_collector(self.dedication)
+ else:
+ node['classes'].insert(0, 'topic')
+ self.visit_block_quote(node)
+
+ def depart_topic(self, node):
+ self.is_toc_list = False
+ if ('abstract' in node['classes']
+ and self.settings.use_latex_abstract):
+ self.out.append('\\end{abstract}\n')
+ elif not 'contents' in node['classes']:
+ self.depart_block_quote(node)
+ if ('abstract' in node['classes'] or
+ 'dedication' in node['classes']):
+ self.pop_output_collector()
+
+ def visit_transition(self, node):
+ self.fallbacks['transition'] = PreambleCmds.transition
+ self.out.append('\n%' + '_' * 75 + '\n')
+ self.out.append('\\DUtransition\n')
+
+ def depart_transition(self, node):
+ pass
+
+ def visit_version(self, node):
+ self.visit_docinfo_item(node, 'version')
+
+ def depart_version(self, node):
+ self.depart_docinfo_item(node)
+
+ def unimplemented_visit(self, node):
+ raise NotImplementedError('visiting unimplemented node type: %s' %
+ node.__class__.__name__)
+
+# def unknown_visit(self, node):
+# def default_visit(self, node):
+
+# vim: set ts=4 et ai :
--- /dev/null
+$head_prefix% generated by Docutils <http://docutils.sourceforge.net/>
+\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}
--- /dev/null
+% ==================================================================
+% Changes to the Docutils latex2e writer since version 0.5
+% ==================================================================
+%
+% A backwards compatibility style sheet
+% *************************************
+%
+% :Author: Guenter Milde
+% :Contact: milde@users.sourceforge.net
+% :Revision: $Revision: 6156 $
+% :Date: $Date: 2009-02-24 $
+% :Copyright: © 2009 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.
+%
+% :Abstract: This file documents changes and provides a style for best
+% possible compatibility to the behaviour of the `latex2e`
+% writer of Doctutils release 0.5.
+%
+% .. _2-Clause BSD license: http://www.spdx.org/licenses/BSD-2-Clause
+%
+% ::
+
+\NeedsTeXFormat{LaTeX2e}
+\ProvidesPackage{docutils-05-compat}
+[2009/03/26 v0.1 compatibility with rst2latex from Docutils 0.5]
+
+% .. contents::
+% :depth: 3
+%
+% Usage
+% =====
+%
+% * To get an (almost) identic look for your old documents,
+% place ``docutils-05-compat.sty`` in the TEXINPUT path (e.g.
+% the current work directory) and pass the
+% ``--stylesheet=docutils-05-compat`` option to ``rst2latex.py``.
+%
+% * To use your custom stylesheets without change, add them to the
+% compatibility style, e.g.
+% ``--stylesheet="docutils-05-compat,mystyle.tex``.
+%
+% .. tip:: As the changes include bug fixes that are partly reverted by this
+% style, it is recommended to adapt the stylesheets to the new version or
+% copy just the relevant parts of this style into them.
+%
+% Changes since 0.5
+% =================
+%
+% Bugfixes
+% --------
+%
+% * Newlines around comments, targets and references prevent run-together
+% paragraphs.
+%
+% + An image directive with hyperlink reference or target did not start a
+% new paragraph (e.g. the first two image examples in
+% standalone_rst_latex.tex).
+%
+% + Paragraphs were not separated if there was a (hyper) target definition
+% inbetween.
+%
+% + Paragraphs did run together, if separated by a comment-paragraph in the
+% rst source.
+%
+% * Fixed missing and spurious internal links/targets.
+% Internal links now take you to the correct place.
+%
+% * Verbose and linked system messages.
+%
+% * `Figure and image alignment`_ now conforms to the rst definition.
+%
+% * Put `header and footer directive`__ content in \DUheader respective
+% \DUfooter macros (ignored by the default style/template).
+%
+% (They were put inside hard-coded markup at the top/bottom of the document
+% without an option to get them on every page.)
+%
+% __ ../ref/rst/directives.html#document-header-footer
+%
+% * Render doctest blocks as literal blocks (fixes bug [1586058] doctest block
+% nested in admonition). I.e.
+%
+% + indent doctest blocks by nesting in a quote environment. This is also
+% the rendering by the HTML writer (html4css2.css).
+% + apply the ``--literal-block-env`` setting also to doctest blocks.
+%
+% .. warning::
+% (``--literal-block-env=verbatim`` and
+% ``--literal-block-env=lstlistings`` fail with literal or doctest
+% blocks nested in an admonition.
+%
+% * Two-way hyperlinked footnotes and support for symbol footnotes and
+% ``--footnote-references=brackets`` with ``--use-latex-footnotes``.
+%
+% * The packages `fixltx2e` (providing LaTeX patches and the \textsubscript
+% command) and `cmap` (including character maps in the generated PDF for
+% better search and copy-and-paste operations) are now always loaded
+% (configurable with custom templates_).
+%
+% Backwards compatibility:
+% "Bug for bug compatibility" is not provided.
+%
+%
+% New configuration setting defaults
+% ----------------------------------
+%
+% - font-encoding: "T1" (formerly implicitely set by 'ae').
+% - use-latex-toc: true (ToC with page numbers).
+% - use-latex-footnotes: true (no mixup with figures).
+%
+% Backwards compatibility:
+% Reset to the former defaults with:
+%
+% | font-encoding: ''
+% | use-latex-toc: False
+% | use-latex-footnotes: False
+%
+% (in the config file) or the command line options:
+%
+% ``--figure-footnotes --use-docutils-toc --font-encoding=''``
+%
+%
+% Cleaner LaTeX source
+% --------------------
+%
+% New features:
+% * Remove redundant "double protection" from the encoding of the "special
+% printing characters" and square brackets, e.g. ``\%`` instead of
+% ``{\%}``.
+% * Remove some spurious whitespace, e.g. ``\item [what:] -> \item[what:]``.
+% * Use conventional style for "named" macros, e.g. ``\dots{}`` instead of
+% ``{\dots}``
+%
+% Backwards compatibility:
+% Changes do not affect the output.
+%
+%
+% LaTeX style sheets
+% ------------------
+%
+% New Feature:
+% LaTeX packages can be used as ``--stylesheet`` argument without
+% restriction.
+%
+% Implementation:
+% Use ``\usepackage`` if style sheet ends with ``.sty`` or has no
+% extension and ``\input`` else.
+%
+% Rationale:
+% while ``\input`` works with extension as well as without extension,
+% ``\usepackage`` expects the package name without extension. (The latex2e
+% writer will strip a ``.sty`` extension.)
+%
+%
+% Backwards compatibility:
+% Up to Docutils 0.5, if no filename extension is given in the
+% ``stylesheet`` argument, ``.tex`` is assumed (by latex).
+%
+% Since Docutils 0.6, a stylesheet without filename extension is assumed to
+% be a LaTeX package (``*.sty``) and referenced with the ``\usepackage``
+% command.
+%
+% .. important::
+% Always specify the extension if you want the style sheet to be
+% ``\input`` by LaTeX.
+%
+%
+% Templates
+% ---------
+%
+% New Feature:
+% Advanced configuration via custom templates.
+%
+% Implementation:
+% A ``--template`` option and config setting allows specification of a
+% template file.
+%
+% See the `LaTeX writer documentation`__ for details.
+%
+% __ latex.html#templates
+%
+%
+% Custom roles
+% ------------
+%
+% New Feature: failsave implementation
+% As with classes to HTML objects, class arguments are silently ignored if
+% there is no styling rule for this class in a custom style sheet.
+%
+% New Feature: custom roles based on standard roles
+% As class support needs to be handled by the LaTeX writer, this feature was
+% not present "automatically" (as in HTML). Modified visit/depart_*()
+% methods for the standard roles now call visit/depart_inline() if there are
+% class arguments to the node.
+%
+% Backwards compatibility:
+% The implementation is fully backwards compatible. (SVN versions 5742 to
+% 5861 contained an implementation that did not work with commands expecting
+% an argument.)
+%
+% Length units
+% ------------
+%
+% New Features:
+% 1. Add default unit if none given.
+% A poll on docutils-users favoured ``bp`` (Big Point: 1 bp = 1/72 in).
+%
+% 2. Do not change ``px`` to ``pt``.
+%
+% 3. Lengths specified in the document with unit "pt" will be written with
+% unit "bp" to the LaTeX source.
+%
+% Rationale:
+% 1. prevent LaTeX error "missing unit".
+%
+% 2. ``px`` is a valid unit in pdftex since version 1.3.0 released on
+% 2005-02-04:
+%
+% 1px defaults to 1bp (or 72dpi), but can be changed with the
+% ``\pdfpxdimen`` primitive.::
+
+ \pdfpxdimen=1in % 1 dpi
+ \divide\pdfpxdimen by 96 % 96 dpi
+
+% -- http://www.tug.org/applications/pdftex/NEWS
+%
+% Modern TeX distributions use pdftex also for dvi generation (i.e.
+% ``latex`` actually calls ``pdftex`` with some options).
+%
+% 3. In Docutils (as well as CSS) the unit symbol "pt" denotes the
+% `Postscript point` or `DTP point` while LaTeX uses "pt" for the `LaTeX
+% point`, which is unknown to Docutils and 0.3 % smaller.
+%
+% The `DTP point` is available in LaTeX as "bp" (big point):
+%
+% 1 pt = 1/72.25 in < 1 bp = 1/72 in
+%
+%
+% Backwards compatibility:
+% Images with width specification in ``px`` come out slightly (0.3 %) larger:
+%
+% 1 px = 1 bp = 1/72 in > 1 pt = 1/72.25 in
+%
+% This can be reset with ::
+
+ \pdfpxdimen=1pt
+
+% .. caution:: It is impossible to revert the change of lengths specified with
+% "pt" or without unit in a style sheet, however the 0.3 % change will be
+% imperceptible in most cases.
+%
+% .. admonition:: Error ``illegal unit px``
+%
+% The unit ``px`` is not defined in "pure" LaTeX, but introduced by the
+% `pdfTeX` converter on 2005-02-04. `pdfTeX` is used in all modern LaTeX
+% distributions (since ca. 2006) also for conversion into DVI.
+%
+% If you convert the LaTeX source with a legacy program, you might get the
+% error ``illegal unit px``.
+%
+% If updating LaTeX is not an option, just remove the ``px`` from the length
+% specification. HTML/CSS will default to ``px`` while the `latexe2` writer
+% will add the fallback unit ``bp``.
+%
+%
+% Font encoding
+% -------------
+%
+% New feature:
+% Do not mix font-encoding and font settings: do not load the obsolete
+% `ae` and `aeguill` packages unless explicitely required via the
+% ``--stylesheet`` option.
+%
+% :font-encoding = "": do not load `ae` and `aeguill`, i.e.
+%
+% * do not change font settings,
+% * do not use the fontenc package
+% (implicitely loaded via `ae`),
+% * use LaTeX default font encoding (OT1)
+%
+% :font-encoding = "OT1": load `fontenc` with ``\usepackage[OT1]{fontenc}``
+%
+% Example:
+% ``--font-encoding=LGR,T1`` becomes ``\usepackage[LGR,T1]{fontenc}``
+% (Latin, Latin-1 Supplement, and Greek)
+%
+%
+% Backwards compatibility:
+% Load the ae and aeguill packages if fontenc is not used.
+%
+% .. tip:: Using `ae` is not recommended. A similar look (but better
+% implementation) can be achieved with the packages `lmodern`, `cmsuper`,
+% or `cmlgr` all providing Computer Modern look-alikes in vector format and
+% T1 encoding, e.g. ``--font-encoding=T1 --stylesheet=lmodern``.
+%
+% Sub- and superscript as text
+% ----------------------------
+%
+% New feature:
+% Set sub- and superscript role argument in text mode not as math.
+%
+% Pass the role content to ``\textsubscript`` or ``\textsuperscript``.
+%
+% Backwards compatibility:
+% The old implementation set the role content in Math mode, where
+%
+% * whitespace is ignored,
+% * a different command set and font setting scheme is active,
+% * Latin letters are typeset italic but numbers upright.
+%
+% Although it is possible to redefine ``\textsubscript`` and
+% ``\textsuperscript`` to typeset the content in math-mode, this can lead to
+% errors with certain input and is therefore not done in this style sheet.
+%
+% .. tip:: To get italic subscripts, define and use in your document
+% `custom roles`_ like ``.. role:: sub(subscript)`` and
+% ``.. role:: super(superscript)`` and define the "role commands"::
+
+ \newcommand{\DUrolesub}{\itshape}
+ \newcommand{\DUrolesuper}{\itshape}
+
+% Alternatively, if you want all sub- and superscripts in italic, redefine
+% the macros::
+
+ %% \let\DUsup\textsubscript
+ %% \let\DUsuper\textsuperscript
+ %% \renewcommand*{\textsubscript}{\DUsub\itshape}
+ %% \renewcommand*{\textsuperscript}{\DUsuper\itshape}
+
+% This is not fully backwards compatible, as it will also set numbers in
+% italic shape and not ignore whitespace.
+%
+% Page layout
+% -----------
+%
+% New features:
+% * Margins are configurable via the ``DIV=...`` document option.
+%
+% * The ``\raggedbottom`` setting is no longer inserted into the document. It
+% is the default for article and report classes. If requested in combination
+% with a book class, it can be given in a custom style sheet.
+%
+% Backwards compatibility:
+% Up to version 0.5, use of `typearea` and a DIV setting of 12 were
+% hard-coded into the latex2e writer ::
+
+ \usepackage{typearea}
+ \typearea{12}
+
+% and the vertical alignment of lower boundary of the text area in book
+% classes disabled via ::
+
+ \raggedbottom
+
+
+% ToC and section numbers
+% -----------------------
+%
+% Better conformance to Docutils specifications.
+%
+% New feature:
+% * The "depth" argument of the "contents" and "sectnum" directives is
+% respected.
+%
+% * section numbering independent of 'use-latex-toc':
+%
+% + sections are only numbered if there is a "sectnum" directive in the
+% document
+%
+% + section numbering by LaTeX if the "sectnum_xforms" config setting is
+% False.
+%
+% Backwards compatibility:
+%
+% The previous behaviour was to always number sections if 'use-latex-toc' is
+% true, using the document class defaults. It cannot be restored
+% universally, the following code sets the default values of the "article"
+% document class::
+
+ \setcounter{secnumdepth}{3}
+ \setcounter{tocdepth}{3}
+
+% .. TODO or not to do? (Back-compatibility problems)
+% * The default "depth" of the LaTeX-created ToC and the LaTeX section
+% numbering is increased to the number of supported section levels.
+%
+% New feature:
+% If 'use-latex-toc' is set, local tables of content are typeset using the
+% 'minitoc' package (instead of being ignored).
+%
+% Backwards compatibility:
+% Disable the creation of local ToCs (ignoring all special commands) by
+% replacing ``\usepackage{minitoc} with ``\usepackage{mtcoff}``.
+%
+%
+% Default font in admonitions and sidebar
+% ---------------------------------------
+%
+% New feature:
+% Use default font in admonitions and sidebar.
+%
+% Backward compatibility:
+% See the fallback definitions for admonitions_, `topic title`_ and
+% `sidebar`_.
+%
+%
+% Figure placement
+% ----------------
+%
+% New feature:
+% Use ``\floatplacement`` from the `float` package instead of
+% "hard-coded" optional argument for the global setting.
+%
+% Default to ``\floatplacement{figure}{H}`` (here definitely). This
+% corresponds most closely to the source and HTML placement (principle of
+% least surprise).
+%
+% Backwards compatibility:
+% Set the global default back to the previous used value::
+
+ \usepackage{float}
+ \floatplacement{figure}{htbp} % here, top, bottom, extra-page
+
+
+% Figure and image alignment
+% --------------------------
+%
+% New features:
+%
+% a) Fix behaviour of 'align' argument to a figure (do not align figure
+% contents).
+%
+% As the 'figwidth' argument is still ignored and the "natural width" of a
+% figure in LaTeX is 100% \textwidth, setting the 'align' argument of a
+% figure has currently no effect on the LaTeX output.
+%
+% b) Set default align of image in a figure to 'center'.
+%
+% c) Also center images that are wider than textwidth.
+%
+% d) Align images with class "align-[right|center|left]" (allows setting the
+% alignment of an image in a figure).
+%
+% Backwards compatibility:
+% There is no "automatic" way to reverse these changes via a style sheet.
+%
+% a) The alignment of the image can be set with the "align-left",
+% "align-center" and "align-right" class arguments.
+%
+% As previously, the caption of a figure is aligned according to the
+% document class -- configurable with a style sheet using the "caption"
+% package.
+%
+% b) See a)
+%
+% c) Set the alignment of "oversized" images to "left" to get back the
+% old placement.
+%
+% Shorter preamble
+% ----------------
+%
+% New feature:
+% The document preamble is pruned to contain only relevant commands and
+% settings.
+%
+% Packages that are no longer required
+% ````````````````````````````````````
+%
+% The following packages where required in pre-0.5 versions and still loaded
+% with version 0.5::
+
+\usepackage{shortvrb}
+\usepackage{amsmath}
+
+
+% Packages that are conditionally loaded
+% ``````````````````````````````````````
+%
+% Additional to the `typearea` for `page layout`_, the following packages are
+% only loaded if actually required by doctree elements:
+%
+% Tables
+% ^^^^^^
+%
+% Standard package for tables across several pages::
+
+\usepackage{longtable}
+
+% Extra space between text in tables and the line above them
+% ('array' is implicitely loaded by 'tabularx', see below)::
+
+\usepackage{array}
+\setlength{\extrarowheight}{2pt}
+
+% Table cells spanning multiple rows::
+
+\usepackage{multirow}
+
+% Docinfo
+% ^^^^^^^
+%
+% One-page tables with auto-width columns::
+
+\usepackage{tabularx}
+
+% Images
+% ^^^^^^
+% Include graphic files::
+
+\usepackage{graphicx}
+
+% Problematic, Sidebar
+% ^^^^^^^^^^^^^^^^^^^^
+% Set text and/or background colour, coloured boxes with ``\colorbox``::
+
+\usepackage{color}
+
+% Floats for footnotes settings
+% `````````````````````````````
+%
+% Settings for the use of floats for footnotes are only included if
+%
+% * the option "use-latex-footnotes" is False, and
+% * there is at least one footnote in the document.
+%
+% ::
+
+% begin: floats for footnotes tweaking.
+\setlength{\floatsep}{0.5em}
+\setlength{\textfloatsep}{\fill}
+\addtolength{\textfloatsep}{3em}
+\renewcommand{\textfraction}{0.5}
+\renewcommand{\topfraction}{0.5}
+\renewcommand{\bottomfraction}{0.5}
+\setcounter{totalnumber}{50}
+\setcounter{topnumber}{50}
+\setcounter{bottomnumber}{50}
+% end floats for footnotes
+
+
+% Special lengths, commands, and environments
+% -------------------------------------------
+%
+% Removed definitions
+% ```````````````````
+%
+% admonition width
+% ^^^^^^^^^^^^^^^^
+% The ``admonitionwith`` lenght is replaced by the more powerful
+% ``\DUadmonition`` command (see admonitions_).
+%
+% Backwards compatibility:
+% The default value (90 % of the textwidth) is unchanged.
+%
+% To configure the admonition width, you must redefine the ``DUadmonition``
+% command instead of changing the ``admonitionwith`` length value.
+%
+%
+% Renamed definitions (now conditional)
+% `````````````````````````````````````
+%
+% The names for special doctree elements are now prefixed with ``DU``.
+%
+% Up to version 0.5, all definitions were included in the preamble (before the
+% style sheet) of every document -- even if not used in the body. Since
+% version 0.6, fallback definitions are included after the style sheet and
+% only if required.
+%
+% Customization is done by an alternative definition in a style sheet with
+% ``\newcommand`` instead of the former ``\renewcommand``.
+%
+% The following code provides the old definitions and maps them (or their
+% custom variants) to the new interface.
+%
+% docinfo width
+% ^^^^^^^^^^^^^
+% ::
+
+\newlength{\docinfowidth}
+\setlength{\docinfowidth}{0.9\textwidth}
+
+\newlength{\DUdocinfowidth}
+\AtBeginDocument{\setlength{\DUdocinfowidth}{\docinfowidth}}
+
+% line block
+% ^^^^^^^^^^
+% ::
+
+\newlength{\lineblockindentation}
+\setlength{\lineblockindentation}{2.5em}
+\newenvironment{lineblock}[1]
+{\begin{list}{}
+ {\setlength{\partopsep}{\parskip}
+ \addtolength{\partopsep}{\baselineskip}
+ \topsep0pt\itemsep0.15\baselineskip\parsep0pt
+ \leftmargin#1}
+ \raggedright}
+{\end{list}}
+
+\newlength{\DUlineblockindent}
+\AtBeginDocument{\setlength{\DUlineblockindent}{\lineblockindentation}}
+\newenvironment{DUlineblock}[1]
+ {\begin{lineblock}{#1}}
+ {\end{lineblock}}
+
+% local line width
+% ^^^^^^^^^^^^^^^^
+%
+% The ``\locallinewidth`` length for internal use in tables is replaced
+% by ``\DUtablewidth``. It was never intended for customization::
+
+\newlength{\locallinewidth}
+
+% option lists
+% ^^^^^^^^^^^^
+% ::
+
+\newcommand{\optionlistlabel}[1]{\bf #1 \hfill}
+\newenvironment{optionlist}[1]
+{\begin{list}{}
+ {\setlength{\labelwidth}{#1}
+ \setlength{\rightmargin}{1cm}
+ \setlength{\leftmargin}{\rightmargin}
+ \addtolength{\leftmargin}{\labelwidth}
+ \addtolength{\leftmargin}{\labelsep}
+ \renewcommand{\makelabel}{\optionlistlabel}}
+}{\end{list}}
+
+\newcommand{\DUoptionlistlabel}{\optionlistlabel}
+\newenvironment{DUoptionlist}
+ {\begin{optionlist}{3cm}}
+ {\end{optionlist}}
+
+% rubric
+% ^^^^^^
+% Now less prominent (not bold, normal size) restore with::
+
+\newcommand{\rubric}[1]{\subsection*{~\hfill {\it #1} \hfill ~}}
+\newcommand{\DUrubric}[2][class-arg]{\rubric{#2}}
+
+% title reference role
+% ^^^^^^^^^^^^^^^^^^^^
+% ::
+
+\newcommand{\titlereference}[1]{\textsl{#1}}
+\newcommand{\DUroletitlereference}[1]{\titlereference{#1}}
+
+
+% New definitions
+% ```````````````
+%
+% New Feature:
+% Enable customization of some more Docutils elements with special commands
+%
+% :admonition: ``DUadmonition`` command (replacing ``\admonitionwidth``),
+% :field list: ``DUfieldlist`` environment,
+% :legend: ``DUlegend`` environment,
+% :sidebar: ``\DUsidebar``, ``\DUtitle``, and
+% ``DUsubtitle`` commands,
+% :topic: ``\DUtopic`` and ``\DUtitle`` commands,
+% :transition: ``\DUtransition`` command.
+% :footnotes: ``\DUfootnotemark`` and ``\DUfootnotetext`` commands with
+% hyperlink support using the Docutils-provided footnote label.
+%
+% Backwards compatibility:
+% In most cases, the default definition corresponds to the previously used
+% construct. The following definitions restore the old behaviour in case of
+% changes.
+%
+% admonitions
+% ^^^^^^^^^^^
+% Use sans-serif fonts::
+
+\newcommand{\DUadmonition}[2][class-arg]{%
+ \begin{center}
+ \fbox{\parbox{0.9\textwidth}{\sffamily #2}}
+ \end{center}
+}
+
+% dedication
+% ^^^^^^^^^^
+% Do not center::
+
+\newcommand{\DUtopicdedication}[1]{#1}
+
+% But center the title::
+
+\newcommand*{\DUtitlededication}[1]{\centerline{\textbf{#1}}}
+
+% sidebar
+% ^^^^^^^
+% Use sans-serif fonts, a frame, and a darker shade of grey::
+
+\providecommand{\DUsidebar}[2][class-arg]{%
+ \begin{center}
+ \sffamily
+ \fbox{\colorbox[gray]{0.80}{\parbox{0.9\textwidth}{#2}}}
+ \end{center}
+}
+
+% sidebar sub-title
+% ^^^^^^^^^^^^^^^^^
+% Bold instead of emphasized::
+
+\providecommand*{\DUsubtitlesidebar}[1]{\hspace*{\fill}\\
+ \textbf{#1}\smallskip}
+
+% topic
+% ^^^^^
+% No quote but normal text::
+
+\newcommand{\DUtopic}[2][class-arg]{%
+ \ifcsname DUtopic#1\endcsname%
+ \csname DUtopic#1\endcsname{#2}%
+ \else
+ #2
+ \fi
+}
+
+% topic title
+% ^^^^^^^^^^^
+% Title for "topics" (admonitions, sidebar).
+%
+% Larger font size::
+
+\providecommand*{\DUtitletopic}[1]{\textbf{\large #1}\smallskip}
+
+% transition
+% ^^^^^^^^^^
+% Do not add vertical space after the transition. ::
+
+\providecommand*{\DUtransition}[1][class-arg]{%
+ \hspace*{\fill}\hrulefill\hspace*{\fill}}
--- /dev/null
+% generated by Docutils <http://docutils.sourceforge.net/>
+$head_prefix
+\usepackage{fixltx2e} % LaTeX patches, \textsubscript
+\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}
--- /dev/null
+$head_prefix% generated by Docutils <http://docutils.sourceforge.net/>
+% 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}
--- /dev/null
+# -*- coding: utf-8 -*-
+# $Id: manpage.py 8451 2019-12-30 14:42:44Z grubert $
+# Author: Engelbert Gruber <grubert@users.sourceforge.net>
+# Copyright: This module is put into the public domain.
+
+"""
+Simple man page writer for reStructuredText.
+
+Man pages (short for "manual pages") contain system documentation on unix-like
+systems. The pages are grouped in numbered sections:
+
+ 1 executable programs and shell commands
+ 2 system calls
+ 3 library functions
+ 4 special files
+ 5 file formats
+ 6 games
+ 7 miscellaneous
+ 8 system administration
+
+Man pages are written *troff*, a text file formatting system.
+
+See http://www.tldp.org/HOWTO/Man-Page for a start.
+
+Man pages have no subsection only parts.
+Standard parts
+
+ NAME ,
+ SYNOPSIS ,
+ DESCRIPTION ,
+ OPTIONS ,
+ FILES ,
+ SEE ALSO ,
+ BUGS ,
+
+and
+
+ AUTHOR .
+
+A unix-like system keeps an index of the DESCRIPTIONs, which is accessible
+by the command whatis or apropos.
+
+"""
+
+__docformat__ = 'reStructuredText'
+
+import re
+import sys
+
+if sys.version_info < (3, 0):
+ range = xrange
+
+import docutils
+from docutils import nodes, writers, languages
+try:
+ import roman
+except ImportError:
+ import docutils.utils.roman as roman
+
+FIELD_LIST_INDENT = 7
+DEFINITION_LIST_INDENT = 7
+OPTION_LIST_INDENT = 7
+BLOCKQOUTE_INDENT = 3.5
+LITERAL_BLOCK_INDENT = 3.5
+
+# Define two macros so man/roff can calculate the
+# indent/unindent margins by itself
+MACRO_DEF = (r""".
+.nr rst2man-indent-level 0
+.
+.de1 rstReportMargin
+\\$1 \\n[an-margin]
+level \\n[rst2man-indent-level]
+level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
+-
+\\n[rst2man-indent0]
+\\n[rst2man-indent1]
+\\n[rst2man-indent2]
+..
+.de1 INDENT
+.\" .rstReportMargin pre:
+. RS \\$1
+. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin]
+. nr rst2man-indent-level +1
+.\" .rstReportMargin post:
+..
+.de UNINDENT
+. RE
+.\" indent \\n[an-margin]
+.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.nr rst2man-indent-level -1
+.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
+..
+""")
+
+class Writer(writers.Writer):
+
+ supported = ('manpage',)
+ """Formats this writer supports."""
+
+ output = None
+ """Final translated form of `document`."""
+
+ def __init__(self):
+ writers.Writer.__init__(self)
+ self.translator_class = Translator
+
+ def translate(self):
+ visitor = self.translator_class(self.document)
+ self.document.walkabout(visitor)
+ self.output = visitor.astext()
+
+
+class Table(object):
+ def __init__(self):
+ self._rows = []
+ self._options = ['center']
+ self._tab_char = '\t'
+ self._coldefs = []
+ def new_row(self):
+ self._rows.append([])
+ def append_separator(self, separator):
+ """Append the separator for table head."""
+ self._rows.append([separator])
+ def append_cell(self, cell_lines):
+ """cell_lines is an array of lines"""
+ start = 0
+ if len(cell_lines) > 0 and cell_lines[0] == '.sp\n':
+ start = 1
+ self._rows[-1].append(cell_lines[start:])
+ if len(self._coldefs) < len(self._rows[-1]):
+ self._coldefs.append('l')
+ def _minimize_cell(self, cell_lines):
+ """Remove leading and trailing blank and ``.sp`` lines"""
+ while (cell_lines and cell_lines[0] in ('\n', '.sp\n')):
+ del cell_lines[0]
+ while (cell_lines and cell_lines[-1] in ('\n', '.sp\n')):
+ del cell_lines[-1]
+ def as_list(self):
+ text = ['.TS\n']
+ text.append(' '.join(self._options) + ';\n')
+ text.append('|%s|.\n' % ('|'.join(self._coldefs)))
+ for row in self._rows:
+ # row = array of cells. cell = array of lines.
+ text.append('_\n') # line above
+ text.append('T{\n')
+ for i in range(len(row)):
+ cell = row[i]
+ self._minimize_cell(cell)
+ text.extend(cell)
+ if not text[-1].endswith('\n'):
+ text[-1] += '\n'
+ if i < len(row)-1:
+ text.append('T}'+self._tab_char+'T{\n')
+ else:
+ text.append('T}\n')
+ text.append('_\n')
+ text.append('.TE\n')
+ return text
+
+class Translator(nodes.NodeVisitor):
+ """"""
+
+ words_and_spaces = re.compile(r'\S+| +|\n')
+ possibly_a_roff_command = re.compile(r'\.\w')
+ document_start = """Man page generated from reStructuredText."""
+
+ def __init__(self, document):
+ nodes.NodeVisitor.__init__(self, document)
+ self.settings = settings = document.settings
+ lcode = settings.language_code
+ self.language = languages.get_language(lcode, document.reporter)
+ self.head = []
+ self.body = []
+ self.foot = []
+ self.section_level = 0
+ self.context = []
+ self.topic_class = ''
+ self.colspecs = []
+ self.compact_p = 1
+ self.compact_simple = None
+ # the list style "*" bullet or "#" numbered
+ self._list_char = []
+ # writing the header .TH and .SH NAME is postboned after
+ # docinfo.
+ self._docinfo = {
+ "title": "", "title_upper": "",
+ "subtitle": "",
+ "manual_section": "", "manual_group": "",
+ "author": [],
+ "date": "",
+ "copyright": "",
+ "version": "",
+ }
+ self._docinfo_keys = [] # a list to keep the sequence as in source.
+ self._docinfo_names = {} # to get name from text not normalized.
+ self._in_docinfo = None
+ self._active_table = None
+ self._in_literal = False
+ self.header_written = 0
+ self._line_block = 0
+ self.authors = []
+ self.section_level = 0
+ self._indent = [0]
+ # central definition of simple processing rules
+ # what to output on : visit, depart
+ # Do not use paragraph requests ``.PP`` because these set indentation.
+ # use ``.sp``. Remove superfluous ``.sp`` in ``astext``.
+ #
+ # Fonts are put on a stack, the top one is used.
+ # ``.ft P`` or ``\\fP`` pop from stack.
+ # But ``.BI`` seams to fill stack with BIBIBIBIB...
+ # ``B`` bold, ``I`` italic, ``R`` roman should be available.
+ # Hopefully ``C`` courier too.
+ self.defs = {
+ 'indent': ('.INDENT %.1f\n', '.UNINDENT\n'),
+ 'definition_list_item': ('.TP', ''),
+ 'field_name': ('.TP\n.B ', '\n'),
+ 'literal': ('\\fB', '\\fP'),
+ 'literal_block': ('.sp\n.nf\n.ft C\n', '\n.ft P\n.fi\n'),
+
+ 'option_list_item': ('.TP\n', ''),
+
+ 'reference': (r'\fI\%', r'\fP'),
+ 'emphasis': ('\\fI', '\\fP'),
+ 'strong': ('\\fB', '\\fP'),
+ 'term': ('\n.B ', '\n'),
+ 'title_reference': ('\\fI', '\\fP'),
+
+ 'topic-title': ('.SS ',),
+ 'sidebar-title': ('.SS ',),
+
+ 'problematic': ('\n.nf\n', '\n.fi\n'),
+ }
+ # NOTE do not specify the newline before a dot-command, but ensure
+ # it is there.
+
+ def comment_begin(self, text):
+ """Return commented version of the passed text WITHOUT end of
+ line/comment."""
+ prefix = '.\\" '
+ out_text = ''.join(
+ [(prefix + in_line + '\n')
+ for in_line in text.split('\n')])
+ return out_text
+
+ def comment(self, text):
+ """Return commented version of the passed text."""
+ return self.comment_begin(text)+'.\n'
+
+ def ensure_eol(self):
+ """Ensure the last line in body is terminated by new line."""
+ if len(self.body) > 0 and self.body[-1][-1] != '\n':
+ self.body.append('\n')
+
+ def astext(self):
+ """Return the final formatted document as a string."""
+ if not self.header_written:
+ # ensure we get a ".TH" as viewers require it.
+ self.append_header()
+ # filter body
+ for i in range(len(self.body)-1, 0, -1):
+ # remove superfluous vertical gaps.
+ if self.body[i] == '.sp\n':
+ if self.body[i - 1][:4] in ('.BI ', '.IP '):
+ self.body[i] = '.\n'
+ elif (self.body[i - 1][:3] == '.B ' and
+ self.body[i - 2][:4] == '.TP\n'):
+ self.body[i] = '.\n'
+ elif (self.body[i - 1] == '\n' and
+ not self.possibly_a_roff_command.match(self.body[i - 2]) and
+ (self.body[i - 3][:7] == '.TP\n.B '
+ or self.body[i - 3][:4] == '\n.B ')
+ ):
+ self.body[i] = '.\n'
+ return ''.join(self.head + self.body + self.foot)
+
+ def deunicode(self, text):
+ text = text.replace(u'\xa0', '\\ ')
+ text = text.replace(u'\u2020', '\\(dg')
+ return text
+
+ def visit_Text(self, node):
+ text = node.astext()
+ text = text.replace('\\', '\\e')
+ replace_pairs = [
+ (u'-', u'\\-'),
+ (u'\'', u'\\(aq'),
+ (u'´', u"\\'"),
+ (u'`', u'\\(ga'),
+ ]
+ for (in_char, out_markup) in replace_pairs:
+ text = text.replace(in_char, out_markup)
+ # unicode
+ text = self.deunicode(text)
+ # prevent interpretation of "." at line start
+ if text.startswith('.'):
+ text = '\\&' + text
+ if self._in_literal:
+ text = text.replace('\n.', '\n\\&.')
+ self.body.append(text)
+
+ def depart_Text(self, node):
+ pass
+
+ def list_start(self, node):
+ class enum_char(object):
+ enum_style = {
+ 'bullet': '\\(bu',
+ 'emdash': '\\(em',
+ }
+
+ def __init__(self, style):
+ self._style = style
+ if 'start' in node:
+ self._cnt = node['start'] - 1
+ else:
+ self._cnt = 0
+ self._indent = 2
+ if style == 'arabic':
+ # indentation depends on number of children
+ # and start value.
+ self._indent = len(str(len(node.children)))
+ self._indent += len(str(self._cnt)) + 1
+ elif style == 'loweralpha':
+ self._cnt += ord('a') - 1
+ self._indent = 3
+ elif style == 'upperalpha':
+ self._cnt += ord('A') - 1
+ self._indent = 3
+ elif style.endswith('roman'):
+ self._indent = 5
+
+ def __next__(self):
+ if self._style == 'bullet':
+ return self.enum_style[self._style]
+ elif self._style == 'emdash':
+ return self.enum_style[self._style]
+ self._cnt += 1
+ # TODO add prefix postfix
+ if self._style == 'arabic':
+ return "%d." % self._cnt
+ elif self._style in ('loweralpha', 'upperalpha'):
+ return "%c." % self._cnt
+ elif self._style.endswith('roman'):
+ res = roman.toRoman(self._cnt) + '.'
+ if self._style.startswith('upper'):
+ return res.upper()
+ return res.lower()
+ else:
+ return "%d." % self._cnt
+
+ if sys.version_info < (3, 0):
+ next = __next__
+
+ def get_width(self):
+ return self._indent
+ def __repr__(self):
+ return 'enum_style-%s' % list(self._style)
+
+ if 'enumtype' in node:
+ self._list_char.append(enum_char(node['enumtype']))
+ else:
+ self._list_char.append(enum_char('bullet'))
+ if len(self._list_char) > 1:
+ # indent nested lists
+ self.indent(self._list_char[-2].get_width())
+ else:
+ self.indent(self._list_char[-1].get_width())
+
+ def list_end(self):
+ self.dedent()
+ self._list_char.pop()
+
+ def header(self):
+ tmpl = (".TH %(title_upper)s %(manual_section)s"
+ " \"%(date)s\" \"%(version)s\" \"%(manual_group)s\"\n"
+ ".SH NAME\n"
+ "%(title)s \\- %(subtitle)s\n")
+ return tmpl % self._docinfo
+
+ def append_header(self):
+ """append header with .TH and .SH NAME"""
+ # NOTE before everything
+ # .TH title_upper section date source manual
+ if self.header_written:
+ return
+ self.head.append(self.header())
+ self.head.append(MACRO_DEF)
+ self.header_written = 1
+
+ def visit_address(self, node):
+ self.visit_docinfo_item(node, 'address')
+
+ def depart_address(self, node):
+ pass
+
+ def visit_admonition(self, node, name=None):
+ #
+ # Make admonitions a simple block quote
+ # with a strong heading
+ #
+ # Using .IP/.RE doesn't preserve indentation
+ # when admonitions contain bullets, literal,
+ # and/or block quotes.
+ #
+ if name:
+ # .. admonition:: has no name
+ self.body.append('.sp\n')
+ name = '%s%s:%s\n' % (
+ self.defs['strong'][0],
+ self.language.labels.get(name, name).upper(),
+ self.defs['strong'][1],
+ )
+ self.body.append(name)
+ self.visit_block_quote(node)
+
+ def depart_admonition(self, node):
+ self.depart_block_quote(node)
+
+ def visit_attention(self, node):
+ self.visit_admonition(node, 'attention')
+
+ depart_attention = depart_admonition
+
+ def visit_docinfo_item(self, node, name):
+ if name == 'author':
+ self._docinfo[name].append(node.astext())
+ else:
+ self._docinfo[name] = node.astext()
+ self._docinfo_keys.append(name)
+ raise nodes.SkipNode
+
+ def depart_docinfo_item(self, node):
+ pass
+
+ def visit_author(self, node):
+ self.visit_docinfo_item(node, 'author')
+
+ depart_author = depart_docinfo_item
+
+ def visit_authors(self, node):
+ # _author is called anyway.
+ pass
+
+ def depart_authors(self, node):
+ pass
+
+ def visit_block_quote(self, node):
+ # BUG/HACK: indent always uses the _last_ indention,
+ # thus we need two of them.
+ self.indent(BLOCKQOUTE_INDENT)
+ self.indent(0)
+
+ def depart_block_quote(self, node):
+ self.dedent()
+ self.dedent()
+
+ def visit_bullet_list(self, node):
+ self.list_start(node)
+
+ def depart_bullet_list(self, node):
+ self.list_end()
+
+ def visit_caption(self, node):
+ pass
+
+ def depart_caption(self, node):
+ pass
+
+ def visit_caution(self, node):
+ self.visit_admonition(node, 'caution')
+
+ depart_caution = depart_admonition
+
+ def visit_citation(self, node):
+ num, text = node.astext().split(None, 1)
+ num = num.strip()
+ self.body.append('.IP [%s] 5\n' % num)
+
+ def depart_citation(self, node):
+ pass
+
+ def visit_citation_reference(self, node):
+ self.body.append('['+node.astext()+']')
+ raise nodes.SkipNode
+
+ def visit_classifier(self, node):
+ pass
+
+ def depart_classifier(self, node):
+ pass
+
+ def visit_colspec(self, node):
+ self.colspecs.append(node)
+
+ def depart_colspec(self, node):
+ pass
+
+ def write_colspecs(self):
+ self.body.append("%s.\n" % ('L '*len(self.colspecs)))
+
+ def visit_comment(self, node,
+ sub=re.compile('-(?=-)').sub):
+ self.body.append(self.comment(node.astext()))
+ raise nodes.SkipNode
+
+ def visit_contact(self, node):
+ self.visit_docinfo_item(node, 'contact')
+
+ depart_contact = depart_docinfo_item
+
+ def visit_container(self, node):
+ pass
+
+ def depart_container(self, node):
+ pass
+
+ def visit_compound(self, node):
+ pass
+
+ def depart_compound(self, node):
+ pass
+
+ def visit_copyright(self, node):
+ self.visit_docinfo_item(node, 'copyright')
+
+ def visit_danger(self, node):
+ self.visit_admonition(node, 'danger')
+
+ depart_danger = depart_admonition
+
+ def visit_date(self, node):
+ self.visit_docinfo_item(node, 'date')
+
+ def visit_decoration(self, node):
+ pass
+
+ def depart_decoration(self, node):
+ pass
+
+ def visit_definition(self, node):
+ pass
+
+ def depart_definition(self, node):
+ pass
+
+ def visit_definition_list(self, node):
+ self.indent(DEFINITION_LIST_INDENT)
+
+ def depart_definition_list(self, node):
+ self.dedent()
+
+ def visit_definition_list_item(self, node):
+ self.body.append(self.defs['definition_list_item'][0])
+
+ def depart_definition_list_item(self, node):
+ self.body.append(self.defs['definition_list_item'][1])
+
+ def visit_description(self, node):
+ pass
+
+ def depart_description(self, node):
+ pass
+
+ def visit_docinfo(self, node):
+ self._in_docinfo = 1
+
+ def depart_docinfo(self, node):
+ self._in_docinfo = None
+ # NOTE nothing should be written before this
+ self.append_header()
+
+ def visit_doctest_block(self, node):
+ self.body.append(self.defs['literal_block'][0])
+ self._in_literal = True
+
+ def depart_doctest_block(self, node):
+ self._in_literal = False
+ self.body.append(self.defs['literal_block'][1])
+
+ def visit_document(self, node):
+ # no blank line between comment and header.
+ self.head.append(self.comment(self.document_start).rstrip()+'\n')
+ # writing header is postponed
+ self.header_written = 0
+
+ def depart_document(self, node):
+ if self._docinfo['author']:
+ self.body.append('.SH AUTHOR\n%s\n'
+ % ', '.join(self._docinfo['author']))
+ skip = ('author', 'copyright', 'date',
+ 'manual_group', 'manual_section',
+ 'subtitle',
+ 'title', 'title_upper', 'version')
+ for name in self._docinfo_keys:
+ if name == 'address':
+ self.body.append("\n%s:\n%s%s.nf\n%s\n.fi\n%s%s" % (
+ self.language.labels.get(name, name),
+ self.defs['indent'][0] % 0,
+ self.defs['indent'][0] % BLOCKQOUTE_INDENT,
+ self._docinfo[name],
+ self.defs['indent'][1],
+ self.defs['indent'][1]))
+ elif not name in skip:
+ if name in self._docinfo_names:
+ label = self._docinfo_names[name]
+ else:
+ label = self.language.labels.get(name, name)
+ self.body.append("\n%s: %s\n" % (label, self._docinfo[name]))
+ if self._docinfo['copyright']:
+ self.body.append('.SH COPYRIGHT\n%s\n'
+ % self._docinfo['copyright'])
+ self.body.append(self.comment(
+ 'Generated by docutils manpage writer.'))
+
+ def visit_emphasis(self, node):
+ self.body.append(self.defs['emphasis'][0])
+
+ def depart_emphasis(self, node):
+ self.body.append(self.defs['emphasis'][1])
+
+ def visit_entry(self, node):
+ # a cell in a table row
+ if 'morerows' in node:
+ self.document.reporter.warning('"table row spanning" not supported',
+ base_node=node)
+ if 'morecols' in node:
+ self.document.reporter.warning(
+ '"table cell spanning" not supported', base_node=node)
+ self.context.append(len(self.body))
+
+ def depart_entry(self, node):
+ start = self.context.pop()
+ self._active_table.append_cell(self.body[start:])
+ del self.body[start:]
+
+ def visit_enumerated_list(self, node):
+ self.list_start(node)
+
+ def depart_enumerated_list(self, node):
+ self.list_end()
+
+ def visit_error(self, node):
+ self.visit_admonition(node, 'error')
+
+ depart_error = depart_admonition
+
+ def visit_field(self, node):
+ pass
+
+ def depart_field(self, node):
+ pass
+
+ def visit_field_body(self, node):
+ if self._in_docinfo:
+ name_normalized = self._field_name.lower().replace(" ", "_")
+ self._docinfo_names[name_normalized] = self._field_name
+ self.visit_docinfo_item(node, name_normalized)
+ raise nodes.SkipNode
+
+ def depart_field_body(self, node):
+ pass
+
+ def visit_field_list(self, node):
+ self.indent(FIELD_LIST_INDENT)
+
+ def depart_field_list(self, node):
+ self.dedent()
+
+ def visit_field_name(self, node):
+ if self._in_docinfo:
+ self._field_name = node.astext()
+ raise nodes.SkipNode
+ else:
+ self.body.append(self.defs['field_name'][0])
+
+ def depart_field_name(self, node):
+ self.body.append(self.defs['field_name'][1])
+
+ def visit_figure(self, node):
+ self.indent(2.5)
+ self.indent(0)
+
+ def depart_figure(self, node):
+ self.dedent()
+ self.dedent()
+
+ def visit_footer(self, node):
+ self.document.reporter.warning('"footer" not supported',
+ base_node=node)
+
+ def depart_footer(self, node):
+ pass
+
+ def visit_footnote(self, node):
+ num, text = node.astext().split(None, 1)
+ num = num.strip()
+ self.body.append('.IP [%s] 5\n' % self.deunicode(num))
+
+ def depart_footnote(self, node):
+ pass
+
+ def footnote_backrefs(self, node):
+ self.document.reporter.warning('"footnote_backrefs" not supported',
+ base_node=node)
+
+ def visit_footnote_reference(self, node):
+ self.body.append('['+self.deunicode(node.astext())+']')
+ raise nodes.SkipNode
+
+ def depart_footnote_reference(self, node):
+ pass
+
+ def visit_generated(self, node):
+ pass
+
+ def depart_generated(self, node):
+ pass
+
+ def visit_header(self, node):
+ raise NotImplementedError(node.astext())
+
+ def depart_header(self, node):
+ pass
+
+ def visit_hint(self, node):
+ self.visit_admonition(node, 'hint')
+
+ depart_hint = depart_admonition
+
+ def visit_subscript(self, node):
+ self.body.append('\\s-2\\d')
+
+ def depart_subscript(self, node):
+ self.body.append('\\u\\s0')
+
+ def visit_superscript(self, node):
+ self.body.append('\\s-2\\u')
+
+ def depart_superscript(self, node):
+ self.body.append('\\d\\s0')
+
+ def visit_attribution(self, node):
+ self.body.append('\\(em ')
+
+ def depart_attribution(self, node):
+ self.body.append('\n')
+
+ def visit_image(self, node):
+ self.document.reporter.warning('"image" not supported',
+ base_node=node)
+ text = []
+ if 'alt' in node.attributes:
+ text.append(node.attributes['alt'])
+ if 'uri' in node.attributes:
+ text.append(node.attributes['uri'])
+ self.body.append('[image: %s]\n' % ('/'.join(text)))
+ raise nodes.SkipNode
+
+ def visit_important(self, node):
+ self.visit_admonition(node, 'important')
+
+ depart_important = depart_admonition
+
+ def visit_inline(self, node):
+ pass
+
+ def depart_inline(self, node):
+ pass
+
+ def visit_label(self, node):
+ # footnote and citation
+ if (isinstance(node.parent, nodes.footnote)
+ or isinstance(node.parent, nodes.citation)):
+ raise nodes.SkipNode
+ self.document.reporter.warning('"unsupported "label"',
+ base_node=node)
+ self.body.append('[')
+
+ def depart_label(self, node):
+ self.body.append(']\n')
+
+ def visit_legend(self, node):
+ pass
+
+ def depart_legend(self, node):
+ pass
+
+ # WHAT should we use .INDENT, .UNINDENT ?
+ def visit_line_block(self, node):
+ self._line_block += 1
+ if self._line_block == 1:
+ # TODO: separate inline blocks from previous paragraphs
+ # see http://hg.intevation.org/mercurial/crew/rev/9c142ed9c405
+ # self.body.append('.sp\n')
+ # but it does not work for me.
+ self.body.append('.nf\n')
+ else:
+ self.body.append('.in +2\n')
+
+ def depart_line_block(self, node):
+ self._line_block -= 1
+ if self._line_block == 0:
+ self.body.append('.fi\n')
+ self.body.append('.sp\n')
+ else:
+ self.body.append('.in -2\n')
+
+ def visit_line(self, node):
+ pass
+
+ def depart_line(self, node):
+ self.body.append('\n')
+
+ def visit_list_item(self, node):
+ # man 7 man argues to use ".IP" instead of ".TP"
+ self.body.append('.IP %s %d\n' % (
+ next(self._list_char[-1]),
+ self._list_char[-1].get_width(),))
+
+ def depart_list_item(self, node):
+ pass
+
+ def visit_literal(self, node):
+ self.body.append(self.defs['literal'][0])
+
+ def depart_literal(self, node):
+ self.body.append(self.defs['literal'][1])
+
+ def visit_literal_block(self, node):
+ # BUG/HACK: indent always uses the _last_ indention,
+ # thus we need two of them.
+ self.indent(LITERAL_BLOCK_INDENT)
+ self.indent(0)
+ self.body.append(self.defs['literal_block'][0])
+ self._in_literal = True
+
+ def depart_literal_block(self, node):
+ self._in_literal = False
+ self.body.append(self.defs['literal_block'][1])
+ self.dedent()
+ self.dedent()
+
+ def visit_math(self, node):
+ self.document.reporter.warning('"math" role not supported',
+ base_node=node)
+ self.visit_literal(node)
+
+ def depart_math(self, node):
+ self.depart_literal(node)
+
+ def visit_math_block(self, node):
+ self.document.reporter.warning('"math" directive not supported',
+ base_node=node)
+ self.visit_literal_block(node)
+
+ def depart_math_block(self, node):
+ self.depart_literal_block(node)
+
+ def visit_meta(self, node):
+ raise NotImplementedError(node.astext())
+
+ def depart_meta(self, node):
+ pass
+
+ def visit_note(self, node):
+ self.visit_admonition(node, 'note')
+
+ depart_note = depart_admonition
+
+ def indent(self, by=0.5):
+ # if we are in a section ".SH" there already is a .RS
+ step = self._indent[-1]
+ self._indent.append(by)
+ self.body.append(self.defs['indent'][0] % step)
+
+ def dedent(self):
+ self._indent.pop()
+ self.body.append(self.defs['indent'][1])
+
+ def visit_option_list(self, node):
+ self.indent(OPTION_LIST_INDENT)
+
+ def depart_option_list(self, node):
+ self.dedent()
+
+ def visit_option_list_item(self, node):
+ # one item of the list
+ self.body.append(self.defs['option_list_item'][0])
+
+ def depart_option_list_item(self, node):
+ self.body.append(self.defs['option_list_item'][1])
+
+ def visit_option_group(self, node):
+ # as one option could have several forms it is a group
+ # options without parameter bold only, .B, -v
+ # options with parameter bold italic, .BI, -f file
+ #
+ # we do not know if .B or .BI
+ self.context.append('.B') # blind guess
+ self.context.append(len(self.body)) # to be able to insert later
+ self.context.append(0) # option counter
+
+ def depart_option_group(self, node):
+ self.context.pop() # the counter
+ start_position = self.context.pop()
+ text = self.body[start_position:]
+ del self.body[start_position:]
+ self.body.append('%s%s\n' % (self.context.pop(), ''.join(text)))
+
+ def visit_option(self, node):
+ # each form of the option will be presented separately
+ if self.context[-1] > 0:
+ if self.context[-3] == '.BI':
+ self.body.append('\\fR,\\fB ')
+ else:
+ self.body.append('\\fP,\\fB ')
+ if self.context[-3] == '.BI':
+ self.body.append('\\')
+ self.body.append(' ')
+
+ def depart_option(self, node):
+ self.context[-1] += 1
+
+ def visit_option_string(self, node):
+ # do not know if .B or .BI
+ pass
+
+ def depart_option_string(self, node):
+ pass
+
+ def visit_option_argument(self, node):
+ self.context[-3] = '.BI' # bold/italic alternate
+ if node['delimiter'] != ' ':
+ self.body.append('\\fB%s ' % node['delimiter'])
+ elif self.body[len(self.body)-1].endswith('='):
+ # a blank only means no blank in output, just changing font
+ self.body.append(' ')
+ else:
+ # blank backslash blank, switch font then a blank
+ self.body.append(' \\ ')
+
+ def depart_option_argument(self, node):
+ pass
+
+ def visit_organization(self, node):
+ self.visit_docinfo_item(node, 'organization')
+
+ def depart_organization(self, node):
+ pass
+
+ def first_child(self, node):
+ first = isinstance(node.parent[0], nodes.label) # skip label
+ for child in node.parent.children[first:]:
+ if isinstance(child, nodes.Invisible):
+ continue
+ if child is node:
+ return 1
+ break
+ return 0
+
+ def visit_paragraph(self, node):
+ # ``.PP`` : Start standard indented paragraph.
+ # ``.LP`` : Start block paragraph, all except the first.
+ # ``.P [type]`` : Start paragraph type.
+ # NOTE do not use paragraph starts because they reset indentation.
+ # ``.sp`` is only vertical space
+ self.ensure_eol()
+ if not self.first_child(node):
+ self.body.append('.sp\n')
+ # set in literal to escape dots after a new-line-character
+ self._in_literal = True
+
+ def depart_paragraph(self, node):
+ self._in_literal = False
+ self.body.append('\n')
+
+ def visit_problematic(self, node):
+ self.body.append(self.defs['problematic'][0])
+
+ def depart_problematic(self, node):
+ self.body.append(self.defs['problematic'][1])
+
+ def visit_raw(self, node):
+ if node.get('format') == 'manpage':
+ self.body.append(node.astext() + "\n")
+ # Keep non-manpage raw text out of output:
+ raise nodes.SkipNode
+
+ def visit_reference(self, node):
+ """E.g. link or email address."""
+ self.body.append(self.defs['reference'][0])
+
+ def depart_reference(self, node):
+ self.body.append(self.defs['reference'][1])
+
+ def visit_revision(self, node):
+ self.visit_docinfo_item(node, 'revision')
+
+ depart_revision = depart_docinfo_item
+
+ def visit_row(self, node):
+ self._active_table.new_row()
+
+ def depart_row(self, node):
+ pass
+
+ def visit_section(self, node):
+ self.section_level += 1
+
+ def depart_section(self, node):
+ self.section_level -= 1
+
+ def visit_status(self, node):
+ self.visit_docinfo_item(node, 'status')
+
+ depart_status = depart_docinfo_item
+
+ def visit_strong(self, node):
+ self.body.append(self.defs['strong'][0])
+
+ def depart_strong(self, node):
+ self.body.append(self.defs['strong'][1])
+
+ def visit_substitution_definition(self, node):
+ """Internal only."""
+ raise nodes.SkipNode
+
+ def visit_substitution_reference(self, node):
+ self.document.reporter.warning('"substitution_reference" not supported',
+ base_node=node)
+
+ def visit_subtitle(self, node):
+ if isinstance(node.parent, nodes.sidebar):
+ self.body.append(self.defs['strong'][0])
+ elif isinstance(node.parent, nodes.document):
+ self.visit_docinfo_item(node, 'subtitle')
+ elif isinstance(node.parent, nodes.section):
+ self.body.append(self.defs['strong'][0])
+
+ def depart_subtitle(self, node):
+ # document subtitle calls SkipNode
+ self.body.append(self.defs['strong'][1]+'\n.PP\n')
+
+ def visit_system_message(self, node):
+ # TODO add report_level
+ #if node['level'] < self.document.reporter['writer'].report_level:
+ # Level is too low to display:
+ # raise nodes.SkipNode
+ attr = {}
+ backref_text = ''
+ if node.hasattr('id'):
+ attr['name'] = node['id']
+ if node.hasattr('line'):
+ line = ', line %s' % node['line']
+ else:
+ line = ''
+ self.body.append('.IP "System Message: %s/%s (%s:%s)"\n'
+ % (node['type'], node['level'], node['source'], line))
+
+ def depart_system_message(self, node):
+ pass
+
+ def visit_table(self, node):
+ self._active_table = Table()
+
+ def depart_table(self, node):
+ self.ensure_eol()
+ self.body.extend(self._active_table.as_list())
+ self._active_table = None
+
+ def visit_target(self, node):
+ # targets are in-document hyper targets, without any use for man-pages.
+ raise nodes.SkipNode
+
+ def visit_tbody(self, node):
+ pass
+
+ def depart_tbody(self, node):
+ pass
+
+ def visit_term(self, node):
+ self.body.append(self.defs['term'][0])
+
+ def depart_term(self, node):
+ self.body.append(self.defs['term'][1])
+
+ def visit_tgroup(self, node):
+ pass
+
+ def depart_tgroup(self, node):
+ pass
+
+ def visit_thead(self, node):
+ # MAYBE double line '='
+ pass
+
+ def depart_thead(self, node):
+ # MAYBE double line '='
+ pass
+
+ def visit_tip(self, node):
+ self.visit_admonition(node, 'tip')
+
+ depart_tip = depart_admonition
+
+ def visit_title(self, node):
+ if isinstance(node.parent, nodes.topic):
+ self.body.append(self.defs['topic-title'][0])
+ elif isinstance(node.parent, nodes.sidebar):
+ self.body.append(self.defs['sidebar-title'][0])
+ elif isinstance(node.parent, nodes.admonition):
+ self.body.append('.IP "')
+ elif self.section_level == 0:
+ self._docinfo['title'] = node.astext()
+ # document title for .TH
+ self._docinfo['title_upper'] = node.astext().upper()
+ raise nodes.SkipNode
+ elif self.section_level == 1:
+ self.body.append('.SH %s\n' % self.deunicode(node.astext().upper()))
+ raise nodes.SkipNode
+ else:
+ self.body.append('.SS ')
+
+ def depart_title(self, node):
+ if isinstance(node.parent, nodes.admonition):
+ self.body.append('"')
+ self.body.append('\n')
+
+ def visit_title_reference(self, node):
+ """inline citation reference"""
+ self.body.append(self.defs['title_reference'][0])
+
+ def depart_title_reference(self, node):
+ self.body.append(self.defs['title_reference'][1])
+
+ def visit_topic(self, node):
+ pass
+
+ def depart_topic(self, node):
+ pass
+
+ def visit_sidebar(self, node):
+ pass
+
+ def depart_sidebar(self, node):
+ pass
+
+ def visit_rubric(self, node):
+ pass
+
+ def depart_rubric(self, node):
+ pass
+
+ def visit_transition(self, node):
+ # .PP Begin a new paragraph and reset prevailing indent.
+ # .sp N leaves N lines of blank space.
+ # .ce centers the next line
+ self.body.append('\n.sp\n.ce\n----\n')
+
+ def depart_transition(self, node):
+ self.body.append('\n.ce 0\n.sp\n')
+
+ def visit_version(self, node):
+ self.visit_docinfo_item(node, 'version')
+
+ def visit_warning(self, node):
+ self.visit_admonition(node, 'warning')
+
+ depart_warning = depart_admonition
+
+ def unimplemented_visit(self, node):
+ raise NotImplementedError('visiting unimplemented node type: %s'
+ % node.__class__.__name__)
+
+# vim: set fileencoding=utf-8 et ts=4 ai :
--- /dev/null
+# $Id: null.py 4564 2006-05-21 20:44:42Z wiemann $
+# Author: David Goodger <goodger@python.org>
+# Copyright: This module has been placed in the public domain.
+
+"""
+A do-nothing Writer.
+"""
+
+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):
+ pass
--- /dev/null
+# $Id: __init__.py 8411 2019-11-05 13:32:13Z milde $
+# Author: Dave Kuhlman <dkuhlman@davekuhlman.org>
+# Copyright: This module has been placed in the public domain.
+
+"""
+Open Document Format (ODF) Writer.
+
+"""
+from __future__ import absolute_import
+
+__docformat__ = 'reStructuredText'
+
+
+import sys
+import os
+import os.path
+import tempfile
+import zipfile
+from xml.etree import ElementTree as etree
+from xml.dom import minidom
+import time
+import re
+import copy
+import itertools
+import weakref
+
+try:
+ import locale # module missing in Jython
+except ImportError:
+ pass
+
+import docutils
+from docutils import frontend, nodes, utils, writers, languages
+from docutils.readers import standalone
+from docutils.transforms import references
+
+if sys.version_info >= (3, 0):
+ from configparser import ConfigParser
+ from io import StringIO
+ from urllib.request import urlopen
+ from urllib.error import HTTPError
+else:
+ from ConfigParser import ConfigParser
+ from StringIO import StringIO
+ from urllib2 import HTTPError
+ from urllib2 import urlopen
+
+
+VERSION = '1.0a'
+
+IMAGE_NAME_COUNTER = itertools.count()
+
+#
+# Import pygments and odtwriter pygments formatters if possible.
+try:
+ import pygments
+ import pygments.lexers
+ from .pygmentsformatter import (OdtPygmentsProgFormatter,
+ OdtPygmentsLaTeXFormatter)
+except (ImportError, SyntaxError):
+ pygments = None
+
+# check for the Python Imaging Library
+try:
+ import PIL.Image
+except ImportError:
+ try: # sometimes PIL modules are put in PYTHONPATH's root
+ import Image
+
+ class PIL(object):
+ pass # dummy wrapper
+ PIL.Image = Image
+ except ImportError:
+ PIL = None
+
+## import warnings
+## warnings.warn('importing IPShellEmbed', UserWarning)
+## from IPython.Shell import IPShellEmbed
+## args = ['-pdb', '-pi1', 'In <\\#>: ', '-pi2', ' .\\D.: ',
+## '-po', 'Out<\\#>: ', '-nosep']
+## ipshell = IPShellEmbed(args,
+## banner = 'Entering IPython. Press Ctrl-D to exit.',
+## exit_msg = 'Leaving Interpreter, back to program.')
+
+
+#
+# ElementTree does not support getparent method (lxml does).
+# This wrapper class and the following support functions provide
+# that support for the ability to get the parent of an element.
+#
+_parents = weakref.WeakKeyDictionary()
+if isinstance(etree.Element, type):
+ _ElementInterface = etree.Element
+else:
+ _ElementInterface = etree._ElementInterface
+
+
+class _ElementInterfaceWrapper(_ElementInterface):
+ def __init__(self, tag, attrib=None):
+ _ElementInterface.__init__(self, tag, attrib)
+ _parents[self] = None
+
+ def setparent(self, parent):
+ _parents[self] = parent
+
+ def getparent(self):
+ return _parents[self]
+
+
+#
+# Constants and globals
+
+SPACES_PATTERN = re.compile(r'( +)')
+TABS_PATTERN = re.compile(r'(\t+)')
+FILL_PAT1 = re.compile(r'^ +')
+FILL_PAT2 = re.compile(r' {2,}')
+
+TABLESTYLEPREFIX = 'rststyle-table-'
+TABLENAMEDEFAULT = '%s0' % TABLESTYLEPREFIX
+TABLEPROPERTYNAMES = (
+ 'border', 'border-top', 'border-left',
+ 'border-right', 'border-bottom', )
+
+GENERATOR_DESC = 'Docutils.org/odf_odt'
+
+NAME_SPACE_1 = 'urn:oasis:names:tc:opendocument:xmlns:office:1.0'
+
+CONTENT_NAMESPACE_DICT = CNSD = {
+ #'office:version': '1.0',
+ 'chart': 'urn:oasis:names:tc:opendocument:xmlns:chart:1.0',
+ 'dc': 'http://purl.org/dc/elements/1.1/',
+ 'dom': 'http://www.w3.org/2001/xml-events',
+ 'dr3d': 'urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0',
+ 'draw': 'urn:oasis:names:tc:opendocument:xmlns:drawing:1.0',
+ 'fo': 'urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0',
+ 'form': 'urn:oasis:names:tc:opendocument:xmlns:form:1.0',
+ 'math': 'http://www.w3.org/1998/Math/MathML',
+ 'meta': 'urn:oasis:names:tc:opendocument:xmlns:meta:1.0',
+ 'number': 'urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0',
+ 'office': NAME_SPACE_1,
+ 'ooo': 'http://openoffice.org/2004/office',
+ 'oooc': 'http://openoffice.org/2004/calc',
+ 'ooow': 'http://openoffice.org/2004/writer',
+ 'presentation': 'urn:oasis:names:tc:opendocument:xmlns:presentation:1.0',
+
+ 'script': 'urn:oasis:names:tc:opendocument:xmlns:script:1.0',
+ 'style': 'urn:oasis:names:tc:opendocument:xmlns:style:1.0',
+ 'svg': 'urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0',
+ 'table': 'urn:oasis:names:tc:opendocument:xmlns:table:1.0',
+ 'text': 'urn:oasis:names:tc:opendocument:xmlns:text:1.0',
+ 'xforms': 'http://www.w3.org/2002/xforms',
+ 'xlink': 'http://www.w3.org/1999/xlink',
+ 'xsd': 'http://www.w3.org/2001/XMLSchema',
+ 'xsi': 'http://www.w3.org/2001/XMLSchema-instance',
+}
+
+STYLES_NAMESPACE_DICT = SNSD = {
+ #'office:version': '1.0',
+ 'chart': 'urn:oasis:names:tc:opendocument:xmlns:chart:1.0',
+ 'dc': 'http://purl.org/dc/elements/1.1/',
+ 'dom': 'http://www.w3.org/2001/xml-events',
+ 'dr3d': 'urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0',
+ 'draw': 'urn:oasis:names:tc:opendocument:xmlns:drawing:1.0',
+ 'fo': 'urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0',
+ 'form': 'urn:oasis:names:tc:opendocument:xmlns:form:1.0',
+ 'math': 'http://www.w3.org/1998/Math/MathML',
+ 'meta': 'urn:oasis:names:tc:opendocument:xmlns:meta:1.0',
+ 'number': 'urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0',
+ 'office': NAME_SPACE_1,
+ 'presentation': 'urn:oasis:names:tc:opendocument:xmlns:presentation:1.0',
+ 'ooo': 'http://openoffice.org/2004/office',
+ 'oooc': 'http://openoffice.org/2004/calc',
+ 'ooow': 'http://openoffice.org/2004/writer',
+ 'script': 'urn:oasis:names:tc:opendocument:xmlns:script:1.0',
+ 'style': 'urn:oasis:names:tc:opendocument:xmlns:style:1.0',
+ 'svg': 'urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0',
+ 'table': 'urn:oasis:names:tc:opendocument:xmlns:table:1.0',
+ 'text': 'urn:oasis:names:tc:opendocument:xmlns:text:1.0',
+ 'xlink': 'http://www.w3.org/1999/xlink',
+}
+
+MANIFEST_NAMESPACE_DICT = MANNSD = {
+ 'manifest': 'urn:oasis:names:tc:opendocument:xmlns:manifest:1.0',
+}
+
+META_NAMESPACE_DICT = METNSD = {
+ #'office:version': '1.0',
+ 'dc': 'http://purl.org/dc/elements/1.1/',
+ 'meta': 'urn:oasis:names:tc:opendocument:xmlns:meta:1.0',
+ 'office': NAME_SPACE_1,
+ 'ooo': 'http://openoffice.org/2004/office',
+ 'xlink': 'http://www.w3.org/1999/xlink',
+}
+
+# Attribute dictionaries for use with ElementTree, which
+# does not support use of nsmap parameter on Element() and SubElement().
+
+CONTENT_NAMESPACE_ATTRIB = {
+ #'office:version': '1.0',
+ 'xmlns:chart': 'urn:oasis:names:tc:opendocument:xmlns:chart:1.0',
+ 'xmlns:dc': 'http://purl.org/dc/elements/1.1/',
+ 'xmlns:dom': 'http://www.w3.org/2001/xml-events',
+ 'xmlns:dr3d': 'urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0',
+ 'xmlns:draw': 'urn:oasis:names:tc:opendocument:xmlns:drawing:1.0',
+ 'xmlns:fo': 'urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0',
+ 'xmlns:form': 'urn:oasis:names:tc:opendocument:xmlns:form:1.0',
+ 'xmlns:math': 'http://www.w3.org/1998/Math/MathML',
+ 'xmlns:meta': 'urn:oasis:names:tc:opendocument:xmlns:meta:1.0',
+ 'xmlns:number': 'urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0',
+ 'xmlns:office': NAME_SPACE_1,
+ 'xmlns:presentation':
+ 'urn:oasis:names:tc:opendocument:xmlns:presentation:1.0',
+ 'xmlns:ooo': 'http://openoffice.org/2004/office',
+ 'xmlns:oooc': 'http://openoffice.org/2004/calc',
+ 'xmlns:ooow': 'http://openoffice.org/2004/writer',
+ 'xmlns:script': 'urn:oasis:names:tc:opendocument:xmlns:script:1.0',
+ 'xmlns:style': 'urn:oasis:names:tc:opendocument:xmlns:style:1.0',
+ 'xmlns:svg': 'urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0',
+ 'xmlns:table': 'urn:oasis:names:tc:opendocument:xmlns:table:1.0',
+ 'xmlns:text': 'urn:oasis:names:tc:opendocument:xmlns:text:1.0',
+ 'xmlns:xforms': 'http://www.w3.org/2002/xforms',
+ 'xmlns:xlink': 'http://www.w3.org/1999/xlink',
+ 'xmlns:xsd': 'http://www.w3.org/2001/XMLSchema',
+ 'xmlns:xsi': 'http://www.w3.org/2001/XMLSchema-instance',
+}
+
+STYLES_NAMESPACE_ATTRIB = {
+ #'office:version': '1.0',
+ 'xmlns:chart': 'urn:oasis:names:tc:opendocument:xmlns:chart:1.0',
+ 'xmlns:dc': 'http://purl.org/dc/elements/1.1/',
+ 'xmlns:dom': 'http://www.w3.org/2001/xml-events',
+ 'xmlns:dr3d': 'urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0',
+ 'xmlns:draw': 'urn:oasis:names:tc:opendocument:xmlns:drawing:1.0',
+ 'xmlns:fo': 'urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0',
+ 'xmlns:form': 'urn:oasis:names:tc:opendocument:xmlns:form:1.0',
+ 'xmlns:math': 'http://www.w3.org/1998/Math/MathML',
+ 'xmlns:meta': 'urn:oasis:names:tc:opendocument:xmlns:meta:1.0',
+ 'xmlns:number': 'urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0',
+ 'xmlns:office': NAME_SPACE_1,
+ 'xmlns:presentation':
+ 'urn:oasis:names:tc:opendocument:xmlns:presentation:1.0',
+ 'xmlns:ooo': 'http://openoffice.org/2004/office',
+ 'xmlns:oooc': 'http://openoffice.org/2004/calc',
+ 'xmlns:ooow': 'http://openoffice.org/2004/writer',
+ 'xmlns:script': 'urn:oasis:names:tc:opendocument:xmlns:script:1.0',
+ 'xmlns:style': 'urn:oasis:names:tc:opendocument:xmlns:style:1.0',
+ 'xmlns:svg': 'urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0',
+ 'xmlns:table': 'urn:oasis:names:tc:opendocument:xmlns:table:1.0',
+ 'xmlns:text': 'urn:oasis:names:tc:opendocument:xmlns:text:1.0',
+ 'xmlns:xlink': 'http://www.w3.org/1999/xlink',
+}
+
+MANIFEST_NAMESPACE_ATTRIB = {
+ 'xmlns:manifest': 'urn:oasis:names:tc:opendocument:xmlns:manifest:1.0',
+}
+
+META_NAMESPACE_ATTRIB = {
+ #'office:version': '1.0',
+ 'xmlns:dc': 'http://purl.org/dc/elements/1.1/',
+ 'xmlns:meta': 'urn:oasis:names:tc:opendocument:xmlns:meta:1.0',
+ 'xmlns:office': NAME_SPACE_1,
+ 'xmlns:ooo': 'http://openoffice.org/2004/office',
+ 'xmlns:xlink': 'http://www.w3.org/1999/xlink',
+}
+
+
+#
+# Functions
+#
+
+#
+# ElementTree support functions.
+# In order to be able to get the parent of elements, must use these
+# instead of the functions with same name provided by ElementTree.
+#
+def Element(tag, attrib=None, nsmap=None, nsdict=CNSD):
+ if attrib is None:
+ attrib = {}
+ tag, attrib = fix_ns(tag, attrib, nsdict)
+ el = _ElementInterfaceWrapper(tag, attrib)
+ return el
+
+
+def SubElement(parent, tag, attrib=None, nsmap=None, nsdict=CNSD):
+ if attrib is None:
+ attrib = {}
+ tag, attrib = fix_ns(tag, attrib, nsdict)
+ el = _ElementInterfaceWrapper(tag, attrib)
+ parent.append(el)
+ el.setparent(parent)
+ return el
+
+
+def fix_ns(tag, attrib, nsdict):
+ nstag = add_ns(tag, nsdict)
+ nsattrib = {}
+ for key, val in list(attrib.items()):
+ nskey = add_ns(key, nsdict)
+ nsattrib[nskey] = val
+ return nstag, nsattrib
+
+
+def add_ns(tag, nsdict=CNSD):
+ return tag
+
+
+def ToString(et):
+ outstream = StringIO()
+ if sys.version_info >= (3, 0):
+ et.write(outstream, encoding="unicode")
+ else:
+ et.write(outstream)
+ s1 = outstream.getvalue()
+ outstream.close()
+ return s1
+
+
+def escape_cdata(text):
+ text = text.replace("&", "&")
+ text = text.replace("<", "<")
+ text = text.replace(">", ">")
+ ascii = ''
+ for char in text:
+ if ord(char) >= ord("\x7f"):
+ ascii += "&#x%X;" % (ord(char), )
+ else:
+ ascii += char
+ return ascii
+
+
+WORD_SPLIT_PAT1 = re.compile(r'\b(\w*)\b\W*')
+
+
+def split_words(line):
+ # We need whitespace at the end of the string for our regexpr.
+ line += ' '
+ words = []
+ pos1 = 0
+ mo = WORD_SPLIT_PAT1.search(line, pos1)
+ while mo is not None:
+ word = mo.groups()[0]
+ words.append(word)
+ pos1 = mo.end()
+ mo = WORD_SPLIT_PAT1.search(line, pos1)
+ return words
+
+
+#
+# Classes
+#
+
+
+class TableStyle(object):
+ def __init__(self, border=None, backgroundcolor=None):
+ self.border = border
+ self.backgroundcolor = backgroundcolor
+
+ def get_border_(self):
+ return self.border_
+
+ def set_border_(self, border):
+ self.border_ = border
+
+ border = property(get_border_, set_border_)
+
+ def get_backgroundcolor_(self):
+ return self.backgroundcolor_
+
+ def set_backgroundcolor_(self, backgroundcolor):
+ self.backgroundcolor_ = backgroundcolor
+ backgroundcolor = property(get_backgroundcolor_, set_backgroundcolor_)
+
+
+BUILTIN_DEFAULT_TABLE_STYLE = TableStyle(
+ border='0.0007in solid #000000')
+
+
+#
+# Information about the indentation level for lists nested inside
+# other contexts, e.g. dictionary lists.
+class ListLevel(object):
+ def __init__(self, level, sibling_level=True, nested_level=True):
+ self.level = level
+ self.sibling_level = sibling_level
+ self.nested_level = nested_level
+
+ def set_sibling(self, sibling_level):
+ self.sibling_level = sibling_level
+
+ def get_sibling(self):
+ return self.sibling_level
+
+ def set_nested(self, nested_level):
+ self.nested_level = nested_level
+
+ def get_nested(self):
+ return self.nested_level
+
+ def set_level(self, level):
+ self.level = level
+
+ def get_level(self):
+ return self.level
+
+
+class Writer(writers.Writer):
+
+ MIME_TYPE = 'application/vnd.oasis.opendocument.text'
+ EXTENSION = '.odt'
+
+ supported = ('odt', )
+ """Formats this writer supports."""
+
+ default_stylesheet = 'styles' + EXTENSION
+
+ 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 = (
+ 'ODF-Specific Options',
+ None,
+ (
+ ('Specify a stylesheet. '
+ 'Default: "%s"' % default_stylesheet_path,
+ ['--stylesheet'],
+ {
+ 'default': default_stylesheet_path,
+ 'dest': 'stylesheet'
+ }),
+ ('Specify a configuration/mapping file relative to the '
+ 'current working '
+ 'directory for additional ODF options. '
+ 'In particular, this file may contain a section named '
+ '"Formats" that maps default style names to '
+ 'names to be used in the resulting output file allowing for '
+ 'adhering to external standards. '
+ 'For more info and the format of the '
+ 'configuration/mapping file, '
+ 'see the odtwriter doc.',
+ ['--odf-config-file'],
+ {'metavar': '<file>'}),
+ ('Obfuscate email addresses to confuse harvesters while still '
+ 'keeping email links usable with '
+ 'standards-compliant browsers.',
+ ['--cloak-email-addresses'],
+ {'default': False,
+ 'action': 'store_true',
+ 'dest': 'cloak_email_addresses',
+ 'validator': frontend.validate_boolean}),
+ ('Do not obfuscate email addresses.',
+ ['--no-cloak-email-addresses'],
+ {'default': False,
+ 'action': 'store_false',
+ 'dest': 'cloak_email_addresses',
+ 'validator': frontend.validate_boolean}),
+ ('Specify the thickness of table borders in thousands of a cm. '
+ 'Default is 35.',
+ ['--table-border-thickness'],
+ {'default': None,
+ 'validator': frontend.validate_nonnegative_int}),
+ ('Add syntax highlighting in literal code blocks.',
+ ['--add-syntax-highlighting'],
+ {'default': False,
+ 'action': 'store_true',
+ 'dest': 'add_syntax_highlighting',
+ 'validator': frontend.validate_boolean}),
+ ('Do not add syntax highlighting in '
+ 'literal code blocks. (default)',
+ ['--no-syntax-highlighting'],
+ {'default': False,
+ 'action': 'store_false',
+ 'dest': 'add_syntax_highlighting',
+ 'validator': frontend.validate_boolean}),
+ ('Create sections for headers. (default)',
+ ['--create-sections'],
+ {'default': True,
+ 'action': 'store_true',
+ 'dest': 'create_sections',
+ 'validator': frontend.validate_boolean}),
+ ('Do not create sections for headers.',
+ ['--no-sections'],
+ {'default': True,
+ 'action': 'store_false',
+ 'dest': 'create_sections',
+ 'validator': frontend.validate_boolean}),
+ ('Create links.',
+ ['--create-links'],
+ {'default': False,
+ 'action': 'store_true',
+ 'dest': 'create_links',
+ 'validator': frontend.validate_boolean}),
+ ('Do not create links. (default)',
+ ['--no-links'],
+ {'default': False,
+ 'action': 'store_false',
+ 'dest': 'create_links',
+ 'validator': frontend.validate_boolean}),
+ ('Generate endnotes at end of document, not footnotes '
+ 'at bottom of page.',
+ ['--endnotes-end-doc'],
+ {'default': False,
+ 'action': 'store_true',
+ 'dest': 'endnotes_end_doc',
+ 'validator': frontend.validate_boolean}),
+ ('Generate footnotes at bottom of page, not endnotes '
+ 'at end of document. (default)',
+ ['--no-endnotes-end-doc'],
+ {'default': False,
+ 'action': 'store_false',
+ 'dest': 'endnotes_end_doc',
+ 'validator': frontend.validate_boolean}),
+ ('Generate a bullet list table of contents, not '
+ 'an ODF/oowriter table of contents.',
+ ['--generate-list-toc'],
+ {'default': True,
+ 'action': 'store_false',
+ 'dest': 'generate_oowriter_toc',
+ 'validator': frontend.validate_boolean}),
+ ('Generate an ODF/oowriter table of contents, not '
+ 'a bullet list. (default)',
+ ['--generate-oowriter-toc'],
+ {'default': True,
+ 'action': 'store_true',
+ 'dest': 'generate_oowriter_toc',
+ 'validator': frontend.validate_boolean}),
+ ('Specify the contents of an custom header line. '
+ 'See odf_odt writer documentation for details '
+ 'about special field character sequences.',
+ ['--custom-odt-header'],
+ {'default': '',
+ 'dest': 'custom_header', }),
+ ('Specify the contents of an custom footer line. '
+ 'See odf_odt writer documentation for details '
+ 'about special field character sequences.',
+ ['--custom-odt-footer'],
+ {'default': '',
+ 'dest': 'custom_footer', }),
+ )
+ )
+
+ settings_defaults = {
+ 'output_encoding_error_handler': 'xmlcharrefreplace',
+ }
+
+ relative_path_settings = (
+ 'stylesheet_path',
+ )
+
+ config_section = 'odf_odt writer'
+ config_section_dependencies = ('writers',)
+
+ def __init__(self):
+ writers.Writer.__init__(self)
+ self.translator_class = ODFTranslator
+
+ def translate(self):
+ self.settings = self.document.settings
+ self.visitor = self.translator_class(self.document)
+ self.visitor.retrieve_styles(self.EXTENSION)
+ self.document.walkabout(self.visitor)
+ self.visitor.add_doc_title()
+ self.assemble_my_parts()
+ self.output = self.parts['whole']
+
+ def assemble_my_parts(self):
+ """Assemble the `self.parts` dictionary. Extend in subclasses.
+ """
+ writers.Writer.assemble_parts(self)
+ f = tempfile.NamedTemporaryFile()
+ zfile = zipfile.ZipFile(f, 'w', zipfile.ZIP_DEFLATED)
+ self.write_zip_str(
+ zfile, 'mimetype', self.MIME_TYPE,
+ compress_type=zipfile.ZIP_STORED)
+ content = self.visitor.content_astext()
+ self.write_zip_str(zfile, 'content.xml', content)
+ s1 = self.create_manifest()
+ self.write_zip_str(zfile, 'META-INF/manifest.xml', s1)
+ s1 = self.create_meta()
+ self.write_zip_str(zfile, 'meta.xml', s1)
+ s1 = self.get_stylesheet()
+ # Set default language in document to be generated.
+ # Language is specified by the -l/--language command line option.
+ # The format is described in BCP 47. If region is omitted, we use
+ # local.normalize(ll) to obtain a region.
+ language_code = None
+ region_code = None
+ if self.visitor.language_code:
+ language_ids = self.visitor.language_code.replace('_', '-')
+ language_ids = language_ids.split('-')
+ # first tag is primary language tag
+ language_code = language_ids[0].lower()
+ # 2-letter region subtag may follow in 2nd or 3rd position
+ for subtag in language_ids[1:]:
+ if len(subtag) == 2 and subtag.isalpha():
+ region_code = subtag.upper()
+ break
+ elif len(subtag) == 1:
+ break # 1-letter tag is never before valid region tag
+ if region_code is None:
+ try:
+ rcode = locale.normalize(language_code)
+ except NameError:
+ rcode = language_code
+ rcode = rcode.split('_')
+ if len(rcode) > 1:
+ rcode = rcode[1].split('.')
+ region_code = rcode[0]
+ if region_code is None:
+ self.document.reporter.warning(
+ 'invalid language-region.\n'
+ ' Could not find region with locale.normalize().\n'
+ ' Please specify both language and region (ll-RR).\n'
+ ' Examples: es-MX (Spanish, Mexico),\n'
+ ' en-AU (English, Australia).')
+ # Update the style ElementTree with the language and region.
+ # Note that we keep a reference to the modified node because
+ # it is possible that ElementTree will throw away the Python
+ # representation of the updated node if we do not.
+ updated, new_dom_styles, updated_node = self.update_stylesheet(
+ self.visitor.get_dom_stylesheet(), language_code, region_code)
+ if updated:
+ s1 = etree.tostring(new_dom_styles)
+ self.write_zip_str(zfile, 'styles.xml', s1)
+ self.store_embedded_files(zfile)
+ self.copy_from_stylesheet(zfile)
+ zfile.close()
+ f.seek(0)
+ whole = f.read()
+ f.close()
+ self.parts['whole'] = whole
+ self.parts['encoding'] = self.document.settings.output_encoding
+ self.parts['version'] = docutils.__version__
+
+ def update_stylesheet(self, stylesheet_root, language_code, region_code):
+ """Update xml style sheet element with language and region/country."""
+ updated = False
+ modified_nodes = set()
+ if language_code is not None or region_code is not None:
+ n1 = stylesheet_root.find(
+ '{urn:oasis:names:tc:opendocument:xmlns:office:1.0}'
+ 'styles')
+ if n1 is None:
+ raise RuntimeError(
+ "Cannot find 'styles' element in styles.odt/styles.xml")
+ n2_nodes = n1.findall(
+ '{urn:oasis:names:tc:opendocument:xmlns:style:1.0}'
+ 'default-style')
+ if not n2_nodes:
+ raise RuntimeError(
+ "Cannot find 'default-style' "
+ "element in styles.xml")
+ for node in n2_nodes:
+ family = node.attrib.get(
+ '{urn:oasis:names:tc:opendocument:xmlns:style:1.0}'
+ 'family')
+ if family == 'paragraph' or family == 'graphic':
+ n3 = node.find(
+ '{urn:oasis:names:tc:opendocument:xmlns:style:1.0}'
+ 'text-properties')
+ if n3 is None:
+ raise RuntimeError(
+ "Cannot find 'text-properties' "
+ "element in styles.xml")
+ if language_code is not None:
+ n3.attrib[
+ '{urn:oasis:names:tc:opendocument:xmlns:'
+ 'xsl-fo-compatible:1.0}language'] = language_code
+ n3.attrib[
+ '{urn:oasis:names:tc:opendocument:xmlns:'
+ 'style:1.0}language-complex'] = language_code
+ updated = True
+ modified_nodes.add(n3)
+ if region_code is not None:
+ n3.attrib[
+ '{urn:oasis:names:tc:opendocument:xmlns:'
+ 'xsl-fo-compatible:1.0}country'] = region_code
+ n3.attrib[
+ '{urn:oasis:names:tc:opendocument:xmlns:'
+ 'style:1.0}country-complex'] = region_code
+ updated = True
+ modified_nodes.add(n3)
+ return updated, stylesheet_root, modified_nodes
+
+ def write_zip_str(
+ self, zfile, name, bytes, compress_type=zipfile.ZIP_DEFLATED):
+ localtime = time.localtime(time.time())
+ zinfo = zipfile.ZipInfo(name, localtime)
+ # Add some standard UNIX file access permissions (-rw-r--r--).
+ zinfo.external_attr = (0x81a4 & 0xFFFF) << 16
+ zinfo.compress_type = compress_type
+ zfile.writestr(zinfo, bytes)
+
+ def store_embedded_files(self, zfile):
+ embedded_files = self.visitor.get_embedded_file_list()
+ for source, destination in embedded_files:
+ if source is None:
+ continue
+ try:
+ zfile.write(source, destination)
+ except OSError:
+ self.document.reporter.warning(
+ "Can't open file %s." % (source, ))
+
+ def get_settings(self):
+ """
+ modeled after get_stylesheet
+ """
+ stylespath = self.settings.stylesheet
+ zfile = zipfile.ZipFile(stylespath, 'r')
+ s1 = zfile.read('settings.xml')
+ zfile.close()
+ return s1
+
+ def get_stylesheet(self):
+ """Get the stylesheet from the visitor.
+ Ask the visitor to setup the page.
+ """
+ s1 = self.visitor.setup_page()
+ return s1
+
+ def copy_from_stylesheet(self, outzipfile):
+ """Copy images, settings, etc from the stylesheet doc into target doc.
+ """
+ stylespath = self.settings.stylesheet
+ inzipfile = zipfile.ZipFile(stylespath, 'r')
+ # Copy the styles.
+ s1 = inzipfile.read('settings.xml')
+ self.write_zip_str(outzipfile, 'settings.xml', s1)
+ # Copy the images.
+ namelist = inzipfile.namelist()
+ for name in namelist:
+ if name.startswith('Pictures/'):
+ imageobj = inzipfile.read(name)
+ outzipfile.writestr(name, imageobj)
+ inzipfile.close()
+
+ def assemble_parts(self):
+ pass
+
+ def create_manifest(self):
+ root = Element(
+ 'manifest:manifest',
+ attrib=MANIFEST_NAMESPACE_ATTRIB,
+ nsdict=MANIFEST_NAMESPACE_DICT,
+ )
+ doc = etree.ElementTree(root)
+ SubElement(root, 'manifest:file-entry', attrib={
+ 'manifest:media-type': self.MIME_TYPE,
+ 'manifest:full-path': '/',
+ }, nsdict=MANNSD)
+ SubElement(root, 'manifest:file-entry', attrib={
+ 'manifest:media-type': 'text/xml',
+ 'manifest:full-path': 'content.xml',
+ }, nsdict=MANNSD)
+ SubElement(root, 'manifest:file-entry', attrib={
+ 'manifest:media-type': 'text/xml',
+ 'manifest:full-path': 'styles.xml',
+ }, nsdict=MANNSD)
+ SubElement(root, 'manifest:file-entry', attrib={
+ 'manifest:media-type': 'text/xml',
+ 'manifest:full-path': 'settings.xml',
+ }, nsdict=MANNSD)
+ SubElement(root, 'manifest:file-entry', attrib={
+ 'manifest:media-type': 'text/xml',
+ 'manifest:full-path': 'meta.xml',
+ }, nsdict=MANNSD)
+ s1 = ToString(doc)
+ doc = minidom.parseString(s1)
+ s1 = doc.toprettyxml(' ')
+ return s1
+
+ def create_meta(self):
+ root = Element(
+ 'office:document-meta',
+ attrib=META_NAMESPACE_ATTRIB,
+ nsdict=META_NAMESPACE_DICT,
+ )
+ doc = etree.ElementTree(root)
+ root = SubElement(root, 'office:meta', nsdict=METNSD)
+ el1 = SubElement(root, 'meta:generator', nsdict=METNSD)
+ el1.text = 'Docutils/rst2odf.py/%s' % (VERSION, )
+ s1 = os.environ.get('USER', '')
+ el1 = SubElement(root, 'meta:initial-creator', nsdict=METNSD)
+ el1.text = s1
+ s2 = time.strftime('%Y-%m-%dT%H:%M:%S', time.localtime())
+ el1 = SubElement(root, 'meta:creation-date', nsdict=METNSD)
+ el1.text = s2
+ el1 = SubElement(root, 'dc:creator', nsdict=METNSD)
+ el1.text = s1
+ el1 = SubElement(root, 'dc:date', nsdict=METNSD)
+ el1.text = s2
+ el1 = SubElement(root, 'dc:language', nsdict=METNSD)
+ el1.text = 'en-US'
+ el1 = SubElement(root, 'meta:editing-cycles', nsdict=METNSD)
+ el1.text = '1'
+ el1 = SubElement(root, 'meta:editing-duration', nsdict=METNSD)
+ el1.text = 'PT00M01S'
+ title = self.visitor.get_title()
+ el1 = SubElement(root, 'dc:title', nsdict=METNSD)
+ if title:
+ el1.text = title
+ else:
+ el1.text = '[no title]'
+ meta_dict = self.visitor.get_meta_dict()
+ keywordstr = meta_dict.get('keywords')
+ if keywordstr is not None:
+ keywords = split_words(keywordstr)
+ for keyword in keywords:
+ el1 = SubElement(root, 'meta:keyword', nsdict=METNSD)
+ el1.text = keyword
+ description = meta_dict.get('description')
+ if description is not None:
+ el1 = SubElement(root, 'dc:description', nsdict=METNSD)
+ el1.text = description
+ s1 = ToString(doc)
+ #doc = minidom.parseString(s1)
+ #s1 = doc.toprettyxml(' ')
+ return s1
+
+
+# class ODFTranslator(nodes.SparseNodeVisitor):
+class ODFTranslator(nodes.GenericNodeVisitor):
+
+ used_styles = (
+ 'attribution', 'blockindent', 'blockquote', 'blockquote-bulletitem',
+ 'blockquote-bulletlist', 'blockquote-enumitem', 'blockquote-enumlist',
+ 'bulletitem', 'bulletlist',
+ 'caption', 'legend',
+ 'centeredtextbody', 'codeblock', 'codeblock-indented',
+ 'codeblock-classname', 'codeblock-comment', 'codeblock-functionname',
+ 'codeblock-keyword', 'codeblock-name', 'codeblock-number',
+ 'codeblock-operator', 'codeblock-string', 'emphasis', 'enumitem',
+ 'enumlist', 'epigraph', 'epigraph-bulletitem', 'epigraph-bulletlist',
+ 'epigraph-enumitem', 'epigraph-enumlist', 'footer',
+ 'footnote', 'citation',
+ 'header', 'highlights', 'highlights-bulletitem',
+ 'highlights-bulletlist', 'highlights-enumitem', 'highlights-enumlist',
+ 'horizontalline', 'inlineliteral', 'quotation', 'rubric',
+ 'strong', 'table-title', 'textbody', 'tocbulletlist', 'tocenumlist',
+ 'title',
+ 'subtitle',
+ 'heading1',
+ 'heading2',
+ 'heading3',
+ 'heading4',
+ 'heading5',
+ 'heading6',
+ 'heading7',
+ 'admon-attention-hdr',
+ 'admon-attention-body',
+ 'admon-caution-hdr',
+ 'admon-caution-body',
+ 'admon-danger-hdr',
+ 'admon-danger-body',
+ 'admon-error-hdr',
+ 'admon-error-body',
+ 'admon-generic-hdr',
+ 'admon-generic-body',
+ 'admon-hint-hdr',
+ 'admon-hint-body',
+ 'admon-important-hdr',
+ 'admon-important-body',
+ 'admon-note-hdr',
+ 'admon-note-body',
+ 'admon-tip-hdr',
+ 'admon-tip-body',
+ 'admon-warning-hdr',
+ 'admon-warning-body',
+ 'tableoption',
+ 'tableoption.%c', 'tableoption.%c%d', 'Table%d', 'Table%d.%c',
+ 'Table%d.%c%d',
+ 'lineblock1',
+ 'lineblock2',
+ 'lineblock3',
+ 'lineblock4',
+ 'lineblock5',
+ 'lineblock6',
+ 'image', 'figureframe',
+ )
+
+ def __init__(self, document):
+ #nodes.SparseNodeVisitor.__init__(self, document)
+ nodes.GenericNodeVisitor.__init__(self, document)
+ self.settings = document.settings
+ self.language_code = self.settings.language_code
+ self.language = languages.get_language(
+ self.language_code,
+ document.reporter)
+ self.format_map = {}
+ if self.settings.odf_config_file:
+ parser = ConfigParser()
+ parser.read(self.settings.odf_config_file)
+ for rststyle, format in parser.items("Formats"):
+ if rststyle not in self.used_styles:
+ self.document.reporter.warning(
+ 'Style "%s" is not a style used by odtwriter.' % (
+ rststyle, ))
+ if sys.version_info >= (3, 0):
+ self.format_map[rststyle] = format
+ else:
+ self.format_map[rststyle] = format.decode('utf-8')
+ self.section_level = 0
+ self.section_count = 0
+ # Create ElementTree content and styles documents.
+ root = Element(
+ 'office:document-content',
+ attrib=CONTENT_NAMESPACE_ATTRIB,
+ )
+ self.content_tree = etree.ElementTree(element=root)
+ self.current_element = root
+ SubElement(root, 'office:scripts')
+ SubElement(root, 'office:font-face-decls')
+ el = SubElement(root, 'office:automatic-styles')
+ self.automatic_styles = el
+ el = SubElement(root, 'office:body')
+ el = self.generate_content_element(el)
+ self.current_element = el
+ self.body_text_element = el
+ self.paragraph_style_stack = [self.rststyle('textbody'), ]
+ self.list_style_stack = []
+ self.table_count = 0
+ self.column_count = ord('A') - 1
+ self.trace_level = -1
+ self.optiontablestyles_generated = False
+ self.field_name = None
+ self.field_element = None
+ self.title = None
+ self.image_count = 0
+ self.image_style_count = 0
+ self.image_dict = {}
+ self.embedded_file_list = []
+ self.syntaxhighlighting = 1
+ self.syntaxhighlight_lexer = 'python'
+ self.header_content = []
+ self.footer_content = []
+ self.in_header = False
+ self.in_footer = False
+ self.blockstyle = ''
+ self.in_table_of_contents = False
+ self.table_of_content_index_body = None
+ self.list_level = 0
+ self.def_list_level = 0
+ self.footnote_ref_dict = {}
+ self.footnote_list = []
+ self.footnote_chars_idx = 0
+ self.footnote_level = 0
+ self.pending_ids = []
+ self.in_paragraph = False
+ self.found_doc_title = False
+ self.bumped_list_level_stack = []
+ self.meta_dict = {}
+ self.line_block_level = 0
+ self.line_indent_level = 0
+ self.citation_id = None
+ self.style_index = 0 # use to form unique style names
+ self.str_stylesheet = ''
+ self.str_stylesheetcontent = ''
+ self.dom_stylesheet = None
+ self.table_styles = None
+ self.in_citation = False
+
+ # Keep track of nested styling classes
+ self.inline_style_count_stack = []
+
+ def get_str_stylesheet(self):
+ return self.str_stylesheet
+
+ def retrieve_styles(self, extension):
+ """Retrieve the stylesheet from either a .xml file or from
+ a .odt (zip) file. Return the content as a string.
+ """
+ s2 = None
+ stylespath = self.settings.stylesheet
+ ext = os.path.splitext(stylespath)[1]
+ if ext == '.xml':
+ stylesfile = open(stylespath, 'r')
+ s1 = stylesfile.read()
+ stylesfile.close()
+ elif ext == extension:
+ zfile = zipfile.ZipFile(stylespath, 'r')
+ s1 = zfile.read('styles.xml')
+ s2 = zfile.read('content.xml')
+ zfile.close()
+ else:
+ raise RuntimeError('stylesheet path (%s) must be %s or '
+ '.xml file' % (stylespath, extension))
+ self.str_stylesheet = s1
+ self.str_stylesheetcontent = s2
+ self.dom_stylesheet = etree.fromstring(self.str_stylesheet)
+ self.dom_stylesheetcontent = etree.fromstring(
+ self.str_stylesheetcontent)
+ self.table_styles = self.extract_table_styles(s2)
+
+ def extract_table_styles(self, styles_str):
+ root = etree.fromstring(styles_str)
+ table_styles = {}
+ auto_styles = root.find(
+ '{%s}automatic-styles' % (CNSD['office'], ))
+ for stylenode in auto_styles:
+ name = stylenode.get('{%s}name' % (CNSD['style'], ))
+ tablename = name.split('.')[0]
+ family = stylenode.get('{%s}family' % (CNSD['style'], ))
+ if name.startswith(TABLESTYLEPREFIX):
+ tablestyle = table_styles.get(tablename)
+ if tablestyle is None:
+ tablestyle = TableStyle()
+ table_styles[tablename] = tablestyle
+ if family == 'table':
+ properties = stylenode.find(
+ '{%s}table-properties' % (CNSD['style'], ))
+ property = properties.get(
+ '{%s}%s' % (CNSD['fo'], 'background-color', ))
+ if property is not None and property != 'none':
+ tablestyle.backgroundcolor = property
+ elif family == 'table-cell':
+ properties = stylenode.find(
+ '{%s}table-cell-properties' % (CNSD['style'], ))
+ if properties is not None:
+ border = self.get_property(properties)
+ if border is not None:
+ tablestyle.border = border
+ return table_styles
+
+ def get_property(self, stylenode):
+ border = None
+ for propertyname in TABLEPROPERTYNAMES:
+ border = stylenode.get('{%s}%s' % (CNSD['fo'], propertyname, ))
+ if border is not None and border != 'none':
+ return border
+ return border
+
+ def add_doc_title(self):
+ text = self.settings.title
+ if text:
+ self.title = text
+ if not self.found_doc_title:
+ el = Element('text:p', attrib={
+ 'text:style-name': self.rststyle('title'),
+ })
+ el.text = text
+ self.body_text_element.insert(0, el)
+ el = self.find_first_text_p(self.body_text_element)
+ if el is not None:
+ self.attach_page_style(el)
+
+ def find_first_text_p(self, el):
+ """Search the generated doc and return the first <text:p> element.
+ """
+ if (
+ el.tag == 'text:p' or
+ el.tag == 'text:h'):
+ return el
+ else:
+ for child in el:
+ el1 = self.find_first_text_p(child)
+ if el1 is not None:
+ return el1
+ return None
+
+ def attach_page_style(self, el):
+ """Attach the default page style.
+
+ Create an automatic-style that refers to the current style
+ of this element and that refers to the default page style.
+ """
+ current_style = el.get('text:style-name')
+ style_name = 'P1003'
+ el1 = SubElement(
+ self.automatic_styles, 'style:style', attrib={
+ 'style:name': style_name,
+ 'style:master-page-name': "rststyle-pagedefault",
+ 'style:family': "paragraph",
+ }, nsdict=SNSD)
+ if current_style:
+ el1.set('style:parent-style-name', current_style)
+ el.set('text:style-name', style_name)
+
+ def rststyle(self, name, parameters=()):
+ """
+ Returns the style name to use for the given style.
+
+ If `parameters` is given `name` must contain a matching number of
+ ``%`` and is used as a format expression with `parameters` as
+ the value.
+ """
+ name1 = name % parameters
+ stylename = self.format_map.get(name1, 'rststyle-%s' % name1)
+ return stylename
+
+ def generate_content_element(self, root):
+ return SubElement(root, 'office:text')
+
+ def setup_page(self):
+ self.setup_paper(self.dom_stylesheet)
+ if (len(self.header_content) > 0 or
+ len(self.footer_content) > 0 or
+ self.settings.custom_header or
+ self.settings.custom_footer):
+ self.add_header_footer(self.dom_stylesheet)
+ new_content = etree.tostring(self.dom_stylesheet)
+ return new_content
+
+ def get_dom_stylesheet(self):
+ return self.dom_stylesheet
+
+ def setup_paper(self, root_el):
+ try:
+ fin = os.popen("paperconf -s 2> /dev/null")
+ dimensions = fin.read().split()
+ w, h = (float(s) for s in dimensions)
+ except (IOError, ValueError):
+ w, h = 612, 792 # default to Letter
+ finally:
+ fin.close()
+
+ def walk(el):
+ if el.tag == "{%s}page-layout-properties" % SNSD["style"] and \
+ "{%s}page-width" % SNSD["fo"] not in el.attrib:
+ el.attrib["{%s}page-width" % SNSD["fo"]] = "%.3fpt" % w
+ el.attrib["{%s}page-height" % SNSD["fo"]] = "%.3fpt" % h
+ el.attrib["{%s}margin-left" % SNSD["fo"]] = \
+ el.attrib["{%s}margin-right" % SNSD["fo"]] = \
+ "%.3fpt" % (.1 * w)
+ el.attrib["{%s}margin-top" % SNSD["fo"]] = \
+ el.attrib["{%s}margin-bottom" % SNSD["fo"]] = \
+ "%.3fpt" % (.1 * h)
+ else:
+ for subel in el:
+ walk(subel)
+ walk(root_el)
+
+ def add_header_footer(self, root_el):
+ automatic_styles = root_el.find(
+ '{%s}automatic-styles' % SNSD['office'])
+ path = '{%s}master-styles' % (NAME_SPACE_1, )
+ master_el = root_el.find(path)
+ if master_el is None:
+ return
+ path = '{%s}master-page' % (SNSD['style'], )
+ master_el_container = master_el.findall(path)
+ master_el = None
+ target_attrib = '{%s}name' % (SNSD['style'], )
+ target_name = self.rststyle('pagedefault')
+ for el in master_el_container:
+ if el.get(target_attrib) == target_name:
+ master_el = el
+ break
+ if master_el is None:
+ return
+ el1 = master_el
+ if self.header_content or self.settings.custom_header:
+ el2 = SubElement(
+ el1, 'style:header',
+ attrib=STYLES_NAMESPACE_ATTRIB,
+ nsdict=STYLES_NAMESPACE_DICT,
+ )
+ for el in self.header_content:
+ attrkey = add_ns('text:style-name', nsdict=SNSD)
+ el.attrib[attrkey] = self.rststyle('header')
+ el2.append(el)
+ if self.settings.custom_header:
+ self.create_custom_headfoot(
+ el2,
+ self.settings.custom_header, 'header', automatic_styles)
+ if self.footer_content or self.settings.custom_footer:
+ el2 = SubElement(
+ el1, 'style:footer',
+ attrib=STYLES_NAMESPACE_ATTRIB,
+ nsdict=STYLES_NAMESPACE_DICT,
+ )
+ for el in self.footer_content:
+ attrkey = add_ns('text:style-name', nsdict=SNSD)
+ el.attrib[attrkey] = self.rststyle('footer')
+ el2.append(el)
+ if self.settings.custom_footer:
+ self.create_custom_headfoot(
+ el2,
+ self.settings.custom_footer, 'footer', automatic_styles)
+
+ code_none, code_field, code_text = list(range(3))
+ field_pat = re.compile(r'%(..?)%')
+
+ def create_custom_headfoot(
+ self, parent, text, style_name, automatic_styles):
+ parent = SubElement(parent, 'text:p', attrib={
+ 'text:style-name': self.rststyle(style_name),
+ })
+ current_element = None
+ field_iter = self.split_field_specifiers_iter(text)
+ for item in field_iter:
+ if item[0] == ODFTranslator.code_field:
+ if item[1] not in (
+ 'p', 'P',
+ 't1', 't2', 't3', 't4',
+ 'd1', 'd2', 'd3', 'd4', 'd5',
+ 's', 't', 'a'):
+ msg = 'bad field spec: %%%s%%' % (item[1], )
+ raise RuntimeError(msg)
+ el1 = self.make_field_element(
+ parent,
+ item[1], style_name, automatic_styles)
+ if el1 is None:
+ msg = 'bad field spec: %%%s%%' % (item[1], )
+ raise RuntimeError(msg)
+ else:
+ current_element = el1
+ else:
+ if current_element is None:
+ parent.text = item[1]
+ else:
+ current_element.tail = item[1]
+
+ def make_field_element(self, parent, text, style_name, automatic_styles):
+ if text == 'p':
+ el1 = SubElement(parent, 'text:page-number', attrib={
+ #'text:style-name': self.rststyle(style_name),
+ 'text:select-page': 'current',
+ })
+ elif text == 'P':
+ el1 = SubElement(parent, 'text:page-count', attrib={
+ #'text:style-name': self.rststyle(style_name),
+ })
+ elif text == 't1':
+ self.style_index += 1
+ el1 = SubElement(parent, 'text:time', attrib={
+ 'text:style-name': self.rststyle(style_name),
+ 'text:fixed': 'true',
+ 'style:data-style-name':
+ 'rst-time-style-%d' % self.style_index,
+ })
+ el2 = SubElement(automatic_styles, 'number:time-style', attrib={
+ 'style:name': 'rst-time-style-%d' % self.style_index,
+ 'xmlns:number': SNSD['number'],
+ 'xmlns:style': SNSD['style'],
+ })
+ el3 = SubElement(el2, 'number:hours', attrib={
+ 'number:style': 'long',
+ })
+ el3 = SubElement(el2, 'number:text')
+ el3.text = ':'
+ el3 = SubElement(el2, 'number:minutes', attrib={
+ 'number:style': 'long',
+ })
+ elif text == 't2':
+ self.style_index += 1
+ el1 = SubElement(parent, 'text:time', attrib={
+ 'text:style-name': self.rststyle(style_name),
+ 'text:fixed': 'true',
+ 'style:data-style-name':
+ 'rst-time-style-%d' % self.style_index,
+ })
+ el2 = SubElement(automatic_styles, 'number:time-style', attrib={
+ 'style:name': 'rst-time-style-%d' % self.style_index,
+ 'xmlns:number': SNSD['number'],
+ 'xmlns:style': SNSD['style'],
+ })
+ el3 = SubElement(el2, 'number:hours', attrib={
+ 'number:style': 'long',
+ })
+ el3 = SubElement(el2, 'number:text')
+ el3.text = ':'
+ el3 = SubElement(el2, 'number:minutes', attrib={
+ 'number:style': 'long',
+ })
+ el3 = SubElement(el2, 'number:text')
+ el3.text = ':'
+ el3 = SubElement(el2, 'number:seconds', attrib={
+ 'number:style': 'long',
+ })
+ elif text == 't3':
+ self.style_index += 1
+ el1 = SubElement(parent, 'text:time', attrib={
+ 'text:style-name': self.rststyle(style_name),
+ 'text:fixed': 'true',
+ 'style:data-style-name':
+ 'rst-time-style-%d' % self.style_index,
+ })
+ el2 = SubElement(automatic_styles, 'number:time-style', attrib={
+ 'style:name': 'rst-time-style-%d' % self.style_index,
+ 'xmlns:number': SNSD['number'],
+ 'xmlns:style': SNSD['style'],
+ })
+ el3 = SubElement(el2, 'number:hours', attrib={
+ 'number:style': 'long',
+ })
+ el3 = SubElement(el2, 'number:text')
+ el3.text = ':'
+ el3 = SubElement(el2, 'number:minutes', attrib={
+ 'number:style': 'long',
+ })
+ el3 = SubElement(el2, 'number:text')
+ el3.text = ' '
+ el3 = SubElement(el2, 'number:am-pm')
+ elif text == 't4':
+ self.style_index += 1
+ el1 = SubElement(parent, 'text:time', attrib={
+ 'text:style-name': self.rststyle(style_name),
+ 'text:fixed': 'true',
+ 'style:data-style-name':
+ 'rst-time-style-%d' % self.style_index,
+ })
+ el2 = SubElement(automatic_styles, 'number:time-style', attrib={
+ 'style:name': 'rst-time-style-%d' % self.style_index,
+ 'xmlns:number': SNSD['number'],
+ 'xmlns:style': SNSD['style'],
+ })
+ el3 = SubElement(el2, 'number:hours', attrib={
+ 'number:style': 'long',
+ })
+ el3 = SubElement(el2, 'number:text')
+ el3.text = ':'
+ el3 = SubElement(el2, 'number:minutes', attrib={
+ 'number:style': 'long',
+ })
+ el3 = SubElement(el2, 'number:text')
+ el3.text = ':'
+ el3 = SubElement(el2, 'number:seconds', attrib={
+ 'number:style': 'long',
+ })
+ el3 = SubElement(el2, 'number:text')
+ el3.text = ' '
+ el3 = SubElement(el2, 'number:am-pm')
+ elif text == 'd1':
+ self.style_index += 1
+ el1 = SubElement(parent, 'text:date', attrib={
+ 'text:style-name': self.rststyle(style_name),
+ 'style:data-style-name':
+ 'rst-date-style-%d' % self.style_index,
+ })
+ el2 = SubElement(automatic_styles, 'number:date-style', attrib={
+ 'style:name': 'rst-date-style-%d' % self.style_index,
+ 'number:automatic-order': 'true',
+ 'xmlns:number': SNSD['number'],
+ 'xmlns:style': SNSD['style'],
+ })
+ el3 = SubElement(el2, 'number:month', attrib={
+ 'number:style': 'long',
+ })
+ el3 = SubElement(el2, 'number:text')
+ el3.text = '/'
+ el3 = SubElement(el2, 'number:day', attrib={
+ 'number:style': 'long',
+ })
+ el3 = SubElement(el2, 'number:text')
+ el3.text = '/'
+ el3 = SubElement(el2, 'number:year')
+ elif text == 'd2':
+ self.style_index += 1
+ el1 = SubElement(parent, 'text:date', attrib={
+ 'text:style-name': self.rststyle(style_name),
+ 'style:data-style-name':
+ 'rst-date-style-%d' % self.style_index,
+ })
+ el2 = SubElement(automatic_styles, 'number:date-style', attrib={
+ 'style:name': 'rst-date-style-%d' % self.style_index,
+ 'number:automatic-order': 'true',
+ 'xmlns:number': SNSD['number'],
+ 'xmlns:style': SNSD['style'],
+ })
+ el3 = SubElement(el2, 'number:month', attrib={
+ 'number:style': 'long',
+ })
+ el3 = SubElement(el2, 'number:text')
+ el3.text = '/'
+ el3 = SubElement(el2, 'number:day', attrib={
+ 'number:style': 'long',
+ })
+ el3 = SubElement(el2, 'number:text')
+ el3.text = '/'
+ el3 = SubElement(el2, 'number:year', attrib={
+ 'number:style': 'long',
+ })
+ elif text == 'd3':
+ self.style_index += 1
+ el1 = SubElement(parent, 'text:date', attrib={
+ 'text:style-name': self.rststyle(style_name),
+ 'style:data-style-name':
+ 'rst-date-style-%d' % self.style_index,
+ })
+ el2 = SubElement(automatic_styles, 'number:date-style', attrib={
+ 'style:name': 'rst-date-style-%d' % self.style_index,
+ 'number:automatic-order': 'true',
+ 'xmlns:number': SNSD['number'],
+ 'xmlns:style': SNSD['style'],
+ })
+ el3 = SubElement(el2, 'number:month', attrib={
+ 'number:textual': 'true',
+ })
+ el3 = SubElement(el2, 'number:text')
+ el3.text = ' '
+ el3 = SubElement(el2, 'number:day', attrib={})
+ el3 = SubElement(el2, 'number:text')
+ el3.text = ', '
+ el3 = SubElement(el2, 'number:year', attrib={
+ 'number:style': 'long',
+ })
+ elif text == 'd4':
+ self.style_index += 1
+ el1 = SubElement(parent, 'text:date', attrib={
+ 'text:style-name': self.rststyle(style_name),
+ 'style:data-style-name':
+ 'rst-date-style-%d' % self.style_index,
+ })
+ el2 = SubElement(automatic_styles, 'number:date-style', attrib={
+ 'style:name': 'rst-date-style-%d' % self.style_index,
+ 'number:automatic-order': 'true',
+ 'xmlns:number': SNSD['number'],
+ 'xmlns:style': SNSD['style'],
+ })
+ el3 = SubElement(el2, 'number:month', attrib={
+ 'number:textual': 'true',
+ 'number:style': 'long',
+ })
+ el3 = SubElement(el2, 'number:text')
+ el3.text = ' '
+ el3 = SubElement(el2, 'number:day', attrib={})
+ el3 = SubElement(el2, 'number:text')
+ el3.text = ', '
+ el3 = SubElement(el2, 'number:year', attrib={
+ 'number:style': 'long',
+ })
+ elif text == 'd5':
+ self.style_index += 1
+ el1 = SubElement(parent, 'text:date', attrib={
+ 'text:style-name': self.rststyle(style_name),
+ 'style:data-style-name':
+ 'rst-date-style-%d' % self.style_index,
+ })
+ el2 = SubElement(automatic_styles, 'number:date-style', attrib={
+ 'style:name': 'rst-date-style-%d' % self.style_index,
+ 'xmlns:number': SNSD['number'],
+ 'xmlns:style': SNSD['style'],
+ })
+ el3 = SubElement(el2, 'number:year', attrib={
+ 'number:style': 'long',
+ })
+ el3 = SubElement(el2, 'number:text')
+ el3.text = '-'
+ el3 = SubElement(el2, 'number:month', attrib={
+ 'number:style': 'long',
+ })
+ el3 = SubElement(el2, 'number:text')
+ el3.text = '-'
+ el3 = SubElement(el2, 'number:day', attrib={
+ 'number:style': 'long',
+ })
+ elif text == 's':
+ el1 = SubElement(parent, 'text:subject', attrib={
+ 'text:style-name': self.rststyle(style_name),
+ })
+ elif text == 't':
+ el1 = SubElement(parent, 'text:title', attrib={
+ 'text:style-name': self.rststyle(style_name),
+ })
+ elif text == 'a':
+ el1 = SubElement(parent, 'text:author-name', attrib={
+ 'text:fixed': 'false',
+ })
+ else:
+ el1 = None
+ return el1
+
+ def split_field_specifiers_iter(self, text):
+ pos1 = 0
+ while True:
+ mo = ODFTranslator.field_pat.search(text, pos1)
+ if mo:
+ pos2 = mo.start()
+ if pos2 > pos1:
+ yield (ODFTranslator.code_text, text[pos1:pos2])
+ yield (ODFTranslator.code_field, mo.group(1))
+ pos1 = mo.end()
+ else:
+ break
+ trailing = text[pos1:]
+ if trailing:
+ yield (ODFTranslator.code_text, trailing)
+
+ def astext(self):
+ root = self.content_tree.getroot()
+ et = etree.ElementTree(root)
+ s1 = ToString(et)
+ return s1
+
+ def content_astext(self):
+ return self.astext()
+
+ def set_title(self, title):
+ self.title = title
+
+ def get_title(self):
+ return self.title
+
+ def set_embedded_file_list(self, embedded_file_list):
+ self.embedded_file_list = embedded_file_list
+
+ def get_embedded_file_list(self):
+ return self.embedded_file_list
+
+ def get_meta_dict(self):
+ return self.meta_dict
+
+ def process_footnotes(self):
+ for node, el1 in self.footnote_list:
+ backrefs = node.attributes.get('backrefs', [])
+ first = True
+ for ref in backrefs:
+ el2 = self.footnote_ref_dict.get(ref)
+ if el2 is not None:
+ if first:
+ first = False
+ el3 = copy.deepcopy(el1)
+ el2.append(el3)
+ else:
+ if len(el2) > 0: # and 'id' in el2.attrib:
+ child = el2[0]
+ ref1 = child.text
+ attribkey = add_ns('text:id', nsdict=SNSD)
+ id1 = el2.get(attribkey, 'footnote-error')
+ if id1 is None:
+ id1 = ''
+ tag = add_ns('text:note-ref', nsdict=SNSD)
+ el2.tag = tag
+ if self.settings.endnotes_end_doc:
+ note_class = 'endnote'
+ else:
+ note_class = 'footnote'
+ el2.attrib.clear()
+ attribkey = add_ns('text:note-class', nsdict=SNSD)
+ el2.attrib[attribkey] = note_class
+ attribkey = add_ns('text:ref-name', nsdict=SNSD)
+ el2.attrib[attribkey] = id1
+ attribkey = add_ns(
+ 'text:reference-format', nsdict=SNSD)
+ el2.attrib[attribkey] = 'page'
+ el2.text = ref1
+
+ #
+ # Utility methods
+
+ def append_child(self, tag, attrib=None, parent=None):
+ if parent is None:
+ parent = self.current_element
+ el = SubElement(parent, tag, attrib)
+ return el
+
+ def append_p(self, style, text=None):
+ result = self.append_child('text:p', attrib={
+ 'text:style-name': self.rststyle(style)})
+ self.append_pending_ids(result)
+ if text is not None:
+ result.text = text
+ return result
+
+ def append_pending_ids(self, el):
+ if self.settings.create_links:
+ for id in self.pending_ids:
+ SubElement(el, 'text:reference-mark', attrib={
+ 'text:name': id})
+ self.pending_ids = []
+
+ def set_current_element(self, el):
+ self.current_element = el
+
+ def set_to_parent(self):
+ self.current_element = self.current_element.getparent()
+
+ def generate_labeled_block(self, node, label):
+ label = '%s:' % (self.language.labels[label], )
+ el = self.append_p('textbody')
+ el1 = SubElement(
+ el, 'text:span',
+ attrib={'text:style-name': self.rststyle('strong')})
+ el1.text = label
+ el = self.append_p('blockindent')
+ return el
+
+ def generate_labeled_line(self, node, label):
+ label = '%s:' % (self.language.labels[label], )
+ el = self.append_p('textbody')
+ el1 = SubElement(
+ el, 'text:span',
+ attrib={'text:style-name': self.rststyle('strong')})
+ el1.text = label
+ el1.tail = node.astext()
+ return el
+
+ def encode(self, text):
+ text = text.replace('\n', " ")
+ return text
+
+ #
+ # Visitor functions
+ #
+ # In alphabetic order, more or less.
+ # See docutils.docutils.nodes.node_class_names.
+ #
+
+ def dispatch_visit(self, node):
+ """Override to catch basic attributes which many nodes have."""
+ self.handle_basic_atts(node)
+ nodes.GenericNodeVisitor.dispatch_visit(self, node)
+
+ def handle_basic_atts(self, node):
+ if isinstance(node, nodes.Element) and node['ids']:
+ self.pending_ids += node['ids']
+
+ def default_visit(self, node):
+ self.document.reporter.warning('missing visit_%s' % (node.tagname, ))
+
+ def default_departure(self, node):
+ self.document.reporter.warning('missing depart_%s' % (node.tagname, ))
+
+ def visit_Text(self, node):
+ # Skip nodes whose text has been processed in parent nodes.
+ if isinstance(node.parent, docutils.nodes.literal_block):
+ return
+ text = node.astext()
+ # Are we in mixed content? If so, add the text to the
+ # etree tail of the previous sibling element.
+ if len(self.current_element) > 0:
+ if self.current_element[-1].tail:
+ self.current_element[-1].tail += text
+ else:
+ self.current_element[-1].tail = text
+ else:
+ if self.current_element.text:
+ self.current_element.text += text
+ else:
+ self.current_element.text = text
+
+ def depart_Text(self, node):
+ pass
+
+ #
+ # Pre-defined fields
+ #
+
+ def visit_address(self, node):
+ el = self.generate_labeled_block(node, 'address')
+ self.set_current_element(el)
+
+ def depart_address(self, node):
+ self.set_to_parent()
+
+ def visit_author(self, node):
+ if isinstance(node.parent, nodes.authors):
+ el = self.append_p('blockindent')
+ else:
+ el = self.generate_labeled_block(node, 'author')
+ self.set_current_element(el)
+
+ def depart_author(self, node):
+ self.set_to_parent()
+
+ def visit_authors(self, node):
+ label = '%s:' % (self.language.labels['authors'], )
+ el = self.append_p('textbody')
+ el1 = SubElement(
+ el, 'text:span',
+ attrib={'text:style-name': self.rststyle('strong')})
+ el1.text = label
+
+ def depart_authors(self, node):
+ pass
+
+ def visit_contact(self, node):
+ el = self.generate_labeled_block(node, 'contact')
+ self.set_current_element(el)
+
+ def depart_contact(self, node):
+ self.set_to_parent()
+
+ def visit_copyright(self, node):
+ el = self.generate_labeled_block(node, 'copyright')
+ self.set_current_element(el)
+
+ def depart_copyright(self, node):
+ self.set_to_parent()
+
+ def visit_date(self, node):
+ self.generate_labeled_line(node, 'date')
+
+ def depart_date(self, node):
+ pass
+
+ def visit_organization(self, node):
+ el = self.generate_labeled_block(node, 'organization')
+ self.set_current_element(el)
+
+ def depart_organization(self, node):
+ self.set_to_parent()
+
+ def visit_status(self, node):
+ el = self.generate_labeled_block(node, 'status')
+ self.set_current_element(el)
+
+ def depart_status(self, node):
+ self.set_to_parent()
+
+ def visit_revision(self, node):
+ self.generate_labeled_line(node, 'revision')
+
+ def depart_revision(self, node):
+ pass
+
+ def visit_version(self, node):
+ self.generate_labeled_line(node, 'version')
+ #self.set_current_element(el)
+
+ def depart_version(self, node):
+ #self.set_to_parent()
+ pass
+
+ def visit_attribution(self, node):
+ self.append_p('attribution', node.astext())
+
+ def depart_attribution(self, node):
+ pass
+
+ def visit_block_quote(self, node):
+ if 'epigraph' in node.attributes['classes']:
+ self.paragraph_style_stack.append(self.rststyle('epigraph'))
+ self.blockstyle = self.rststyle('epigraph')
+ elif 'highlights' in node.attributes['classes']:
+ self.paragraph_style_stack.append(self.rststyle('highlights'))
+ self.blockstyle = self.rststyle('highlights')
+ else:
+ self.paragraph_style_stack.append(self.rststyle('blockquote'))
+ self.blockstyle = self.rststyle('blockquote')
+ self.line_indent_level += 1
+
+ def depart_block_quote(self, node):
+ self.paragraph_style_stack.pop()
+ self.blockstyle = ''
+ self.line_indent_level -= 1
+
+ def visit_bullet_list(self, node):
+ self.list_level += 1
+ if self.in_table_of_contents:
+ if self.settings.generate_oowriter_toc:
+ pass
+ else:
+ if 'classes' in node and \
+ 'auto-toc' in node.attributes['classes']:
+ el = SubElement(self.current_element, 'text:list', attrib={
+ 'text:style-name': self.rststyle('tocenumlist'),
+ })
+ self.list_style_stack.append(self.rststyle('enumitem'))
+ else:
+ el = SubElement(self.current_element, 'text:list', attrib={
+ 'text:style-name': self.rststyle('tocbulletlist'),
+ })
+ self.list_style_stack.append(self.rststyle('bulletitem'))
+ self.set_current_element(el)
+ else:
+ if self.blockstyle == self.rststyle('blockquote'):
+ el = SubElement(self.current_element, 'text:list', attrib={
+ 'text:style-name': self.rststyle('blockquote-bulletlist'),
+ })
+ self.list_style_stack.append(
+ self.rststyle('blockquote-bulletitem'))
+ elif self.blockstyle == self.rststyle('highlights'):
+ el = SubElement(self.current_element, 'text:list', attrib={
+ 'text:style-name': self.rststyle('highlights-bulletlist'),
+ })
+ self.list_style_stack.append(
+ self.rststyle('highlights-bulletitem'))
+ elif self.blockstyle == self.rststyle('epigraph'):
+ el = SubElement(self.current_element, 'text:list', attrib={
+ 'text:style-name': self.rststyle('epigraph-bulletlist'),
+ })
+ self.list_style_stack.append(
+ self.rststyle('epigraph-bulletitem'))
+ else:
+ el = SubElement(self.current_element, 'text:list', attrib={
+ 'text:style-name': self.rststyle('bulletlist'),
+ })
+ self.list_style_stack.append(self.rststyle('bulletitem'))
+ self.set_current_element(el)
+
+ def depart_bullet_list(self, node):
+ if self.in_table_of_contents:
+ if self.settings.generate_oowriter_toc:
+ pass
+ else:
+ self.set_to_parent()
+ self.list_style_stack.pop()
+ else:
+ self.set_to_parent()
+ self.list_style_stack.pop()
+ self.list_level -= 1
+
+ def visit_caption(self, node):
+ raise nodes.SkipChildren()
+ pass
+
+ def depart_caption(self, node):
+ pass
+
+ def visit_comment(self, node):
+ el = self.append_p('textbody')
+ el1 = SubElement(el, 'office:annotation', attrib={})
+ el2 = SubElement(el1, 'dc:creator', attrib={})
+ s1 = os.environ.get('USER', '')
+ el2.text = s1
+ el2 = SubElement(el1, 'text:p', attrib={})
+ el2.text = node.astext()
+
+ def depart_comment(self, node):
+ pass
+
+ def visit_compound(self, node):
+ # The compound directive currently receives no special treatment.
+ pass
+
+ def depart_compound(self, node):
+ pass
+
+ def visit_container(self, node):
+ styles = node.attributes.get('classes', ())
+ if len(styles) > 0:
+ self.paragraph_style_stack.append(self.rststyle(styles[0]))
+
+ def depart_container(self, node):
+ styles = node.attributes.get('classes', ())
+ if len(styles) > 0:
+ self.paragraph_style_stack.pop()
+
+ def visit_decoration(self, node):
+ pass
+
+ def depart_decoration(self, node):
+ pass
+
+ def visit_definition_list(self, node):
+ self.def_list_level += 1
+ if self.list_level > 5:
+ raise RuntimeError(
+ 'max definition list nesting level exceeded')
+
+ def depart_definition_list(self, node):
+ self.def_list_level -= 1
+
+ def visit_definition_list_item(self, node):
+ pass
+
+ def depart_definition_list_item(self, node):
+ pass
+
+ def visit_term(self, node):
+ el = self.append_p('deflist-term-%d' % self.def_list_level)
+ el.text = node.astext()
+ self.set_current_element(el)
+ raise nodes.SkipChildren()
+
+ def depart_term(self, node):
+ self.set_to_parent()
+
+ def visit_definition(self, node):
+ self.paragraph_style_stack.append(
+ self.rststyle('deflist-def-%d' % self.def_list_level))
+ self.bumped_list_level_stack.append(ListLevel(1))
+
+ def depart_definition(self, node):
+ self.paragraph_style_stack.pop()
+ self.bumped_list_level_stack.pop()
+
+ def visit_classifier(self, node):
+ if len(self.current_element) > 0:
+ el = self.current_element[-1]
+ el1 = SubElement(
+ el, 'text:span',
+ attrib={'text:style-name': self.rststyle('emphasis')})
+ el1.text = ' (%s)' % (node.astext(), )
+
+ def depart_classifier(self, node):
+ pass
+
+ def visit_document(self, node):
+ pass
+
+ def depart_document(self, node):
+ self.process_footnotes()
+
+ def visit_docinfo(self, node):
+ self.section_level += 1
+ self.section_count += 1
+ if self.settings.create_sections:
+ el = self.append_child(
+ 'text:section', attrib={
+ 'text:name': 'Section%d' % self.section_count,
+ 'text:style-name': 'Sect%d' % self.section_level,
+ }
+ )
+ self.set_current_element(el)
+
+ def depart_docinfo(self, node):
+ self.section_level -= 1
+ if self.settings.create_sections:
+ self.set_to_parent()
+
+ def visit_emphasis(self, node):
+ el = SubElement(
+ self.current_element, 'text:span',
+ attrib={'text:style-name': self.rststyle('emphasis')})
+ self.set_current_element(el)
+
+ def depart_emphasis(self, node):
+ self.set_to_parent()
+
+ def visit_enumerated_list(self, node):
+ el1 = self.current_element
+ if self.blockstyle == self.rststyle('blockquote'):
+ el2 = SubElement(el1, 'text:list', attrib={
+ 'text:style-name': self.rststyle('blockquote-enumlist'),
+ })
+ self.list_style_stack.append(self.rststyle('blockquote-enumitem'))
+ elif self.blockstyle == self.rststyle('highlights'):
+ el2 = SubElement(el1, 'text:list', attrib={
+ 'text:style-name': self.rststyle('highlights-enumlist'),
+ })
+ self.list_style_stack.append(self.rststyle('highlights-enumitem'))
+ elif self.blockstyle == self.rststyle('epigraph'):
+ el2 = SubElement(el1, 'text:list', attrib={
+ 'text:style-name': self.rststyle('epigraph-enumlist'),
+ })
+ self.list_style_stack.append(self.rststyle('epigraph-enumitem'))
+ else:
+ liststylename = 'enumlist-%s' % (node.get('enumtype', 'arabic'), )
+ el2 = SubElement(el1, 'text:list', attrib={
+ 'text:style-name': self.rststyle(liststylename),
+ })
+ self.list_style_stack.append(self.rststyle('enumitem'))
+ self.set_current_element(el2)
+
+ def depart_enumerated_list(self, node):
+ self.set_to_parent()
+ self.list_style_stack.pop()
+
+ def visit_list_item(self, node):
+ # If we are in a "bumped" list level, then wrap this
+ # list in an outer lists in order to increase the
+ # indentation level.
+ if self.in_table_of_contents:
+ if self.settings.generate_oowriter_toc:
+ self.paragraph_style_stack.append(
+ self.rststyle('contents-%d' % (self.list_level, )))
+ else:
+ el1 = self.append_child('text:list-item')
+ self.set_current_element(el1)
+ else:
+ el1 = self.append_child('text:list-item')
+ el3 = el1
+ if len(self.bumped_list_level_stack) > 0:
+ level_obj = self.bumped_list_level_stack[-1]
+ if level_obj.get_sibling():
+ level_obj.set_nested(False)
+ for level_obj1 in self.bumped_list_level_stack:
+ for idx in range(level_obj1.get_level()):
+ el2 = self.append_child('text:list', parent=el3)
+ el3 = self.append_child(
+ 'text:list-item', parent=el2)
+ self.paragraph_style_stack.append(self.list_style_stack[-1])
+ self.set_current_element(el3)
+
+ def depart_list_item(self, node):
+ if self.in_table_of_contents:
+ if self.settings.generate_oowriter_toc:
+ self.paragraph_style_stack.pop()
+ else:
+ self.set_to_parent()
+ else:
+ if len(self.bumped_list_level_stack) > 0:
+ level_obj = self.bumped_list_level_stack[-1]
+ if level_obj.get_sibling():
+ level_obj.set_nested(True)
+ for level_obj1 in self.bumped_list_level_stack:
+ for idx in range(level_obj1.get_level()):
+ self.set_to_parent()
+ self.set_to_parent()
+ self.paragraph_style_stack.pop()
+ self.set_to_parent()
+
+ def visit_header(self, node):
+ self.in_header = True
+
+ def depart_header(self, node):
+ self.in_header = False
+
+ def visit_footer(self, node):
+ self.in_footer = True
+
+ def depart_footer(self, node):
+ self.in_footer = False
+
+ def visit_field(self, node):
+ pass
+
+ def depart_field(self, node):
+ pass
+
+ def visit_field_list(self, node):
+ pass
+
+ def depart_field_list(self, node):
+ pass
+
+ def visit_field_name(self, node):
+ el = self.append_p('textbody')
+ el1 = SubElement(
+ el, 'text:span',
+ attrib={'text:style-name': self.rststyle('strong')})
+ el1.text = node.astext()
+
+ def depart_field_name(self, node):
+ pass
+
+ def visit_field_body(self, node):
+ self.paragraph_style_stack.append(self.rststyle('blockindent'))
+
+ def depart_field_body(self, node):
+ self.paragraph_style_stack.pop()
+
+ def visit_figure(self, node):
+ pass
+
+ def depart_figure(self, node):
+ pass
+
+ def visit_footnote(self, node):
+ self.footnote_level += 1
+ self.save_footnote_current = self.current_element
+ el1 = Element('text:note-body')
+ self.current_element = el1
+ self.footnote_list.append((node, el1))
+ if isinstance(node, docutils.nodes.citation):
+ self.paragraph_style_stack.append(self.rststyle('citation'))
+ else:
+ self.paragraph_style_stack.append(self.rststyle('footnote'))
+
+ def depart_footnote(self, node):
+ self.paragraph_style_stack.pop()
+ self.current_element = self.save_footnote_current
+ self.footnote_level -= 1
+
+ footnote_chars = [
+ '*', '**', '***',
+ '++', '+++',
+ '##', '###',
+ '@@', '@@@',
+ ]
+
+ def visit_footnote_reference(self, node):
+ if self.footnote_level <= 0:
+ id = node.attributes['ids'][0]
+ refid = node.attributes.get('refid')
+ if refid is None:
+ refid = ''
+ if self.settings.endnotes_end_doc:
+ note_class = 'endnote'
+ else:
+ note_class = 'footnote'
+ el1 = self.append_child('text:note', attrib={
+ 'text:id': '%s' % (refid, ),
+ 'text:note-class': note_class,
+ })
+ note_auto = str(node.attributes.get('auto', 1))
+ if isinstance(node, docutils.nodes.citation_reference):
+ citation = '[%s]' % node.astext()
+ el2 = SubElement(el1, 'text:note-citation', attrib={
+ 'text:label': citation,
+ })
+ el2.text = citation
+ elif note_auto == '1':
+ el2 = SubElement(el1, 'text:note-citation', attrib={
+ 'text:label': node.astext(),
+ })
+ el2.text = node.astext()
+ elif note_auto == '*':
+ if self.footnote_chars_idx >= len(
+ ODFTranslator.footnote_chars):
+ self.footnote_chars_idx = 0
+ footnote_char = ODFTranslator.footnote_chars[
+ self.footnote_chars_idx]
+ self.footnote_chars_idx += 1
+ el2 = SubElement(el1, 'text:note-citation', attrib={
+ 'text:label': footnote_char,
+ })
+ el2.text = footnote_char
+ self.footnote_ref_dict[id] = el1
+ raise nodes.SkipChildren()
+
+ def depart_footnote_reference(self, node):
+ pass
+
+ def visit_citation(self, node):
+ self.in_citation = True
+ for id in node.attributes['ids']:
+ self.citation_id = id
+ break
+ self.paragraph_style_stack.append(self.rststyle('blockindent'))
+ self.bumped_list_level_stack.append(ListLevel(1))
+
+ def depart_citation(self, node):
+ self.citation_id = None
+ self.paragraph_style_stack.pop()
+ self.bumped_list_level_stack.pop()
+ self.in_citation = False
+
+ def visit_citation_reference(self, node):
+ if self.settings.create_links:
+ id = node.attributes['refid']
+ el = self.append_child('text:reference-ref', attrib={
+ 'text:ref-name': '%s' % (id, ),
+ 'text:reference-format': 'text',
+ })
+ el.text = '['
+ self.set_current_element(el)
+ elif self.current_element.text is None:
+ self.current_element.text = '['
+ else:
+ self.current_element.text += '['
+
+ def depart_citation_reference(self, node):
+ self.current_element.text += ']'
+ if self.settings.create_links:
+ self.set_to_parent()
+
+ def visit_label(self, node):
+ if isinstance(node.parent, docutils.nodes.footnote):
+ raise nodes.SkipChildren()
+ elif self.citation_id is not None:
+ el = self.append_p('textbody')
+ self.set_current_element(el)
+ if self.settings.create_links:
+ el0 = SubElement(el, 'text:span')
+ el0.text = '['
+ self.append_child('text:reference-mark-start', attrib={
+ 'text:name': '%s' % (self.citation_id, ),
+ })
+ else:
+ el.text = '['
+
+ def depart_label(self, node):
+ if isinstance(node.parent, docutils.nodes.footnote):
+ pass
+ elif self.citation_id is not None:
+ if self.settings.create_links:
+ self.append_child('text:reference-mark-end', attrib={
+ 'text:name': '%s' % (self.citation_id, ),
+ })
+ el0 = SubElement(self.current_element, 'text:span')
+ el0.text = ']'
+ else:
+ self.current_element.text += ']'
+ self.set_to_parent()
+
+ def visit_generated(self, node):
+ pass
+
+ def depart_generated(self, node):
+ pass
+
+ def check_file_exists(self, path):
+ if os.path.exists(path):
+ return 1
+ else:
+ return 0
+
+ def visit_image(self, node):
+ # Capture the image file.
+ if 'uri' in node.attributes:
+ source = node.attributes['uri']
+ if not (source.startswith('http:') or source.startswith('https:')):
+ if not source.startswith(os.sep):
+ docsource, line = utils.get_source_line(node)
+ if docsource:
+ dirname = os.path.dirname(docsource)
+ if dirname:
+ source = '%s%s%s' % (dirname, os.sep, source, )
+ if not self.check_file_exists(source):
+ self.document.reporter.warning(
+ 'Cannot find image file %s.' % (source, ))
+ return
+ else:
+ return
+ if source in self.image_dict:
+ filename, destination = self.image_dict[source]
+ else:
+ self.image_count += 1
+ filename = os.path.split(source)[1]
+ destination = 'Pictures/1%08x%s' % (self.image_count, filename, )
+ if source.startswith('http:') or source.startswith('https:'):
+ try:
+ imgfile = urlopen(source)
+ content = imgfile.read()
+ imgfile.close()
+ imgfile2 = tempfile.NamedTemporaryFile('wb', delete=False)
+ imgfile2.write(content)
+ imgfile2.close()
+ imgfilename = imgfile2.name
+ source = imgfilename
+ except HTTPError:
+ self.document.reporter.warning(
+ "Can't open image url %s." % (source, ))
+ spec = (source, destination,)
+ else:
+ spec = (os.path.abspath(source), destination,)
+ self.embedded_file_list.append(spec)
+ self.image_dict[source] = (source, destination,)
+ # Is this a figure (containing an image) or just a plain image?
+ if self.in_paragraph:
+ el1 = self.current_element
+ else:
+ el1 = SubElement(
+ self.current_element, 'text:p',
+ attrib={'text:style-name': self.rststyle('textbody')})
+ el2 = el1
+ if isinstance(node.parent, docutils.nodes.figure):
+ el3, el4, el5, caption = self.generate_figure(
+ node, source,
+ destination, el2)
+ attrib = {}
+ el6, width = self.generate_image(
+ node, source, destination,
+ el5, attrib)
+ if caption is not None:
+ el6.tail = caption
+ else: # if isinstance(node.parent, docutils.nodes.image):
+ self.generate_image(node, source, destination, el2)
+
+ def depart_image(self, node):
+ pass
+
+ def get_image_width_height(self, node, attr):
+ size = None
+ unit = None
+ if attr in node.attributes:
+ size = node.attributes[attr]
+ size = size.strip()
+ # For conversion factors, see:
+ # http://www.unitconversion.org/unit_converter/typography-ex.html
+ try:
+ if size.endswith('%'):
+ if attr == 'height':
+ # Percentage allowed for width but not height.
+ raise ValueError('percentage not allowed for height')
+ size = size.rstrip(' %')
+ size = float(size) / 100.0
+ unit = '%'
+ else:
+ size, unit = self.convert_to_cm(size)
+ except ValueError as exp:
+ self.document.reporter.warning(
+ 'Invalid %s for image: "%s". '
+ 'Error: "%s".' % (
+ attr, node.attributes[attr], exp))
+ return size, unit
+
+ def convert_to_cm(self, size):
+ """Convert various units to centimeters.
+
+ Note that a call to this method should be wrapped in:
+ try: except ValueError:
+ """
+ size = size.strip()
+ if size.endswith('px'):
+ size = float(size[:-2]) * 0.026 # convert px to cm
+ elif size.endswith('in'):
+ size = float(size[:-2]) * 2.54 # convert in to cm
+ elif size.endswith('pt'):
+ size = float(size[:-2]) * 0.035 # convert pt to cm
+ elif size.endswith('pc'):
+ size = float(size[:-2]) * 2.371 # convert pc to cm
+ elif size.endswith('mm'):
+ size = float(size[:-2]) * 0.1 # convert mm to cm
+ elif size.endswith('cm'):
+ size = float(size[:-2])
+ else:
+ raise ValueError('unknown unit type')
+ unit = 'cm'
+ return size, unit
+
+ def get_image_scale(self, node):
+ if 'scale' in node.attributes:
+ scale = node.attributes['scale']
+ try:
+ scale = int(scale)
+ except ValueError:
+ self.document.reporter.warning(
+ 'Invalid scale for image: "%s"' % (
+ node.attributes['scale'], ))
+ if scale < 1: # or scale > 100:
+ self.document.reporter.warning(
+ 'scale out of range (%s), using 1.' % (scale, ))
+ scale = 1
+ scale = scale * 0.01
+ else:
+ scale = 1.0
+ return scale
+
+ def get_image_scaled_width_height(self, node, source):
+ """Return the image size in centimeters adjusted by image attrs."""
+ scale = self.get_image_scale(node)
+ width, width_unit = self.get_image_width_height(node, 'width')
+ height, _ = self.get_image_width_height(node, 'height')
+ dpi = (72, 72)
+ if PIL is not None and source in self.image_dict:
+ filename, destination = self.image_dict[source]
+ imageobj = PIL.Image.open(filename, 'r')
+ dpi = imageobj.info.get('dpi', dpi)
+ # dpi information can be (xdpi, ydpi) or xydpi
+ try:
+ iter(dpi)
+ except TypeError:
+ dpi = (dpi, dpi)
+ else:
+ imageobj = None
+ if width is None or height is None:
+ if imageobj is None:
+ raise RuntimeError(
+ 'image size not fully specified and PIL not installed')
+ if width is None:
+ width = imageobj.size[0]
+ width = float(width) * 0.026 # convert px to cm
+ if height is None:
+ height = imageobj.size[1]
+ height = float(height) * 0.026 # convert px to cm
+ if width_unit == '%':
+ factor = width
+ image_width = imageobj.size[0]
+ image_width = float(image_width) * 0.026 # convert px to cm
+ image_height = imageobj.size[1]
+ image_height = float(image_height) * 0.026 # convert px to cm
+ line_width = self.get_page_width()
+ width = factor * line_width
+ factor = (factor * line_width) / image_width
+ height = factor * image_height
+ width *= scale
+ height *= scale
+ width = '%.2fcm' % width
+ height = '%.2fcm' % height
+ return width, height
+
+ def get_page_width(self):
+ """Return the document's page width in centimeters."""
+ root = self.get_dom_stylesheet()
+ nodes = root.iterfind(
+ './/{urn:oasis:names:tc:opendocument:xmlns:style:1.0}'
+ 'page-layout/'
+ '{urn:oasis:names:tc:opendocument:xmlns:style:1.0}'
+ 'page-layout-properties')
+ width = None
+ for node in nodes:
+ page_width = node.get(
+ '{urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0}'
+ 'page-width')
+ margin_left = node.get(
+ '{urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0}'
+ 'margin-left')
+ margin_right = node.get(
+ '{urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0}'
+ 'margin-right')
+ if (page_width is None or
+ margin_left is None or
+ margin_right is None):
+ continue
+ try:
+ page_width, _ = self.convert_to_cm(page_width)
+ margin_left, _ = self.convert_to_cm(margin_left)
+ margin_right, _ = self.convert_to_cm(margin_right)
+ except ValueError:
+ self.document.reporter.warning(
+ 'Stylesheet file contains invalid page width '
+ 'or margin size.')
+ width = page_width - margin_left - margin_right
+ if width is None:
+ # We can't find the width in styles, so we make a guess.
+ # Use a width of 6 in = 15.24 cm.
+ width = 15.24
+ return width
+
+ def generate_figure(self, node, source, destination, current_element):
+ caption = None
+ width, height = self.get_image_scaled_width_height(node, source)
+ for node1 in node.parent.children:
+ if node1.tagname == 'caption':
+ caption = node1.astext()
+ self.image_style_count += 1
+ #
+ # Add the style for the caption.
+ if caption is not None:
+ attrib = {
+ 'style:class': 'extra',
+ 'style:family': 'paragraph',
+ 'style:name': 'Caption',
+ 'style:parent-style-name': 'Standard',
+ }
+ el1 = SubElement(self.automatic_styles, 'style:style',
+ attrib=attrib, nsdict=SNSD)
+ attrib = {
+ 'fo:margin-bottom': '0.0835in',
+ 'fo:margin-top': '0.0835in',
+ 'text:line-number': '0',
+ 'text:number-lines': 'false',
+ }
+ SubElement(el1, 'style:paragraph-properties',
+ attrib=attrib, nsdict=SNSD)
+ attrib = {
+ 'fo:font-size': '12pt',
+ 'fo:font-style': 'italic',
+ 'style:font-name': 'Times',
+ 'style:font-name-complex': 'Lucidasans1',
+ 'style:font-size-asian': '12pt',
+ 'style:font-size-complex': '12pt',
+ 'style:font-style-asian': 'italic',
+ 'style:font-style-complex': 'italic',
+ }
+ SubElement(el1, 'style:text-properties',
+ attrib=attrib, nsdict=SNSD)
+ style_name = 'rstframestyle%d' % self.image_style_count
+ draw_name = 'graphics%d' % next(IMAGE_NAME_COUNTER)
+ # Add the styles
+ attrib = {
+ 'style:name': style_name,
+ 'style:family': 'graphic',
+ 'style:parent-style-name': self.rststyle('figureframe'),
+ }
+ el1 = SubElement(self.automatic_styles,
+ 'style:style', attrib=attrib, nsdict=SNSD)
+ attrib = {}
+ wrap = False
+ classes = node.parent.attributes.get('classes')
+ if classes and 'wrap' in classes:
+ wrap = True
+ if wrap:
+ attrib['style:wrap'] = 'dynamic'
+ else:
+ attrib['style:wrap'] = 'none'
+ SubElement(el1, 'style:graphic-properties',
+ attrib=attrib, nsdict=SNSD)
+ attrib = {
+ 'draw:style-name': style_name,
+ 'draw:name': draw_name,
+ 'text:anchor-type': 'paragraph',
+ 'draw:z-index': '0',
+ }
+ attrib['svg:width'] = width
+ el3 = SubElement(current_element, 'draw:frame', attrib=attrib)
+ attrib = {}
+ el4 = SubElement(el3, 'draw:text-box', attrib=attrib)
+ attrib = {
+ 'text:style-name': self.rststyle('caption'),
+ }
+ el5 = SubElement(el4, 'text:p', attrib=attrib)
+ return el3, el4, el5, caption
+
+ def generate_image(self, node, source, destination, current_element,
+ frame_attrs=None):
+ width, height = self.get_image_scaled_width_height(node, source)
+ self.image_style_count += 1
+ style_name = 'rstframestyle%d' % self.image_style_count
+ # Add the style.
+ attrib = {
+ 'style:name': style_name,
+ 'style:family': 'graphic',
+ 'style:parent-style-name': self.rststyle('image'),
+ }
+ el1 = SubElement(self.automatic_styles,
+ 'style:style', attrib=attrib, nsdict=SNSD)
+ halign = None
+ valign = None
+ if 'align' in node.attributes:
+ align = node.attributes['align'].split()
+ for val in align:
+ if val in ('left', 'center', 'right'):
+ halign = val
+ elif val in ('top', 'middle', 'bottom'):
+ valign = val
+ if frame_attrs is None:
+ attrib = {
+ 'style:vertical-pos': 'top',
+ 'style:vertical-rel': 'paragraph',
+ 'style:horizontal-rel': 'paragraph',
+ 'style:mirror': 'none',
+ 'fo:clip': 'rect(0cm 0cm 0cm 0cm)',
+ 'draw:luminance': '0%',
+ 'draw:contrast': '0%',
+ 'draw:red': '0%',
+ 'draw:green': '0%',
+ 'draw:blue': '0%',
+ 'draw:gamma': '100%',
+ 'draw:color-inversion': 'false',
+ 'draw:image-opacity': '100%',
+ 'draw:color-mode': 'standard',
+ }
+ else:
+ attrib = frame_attrs
+ if halign is not None:
+ attrib['style:horizontal-pos'] = halign
+ if valign is not None:
+ attrib['style:vertical-pos'] = valign
+ # If there is a classes/wrap directive or we are
+ # inside a table, add a no-wrap style.
+ wrap = False
+ classes = node.attributes.get('classes')
+ if classes and 'wrap' in classes:
+ wrap = True
+ if wrap:
+ attrib['style:wrap'] = 'dynamic'
+ else:
+ attrib['style:wrap'] = 'none'
+ # If we are inside a table, add a no-wrap style.
+ if self.is_in_table(node):
+ attrib['style:wrap'] = 'none'
+ SubElement(el1, 'style:graphic-properties',
+ attrib=attrib, nsdict=SNSD)
+ draw_name = 'graphics%d' % next(IMAGE_NAME_COUNTER)
+ # Add the content.
+ #el = SubElement(current_element, 'text:p',
+ # attrib={'text:style-name': self.rststyle('textbody')})
+ attrib = {
+ 'draw:style-name': style_name,
+ 'draw:name': draw_name,
+ 'draw:z-index': '1',
+ }
+ if isinstance(node.parent, nodes.TextElement):
+ attrib['text:anchor-type'] = 'as-char' # vds
+ else:
+ attrib['text:anchor-type'] = 'paragraph'
+ attrib['svg:width'] = width
+ attrib['svg:height'] = height
+ el1 = SubElement(current_element, 'draw:frame', attrib=attrib)
+ SubElement(el1, 'draw:image', attrib={
+ 'xlink:href': '%s' % (destination, ),
+ 'xlink:type': 'simple',
+ 'xlink:show': 'embed',
+ 'xlink:actuate': 'onLoad',
+ })
+ return el1, width
+
+ def is_in_table(self, node):
+ node1 = node.parent
+ while node1:
+ if isinstance(node1, docutils.nodes.entry):
+ return True
+ node1 = node1.parent
+ return False
+
+ def visit_legend(self, node):
+ if isinstance(node.parent, docutils.nodes.figure):
+ el1 = self.current_element[-1]
+ el1 = el1[0][0]
+ self.current_element = el1
+ self.paragraph_style_stack.append(self.rststyle('legend'))
+
+ def depart_legend(self, node):
+ if isinstance(node.parent, docutils.nodes.figure):
+ self.paragraph_style_stack.pop()
+ self.set_to_parent()
+ self.set_to_parent()
+ self.set_to_parent()
+
+ def visit_line_block(self, node):
+ self.line_indent_level += 1
+ self.line_block_level += 1
+
+ def depart_line_block(self, node):
+ self.line_indent_level -= 1
+ self.line_block_level -= 1
+
+ def visit_line(self, node):
+ style = 'lineblock%d' % self.line_indent_level
+ el1 = SubElement(self.current_element, 'text:p',
+ attrib={'text:style-name': self.rststyle(style), })
+ self.current_element = el1
+
+ def depart_line(self, node):
+ self.set_to_parent()
+
+ def visit_literal(self, node):
+ el = SubElement(
+ self.current_element, 'text:span',
+ attrib={'text:style-name': self.rststyle('inlineliteral')})
+ self.set_current_element(el)
+
+ def depart_literal(self, node):
+ self.set_to_parent()
+
+ def visit_inline(self, node):
+ styles = node.attributes.get('classes', ())
+ if styles:
+ el = self.current_element
+ for inline_style in styles:
+ el = SubElement(el, 'text:span',
+ attrib={'text:style-name':
+ self.rststyle(inline_style)})
+ count = len(styles)
+ else:
+ # No style was specified so use a default style (old code
+ # crashed if no style was given)
+ el = SubElement(self.current_element, 'text:span')
+ count = 1
+
+ self.set_current_element(el)
+ self.inline_style_count_stack.append(count)
+
+ def depart_inline(self, node):
+ count = self.inline_style_count_stack.pop()
+ for x in range(count):
+ self.set_to_parent()
+
+ def _calculate_code_block_padding(self, line):
+ count = 0
+ matchobj = SPACES_PATTERN.match(line)
+ if matchobj:
+ pad = matchobj.group()
+ count = len(pad)
+ else:
+ matchobj = TABS_PATTERN.match(line)
+ if matchobj:
+ pad = matchobj.group()
+ count = len(pad) * 8
+ return count
+
+ def _add_syntax_highlighting(self, insource, language):
+ lexer = pygments.lexers.get_lexer_by_name(language, stripall=True)
+ if language in ('latex', 'tex'):
+ fmtr = OdtPygmentsLaTeXFormatter(
+ lambda name, parameters=():
+ self.rststyle(name, parameters),
+ escape_function=escape_cdata)
+ else:
+ fmtr = OdtPygmentsProgFormatter(
+ lambda name, parameters=():
+ self.rststyle(name, parameters),
+ escape_function=escape_cdata)
+ outsource = pygments.highlight(insource, lexer, fmtr)
+ return outsource
+
+ def fill_line(self, line):
+ line = FILL_PAT1.sub(self.fill_func1, line)
+ line = FILL_PAT2.sub(self.fill_func2, line)
+ return line
+
+ def fill_func1(self, matchobj):
+ spaces = matchobj.group(0)
+ repl = '<text:s text:c="%d"/>' % (len(spaces), )
+ return repl
+
+ def fill_func2(self, matchobj):
+ spaces = matchobj.group(0)
+ repl = ' <text:s text:c="%d"/>' % (len(spaces) - 1, )
+ return repl
+
+ def visit_literal_block(self, node):
+ if len(self.paragraph_style_stack) > 1:
+ wrapper1 = '<text:p text:style-name="%s">%%s</text:p>' % (
+ self.rststyle('codeblock-indented'), )
+ else:
+ wrapper1 = '<text:p text:style-name="%s">%%s</text:p>' % (
+ self.rststyle('codeblock'), )
+ source = node.astext()
+ if (
+ pygments and
+ self.settings.add_syntax_highlighting
+ #and
+ #node.get('hilight', False)
+ ):
+ language = node.get('language', 'python')
+ source = self._add_syntax_highlighting(source, language)
+ else:
+ source = escape_cdata(source)
+ lines = source.split('\n')
+ # If there is an empty last line, remove it.
+ if lines[-1] == '':
+ del lines[-1]
+ lines1 = ['<wrappertag1 xmlns:text="urn:oasis:names:tc:'
+ 'opendocument:xmlns:text:1.0">']
+ my_lines = []
+ for my_line in lines:
+ my_line = self.fill_line(my_line)
+ my_line = my_line.replace(" ", "\n")
+ my_lines.append(my_line)
+ my_lines_str = '<text:line-break/>'.join(my_lines)
+ my_lines_str2 = wrapper1 % (my_lines_str, )
+ lines1.append(my_lines_str2)
+ lines1.append('</wrappertag1>')
+ s1 = ''.join(lines1)
+ s1 = s1.encode("utf-8")
+ el1 = etree.fromstring(s1)
+ for child in el1:
+ self.current_element.append(child)
+
+ def depart_literal_block(self, node):
+ pass
+
+ visit_doctest_block = visit_literal_block
+ depart_doctest_block = depart_literal_block
+
+ # placeholder for math (see docs/dev/todo.txt)
+ def visit_math(self, node):
+ self.document.reporter.warning('"math" role not supported',
+ base_node=node)
+ self.visit_literal(node)
+
+ def depart_math(self, node):
+ self.depart_literal(node)
+
+ def visit_math_block(self, node):
+ self.document.reporter.warning('"math" directive not supported',
+ base_node=node)
+ self.visit_literal_block(node)
+
+ def depart_math_block(self, node):
+ self.depart_literal_block(node)
+
+ def visit_meta(self, node):
+ name = node.attributes.get('name')
+ content = node.attributes.get('content')
+ if name is not None and content is not None:
+ self.meta_dict[name] = content
+
+ def depart_meta(self, node):
+ pass
+
+ def visit_option_list(self, node):
+ table_name = 'tableoption'
+ #
+ # Generate automatic styles
+ if not self.optiontablestyles_generated:
+ self.optiontablestyles_generated = True
+ el = SubElement(self.automatic_styles, 'style:style', attrib={
+ 'style:name': self.rststyle(table_name),
+ 'style:family': 'table'}, nsdict=SNSD)
+ el1 = SubElement(el, 'style:table-properties', attrib={
+ 'style:width': '17.59cm',
+ 'table:align': 'left',
+ 'style:shadow': 'none'}, nsdict=SNSD)
+ el = SubElement(self.automatic_styles, 'style:style', attrib={
+ 'style:name': self.rststyle('%s.%%c' % table_name, ('A', )),
+ 'style:family': 'table-column'}, nsdict=SNSD)
+ el1 = SubElement(el, 'style:table-column-properties', attrib={
+ 'style:column-width': '4.999cm'}, nsdict=SNSD)
+ el = SubElement(self.automatic_styles, 'style:style', attrib={
+ 'style:name': self.rststyle('%s.%%c' % table_name, ('B', )),
+ 'style:family': 'table-column'}, nsdict=SNSD)
+ el1 = SubElement(el, 'style:table-column-properties', attrib={
+ 'style:column-width': '12.587cm'}, nsdict=SNSD)
+ el = SubElement(self.automatic_styles, 'style:style', attrib={
+ 'style:name': self.rststyle(
+ '%s.%%c%%d' % table_name, ('A', 1, )),
+ 'style:family': 'table-cell'}, nsdict=SNSD)
+ el1 = SubElement(el, 'style:table-cell-properties', attrib={
+ 'fo:background-color': 'transparent',
+ 'fo:padding': '0.097cm',
+ 'fo:border-left': '0.035cm solid #000000',
+ 'fo:border-right': 'none',
+ 'fo:border-top': '0.035cm solid #000000',
+ 'fo:border-bottom': '0.035cm solid #000000'}, nsdict=SNSD)
+ el2 = SubElement(el1, 'style:background-image', nsdict=SNSD)
+ el = SubElement(self.automatic_styles, 'style:style', attrib={
+ 'style:name': self.rststyle(
+ '%s.%%c%%d' % table_name, ('B', 1, )),
+ 'style:family': 'table-cell'}, nsdict=SNSD)
+ el1 = SubElement(el, 'style:table-cell-properties', attrib={
+ 'fo:padding': '0.097cm',
+ 'fo:border': '0.035cm solid #000000'}, nsdict=SNSD)
+ el = SubElement(self.automatic_styles, 'style:style', attrib={
+ 'style:name': self.rststyle(
+ '%s.%%c%%d' % table_name, ('A', 2, )),
+ 'style:family': 'table-cell'}, nsdict=SNSD)
+ el1 = SubElement(el, 'style:table-cell-properties', attrib={
+ 'fo:padding': '0.097cm',
+ 'fo:border-left': '0.035cm solid #000000',
+ 'fo:border-right': 'none',
+ 'fo:border-top': 'none',
+ 'fo:border-bottom': '0.035cm solid #000000'}, nsdict=SNSD)
+ el = SubElement(self.automatic_styles, 'style:style', attrib={
+ 'style:name': self.rststyle(
+ '%s.%%c%%d' % table_name, ('B', 2, )),
+ 'style:family': 'table-cell'}, nsdict=SNSD)
+ el1 = SubElement(el, 'style:table-cell-properties', attrib={
+ 'fo:padding': '0.097cm',
+ 'fo:border-left': '0.035cm solid #000000',
+ 'fo:border-right': '0.035cm solid #000000',
+ 'fo:border-top': 'none',
+ 'fo:border-bottom': '0.035cm solid #000000'}, nsdict=SNSD)
+ #
+ # Generate table data
+ el = self.append_child('table:table', attrib={
+ 'table:name': self.rststyle(table_name),
+ 'table:style-name': self.rststyle(table_name),
+ })
+ el1 = SubElement(el, 'table:table-column', attrib={
+ 'table:style-name': self.rststyle(
+ '%s.%%c' % table_name, ('A', ))})
+ el1 = SubElement(el, 'table:table-column', attrib={
+ 'table:style-name': self.rststyle(
+ '%s.%%c' % table_name, ('B', ))})
+ el1 = SubElement(el, 'table:table-header-rows')
+ el2 = SubElement(el1, 'table:table-row')
+ el3 = SubElement(el2, 'table:table-cell', attrib={
+ 'table:style-name': self.rststyle(
+ '%s.%%c%%d' % table_name, ('A', 1, )),
+ 'office:value-type': 'string'})
+ el4 = SubElement(el3, 'text:p', attrib={
+ 'text:style-name': 'Table_20_Heading'})
+ el4.text = 'Option'
+ el3 = SubElement(el2, 'table:table-cell', attrib={
+ 'table:style-name': self.rststyle(
+ '%s.%%c%%d' % table_name, ('B', 1, )),
+ 'office:value-type': 'string'})
+ el4 = SubElement(el3, 'text:p', attrib={
+ 'text:style-name': 'Table_20_Heading'})
+ el4.text = 'Description'
+ self.set_current_element(el)
+
+ def depart_option_list(self, node):
+ self.set_to_parent()
+
+ def visit_option_list_item(self, node):
+ el = self.append_child('table:table-row')
+ self.set_current_element(el)
+
+ def depart_option_list_item(self, node):
+ self.set_to_parent()
+
+ def visit_option_group(self, node):
+ el = self.append_child('table:table-cell', attrib={
+ 'table:style-name': 'Table%d.A2' % self.table_count,
+ 'office:value-type': 'string',
+ })
+ self.set_current_element(el)
+
+ def depart_option_group(self, node):
+ self.set_to_parent()
+
+ def visit_option(self, node):
+ el = self.append_child('text:p', attrib={
+ 'text:style-name': 'Table_20_Contents'})
+ el.text = node.astext()
+
+ def depart_option(self, node):
+ pass
+
+ def visit_option_string(self, node):
+ pass
+
+ def depart_option_string(self, node):
+ pass
+
+ def visit_option_argument(self, node):
+ pass
+
+ def depart_option_argument(self, node):
+ pass
+
+ def visit_description(self, node):
+ el = self.append_child('table:table-cell', attrib={
+ 'table:style-name': 'Table%d.B2' % self.table_count,
+ 'office:value-type': 'string',
+ })
+ el1 = SubElement(el, 'text:p', attrib={
+ 'text:style-name': 'Table_20_Contents'})
+ el1.text = node.astext()
+ raise nodes.SkipChildren()
+
+ def depart_description(self, node):
+ pass
+
+ def visit_paragraph(self, node):
+ self.in_paragraph = True
+ if self.in_header:
+ el = self.append_p('header')
+ elif self.in_footer:
+ el = self.append_p('footer')
+ else:
+ style_name = self.paragraph_style_stack[-1]
+ el = self.append_child(
+ 'text:p',
+ attrib={'text:style-name': style_name})
+ self.append_pending_ids(el)
+ self.set_current_element(el)
+
+ def depart_paragraph(self, node):
+ self.in_paragraph = False
+ self.set_to_parent()
+ if self.in_header:
+ self.header_content.append( self.current_element[-1] )
+ self.current_element.remove( self.current_element[-1] )
+ elif self.in_footer:
+ self.footer_content.append( self.current_element[-1] )
+ self.current_element.remove( self.current_element[-1] )
+
+ def visit_problematic(self, node):
+ pass
+
+ def depart_problematic(self, node):
+ pass
+
+ def visit_raw(self, node):
+ if 'format' in node.attributes:
+ formats = node.attributes['format']
+ formatlist = formats.split()
+ if 'odt' in formatlist:
+ rawstr = node.astext()
+ attrstr = ' '.join([
+ '%s="%s"' % (k, v, )
+ for k, v in list(CONTENT_NAMESPACE_ATTRIB.items())])
+ contentstr = '<stuff %s>%s</stuff>' % (attrstr, rawstr, )
+ contentstr = contentstr.encode("utf-8")
+ content = etree.fromstring(contentstr)
+ if len(content) > 0:
+ el1 = content[0]
+ if self.in_header:
+ pass
+ elif self.in_footer:
+ pass
+ else:
+ self.current_element.append(el1)
+ raise nodes.SkipChildren()
+
+ def depart_raw(self, node):
+ if self.in_header:
+ pass
+ elif self.in_footer:
+ pass
+ else:
+ pass
+
+ def visit_reference(self, node):
+ #text = node.astext()
+ if self.settings.create_links:
+ if 'refuri' in node:
+ href = node['refuri']
+ if (
+ self.settings.cloak_email_addresses and
+ href.startswith('mailto:')):
+ href = self.cloak_mailto(href)
+ el = self.append_child('text:a', attrib={
+ 'xlink:href': '%s' % href,
+ 'xlink:type': 'simple',
+ })
+ self.set_current_element(el)
+ elif 'refid' in node:
+ if self.settings.create_links:
+ href = node['refid']
+ el = self.append_child('text:reference-ref', attrib={
+ 'text:ref-name': '%s' % href,
+ 'text:reference-format': 'text',
+ })
+ else:
+ self.document.reporter.warning(
+ 'References must have "refuri" or "refid" attribute.')
+ if (
+ self.in_table_of_contents and
+ len(node.children) >= 1 and
+ isinstance(node.children[0], docutils.nodes.generated)):
+ node.remove(node.children[0])
+
+ def depart_reference(self, node):
+ if self.settings.create_links:
+ if 'refuri' in node:
+ self.set_to_parent()
+
+ def visit_rubric(self, node):
+ style_name = self.rststyle('rubric')
+ classes = node.get('classes')
+ if classes:
+ class1 = classes[0]
+ if class1:
+ style_name = class1
+ el = SubElement(self.current_element, 'text:h', attrib={
+ #'text:outline-level': '%d' % section_level,
+ #'text:style-name': 'Heading_20_%d' % section_level,
+ 'text:style-name': style_name,
+ })
+ text = node.astext()
+ el.text = self.encode(text)
+
+ def depart_rubric(self, node):
+ pass
+
+ def visit_section(self, node, move_ids=1):
+ self.section_level += 1
+ self.section_count += 1
+ if self.settings.create_sections:
+ el = self.append_child('text:section', attrib={
+ 'text:name': 'Section%d' % self.section_count,
+ 'text:style-name': 'Sect%d' % self.section_level,
+ })
+ self.set_current_element(el)
+
+ def depart_section(self, node):
+ self.section_level -= 1
+ if self.settings.create_sections:
+ self.set_to_parent()
+
+ def visit_strong(self, node):
+ el = SubElement(self.current_element, 'text:span',
+ attrib={'text:style-name': self.rststyle('strong')})
+ self.set_current_element(el)
+
+ def depart_strong(self, node):
+ self.set_to_parent()
+
+ def visit_substitution_definition(self, node):
+ raise nodes.SkipChildren()
+
+ def depart_substitution_definition(self, node):
+ pass
+
+ def visit_system_message(self, node):
+ pass
+
+ def depart_system_message(self, node):
+ pass
+
+ def get_table_style(self, node):
+ table_style = None
+ table_name = None
+ str_classes = node.get('classes')
+ if str_classes is not None:
+ for str_class in str_classes:
+ if str_class.startswith(TABLESTYLEPREFIX):
+ table_name = str_class
+ break
+ if table_name is not None:
+ table_style = self.table_styles.get(table_name)
+ if table_style is None:
+ # If we can't find the table style, issue warning
+ # and use the default table style.
+ self.document.reporter.warning(
+ 'Can\'t find table style "%s". Using default.' % (
+ table_name, ))
+ table_name = TABLENAMEDEFAULT
+ table_style = self.table_styles.get(table_name)
+ if table_style is None:
+ # If we can't find the default table style, issue a warning
+ # and use a built-in default style.
+ self.document.reporter.warning(
+ 'Can\'t find default table style "%s". '
+ 'Using built-in default.' % (
+ table_name, ))
+ table_style = BUILTIN_DEFAULT_TABLE_STYLE
+ else:
+ table_name = TABLENAMEDEFAULT
+ table_style = self.table_styles.get(table_name)
+ if table_style is None:
+ # If we can't find the default table style, issue a warning
+ # and use a built-in default style.
+ self.document.reporter.warning(
+ 'Can\'t find default table style "%s". '
+ 'Using built-in default.' % (
+ table_name, ))
+ table_style = BUILTIN_DEFAULT_TABLE_STYLE
+ return table_style
+
+ def visit_table(self, node):
+ self.table_count += 1
+ table_style = self.get_table_style(node)
+ table_name = '%s%%d' % TABLESTYLEPREFIX
+ el1 = SubElement(self.automatic_styles, 'style:style', attrib={
+ 'style:name': self.rststyle(
+ '%s' % table_name, (self.table_count, )),
+ 'style:family': 'table',
+ }, nsdict=SNSD)
+ if table_style.backgroundcolor is None:
+ SubElement(el1, 'style:table-properties', attrib={
+ #'style:width': '17.59cm',
+ #'table:align': 'margins',
+ 'table:align': 'left',
+ 'fo:margin-top': '0in',
+ 'fo:margin-bottom': '0.10in',
+ }, nsdict=SNSD)
+ else:
+ SubElement(el1, 'style:table-properties', attrib={
+ #'style:width': '17.59cm',
+ 'table:align': 'margins',
+ 'fo:margin-top': '0in',
+ 'fo:margin-bottom': '0.10in',
+ 'fo:background-color': table_style.backgroundcolor,
+ }, nsdict=SNSD)
+ # We use a single cell style for all cells in this table.
+ # That's probably not correct, but seems to work.
+ el2 = SubElement(self.automatic_styles, 'style:style', attrib={
+ 'style:name': self.rststyle(
+ '%s.%%c%%d' % table_name, (self.table_count, 'A', 1, )),
+ 'style:family': 'table-cell',
+ }, nsdict=SNSD)
+ thickness = self.settings.table_border_thickness
+ if thickness is None:
+ line_style1 = table_style.border
+ else:
+ line_style1 = '0.%03dcm solid #000000' % (thickness, )
+ SubElement(el2, 'style:table-cell-properties', attrib={
+ 'fo:padding': '0.049cm',
+ 'fo:border-left': line_style1,
+ 'fo:border-right': line_style1,
+ 'fo:border-top': line_style1,
+ 'fo:border-bottom': line_style1,
+ }, nsdict=SNSD)
+ title = None
+ for child in node.children:
+ if child.tagname == 'title':
+ title = child.astext()
+ break
+ if title is not None:
+ self.append_p('table-title', title)
+ else:
+ pass
+ el4 = SubElement(self.current_element, 'table:table', attrib={
+ 'table:name': self.rststyle(
+ '%s' % table_name, (self.table_count, )),
+ 'table:style-name': self.rststyle(
+ '%s' % table_name, (self.table_count, )),
+ })
+ self.set_current_element(el4)
+ self.current_table_style = el1
+ self.table_width = 0.0
+
+ def depart_table(self, node):
+ attribkey = add_ns('style:width', nsdict=SNSD)
+ attribval = '%.4fin' % (self.table_width, )
+ el1 = self.current_table_style
+ el2 = el1[0]
+ el2.attrib[attribkey] = attribval
+ self.set_to_parent()
+
+ def visit_tgroup(self, node):
+ self.column_count = ord('A') - 1
+
+ def depart_tgroup(self, node):
+ pass
+
+ def visit_colspec(self, node):
+ self.column_count += 1
+ colspec_name = self.rststyle(
+ '%s%%d.%%s' % TABLESTYLEPREFIX,
+ (self.table_count, chr(self.column_count), )
+ )
+ colwidth = node['colwidth'] / 12.0
+ el1 = SubElement(self.automatic_styles, 'style:style', attrib={
+ 'style:name': colspec_name,
+ 'style:family': 'table-column',
+ }, nsdict=SNSD)
+ SubElement(el1, 'style:table-column-properties',
+ attrib={'style:column-width': '%.4fin' % colwidth},
+ nsdict=SNSD)
+ self.append_child('table:table-column',
+ attrib={'table:style-name': colspec_name, })
+ self.table_width += colwidth
+
+ def depart_colspec(self, node):
+ pass
+
+ def visit_thead(self, node):
+ el = self.append_child('table:table-header-rows')
+ self.set_current_element(el)
+ self.in_thead = True
+ self.paragraph_style_stack.append('Table_20_Heading')
+
+ def depart_thead(self, node):
+ self.set_to_parent()
+ self.in_thead = False
+ self.paragraph_style_stack.pop()
+
+ def visit_row(self, node):
+ self.column_count = ord('A') - 1
+ el = self.append_child('table:table-row')
+ self.set_current_element(el)
+
+ def depart_row(self, node):
+ self.set_to_parent()
+
+ def visit_entry(self, node):
+ self.column_count += 1
+ cellspec_name = self.rststyle(
+ '%s%%d.%%c%%d' % TABLESTYLEPREFIX,
+ (self.table_count, 'A', 1, )
+ )
+ attrib = {
+ 'table:style-name': cellspec_name,
+ 'office:value-type': 'string',
+ }
+ morecols = node.get('morecols', 0)
+ if morecols > 0:
+ attrib['table:number-columns-spanned'] = '%d' % (morecols + 1,)
+ self.column_count += morecols
+ morerows = node.get('morerows', 0)
+ if morerows > 0:
+ attrib['table:number-rows-spanned'] = '%d' % (morerows + 1,)
+ el1 = self.append_child('table:table-cell', attrib=attrib)
+ self.set_current_element(el1)
+
+ def depart_entry(self, node):
+ self.set_to_parent()
+
+ def visit_tbody(self, node):
+ pass
+
+ def depart_tbody(self, node):
+ pass
+
+ def visit_target(self, node):
+ #
+ # I don't know how to implement targets in ODF.
+ # How do we create a target in oowriter? A cross-reference?
+ if not ('refuri' in node or
+ 'refid' in node or
+ 'refname' in node):
+ pass
+ else:
+ pass
+
+ def depart_target(self, node):
+ pass
+
+ def visit_title(self, node, move_ids=1, title_type='title'):
+ if isinstance(node.parent, docutils.nodes.section):
+ section_level = self.section_level
+ if section_level > 7:
+ self.document.reporter.warning(
+ 'Heading/section levels greater than 7 not supported.')
+ self.document.reporter.warning(
+ ' Reducing to heading level 7 for heading: "%s"' % (
+ node.astext(), ))
+ section_level = 7
+ el1 = self.append_child(
+ 'text:h', attrib={
+ 'text:outline-level': '%d' % section_level,
+ #'text:style-name': 'Heading_20_%d' % section_level,
+ 'text:style-name': self.rststyle(
+ 'heading%d', (section_level, )),
+ })
+ self.append_pending_ids(el1)
+ self.set_current_element(el1)
+ elif isinstance(node.parent, docutils.nodes.document):
+ # text = self.settings.title
+ #else:
+ # text = node.astext()
+ el1 = SubElement(self.current_element, 'text:p', attrib={
+ 'text:style-name': self.rststyle(title_type),
+ })
+ self.append_pending_ids(el1)
+ text = node.astext()
+ self.title = text
+ self.found_doc_title = True
+ self.set_current_element(el1)
+
+ def depart_title(self, node):
+ if (
+ isinstance(node.parent, docutils.nodes.section) or
+ isinstance(node.parent, docutils.nodes.document)):
+ self.set_to_parent()
+
+ def visit_subtitle(self, node, move_ids=1):
+ self.visit_title(node, move_ids, title_type='subtitle')
+
+ def depart_subtitle(self, node):
+ self.depart_title(node)
+
+ def visit_title_reference(self, node):
+ el = self.append_child('text:span', attrib={
+ 'text:style-name': self.rststyle('quotation')})
+ el.text = self.encode(node.astext())
+ raise nodes.SkipChildren()
+
+ def depart_title_reference(self, node):
+ pass
+
+ def generate_table_of_content_entry_template(self, el1):
+ for idx in range(1, 11):
+ el2 = SubElement(
+ el1,
+ 'text:table-of-content-entry-template',
+ attrib={
+ 'text:outline-level': "%d" % (idx, ),
+ 'text:style-name': self.rststyle('contents-%d' % (idx, )),
+ })
+ SubElement(el2, 'text:index-entry-chapter')
+ SubElement(el2, 'text:index-entry-text')
+ SubElement(el2, 'text:index-entry-tab-stop', attrib={
+ 'style:leader-char': ".",
+ 'style:type': "right",
+ })
+ SubElement(el2, 'text:index-entry-page-number')
+
+ def find_title_label(self, node, class_type, label_key):
+ label = ''
+ title_node = None
+ for child in node.children:
+ if isinstance(child, class_type):
+ title_node = child
+ break
+ if title_node is not None:
+ label = title_node.astext()
+ else:
+ label = self.language.labels[label_key]
+ return label
+
+ def visit_topic(self, node):
+ if 'classes' in node.attributes:
+ if 'contents' in node.attributes['classes']:
+ label = self.find_title_label(
+ node, docutils.nodes.title, 'contents')
+ if self.settings.generate_oowriter_toc:
+ el1 = self.append_child('text:table-of-content', attrib={
+ 'text:name': 'Table of Contents1',
+ 'text:protected': 'true',
+ 'text:style-name': 'Sect1',
+ })
+ el2 = SubElement(
+ el1,
+ 'text:table-of-content-source',
+ attrib={
+ 'text:outline-level': '10',
+ })
+ el3 = SubElement(el2, 'text:index-title-template', attrib={
+ 'text:style-name': 'Contents_20_Heading',
+ })
+ el3.text = label
+ self.generate_table_of_content_entry_template(el2)
+ el4 = SubElement(el1, 'text:index-body')
+ el5 = SubElement(el4, 'text:index-title')
+ el6 = SubElement(el5, 'text:p', attrib={
+ 'text:style-name': self.rststyle('contents-heading'),
+ })
+ el6.text = label
+ self.save_current_element = self.current_element
+ self.table_of_content_index_body = el4
+ self.set_current_element(el4)
+ else:
+ el = self.append_p('horizontalline')
+ el = self.append_p('centeredtextbody')
+ el1 = SubElement(
+ el, 'text:span',
+ attrib={'text:style-name': self.rststyle('strong')})
+ el1.text = label
+ self.in_table_of_contents = True
+ elif 'abstract' in node.attributes['classes']:
+ el = self.append_p('horizontalline')
+ el = self.append_p('centeredtextbody')
+ el1 = SubElement(
+ el, 'text:span',
+ attrib={'text:style-name': self.rststyle('strong')})
+ label = self.find_title_label(
+ node, docutils.nodes.title,
+ 'abstract')
+ el1.text = label
+ elif 'dedication' in node.attributes['classes']:
+ el = self.append_p('horizontalline')
+ el = self.append_p('centeredtextbody')
+ el1 = SubElement(
+ el, 'text:span',
+ attrib={'text:style-name': self.rststyle('strong')})
+ label = self.find_title_label(
+ node, docutils.nodes.title,
+ 'dedication')
+ el1.text = label
+
+ def depart_topic(self, node):
+ if 'classes' in node.attributes:
+ if 'contents' in node.attributes['classes']:
+ if self.settings.generate_oowriter_toc:
+ self.update_toc_page_numbers(
+ self.table_of_content_index_body)
+ self.set_current_element(self.save_current_element)
+ else:
+ self.append_p('horizontalline')
+ self.in_table_of_contents = False
+
+ def update_toc_page_numbers(self, el):
+ collection = []
+ self.update_toc_collect(el, 0, collection)
+ self.update_toc_add_numbers(collection)
+
+ def update_toc_collect(self, el, level, collection):
+ collection.append((level, el))
+ level += 1
+ for child_el in el:
+ if child_el.tag != 'text:index-body':
+ self.update_toc_collect(child_el, level, collection)
+
+ def update_toc_add_numbers(self, collection):
+ for level, el1 in collection:
+ if (
+ el1.tag == 'text:p' and
+ el1.text != 'Table of Contents'):
+ el2 = SubElement(el1, 'text:tab')
+ el2.tail = '9999'
+
+ def visit_transition(self, node):
+ self.append_p('horizontalline')
+
+ def depart_transition(self, node):
+ pass
+
+ #
+ # Admonitions
+ #
+ def visit_warning(self, node):
+ self.generate_admonition(node, 'warning')
+
+ def depart_warning(self, node):
+ self.paragraph_style_stack.pop()
+
+ def visit_attention(self, node):
+ self.generate_admonition(node, 'attention')
+
+ depart_attention = depart_warning
+
+ def visit_caution(self, node):
+ self.generate_admonition(node, 'caution')
+
+ depart_caution = depart_warning
+
+ def visit_danger(self, node):
+ self.generate_admonition(node, 'danger')
+
+ depart_danger = depart_warning
+
+ def visit_error(self, node):
+ self.generate_admonition(node, 'error')
+
+ depart_error = depart_warning
+
+ def visit_hint(self, node):
+ self.generate_admonition(node, 'hint')
+
+ depart_hint = depart_warning
+
+ def visit_important(self, node):
+ self.generate_admonition(node, 'important')
+
+ depart_important = depart_warning
+
+ def visit_note(self, node):
+ self.generate_admonition(node, 'note')
+
+ depart_note = depart_warning
+
+ def visit_tip(self, node):
+ self.generate_admonition(node, 'tip')
+
+ depart_tip = depart_warning
+
+ def visit_admonition(self, node):
+ title = None
+ for child in node.children:
+ if child.tagname == 'title':
+ title = child.astext()
+ if title is None:
+ classes1 = node.get('classes')
+ if classes1:
+ title = classes1[0]
+ self.generate_admonition(node, 'generic', title)
+
+ depart_admonition = depart_warning
+
+ def generate_admonition(self, node, label, title=None):
+ if hasattr(self.language, 'labels'):
+ translated_label = self.language.labels.get(label, label)
+ else:
+ translated_label = label
+ el1 = SubElement(self.current_element, 'text:p', attrib={
+ 'text:style-name': self.rststyle(
+ 'admon-%s-hdr', (label, )),
+ })
+ if title:
+ el1.text = title
+ else:
+ el1.text = '%s!' % (translated_label.capitalize(), )
+ s1 = self.rststyle('admon-%s-body', (label, ))
+ self.paragraph_style_stack.append(s1)
+
+ #
+ # Roles (e.g. subscript, superscript, strong, ...
+ #
+ def visit_subscript(self, node):
+ el = self.append_child('text:span', attrib={
+ 'text:style-name': 'rststyle-subscript',
+ })
+ self.set_current_element(el)
+
+ def depart_subscript(self, node):
+ self.set_to_parent()
+
+ def visit_superscript(self, node):
+ el = self.append_child('text:span', attrib={
+ 'text:style-name': 'rststyle-superscript',
+ })
+ self.set_current_element(el)
+
+ def depart_superscript(self, node):
+ self.set_to_parent()
+
+ def visit_abbreviation(self, node):
+ pass
+
+ def depart_abbreviation(self, node):
+ pass
+
+ def visit_acronym(self, node):
+ pass
+
+ def depart_acronym(self, node):
+ pass
+
+ def visit_sidebar(self, node):
+ pass
+
+ def depart_sidebar(self, node):
+ pass
+
+
+# Use an own reader to modify transformations done.
+class Reader(standalone.Reader):
+
+ def get_transforms(self):
+ default = standalone.Reader.get_transforms(self)
+ if self.settings.create_links:
+ return default
+ return [i for i in default
+ if i is not references.DanglingReferences]
--- /dev/null
+# $Id: pygmentsformatter.py 5853 2009-01-19 21:02:02Z dkuhlman $
+# 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)
--- /dev/null
+# $Id: __init__.py 8412 2019-11-06 18:15:21Z milde $
+# Author: David Goodger <goodger@python.org>
+# Copyright: This module has been placed in the public domain.
+
+"""
+PEP HTML Writer.
+"""
+
+__docformat__ = 'reStructuredText'
+
+
+import sys
+import os
+import os.path
+import codecs
+import docutils
+from docutils import frontend, nodes, utils, writers
+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-Specific 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-Specific Options above.'
+ % (default_stylesheet_path, default_template_path),
+ (('Python\'s home URL. Default is "http://www.python.org".',
+ ['--python-home'],
+ {'default': 'http://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')
--- /dev/null
+/*
+:Author: David Goodger
+:Contact: goodger@python.org
+:date: $Date: 2006-05-21 22:44:42 +0200 (So, 21. Mai 2006) $
+:version: $Revision: 4564 $
+: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 }
--- /dev/null
+<?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://www.python.org/dev/peps/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: http://docutils.sourceforge.net/" />
+ <title>PEP %(pep)s -- %(title)s</title>
+ %(stylesheet)s
+</head>
+<body bgcolor="white">
+<table class="navigation" cellpadding="0" cellspacing="0"
+ width="100%%" border="0">
+<tr><td class="navicon" width="150" height="35">
+<a href="%(pyhome)s/" title="Python Home Page">
+<img src="%(pyhome)s/pics/PyBanner%(banner)03d.gif" alt="[Python]"
+ border="0" width="150" height="35" /></a></td>
+<td class="textlinks" align="left">
+[<b><a href="%(pyhome)s/">Python Home</a></b>]
+[<b><a href="%(pepindex)s/">PEP Index</a></b>]
+[<b><a href="%(pephome)s/pep-%(pepnum)s.txt">PEP Source</a></b>]
+</td></tr></table>
+<div class="document">
+%(body)s
+%(body_suffix)s
--- /dev/null
+# $Id: pseudoxml.py 7320 2012-01-19 22:33:02Z 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
+
+
+class Writer(writers.Writer):
+
+ supported = ('pprint', 'pformat', 'pseudoxml')
+ """Formats this writer supports."""
+
+ 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
--- /dev/null
+# $Id: __init__.py 8412 2019-11-06 18:15:21Z 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
+from docutils.parsers.rst import directives
+
+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', 'blank.gif', 'iepngfix.htc')
+ """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
+ self.setup_theme()
+ 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.add_meta('<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 = '%s/%s' % ('ui', settings.theme)
+ if settings._destination:
+ dest = os.path.join(
+ os.path.dirname(settings._destination), 'ui', settings.theme)
+ if not os.path.isdir(dest):
+ os.makedirs(dest)
+ else:
+ # no destination, so we can't copy the theme
+ return
+ 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] = 1
+ 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) 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 1 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 1
+ else:
+ self.theme_files_copied[dest] = 1
+ 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:
+ src_file = open(source, 'rb')
+ src_data = src_file.read()
+ src_file.close()
+ dest_file = open(dest, 'wb')
+ 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())))
+ dest_file.close()
+ settings.record_dependencies.add(source)
+ return 1
+ if os.path.isfile(dest):
+ return 1
+
+ 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.meta.insert(0, self.content_type % self.settings.output_encoding)
+ self.head.insert(0, self.content_type % self.settings.output_encoding)
+ 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)
--- /dev/null
+Except where otherwise noted (default/iepngfix.htc), 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.
--- /dev/null
+# base theme of this theme:
+big-white
--- /dev/null
+/* 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;}
+*/
--- /dev/null
+/* 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;}
+*/
--- /dev/null
+/* 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;}
+*/
--- /dev/null
+/* 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;}
+*/
--- /dev/null
+/* 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;}
+*/
--- /dev/null
+<public:component>
+<public:attach event="onpropertychange" onevent="doFix()" />
+
+<script>
+
+// IE5.5+ PNG Alpha Fix v1.0 by Angus Turnbull http://www.twinhelix.com
+// Free usage permitted as long as this notice remains intact.
+
+// This must be a path to a blank image. That's all the configuration you need here.
+var blankImg = 'ui/default/blank.gif';
+
+var f = 'DXImageTransform.Microsoft.AlphaImageLoader';
+
+function filt(s, m) {
+ if (filters[f]) {
+ filters[f].enabled = s ? true : false;
+ if (s) with (filters[f]) { src = s; sizingMethod = m }
+ } else if (s) style.filter = 'progid:'+f+'(src="'+s+'",sizingMethod="'+m+'")';
+}
+
+function doFix() {
+ if ((parseFloat(navigator.userAgent.match(/MSIE (\S+)/)[1]) < 5.5) ||
+ (event && !/(background|src)/.test(event.propertyName))) return;
+
+ if (tagName == 'IMG') {
+ if ((/\.png$/i).test(src)) {
+ filt(src, 'image'); // was 'scale'
+ src = blankImg;
+ } else if (src.indexOf(blankImg) < 0) filt();
+ } else if (style.backgroundImage) {
+ if (style.backgroundImage.match(/^url[("']+(.*\.png)[)"']+$/i)) {
+ var s = RegExp.$1;
+ style.backgroundImage = '';
+ filt(s, 'crop');
+ } else filt();
+ }
+}
+
+doFix();
+
+</script>
+</public:component>
\ No newline at end of file
--- /dev/null
+/* 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;}
--- /dev/null
+/* 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;}
--- /dev/null
+/* 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;}
+*/
--- /dev/null
+/* 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;}
--- /dev/null
+/* 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;}
--- /dev/null
+/* 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);
--- /dev/null
+// S5 v1.1 slides.js -- released into the Public Domain
+// Modified for Docutils (http://docutils.sf.net) 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();">Ø<\/a>' +
+ '<a accesskey="z" id="prev" href="javascript:go(-1);">«<\/a>' +
+ '<a accesskey="x" id="next" href="javascript:go(1);">»<\/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);}
--- /dev/null
+# base theme of this theme:
+medium-white
--- /dev/null
+/* 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;}
+*/
--- /dev/null
+/* 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;}
+*/
--- /dev/null
+/* 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;}
+*/
--- /dev/null
+# base theme of this theme:
+small-white
--- /dev/null
+/* 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;}
+*/
--- /dev/null
+/* 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;}
+*/
--- /dev/null
+/* 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;}
+*/
--- /dev/null
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+# :Author: Günter Milde <milde@users.sourceforge.net>
+# :Revision: $Revision: 8411 $
+# :Date: $Date: 2019-11-05 14:32:13 +0100 (Di, 05. Nov 2019) $
+# :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: http://www.spdx.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'
+
+import os
+import os.path
+import re
+
+import docutils
+from docutils import frontend, nodes, utils, writers, languages
+from docutils.writers import latex2e
+
+class Writer(latex2e.Writer):
+ """A writer for Unicode-aware LaTeX variants (XeTeX, LuaTeX)"""
+
+ supported = ('lxtex', 'xetex', 'xelatex', 'luatex', 'lualatex')
+ """Formats this writer supports."""
+
+ default_template = 'xelatex.tex'
+ default_preamble = '\n'.join([
+ r'% Linux Libertine (free, wide coverage, not only for Linux)',
+ r'\setmainfont{Linux Libertine O}',
+ r'\setsansfont{Linux Biolinum O}',
+ r'\setmonofont[HyphenChar=None,Scale=MatchLowercase]{DejaVu Sans Mono}',
+ ])
+
+ config_section = 'xetex writer'
+ config_section_dependencies = ('writers', 'latex writers',
+ 'latex2e writer') # TODO: remove dependency on `latex2e writer`.
+
+ settings_spec = frontend.filter_settings_spec(
+ latex2e.Writer.settings_spec,
+ 'font_encoding',
+ 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 (EU1 or EU2)
+ 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',
+ '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 = dict([(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 = u'"' # 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)
--- /dev/null
+#!/usr/bin/env python
+# $Id: install.py 8346 2019-08-26 12:11:32Z milde $
+# Copyright: This file has been placed in the public domain.
+
+"""
+This is a quick & dirty installation shortcut. It is equivalent to the
+command::
+
+ python setup.py install
+
+However, the shortcut lacks error checking and command-line option
+processing. If you need any kind of customization or help, please use
+one of::
+
+ python setup.py install --help
+ python setup.py --help
+"""
+from __future__ import print_function
+
+from distutils import core
+from setup import do_setup
+
+if __name__ == '__main__':
+ print(__doc__)
+ core._setup_stop_after = 'config'
+ dist = do_setup()
+ dist.commands = ['install']
+ dist.run_commands()
--- /dev/null
+2-Clause BSD license / FreeBSD license
+======================================
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
--- /dev/null
+# This configuration file is to prevent tools/buildhtml.py from
+# processing text files in and below this directory.
+
+[buildhtml application]
+prune: .
--- /dev/null
+ GNU GENERAL PUBLIC LICENSE
+ Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The GNU General Public License is a free, copyleft license for
+software and other kinds of works.
+
+ The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works. By contrast,
+the GNU General Public License is intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users. We, the Free Software Foundation, use the
+GNU General Public License for most of our software; it applies also to
+any other work released this way by its authors. You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+them if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs, and that you know you can do these things.
+
+ To protect your rights, we need to prevent others from denying you
+these rights or asking you to surrender the rights. Therefore, you have
+certain responsibilities if you distribute copies of the software, or if
+you modify it: responsibilities to respect the freedom of others.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received. You must make sure that they, too, receive
+or can get the source code. And you must show them these terms so they
+know their rights.
+
+ Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
+
+ For the developers' and authors' protection, the GPL clearly explains
+that there is no warranty for this free software. For both users' and
+authors' sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+
+ Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the manufacturer
+can do so. This is fundamentally incompatible with the aim of
+protecting users' freedom to change the software. The systematic
+pattern of such abuse occurs in the area of products for individuals to
+use, which is precisely where it is most unacceptable. Therefore, we
+have designed this version of the GPL to prohibit the practice for those
+products. If such problems arise substantially in other domains, we
+stand ready to extend this provision to those domains in future versions
+of the GPL, as needed to protect the freedom of users.
+
+ Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish to
+avoid the special danger that patents applied to a free program could
+make it effectively proprietary. To prevent this, the GPL assures that
+patents cannot be used to render the program non-free.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ TERMS AND CONDITIONS
+
+ 0. Definitions.
+
+ "This License" refers to version 3 of the GNU General Public License.
+
+ "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+ "The Program" refers to any copyrightable work licensed under this
+License. Each licensee is addressed as "you". "Licensees" and
+"recipients" may be individuals or organizations.
+
+ To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy. The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+ A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+ To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy. Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+ To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies. Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+ An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License. If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+ 1. Source Code.
+
+ The "source code" for a work means the preferred form of the work
+for making modifications to it. "Object code" means any non-source
+form of a work.
+
+ A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+ The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form. A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+ The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities. However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work. For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+ The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+ The Corresponding Source for a work in source code form is that
+same work.
+
+ 2. Basic Permissions.
+
+ All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met. This License explicitly affirms your unlimited
+permission to run the unmodified Program. The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work. This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+ You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force. You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright. Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+ Conveying under any other circumstances is permitted solely under
+the conditions stated below. Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+ 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+ No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+ When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+ 4. Conveying Verbatim Copies.
+
+ You may convey verbatim copies of the Program's source code as you
+receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+ You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+ 5. Conveying Modified Source Versions.
+
+ You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+ a) The work must carry prominent notices stating that you modified
+ it, and giving a relevant date.
+
+ b) The work must carry prominent notices stating that it is
+ released under this License and any conditions added under section
+ 7. This requirement modifies the requirement in section 4 to
+ "keep intact all notices".
+
+ c) You must license the entire work, as a whole, under this
+ License to anyone who comes into possession of a copy. This
+ License will therefore apply, along with any applicable section 7
+ additional terms, to the whole of the work, and all its parts,
+ regardless of how they are packaged. This License gives no
+ permission to license the work in any other way, but it does not
+ invalidate such permission if you have separately received it.
+
+ d) If the work has interactive user interfaces, each must display
+ Appropriate Legal Notices; however, if the Program has interactive
+ interfaces that do not display Appropriate Legal Notices, your
+ work need not make them do so.
+
+ A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit. Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+ 6. Conveying Non-Source Forms.
+
+ You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+ a) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by the
+ Corresponding Source fixed on a durable physical medium
+ customarily used for software interchange.
+
+ b) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by a
+ written offer, valid for at least three years and valid for as
+ long as you offer spare parts or customer support for that product
+ model, to give anyone who possesses the object code either (1) a
+ copy of the Corresponding Source for all the software in the
+ product that is covered by this License, on a durable physical
+ medium customarily used for software interchange, for a price no
+ more than your reasonable cost of physically performing this
+ conveying of source, or (2) access to copy the
+ Corresponding Source from a network server at no charge.
+
+ c) Convey individual copies of the object code with a copy of the
+ written offer to provide the Corresponding Source. This
+ alternative is allowed only occasionally and noncommercially, and
+ only if you received the object code with such an offer, in accord
+ with subsection 6b.
+
+ d) Convey the object code by offering access from a designated
+ place (gratis or for a charge), and offer equivalent access to the
+ Corresponding Source in the same way through the same place at no
+ further charge. You need not require recipients to copy the
+ Corresponding Source along with the object code. If the place to
+ copy the object code is a network server, the Corresponding Source
+ may be on a different server (operated by you or a third party)
+ that supports equivalent copying facilities, provided you maintain
+ clear directions next to the object code saying where to find the
+ Corresponding Source. Regardless of what server hosts the
+ Corresponding Source, you remain obligated to ensure that it is
+ available for as long as needed to satisfy these requirements.
+
+ e) Convey the object code using peer-to-peer transmission, provided
+ you inform other peers where the object code and Corresponding
+ Source of the work are being offered to the general public at no
+ charge under subsection 6d.
+
+ A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+ A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling. In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage. For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product. A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+ "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source. The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+ If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information. But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+ The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed. Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+ Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+ 7. Additional Terms.
+
+ "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law. If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+ When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it. (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.) You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+ Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+ a) Disclaiming warranty or limiting liability differently from the
+ terms of sections 15 and 16 of this License; or
+
+ b) Requiring preservation of specified reasonable legal notices or
+ author attributions in that material or in the Appropriate Legal
+ Notices displayed by works containing it; or
+
+ c) Prohibiting misrepresentation of the origin of that material, or
+ requiring that modified versions of such material be marked in
+ reasonable ways as different from the original version; or
+
+ d) Limiting the use for publicity purposes of names of licensors or
+ authors of the material; or
+
+ e) Declining to grant rights under trademark law for use of some
+ trade names, trademarks, or service marks; or
+
+ f) Requiring indemnification of licensors and authors of that
+ material by anyone who conveys the material (or modified versions of
+ it) with contractual assumptions of liability to the recipient, for
+ any liability that these contractual assumptions directly impose on
+ those licensors and authors.
+
+ All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10. If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term. If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+ If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+ Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+ 8. Termination.
+
+ You may not propagate or modify a covered work except as expressly
+provided under this License. Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+ However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+ Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+ Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License. If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+ 9. Acceptance Not Required for Having Copies.
+
+ You are not required to accept this License in order to receive or
+run a copy of the Program. Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance. However,
+nothing other than this License grants you permission to propagate or
+modify any covered work. These actions infringe copyright if you do
+not accept this License. Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+ 10. Automatic Licensing of Downstream Recipients.
+
+ Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License. You are not responsible
+for enforcing compliance by third parties with this License.
+
+ An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations. If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+ You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License. For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+ 11. Patents.
+
+ A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based. The
+work thus licensed is called the contributor's "contributor version".
+
+ A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version. For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+ Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+ In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement). To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+ If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients. "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+ If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+ A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License. You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+ Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+ 12. No Surrender of Others' Freedom.
+
+ If conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all. For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+ 13. Use with the GNU Affero General Public License.
+
+ Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU Affero General Public License into a single
+combined work, and to convey the resulting work. The terms of this
+License will continue to apply to the part which is the covered work,
+but the special requirements of the GNU Affero General Public License,
+section 13, concerning interaction through a network will apply to the
+combination as such.
+
+ 14. Revised Versions of this License.
+
+ The Free Software Foundation may publish revised and/or new versions of
+the GNU General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+ Each version is given a distinguishing version number. If the
+Program specifies that a certain numbered version of the GNU General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation. If the Program does not specify a version number of the
+GNU General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+ If the Program specifies that a proxy can decide which future
+versions of the GNU General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+ Later license versions may give you additional or different
+permissions. However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+ 15. Disclaimer of Warranty.
+
+ THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
+IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. Limitation of Liability.
+
+ IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+ 17. Interpretation of Sections 15 and 16.
+
+ If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+state the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+Also add information on how to contact you by electronic and paper mail.
+
+ If the program does terminal interaction, make it output a short
+notice like this when it starts in an interactive mode:
+
+ <program> Copyright (C) <year> <name of author>
+ This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, your program's commands
+might be different; for a GUI interface, you would use an "about box".
+
+ You should also get your employer (if you work as a programmer) or school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.
+For more information on this, and how to apply and follow the GNU GPL, see
+<http://www.gnu.org/licenses/>.
+
+ The GNU General Public License does not permit incorporating your program
+into proprietary programs. If your program is a subroutine library, you
+may consider it more useful to permit linking proprietary applications with
+the library. If this is what you want to do, use the GNU Lesser General
+Public License instead of this License. But first, please read
+<http://www.gnu.org/philosophy/why-not-lgpl.html>.
--- /dev/null
+A. HISTORY OF THE SOFTWARE
+==========================
+
+Python was created in the early 1990s by Guido van Rossum at Stichting
+Mathematisch Centrum (CWI) in the Netherlands as a successor of a
+language called ABC. Guido is Python's principal author, although it
+includes many contributions from others. The last version released
+from CWI was Python 1.2. In 1995, Guido continued his work on Python
+at the Corporation for National Research Initiatives (CNRI) in Reston,
+Virginia where he released several versions of the software. Python
+1.6 was the last of the versions released by CNRI. In 2000, Guido and
+the Python core development team moved to BeOpen.com to form the
+BeOpen PythonLabs team. Python 2.0 was the first and only release
+from BeOpen.com.
+
+Following the release of Python 1.6, and after Guido van Rossum left
+CNRI to work with commercial software developers, it became clear that
+the ability to use Python with software available under the GNU Public
+License (GPL) was very desirable. CNRI and the Free Software
+Foundation (FSF) interacted to develop enabling wording changes to the
+Python license. Python 1.6.1 is essentially the same as Python 1.6,
+with a few minor bug fixes, and with a different license that enables
+later versions to be GPL-compatible. Python 2.1 is a derivative work
+of Python 1.6.1, as well as of Python 2.0.
+
+After Python 2.0 was released by BeOpen.com, Guido van Rossum and the
+other PythonLabs developers joined Digital Creations. All
+intellectual property added from this point on, starting with Python
+2.1 and its alpha and beta releases, is owned by the Python Software
+Foundation (PSF), a non-profit modeled after the Apache Software
+Foundation. See http://www.python.org/psf/ for more information about
+the PSF.
+
+Thanks to the many outside volunteers who have worked under Guido's
+direction to make these releases possible.
+
+
+B. TERMS AND CONDITIONS FOR ACCESSING OR OTHERWISE USING PYTHON
+===============================================================
+
+PSF LICENSE AGREEMENT
+---------------------
+
+1. This LICENSE AGREEMENT is between the Python Software Foundation
+("PSF"), and the Individual or Organization ("Licensee") accessing and
+otherwise using Python 2.1.1 software in source or binary form and its
+associated documentation.
+
+2. Subject to the terms and conditions of this License Agreement, PSF
+hereby grants Licensee a nonexclusive, royalty-free, world-wide
+license to reproduce, analyze, test, perform and/or display publicly,
+prepare derivative works, distribute, and otherwise use Python 2.1.1
+alone or in any derivative version, provided, however, that PSF's
+License Agreement and PSF's notice of copyright, i.e., "Copyright (c)
+2001 Python Software Foundation; All Rights Reserved" are retained in
+Python 2.1.1 alone or in any derivative version prepared by Licensee.
+
+3. In the event Licensee prepares a derivative work that is based on
+or incorporates Python 2.1.1 or any part thereof, and wants to make
+the derivative work available to others as provided herein, then
+Licensee hereby agrees to include in any such work a brief summary of
+the changes made to Python 2.1.1.
+
+4. PSF is making Python 2.1.1 available to Licensee on an "AS IS"
+basis. PSF MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR
+IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, PSF MAKES NO AND
+DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS
+FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF PYTHON 2.1.1 WILL NOT
+INFRINGE ANY THIRD PARTY RIGHTS.
+
+5. PSF SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON
+2.1.1 FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS
+A RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON 2.1.1,
+OR ANY DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF.
+
+6. This License Agreement will automatically terminate upon a material
+breach of its terms and conditions.
+
+7. Nothing in this License Agreement shall be deemed to create any
+relationship of agency, partnership, or joint venture between PSF and
+Licensee. This License Agreement does not grant permission to use PSF
+trademarks or trade name in a trademark sense to endorse or promote
+products or services of Licensee, or any third party.
+
+8. By copying, installing or otherwise using Python 2.1.1, Licensee
+agrees to be bound by the terms and conditions of this License
+Agreement.
+
+
+BEOPEN.COM TERMS AND CONDITIONS FOR PYTHON 2.0
+----------------------------------------------
+
+BEOPEN PYTHON OPEN SOURCE LICENSE AGREEMENT VERSION 1
+
+1. This LICENSE AGREEMENT is between BeOpen.com ("BeOpen"), having an
+office at 160 Saratoga Avenue, Santa Clara, CA 95051, and the
+Individual or Organization ("Licensee") accessing and otherwise using
+this software in source or binary form and its associated
+documentation ("the Software").
+
+2. Subject to the terms and conditions of this BeOpen Python License
+Agreement, BeOpen hereby grants Licensee a non-exclusive,
+royalty-free, world-wide license to reproduce, analyze, test, perform
+and/or display publicly, prepare derivative works, distribute, and
+otherwise use the Software alone or in any derivative version,
+provided, however, that the BeOpen Python License is retained in the
+Software, alone or in any derivative version prepared by Licensee.
+
+3. BeOpen is making the Software available to Licensee on an "AS IS"
+basis. BEOPEN MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR
+IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, BEOPEN MAKES NO AND
+DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS
+FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF THE SOFTWARE WILL NOT
+INFRINGE ANY THIRD PARTY RIGHTS.
+
+4. BEOPEN SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF THE
+SOFTWARE FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS
+AS A RESULT OF USING, MODIFYING OR DISTRIBUTING THE SOFTWARE, OR ANY
+DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF.
+
+5. This License Agreement will automatically terminate upon a material
+breach of its terms and conditions.
+
+6. This License Agreement shall be governed by and interpreted in all
+respects by the law of the State of California, excluding conflict of
+law provisions. Nothing in this License Agreement shall be deemed to
+create any relationship of agency, partnership, or joint venture
+between BeOpen and Licensee. This License Agreement does not grant
+permission to use BeOpen trademarks or trade names in a trademark
+sense to endorse or promote products or services of Licensee, or any
+third party. As an exception, the "BeOpen Python" logos available at
+http://www.pythonlabs.com/logos.html may be used according to the
+permissions granted on that web page.
+
+7. By copying, installing or otherwise using the software, Licensee
+agrees to be bound by the terms and conditions of this License
+Agreement.
+
+
+CNRI OPEN SOURCE GPL-COMPATIBLE LICENSE AGREEMENT
+-------------------------------------------------
+
+1. This LICENSE AGREEMENT is between the Corporation for National
+Research Initiatives, having an office at 1895 Preston White Drive,
+Reston, VA 20191 ("CNRI"), and the Individual or Organization
+("Licensee") accessing and otherwise using Python 1.6.1 software in
+source or binary form and its associated documentation.
+
+2. Subject to the terms and conditions of this License Agreement, CNRI
+hereby grants Licensee a nonexclusive, royalty-free, world-wide
+license to reproduce, analyze, test, perform and/or display publicly,
+prepare derivative works, distribute, and otherwise use Python 1.6.1
+alone or in any derivative version, provided, however, that CNRI's
+License Agreement and CNRI's notice of copyright, i.e., "Copyright (c)
+1995-2001 Corporation for National Research Initiatives; All Rights
+Reserved" are retained in Python 1.6.1 alone or in any derivative
+version prepared by Licensee. Alternately, in lieu of CNRI's License
+Agreement, Licensee may substitute the following text (omitting the
+quotes): "Python 1.6.1 is made available subject to the terms and
+conditions in CNRI's License Agreement. This Agreement together with
+Python 1.6.1 may be located on the Internet using the following
+unique, persistent identifier (known as a handle): 1895.22/1013. This
+Agreement may also be obtained from a proxy server on the Internet
+using the following URL: http://hdl.handle.net/1895.22/1013".
+
+3. In the event Licensee prepares a derivative work that is based on
+or incorporates Python 1.6.1 or any part thereof, and wants to make
+the derivative work available to others as provided herein, then
+Licensee hereby agrees to include in any such work a brief summary of
+the changes made to Python 1.6.1.
+
+4. CNRI is making Python 1.6.1 available to Licensee on an "AS IS"
+basis. CNRI MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR
+IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, CNRI MAKES NO AND
+DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS
+FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF PYTHON 1.6.1 WILL NOT
+INFRINGE ANY THIRD PARTY RIGHTS.
+
+5. CNRI SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON
+1.6.1 FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS
+A RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON 1.6.1,
+OR ANY DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF.
+
+6. This License Agreement will automatically terminate upon a material
+breach of its terms and conditions.
+
+7. This License Agreement shall be governed by the federal
+intellectual property law of the United States, including without
+limitation the federal copyright law, and, to the extent such
+U.S. federal law does not apply, by the law of the Commonwealth of
+Virginia, excluding Virginia's conflict of law provisions.
+Notwithstanding the foregoing, with regard to derivative works based
+on Python 1.6.1 that incorporate non-separable material that was
+previously distributed under the GNU General Public License (GPL), the
+law of the Commonwealth of Virginia shall govern this License
+Agreement only as to issues arising under or with respect to
+Paragraphs 4, 5, and 7 of this License Agreement. Nothing in this
+License Agreement shall be deemed to create any relationship of
+agency, partnership, or joint venture between CNRI and Licensee. This
+License Agreement does not grant permission to use CNRI trademarks or
+trade name in a trademark sense to endorse or promote products or
+services of Licensee, or any third party.
+
+8. By clicking on the "ACCEPT" button where indicated, or by copying,
+installing or otherwise using Python 1.6.1, Licensee agrees to be
+bound by the terms and conditions of this License Agreement.
+
+ ACCEPT
+
+
+CWI PERMISSIONS STATEMENT AND DISCLAIMER
+----------------------------------------
+
+Copyright (c) 1991 - 1995, Stichting Mathematisch Centrum Amsterdam,
+The Netherlands. All rights reserved.
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the name of Stichting Mathematisch
+Centrum or CWI not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior
+permission.
+
+STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
--- /dev/null
+[bdist_rpm]
+doc_files = BUGS.txt
+ COPYING.txt
+ FAQ.txt
+ HISTORY.txt
+ README.txt
+ RELEASE-NOTES.txt
+ THANKS.txt
+ docs/
+ licenses/
+
+[bdist_wheel]
+universal = 1
+
+[egg_info]
+tag_build =
+tag_date = 0
+
--- /dev/null
+#!/usr/bin/env python
+# $Id: setup.py 8453 2020-01-12 13:28:32Z grubert $
+# Copyright: This file has been placed in the public domain.
+
+from __future__ import print_function
+
+import sys
+import os
+import glob
+
+try:
+ import setuptools
+except ImportError:
+ print('Warning: Could not load package `setuptools`.')
+ print('Actions requiring `setuptools` instead of `distutils` will fail')
+try:
+ from distutils.core import setup, Command
+ from distutils.command.build import build
+ from distutils.command.build_py import build_py
+ from distutils.command.install_data import install_data
+ from distutils.util import convert_path
+ from distutils import log
+except ImportError:
+ print('Error: The "distutils" standard module, which is required for the ')
+ print('installation of Docutils, could not be found. You may need to ')
+ print('install a package called "python-devel" (or similar) on your ')
+ print('system using your package manager.')
+ sys.exit(1)
+
+
+class smart_install_data(install_data):
+ # From <http://wiki.python.org/moin/DistutilsInstallDataScattered>,
+ # by Pete Shinners.
+
+ def run(self):
+ # need to change self.install_dir to the library dir
+ install_cmd = self.get_finalized_command('install')
+ self.install_dir = getattr(install_cmd, 'install_lib')
+ return install_data.run(self)
+
+
+class build_data(Command):
+
+ def initialize_options(self):
+ pass
+
+ def finalize_options(self):
+ pass
+
+ def run(self):
+ build_py_cmd = self.get_finalized_command('build_py')
+ data_files = self.distribution.data_files
+ for f in data_files:
+ dir = convert_path(f[0])
+ dir = os.path.join(build_py_cmd.build_lib, dir)
+ self.mkpath(dir)
+ for data in f[1]:
+ data = convert_path(data)
+ self.copy_file(data, dir)
+
+
+# let our build_data run
+build.sub_commands.append(('build_data', lambda *a: True))
+
+
+s5_theme_files = []
+for dir in glob.glob('docutils/writers/s5_html/themes/*'):
+ if os.path.isdir(dir):
+ theme_files = glob.glob('%s/*' % dir)
+ s5_theme_files.append((dir, theme_files))
+
+
+package_data = {
+ 'name': 'docutils',
+ 'description': 'Docutils -- Python Documentation Utilities',
+ 'long_description': """\
+Docutils is a modular system for processing documentation
+into useful formats, such as HTML, XML, and LaTeX. For
+input Docutils supports reStructuredText, an easy-to-read,
+what-you-see-is-what-you-get plaintext markup syntax.""", # wrap at col 60
+ 'url': 'http://docutils.sourceforge.net/',
+ 'version': '0.16',
+ 'author': 'David Goodger',
+ 'author_email': 'goodger@python.org',
+ 'maintainer': 'docutils-develop list',
+ 'maintainer_email': 'docutils-develop@lists.sourceforge.net',
+ 'license': 'public domain, Python, 2-Clause BSD, GPL 3 (see COPYING.txt)',
+ 'platforms': 'OS-independent',
+ 'python_requires': '>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*',
+ 'cmdclass': {
+ 'build_data': build_data,
+ 'install_data': smart_install_data,
+ },
+ 'package_dir': {
+ 'docutils': 'docutils',
+ 'docutils.tools': 'tools'
+ },
+ 'packages': [
+ 'docutils',
+ 'docutils.languages',
+ 'docutils.parsers',
+ 'docutils.parsers.rst',
+ 'docutils.parsers.rst.directives',
+ 'docutils.parsers.rst.languages',
+ 'docutils.readers',
+ 'docutils.transforms',
+ 'docutils.utils',
+ 'docutils.utils.math',
+ 'docutils.writers',
+ 'docutils.writers.html4css1',
+ 'docutils.writers.html5_polyglot',
+ 'docutils.writers.pep_html',
+ 'docutils.writers.s5_html',
+ 'docutils.writers.latex2e',
+ 'docutils.writers.xetex',
+ 'docutils.writers.odf_odt',
+ ],
+ 'data_files': [
+ ('docutils/parsers/rst/include',
+ glob.glob('docutils/parsers/rst/include/*.txt')),
+ ('docutils/writers/html5_polyglot', [
+ 'docutils/writers/html5_polyglot/minimal.css',
+ 'docutils/writers/html5_polyglot/plain.css',
+ 'docutils/writers/html5_polyglot/math.css',
+ 'docutils/writers/html5_polyglot/template.txt']),
+ ('docutils/writers/html4css1', [
+ 'docutils/writers/html4css1/html4css1.css',
+ 'docutils/writers/html4css1/template.txt']),
+ ('docutils/writers/latex2e', [
+ 'docutils/writers/latex2e/default.tex',
+ 'docutils/writers/latex2e/titlepage.tex',
+ 'docutils/writers/latex2e/xelatex.tex']),
+ ('docutils/writers/pep_html', [
+ 'docutils/writers/pep_html/pep.css',
+ 'docutils/writers/pep_html/template.txt']),
+ ('docutils/writers/s5_html/themes', [
+ 'docutils/writers/s5_html/themes/README.txt']),
+ ('docutils/writers/odf_odt', ['docutils/writers/odf_odt/styles.odt']),
+ ] + s5_theme_files,
+ 'scripts': [
+ 'tools/rst2html.py',
+ 'tools/rst2html4.py',
+ 'tools/rst2html5.py',
+ 'tools/rst2s5.py',
+ 'tools/rst2latex.py',
+ 'tools/rst2xetex.py',
+ 'tools/rst2man.py',
+ 'tools/rst2xml.py',
+ 'tools/rst2pseudoxml.py',
+ 'tools/rstpep2html.py',
+ 'tools/rst2odt.py',
+ 'tools/rst2odt_prepstyles.py',
+ ],
+ 'classifiers': [
+ 'Development Status :: 4 - Beta',
+ 'Environment :: Console',
+ 'Intended Audience :: End Users/Desktop',
+ 'Intended Audience :: Other Audience',
+ 'Intended Audience :: Developers',
+ 'Intended Audience :: System Administrators',
+ 'License :: Public Domain',
+ 'License :: OSI Approved :: Python Software Foundation License',
+ 'License :: OSI Approved :: BSD License',
+ 'License :: OSI Approved :: GNU General Public License (GPL)',
+ 'Operating System :: OS Independent',
+ 'Programming Language :: Python :: 2',
+ 'Programming Language :: Python :: 2.7',
+ 'Programming Language :: Python :: 3',
+ 'Programming Language :: Python :: 3.5',
+ 'Programming Language :: Python :: 3.6',
+ 'Programming Language :: Python :: 3.7',
+ 'Topic :: Documentation',
+ 'Topic :: Software Development :: Documentation',
+ 'Topic :: Text Processing',
+ 'Natural Language :: English', # main/default language, keep first
+ 'Natural Language :: Afrikaans',
+ 'Natural Language :: Catalan',
+ 'Natural Language :: Chinese (Simplified)',
+ 'Natural Language :: Chinese (Traditional)',
+ 'Natural Language :: Czech',
+ 'Natural Language :: Danish',
+ 'Natural Language :: Dutch',
+ 'Natural Language :: Esperanto',
+ 'Natural Language :: Finnish',
+ 'Natural Language :: French',
+ 'Natural Language :: Galician',
+ 'Natural Language :: German',
+ 'Natural Language :: Hebrew',
+ 'Natural Language :: Italian',
+ 'Natural Language :: Japanese',
+ 'Natural Language :: Korean',
+ 'Natural Language :: Latvian',
+ 'Natural Language :: Lithuanian',
+ 'Natural Language :: Persian',
+ 'Natural Language :: Polish',
+ 'Natural Language :: Portuguese (Brazilian)',
+ 'Natural Language :: Russian',
+ 'Natural Language :: Slovak',
+ 'Natural Language :: Spanish',
+ 'Natural Language :: Swedish',
+ ],
+}
+"""Distutils setup parameters."""
+
+
+def do_setup():
+ # Install data files properly.
+ dist = setup(**package_data)
+ return dist
+
+
+if __name__ == '__main__':
+ do_setup()
--- /dev/null
+# $Id: DocutilsTestSupport.py 8373 2019-08-27 12:11:30Z milde $
+# Authors: David Goodger <goodger@python.org>;
+# Garth Kidd <garth@deadlybloodyserious.com>
+# Copyright: This module has been placed in the public domain.
+
+"""
+Exports the following:
+
+:Modules:
+ - `statemachine` is 'docutils.statemachine'
+ - `nodes` is 'docutils.nodes'
+ - `urischemes` is 'docutils.utils.urischemes'
+ - `utils` is 'docutils.utils'
+ - `transforms` is 'docutils.transforms'
+ - `states` is 'docutils.parsers.rst.states'
+ - `tableparser` is 'docutils.parsers.rst.tableparser'
+
+:Classes:
+ - `StandardTestCase`
+ - `CustomTestCase`
+ - `CustomTestSuite`
+ - `TransformTestCase`
+ - `TransformTestSuite`
+ - `ParserTestCase`
+ - `ParserTestSuite`
+ - `ParserTransformTestCase`
+ - `PEPParserTestCase`
+ - `PEPParserTestSuite`
+ - `GridTableParserTestCase`
+ - `GridTableParserTestSuite`
+ - `SimpleTableParserTestCase`
+ - `SimpleTableParserTestSuite`
+ - `WriterPublishTestCase`
+ - `LatexWriterPublishTestCase`
+ - `PseudoXMLWriterPublishTestCase`
+ - `HtmlWriterPublishTestCase`
+ - `PublishTestSuite`
+ - `HtmlFragmentTestSuite`
+ - `DevNull` (output sink)
+"""
+from __future__ import print_function
+__docformat__ = 'reStructuredText'
+
+import sys
+import os
+import unittest
+import re
+import inspect
+import traceback
+from pprint import pformat
+
+testroot = os.path.abspath(os.path.dirname(__file__) or os.curdir)
+os.chdir(testroot)
+if sys.version_info >= (3, 0):
+ sys.path.insert(0, os.path.normpath(os.path.join(testroot,
+ '..', 'build', 'lib')))
+ sys.path.append(os.path.normpath(os.path.join(testroot, '..',
+ 'build', 'lib', 'extras')))
+else:
+ sys.path.insert(0, os.path.normpath(os.path.join(testroot, '..')))
+ sys.path.append(os.path.normpath(os.path.join(testroot, '..', 'extras')))
+sys.path.insert(0, testroot)
+
+try:
+ import difflib
+ import package_unittest
+ import docutils
+ import docutils.core
+ from docutils import frontend, nodes, statemachine, utils
+ from docutils.utils import urischemes
+ from docutils.transforms import universal
+ from docutils.parsers import rst
+ from docutils.parsers.rst import states, tableparser, roles, languages
+ from docutils.readers import standalone, pep
+ from docutils.statemachine import StringList, string2lines
+except ImportError:
+ # The importing module (usually __init__.py in one of the
+ # subdirectories) may catch ImportErrors in order to detect the
+ # absence of DocutilsTestSupport in sys.path. Thus, ImportErrors
+ # resulting from problems with importing Docutils modules must
+ # caught here.
+ traceback.print_exc()
+ sys.exit(1)
+
+
+try:
+ import mypdb as pdb
+except:
+ import pdb
+
+
+if sys.version_info >= (3, 0):
+ unicode = str # noqa
+
+
+# Hack to make repr(StringList) look like repr(list):
+StringList.__repr__ = StringList.__str__
+
+
+class DevNull(object):
+
+ """Output sink."""
+
+ def write(self, string):
+ pass
+
+ def close(self):
+ pass
+
+
+class StandardTestCase(unittest.TestCase):
+
+ """
+ Helper class, providing the same interface as unittest.TestCase,
+ but with useful setUp and comparison methods.
+ """
+
+ def setUp(self):
+ os.chdir(testroot)
+
+ def assertEqual(self, first, second, msg=None):
+ """Fail if the two objects are unequal as determined by the '=='
+ operator.
+ """
+ if not first == second:
+ raise self.failureException(
+ msg or '%s != %s' % _format_str(first, second))
+
+ def assertNotEqual(self, first, second, msg=None):
+ """Fail if the two objects are equal as determined by the '=='
+ operator.
+ """
+ if first == second:
+ raise self.failureException(
+ msg or '%s == %s' % _format_str(first, second))
+
+ # aliases for assertion methods, deprecated since Python 2.7
+
+ failUnlessEqual = assertEquals = assertEqual
+
+ assertNotEquals = failIfEqual = assertNotEqual
+
+
+class CustomTestCase(StandardTestCase):
+
+ """
+ Helper class, providing extended functionality over unittest.TestCase.
+
+ The methods assertEqual and assertNotEqual have been overwritten
+ to provide better support for multi-line strings. Furthermore,
+ see the compare_output method and the parameter list of __init__.
+ """
+
+ compare = difflib.Differ().compare
+ """Comparison method shared by all subclasses."""
+
+ def __init__(self, method_name, input, expected, id,
+ run_in_debugger=True, suite_settings=None):
+ """
+ Initialise the CustomTestCase.
+
+ Arguments:
+
+ method_name -- name of test method to run.
+ input -- input to the parser.
+ expected -- expected output from the parser.
+ id -- unique test identifier, used by the test framework.
+ run_in_debugger -- if true, run this test under the pdb debugger.
+ suite_settings -- settings overrides for this test suite.
+ """
+ self.id = id
+ self.input = input
+ self.expected = expected
+ self.run_in_debugger = run_in_debugger
+ self.suite_settings = suite_settings.copy() or {}
+
+ # Ring your mother.
+ unittest.TestCase.__init__(self, method_name)
+
+ def __str__(self):
+ """
+ Return string conversion. Overridden to give test id, in addition to
+ method name.
+ """
+ return '%s; %s' % (self.id, unittest.TestCase.__str__(self))
+
+ def __repr__(self):
+ return "<%s %s>" % (self.id, unittest.TestCase.__repr__(self))
+
+ def clear_roles(self):
+ # Language-specific roles and roles added by the
+ # "default-role" and "role" directives are currently stored
+ # globally in the roles._roles dictionary. This workaround
+ # empties that dictionary.
+ roles._roles = {}
+
+ def setUp(self):
+ StandardTestCase.setUp(self)
+ self.clear_roles()
+
+ def compare_output(self, input, output, expected):
+ """`input`, `output`, and `expected` should all be strings."""
+ if isinstance(input, unicode):
+ input = input.encode('raw_unicode_escape')
+ if sys.version_info > (3, 0):
+ # API difference: Python 3's node.__str__ doesn't escape
+ #assert expected is None or isinstance(expected, unicode)
+ if isinstance(expected, bytes):
+ expected = expected.decode('utf-8')
+ if isinstance(output, bytes):
+ output = output.decode('utf-8')
+ else:
+ if isinstance(expected, unicode):
+ expected = expected.encode('raw_unicode_escape')
+ if isinstance(output, unicode):
+ output = output.encode('raw_unicode_escape')
+ # Normalize line endings:
+ if expected:
+ expected = '\n'.join(expected.splitlines())
+ if output:
+ output = '\n'.join(output.splitlines())
+ try:
+ self.assertEqual(output, expected)
+ except AssertionError as error:
+ print('\n%s\ninput:' % (self,), file=sys.stderr)
+ print(input, file=sys.stderr)
+ try:
+ comparison = ''.join(self.compare(expected.splitlines(1),
+ output.splitlines(1)))
+ print('-: expected\n+: output', file=sys.stderr)
+ print(comparison, file=sys.stderr)
+ except AttributeError: # expected or output not a string
+ # alternative output for non-strings:
+ print('expected: %r' % expected, file=sys.stderr)
+ print('output: %r' % output, file=sys.stderr)
+ raise error
+
+
+class CustomTestSuite(unittest.TestSuite):
+
+ """
+ A collection of CustomTestCases.
+
+ Provides test suite ID generation and a method for adding test cases.
+ """
+
+ id = ''
+ """Identifier for the TestSuite. Prepended to the
+ TestCase identifiers to make identification easier."""
+
+ next_test_case_id = 0
+ """The next identifier to use for non-identified test cases."""
+
+ def __init__(self, tests=(), id=None, suite_settings=None):
+ """
+ Initialize the CustomTestSuite.
+
+ Arguments:
+
+ id -- identifier for the suite, prepended to test cases.
+ suite_settings -- settings overrides for this test suite.
+ """
+ unittest.TestSuite.__init__(self, tests)
+ self.suite_settings = suite_settings or {}
+ if id is None:
+ mypath = os.path.abspath(
+ sys.modules[CustomTestSuite.__module__].__file__)
+ outerframes = inspect.getouterframes(inspect.currentframe())
+ for outerframe in outerframes[1:]:
+ if outerframe[3] != '__init__':
+ callerpath = outerframe[1]
+ if callerpath is None:
+ # It happens sometimes. Why is a mystery.
+ callerpath = os.getcwd()
+ callerpath = os.path.abspath(callerpath)
+ break
+ mydir, myname = os.path.split(mypath)
+ if not mydir:
+ mydir = os.curdir
+ if callerpath.startswith(mydir):
+ self.id = callerpath[len(mydir) + 1:] # caller's module
+ else:
+ self.id = callerpath
+ else:
+ self.id = id
+
+ def addTestCase(self, test_case_class, method_name, input, expected,
+ id=None, run_in_debugger=False, **kwargs):
+ """
+ Create a CustomTestCase in the CustomTestSuite.
+ Also return it, just in case.
+
+ Arguments:
+
+ test_case_class -- the CustomTestCase to add
+ method_name -- a string; CustomTestCase.method_name is the test
+ input -- input to the parser.
+ expected -- expected output from the parser.
+ id -- unique test identifier, used by the test framework.
+ run_in_debugger -- if true, run this test under the pdb debugger.
+ """
+ if id is None: # generate id if required
+ id = self.next_test_case_id
+ self.next_test_case_id += 1
+ # test identifier will become suiteid.testid
+ tcid = '%s: %s' % (self.id, id)
+ # suite_settings may be passed as a parameter;
+ # if not, set from attribute:
+ kwargs.setdefault('suite_settings', self.suite_settings)
+ # generate and add test case
+ tc = test_case_class(method_name, input, expected, tcid,
+ run_in_debugger=run_in_debugger, **kwargs)
+ self.addTest(tc)
+ return tc
+
+ def generate_no_tests(self, *args, **kwargs):
+ pass
+
+
+class TransformTestCase(CustomTestCase):
+
+ """
+ Output checker for the transform.
+
+ Should probably be called TransformOutputChecker, but I can deal with
+ that later when/if someone comes up with a category of transform test
+ cases that have nothing to do with the input and output of the transform.
+ """
+
+ option_parser = frontend.OptionParser(components=(rst.Parser,))
+ settings = option_parser.get_default_values()
+ settings.report_level = 1
+ settings.halt_level = 5
+ settings.debug = package_unittest.debug
+ settings.warning_stream = DevNull()
+ unknown_reference_resolvers = ()
+
+ def __init__(self, *args, **kwargs):
+ self.transforms = kwargs['transforms']
+ """List of transforms to perform for this test case."""
+
+ self.parser = kwargs['parser']
+ """Input parser for this test case."""
+
+ del kwargs['transforms'], kwargs['parser'] # only wanted here
+ CustomTestCase.__init__(self, *args, **kwargs)
+
+ def supports(self, format):
+ return 1
+
+ def test_transforms(self):
+ if self.run_in_debugger:
+ pdb.set_trace()
+ settings = self.settings.copy()
+ settings.__dict__.update(self.suite_settings)
+ document = utils.new_document('test data', settings)
+ self.parser.parse(self.input, document)
+ # Don't do a ``populate_from_components()`` because that would
+ # enable the Transformer's default transforms.
+ document.transformer.add_transforms(self.transforms)
+ document.transformer.add_transform(universal.TestMessages)
+ document.transformer.components['writer'] = self
+ document.transformer.apply_transforms()
+ output = document.pformat()
+ self.compare_output(self.input, output, self.expected)
+
+ def test_transforms_verbosely(self):
+ if self.run_in_debugger:
+ pdb.set_trace()
+ print('\n', self.id)
+ print('-' * 70)
+ print(self.input)
+ settings = self.settings.copy()
+ settings.__dict__.update(self.suite_settings)
+ document = utils.new_document('test data', settings)
+ self.parser.parse(self.input, document)
+ print('-' * 70)
+ print(document.pformat())
+ for transformClass in self.transforms:
+ transformClass(document).apply()
+ output = document.pformat()
+ print('-' * 70)
+ print(output)
+ self.compare_output(self.input, output, self.expected)
+
+
+class TransformTestSuite(CustomTestSuite):
+
+ """
+ A collection of TransformTestCases.
+
+ A TransformTestSuite instance manufactures TransformTestCases,
+ keeps track of them, and provides a shared test fixture (a-la
+ setUp and tearDown).
+ """
+
+ def __init__(self, parser, suite_settings=None):
+ self.parser = parser
+ """Parser shared by all test cases."""
+
+ CustomTestSuite.__init__(self, suite_settings=suite_settings)
+
+ def generateTests(self, dict, dictname='totest',
+ testmethod='test_transforms'):
+ """
+ Stock the suite with test cases generated from a test data dictionary.
+
+ Each dictionary key (test type's name) maps to a tuple, whose
+ first item is a list of transform classes and whose second
+ item is a list of tests. Each test is a list: input, expected
+ output, optional modifier. The optional third entry, a
+ behavior modifier, can be 0 (temporarily disable this test) or
+ 1 (run this test under the pdb debugger). Tests should be
+ self-documenting and not require external comments.
+ """
+ for name, (transforms, cases) in dict.items():
+ for casenum in range(len(cases)):
+ case = cases[casenum]
+ run_in_debugger = False
+ if len(case)==3:
+ # TODO: (maybe) change the 3rd argument to a dict, so it
+ # can handle more cases by keyword ('disable', 'debug',
+ # 'settings'), here and in other generateTests methods.
+ # But there's also the method that
+ # HtmlPublishPartsTestSuite uses <DJG>
+ if case[2]:
+ run_in_debugger = True
+ else:
+ continue
+ self.addTestCase(
+ TransformTestCase, testmethod,
+ transforms=transforms, parser=self.parser,
+ input=case[0], expected=case[1],
+ id='%s[%r][%s]' % (dictname, name, casenum),
+ run_in_debugger=run_in_debugger)
+
+
+class ParserTestCase(CustomTestCase):
+
+ """
+ Output checker for the parser.
+
+ Should probably be called ParserOutputChecker, but I can deal with
+ that later when/if someone comes up with a category of parser test
+ cases that have nothing to do with the input and output of the parser.
+ """
+
+ parser = rst.Parser()
+ """Parser shared by all ParserTestCases."""
+
+ option_parser = frontend.OptionParser(components=(rst.Parser,))
+ settings = option_parser.get_default_values()
+ settings.report_level = 5
+ settings.halt_level = 5
+ settings.debug = package_unittest.debug
+
+ def test_parser(self):
+ if self.run_in_debugger:
+ pdb.set_trace()
+ settings = self.settings.copy()
+ settings.__dict__.update(self.suite_settings)
+ document = utils.new_document('test data', settings)
+ self.parser.parse(self.input, document)
+ output = document.pformat()
+ self.compare_output(self.input, output, self.expected)
+
+
+class ParserTestSuite(CustomTestSuite):
+
+ """
+ A collection of ParserTestCases.
+
+ A ParserTestSuite instance manufactures ParserTestCases,
+ keeps track of them, and provides a shared test fixture (a-la
+ setUp and tearDown).
+ """
+
+ test_case_class = ParserTestCase
+
+ def generateTests(self, dict, dictname='totest'):
+ """
+ Stock the suite with test cases generated from a test data dictionary.
+
+ Each dictionary key (test type name) maps to a list of tests. Each
+ test is a list: input, expected output, optional modifier. The
+ optional third entry, a behavior modifier, can be 0 (temporarily
+ disable this test) or 1 (run this test under the pdb debugger). Tests
+ should be self-documenting and not require external comments.
+ """
+ for name, cases in dict.items():
+ for casenum in range(len(cases)):
+ case = cases[casenum]
+ run_in_debugger = False
+ if len(case)==3:
+ if case[2]:
+ run_in_debugger = True
+ else:
+ continue
+ self.addTestCase(
+ self.test_case_class, 'test_parser',
+ input=case[0], expected=case[1],
+ id='%s[%r][%s]' % (dictname, name, casenum),
+ run_in_debugger=run_in_debugger)
+
+
+class PEPParserTestCase(ParserTestCase):
+
+ """PEP-specific parser test case."""
+
+ parser = rst.Parser(rfc2822=True, inliner=rst.states.Inliner())
+ """Parser shared by all PEPParserTestCases."""
+
+ option_parser = frontend.OptionParser(components=(rst.Parser, pep.Reader))
+ settings = option_parser.get_default_values()
+ settings.report_level = 5
+ settings.halt_level = 5
+ settings.debug = package_unittest.debug
+
+
+class PEPParserTestSuite(ParserTestSuite):
+
+ """A collection of PEPParserTestCases."""
+
+ test_case_class = PEPParserTestCase
+
+
+class GridTableParserTestCase(CustomTestCase):
+
+ parser = tableparser.GridTableParser()
+
+ def test_parse_table(self):
+ self.parser.setup(StringList(string2lines(self.input), 'test data'))
+ try:
+ self.parser.find_head_body_sep()
+ self.parser.parse_table()
+ output = self.parser.cells
+ except Exception as details:
+ output = '%s: %s' % (details.__class__.__name__, details)
+ self.compare_output(self.input, pformat(output) + '\n',
+ pformat(self.expected) + '\n')
+
+ def test_parse(self):
+ try:
+ output = self.parser.parse(StringList(string2lines(self.input),
+ 'test data'))
+ except Exception as details:
+ output = '%s: %s' % (details.__class__.__name__, details)
+ self.compare_output(self.input, pformat(output) + '\n',
+ pformat(self.expected) + '\n')
+
+
+class GridTableParserTestSuite(CustomTestSuite):
+
+ """
+ A collection of GridTableParserTestCases.
+
+ A GridTableParserTestSuite instance manufactures GridTableParserTestCases,
+ keeps track of them, and provides a shared test fixture (a-la setUp and
+ tearDown).
+ """
+
+ test_case_class = GridTableParserTestCase
+
+ def generateTests(self, dict, dictname='totest'):
+ """
+ Stock the suite with test cases generated from a test data dictionary.
+
+ Each dictionary key (test type name) maps to a list of tests. Each
+ test is a list: an input table, expected output from parse_table(),
+ expected output from parse(), optional modifier. The optional fourth
+ entry, a behavior modifier, can be 0 (temporarily disable this test)
+ or 1 (run this test under the pdb debugger). Tests should be
+ self-documenting and not require external comments.
+ """
+ for name, cases in dict.items():
+ for casenum in range(len(cases)):
+ case = cases[casenum]
+ run_in_debugger = False
+ if len(case) == 4:
+ if case[-1]:
+ run_in_debugger = True
+ else:
+ continue
+ self.addTestCase(self.test_case_class, 'test_parse_table',
+ input=case[0], expected=case[1],
+ id='%s[%r][%s]' % (dictname, name, casenum),
+ run_in_debugger=run_in_debugger)
+ self.addTestCase(self.test_case_class, 'test_parse',
+ input=case[0], expected=case[2],
+ id='%s[%r][%s]' % (dictname, name, casenum),
+ run_in_debugger=run_in_debugger)
+
+
+class SimpleTableParserTestCase(GridTableParserTestCase):
+
+ parser = tableparser.SimpleTableParser()
+
+
+class SimpleTableParserTestSuite(CustomTestSuite):
+
+ """
+ A collection of SimpleTableParserTestCases.
+ """
+
+ test_case_class = SimpleTableParserTestCase
+
+ def generateTests(self, dict, dictname='totest'):
+ """
+ Stock the suite with test cases generated from a test data dictionary.
+
+ Each dictionary key (test type name) maps to a list of tests. Each
+ test is a list: an input table, expected output from parse(), optional
+ modifier. The optional third entry, a behavior modifier, can be 0
+ (temporarily disable this test) or 1 (run this test under the pdb
+ debugger). Tests should be self-documenting and not require external
+ comments.
+ """
+ for name, cases in dict.items():
+ for casenum in range(len(cases)):
+ case = cases[casenum]
+ run_in_debugger = False
+ if len(case) == 3:
+ if case[-1]:
+ run_in_debugger = True
+ else:
+ continue
+ self.addTestCase(self.test_case_class, 'test_parse',
+ input=case[0], expected=case[1],
+ id='%s[%r][%s]' % (dictname, name, casenum),
+ run_in_debugger=run_in_debugger)
+
+
+class PythonModuleParserTestCase(CustomTestCase):
+
+ def test_parser(self):
+ if self.run_in_debugger:
+ pdb.set_trace()
+ try:
+ import compiler
+ except ImportError:
+ # skip on Python 3
+ return
+ from docutils.readers.python import moduleparser
+ module = moduleparser.parse_module(self.input, 'test data').pformat()
+ output = str(module)
+ self.compare_output(self.input, output, self.expected)
+
+ def test_token_parser_rhs(self):
+ if self.run_in_debugger:
+ pdb.set_trace()
+ try:
+ import compiler
+ except ImportError:
+ # skip on Python 3
+ return
+ from docutils.readers.python import moduleparser
+ tr = moduleparser.TokenParser(self.input)
+ output = tr.rhs(1)
+ self.compare_output(self.input, output, self.expected)
+
+
+class PythonModuleParserTestSuite(CustomTestSuite):
+
+ """
+ A collection of PythonModuleParserTestCase.
+ """
+
+ def generateTests(self, dict, dictname='totest',
+ testmethod='test_parser'):
+ """
+ Stock the suite with test cases generated from a test data dictionary.
+
+ Each dictionary key (test type's name) maps to a list of tests. Each
+ test is a list: input, expected output, optional modifier. The
+ optional third entry, a behavior modifier, can be 0 (temporarily
+ disable this test) or 1 (run this test under the pdb debugger). Tests
+ should be self-documenting and not require external comments.
+ """
+ for name, cases in dict.items():
+ for casenum in range(len(cases)):
+ case = cases[casenum]
+ run_in_debugger = False
+ if len(case)==3:
+ if case[2]:
+ run_in_debugger = True
+ else:
+ continue
+ self.addTestCase(
+ PythonModuleParserTestCase, testmethod,
+ input=case[0], expected=case[1],
+ id='%s[%r][%s]' % (dictname, name, casenum),
+ run_in_debugger=run_in_debugger)
+
+
+class WriterPublishTestCase(CustomTestCase, docutils.SettingsSpec):
+
+ """
+ Test case for publish.
+ """
+
+ settings_default_overrides = {'_disable_config': True,
+ 'strict_visitor': True}
+ writer_name = '' # set in subclasses or constructor
+
+ def __init__(self, *args, **kwargs):
+ if 'writer_name' in kwargs:
+ self.writer_name = kwargs['writer_name']
+ del kwargs['writer_name']
+ CustomTestCase.__init__(self, *args, **kwargs)
+
+ def test_publish(self):
+ if self.run_in_debugger:
+ pdb.set_trace()
+ output = docutils.core.publish_string(
+ source=self.input,
+ reader_name='standalone',
+ parser_name='restructuredtext',
+ writer_name=self.writer_name,
+ settings_spec=self,
+ settings_overrides=self.suite_settings)
+ self.compare_output(self.input, output, self.expected)
+
+
+class PublishTestSuite(CustomTestSuite):
+
+ def __init__(self, writer_name, suite_settings=None):
+ """
+ `writer_name` is the name of the writer to use.
+ """
+ CustomTestSuite.__init__(self, suite_settings=suite_settings)
+ self.test_class = WriterPublishTestCase
+ self.writer_name = writer_name
+
+ def generateTests(self, dict, dictname='totest'):
+ for name, cases in dict.items():
+ for casenum in range(len(cases)):
+ case = cases[casenum]
+ run_in_debugger = False
+ if len(case)==3:
+ if case[2]:
+ run_in_debugger = True
+ else:
+ continue
+ self.addTestCase(
+ self.test_class, 'test_publish',
+ input=case[0], expected=case[1],
+ id='%s[%r][%s]' % (dictname, name, casenum),
+ run_in_debugger=run_in_debugger,
+ # Passed to constructor of self.test_class:
+ writer_name=self.writer_name)
+
+
+class HtmlWriterPublishPartsTestCase(WriterPublishTestCase):
+
+ """
+ Test case for HTML writer via the publish_parts interface.
+ """
+
+ writer_name = 'html'
+
+ settings_default_overrides = \
+ WriterPublishTestCase.settings_default_overrides.copy()
+ settings_default_overrides['stylesheet'] = ''
+
+ def test_publish(self):
+ if self.run_in_debugger:
+ pdb.set_trace()
+ parts = docutils.core.publish_parts(
+ source=self.input,
+ reader_name='standalone',
+ parser_name='restructuredtext',
+ writer_name=self.writer_name,
+ settings_spec=self,
+ settings_overrides=self.suite_settings)
+ output = self.format_output(parts)
+ # interpolate standard variables:
+ expected = self.expected % {'version': docutils.__version__}
+ self.compare_output(self.input, output, expected)
+
+ standard_content_type_template = ('<meta http-equiv="Content-Type"'
+ ' content="text/html; charset=%s" />\n')
+ standard_generator_template = (
+ '<meta name="generator"'
+ ' content="Docutils %s: http://docutils.sourceforge.net/" />\n')
+ standard_html_meta_value = (
+ standard_content_type_template
+ + standard_generator_template % docutils.__version__)
+ standard_meta_value = standard_html_meta_value % 'utf-8'
+ standard_html_prolog = """\
+<?xml version="1.0" encoding="%s" ?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+"""
+
+ def format_output(self, parts):
+ """Minimize & standardize the output."""
+ # remove redundant parts & uninteresting parts:
+ del parts['whole']
+ assert parts['body'] == parts['fragment']
+ del parts['body']
+ del parts['body_pre_docinfo']
+ del parts['body_prefix']
+ del parts['body_suffix']
+ del parts['head']
+ del parts['head_prefix']
+ del parts['encoding']
+ del parts['version']
+ # remove standard portions:
+ parts['meta'] = parts['meta'].replace(self.standard_meta_value, '')
+ parts['html_head'] = parts['html_head'].replace(
+ self.standard_html_meta_value, '...')
+ parts['html_prolog'] = parts['html_prolog'].replace(
+ self.standard_html_prolog, '')
+ output = []
+ for key in sorted(parts.keys()):
+ if not parts[key]:
+ continue
+ output.append("%r: '''%s'''"
+ % (key, parts[key]))
+ if output[-1].endswith("\n'''"):
+ output[-1] = output[-1][:-4] + "\\n'''"
+ return '{' + ',\n '.join(output) + '}\n'
+
+
+class HtmlPublishPartsTestSuite(CustomTestSuite):
+
+ testcase_class = HtmlWriterPublishPartsTestCase
+
+ def generateTests(self, dict, dictname='totest'):
+ for name, (settings_overrides, cases) in dict.items():
+ settings = self.suite_settings.copy()
+ settings.update(settings_overrides)
+ for casenum in range(len(cases)):
+ case = cases[casenum]
+ run_in_debugger = False
+ if len(case)==3:
+ if case[2]:
+ run_in_debugger = True
+ else:
+ continue
+ self.addTestCase(self.testcase_class, 'test_publish',
+ input=case[0], expected=case[1],
+ id='%s[%r][%s]' % (dictname, name, casenum),
+ run_in_debugger=run_in_debugger,
+ suite_settings=settings)
+
+
+def exception_data(func, *args, **kwds):
+ """
+ Execute `func(*args, **kwds)` and return the resulting exception, the
+ exception arguments, and the formatted exception string.
+ """
+ try:
+ func(*args, **kwds)
+ except Exception as detail:
+ return (detail, detail.args,
+ '%s: %s' % (detail.__class__.__name__, detail))
+
+
+def _format_str(*args):
+ r"""
+ Return a tuple containing representations of all args.
+
+ Same as map(repr, args) except that it returns multi-line
+ representations for strings containing newlines, e.g.::
+
+ '''\
+ foo \n\
+ bar
+
+ baz'''
+
+ instead of::
+
+ 'foo \nbar\n\nbaz'
+
+ This is a helper function for CustomTestCase.
+ """
+ return_tuple = []
+ for i in args:
+ r = repr(i)
+ if ( (isinstance(i, bytes) or isinstance(i, unicode))
+ and '\n' in i):
+ stripped = ''
+ if isinstance(i, unicode) and r.startswith('u'):
+ stripped = r[0]
+ r = r[1:]
+ elif isinstance(i, bytes) and r.startswith('b'):
+ stripped = r[0]
+ r = r[1:]
+ # quote_char = "'" or '"'
+ quote_char = r[0]
+ assert quote_char in ("'", '"'), quote_char
+ assert r[0] == r[-1]
+ r = r[1:-1]
+ r = (stripped + 3 * quote_char + '\\\n' +
+ re.sub(r'(?<!\\)((\\\\)*)\\n', r'\1\n', r) +
+ 3 * quote_char)
+ r = re.sub(r' \n', r' \\n\\\n', r)
+ return_tuple.append(r)
+ return tuple(return_tuple)
--- /dev/null
+Testing Docutils 0.16 with Python 2.7.16 on 2020-01-12 at 14:29:30
+OS: Linux 5.0.0-38-generic #41-Ubuntu SMP Tue Dec 3 00:27:35 UTC 2019 (linux2, Linux-5.0.0-38-generic-x86_64-with-Ubuntu-19.04-disco)
+Working directory: /home/engelbert/projects/docutils-code/docutils/test
+Docutils package: /home/engelbert/projects/docutils-code/docutils/docutils
+Elapsed time: 6.861 seconds
--- /dev/null
+#!/bin/sh
+''''exec python -u "$0" "$@" #'''
+from __future__ import print_function
+
+# $Id: alltests.py 8346 2019-08-26 12:11:32Z milde $
+# Author: David Goodger <goodger@python.org>
+# Copyright: This module has been placed in the public domain.
+
+__doc__ = """\
+All modules named 'test_*.py' in the current directory, and recursively in
+subdirectories (packages) called 'test_*', are loaded and test suites within
+are run.
+"""
+
+import time
+# Start point for actual elapsed time, including imports
+# and setup outside of unittest.
+start = time.time() # noqa
+
+import sys
+import atexit
+import os
+import platform
+import DocutilsTestSupport # must be imported before docutils
+import docutils
+
+
+class Tee(object):
+
+ """Write to a file and a stream (default: stdout) simultaneously."""
+
+ def __init__(self, filename, stream=sys.__stdout__):
+ self.file = open(filename, 'w')
+ atexit.register(self.close)
+ self.stream = stream
+ self.encoding = getattr(stream, 'encoding', None)
+
+ def close(self):
+ self.file.close()
+ self.file = None
+
+ def write(self, string):
+ try:
+ self.stream.write(string)
+ if self.file:
+ self.file.write(string)
+ except UnicodeEncodeError: # Py3k writing to "ascii" stream/file
+ string = string.encode('raw_unicode_escape').decode('ascii')
+ self.stream.write(string)
+ if self.file:
+ self.file.write(string)
+
+ def flush(self):
+ self.stream.flush()
+ if self.file:
+ self.file.flush()
+
+
+def pformat(suite):
+ step = 4
+ suitestr = repr(suite).replace('=[<', '=[\n<').replace(', ', ',\n')
+ indent = 0
+ output = []
+ for line in suitestr.splitlines():
+ output.append(' ' * indent + line)
+ if line[-1:] == '[':
+ indent += step
+ else:
+ if line[-5:] == ']>]>,':
+ indent -= step * 2
+ elif line[-3:] == ']>,':
+ indent -= step
+ return '\n'.join(output)
+
+
+def suite():
+ path, script = os.path.split(sys.argv[0])
+ suite = package_unittest.loadTestModules(DocutilsTestSupport.testroot,
+ 'test_', packages=1)
+ sys.stdout.flush()
+ return suite
+
+
+# must redirect stderr *before* first import of unittest
+sys.stdout = sys.stderr = Tee('alltests.out')
+
+import package_unittest # noqa
+
+
+if __name__ == '__main__':
+ suite = suite()
+ print('Testing Docutils %s with Python %s on %s at %s' % (
+ docutils.__version__, sys.version.split()[0],
+ time.strftime('%Y-%m-%d'), time.strftime('%H:%M:%S')))
+ print('OS: %s %s %s (%s, %s)' % (
+ platform.system(), platform.release(), platform.version(),
+ sys.platform, platform.platform()))
+ print('Working directory: %s' % os.getcwd())
+ print('Docutils package: %s' % os.path.dirname(docutils.__file__))
+ sys.stdout.flush()
+ result = package_unittest.main(suite)
+ finish = time.time()
+ print('Elapsed time: %.3f seconds' % (finish - start))
+ sys.exit(not result.wasSuccessful())
--- /dev/null
+#!/bin/bash
+
+# $Id: coverage.sh 5539 2008-03-30 09:05:39Z wiemann $
+# Author: Lea Wiemann <LeWiemann@gmail.com>
+# Copyright: This script has been placed in the public domain.
+
+# Usage: ./coverage.sh [project, [module]]
+
+set -e
+# Resolve all symlinks in current path.
+cd -P .
+proj="${PWD##*/}"
+if test "$proj" == test; then
+ cd ..
+ proj="${PWD##*/}"
+fi
+if test "$1"; then
+ proj="$1"
+fi
+module="${2:-alltests.py}"
+module="${module#test/}"
+echo "Performing code coverage test for project \"$proj\", test module \"$module\"..."
+echo
+echo "Please be patient; coverage tracking slows test execution down by more"
+echo "than factor 10."
+echo
+cd test
+rm -rf cover
+mkdir -p cover
+python -u -m trace --count --coverdir=cover --missing "$module"
+cd ..
+echo
+echo
+echo Uncovered lines
+echo ===============
+echo
+(
+ find "$proj/" -name \*.py | while read i; do
+ i="${i%.py}"
+ test -f test/cover/"${i//\//.}".cover -o "${i##*/}" == Template || echo "${i//\//.}" "`cat "$i.py" | wc -l`"
+ done
+ cd test/cover
+ find . \( -name . -o ! -name "$proj".\* -exec rm {} \; \)
+ for i in *.cover; do
+ sed 's/^>>>>>> \(.*"""\)/ \1/' < "$i" > "${i%.cover}"
+ rm "$i"
+ done
+ for i in *; do echo -n "$i "; grep -c '^>>>>>> ' "$i" || true; done
+) | grep -v ' 0$' | sort -nk 2
--- /dev/null
+# Test config file (new format)
+
+[general]
+
+source-link: on
+datestamp: %Y-%m-%d %H:%M UTC
+generator: true
+raw-enabled: off
+
+[restructuredtext parser]
+
+trim-footnote-reference-space: 1
+tab-width = 8
+
+
+[html4css1 writer]
+
+stylesheet-path: stylesheets/default.css
+
+
+[pep_html writer]
+
+template: pep-html-template
+stylesheet-path: stylesheets/pep.css
+python-home: http://www.python.org
+no-random: yes
--- /dev/null
+# Test config file (new format)
+
+[general]
+
+generator: no
+
+
+[html4css1 writer]
+
+footnote-references: superscript
+stylesheet-path: test.css
--- /dev/null
+[general]
+error_encoding: ascii:strict
--- /dev/null
+[general]
+expose_internals: a
+strip-classes: spam
+strip-elements-with-classes: sugar, flour
+
+[html4css1 writer]
+expose_internals: b:c:d
+strip-classes: pan,
+ fun,
+strip-elements-with-classes: milk
+
+[pep_html writer]
+expose_internals: e
+strip-classes: parrot
+strip-elements-with-classes: safran
--- /dev/null
+[general]
+expose_internals: f
+strip-classes: ham, eggs
+strip-elements-with-classes: eggs,salt
--- /dev/null
+# Test config file (old format)
+
+[options]
+
+source-link: 1
+datestamp: %Y-%m-%d %H:%M UTC
+generator: 1
+
+stylesheet-path: stylesheets/default.css
+
+pep-template: pep-html-template
+pep-stylesheet-path: stylesheets/pep.css
+python-home: http://www.python.org
+no-random: 1
--- /dev/null
+.. csv-table::
+ :file: csv_data.txt
--- /dev/null
+Test input for test_dependencies.
+
+Docutils can write a list of files required to generate the output like
+included files or embedded stylesheets. This is particularly useful in
+conjunction with programs like ``make``.
+
+Included files are recorded:
+
+.. include:: include.txt
+
+.. raw:: HTML
+ :file: raw.txt
+
+Dependencies are recorded only once:
+
+.. include:: include.txt
+
+Image files are only recorded, if actually accessed
+(to extract the size or if embedded in the output document):
+
+.. image:: test.jpg
+
+.. figure:: ../docs/user/rst/images/title.png
+ :figwidth: image
+
+Scaled images without given size are recorded by the html writer:
+
+.. image:: ../docs/user/rst/images/biohazard.png
+ :scale: 50 %
+
+TODO: Paths in included files should be rewritten relative to the base
+ document.
+
+ * when loading images,
+ * when recording dependencies.
+
+.. include: subdir/dependencies-included.txt
--- /dev/null
+head_prefix = """\
+%(head_prefix)s"""
+
+
+head = """\
+%(head)s"""
+
+
+stylesheet = """\
+%(stylesheet)s"""
+
+
+body_prefix = """\
+%(body_prefix)s"""
+
+
+body_pre_docinfo = """\
+%(body_pre_docinfo)s"""
+
+
+docinfo = """\
+%(docinfo)s"""
+
+
+body = """\
+%(body)s"""
+
+
+body_suffix = """\
+%(body_suffix)s"""
+
+
+head_prefix = """\
+%(head_prefix)s"""
+
+
+head = """\
+%(head)s"""
+
+
+stylesheet = """\
+%(stylesheet)s"""
+
+
+body_prefix = """\
+%(body_prefix)s"""
+
+
+body_pre_docinfo = """\
+%(body_pre_docinfo)s"""
+
+
+docinfo = """\
+%(docinfo)s"""
+
+
+body = """\
+%(body)s"""
+
+
+body_suffix = """\
+%(body_suffix)s"""
+
+
+title = """\
+%(title)s"""
+
+
+subtitle = """\
+%(subtitle)s"""
+
+
+header = """\
+%(header)s"""
+
+
+footer = """\
+%(footer)s"""
+
+
+meta = """\
+%(meta)s"""
+
+
+fragment = """\
+%(fragment)s"""
+
+
+html_prolog = """\
+%(html_prolog)s"""
+
+
+html_head = """\
+%(html_head)s"""
+
+
+html_title = """\
+%(html_title)s"""
+
+
+html_subtitle = """\
+%(html_subtitle)s"""
+
+
+html_body = """\
+%(html_body)s"""
--- /dev/null
+dl.docutils dd {
+ margin-bottom: 0.5em }
--- /dev/null
+\newcommand{\ham}{wonderful ham}
--- /dev/null
+Some include text.
--- /dev/null
+[general]
+# This tests the test framework; this config file should *not* be read
+# when testing.
+source-link: yes
+datestamp: %Y-%m-%d %H:%M UTC (If you see this in test output, there's a bug in the test code!)
+generator: on
+
+[buildhtml application]
+# This part is not for testing, but to prevent tools/buildhtml.py from
+# processing text files in and below this directory.
+prune: .
--- /dev/null
+This directory stores data files for functional tests.
+
+Please see the documentation on `functional testing`__ for details.
+
+__ ../../docs/dev/testing.html#functional
--- /dev/null
+<?xml version="1.0" encoding="utf-8" ?>
+<!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">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<meta name="generator" content="Docutils 0.16: http://docutils.sourceforge.net/" />
+<title>compact_lists.txt</title>
+<link rel="stylesheet" href="../input/data/html4css1.css" type="text/css" />
+</head>
+<body>
+<div class="document">
+
+
+<ul class="simple">
+<li>This is an ordinary simple bullet list.</li>
+<li>It should be made compact (<p> & </p> tags omitted).</li>
+</ul>
+<hr class="docutils" />
+<ul>
+<li><p class="first">This is a bullet list that is not simple.</p>
+<p>There are multiple paragraphs in some items.</p>
+</li>
+<li><p class="first">It should not be made compact.</p>
+</li>
+<li><p class="first">Even though some items may have only one paragraph.</p>
+</li>
+</ul>
+<hr class="docutils" />
+<ul class="open">
+<li><p class="first">This is a simple bullet list, but class="open" is set.</p>
+</li>
+<li><p class="first">It should not be made compact.</p>
+</li>
+</ul>
+<hr class="docutils" />
+<ul class="compact simple">
+<li>This is a bullet list that is not simple.<p>There are multiple paragraphs in some items.</p>
+</li>
+<li>However, the class="compact" setting will cause
+all first paragraph's <p> & </p> tags to be omitted.</li>
+<li>Items with multiple paragraphs will not appear changed.</li>
+<li>Items may have one paragraph, or multiple.<p>Items with multiple paragraphs will still be followed
+by vertical whitespace because of the later paragraphs.</p>
+</li>
+<li>The effect is interesting.</li>
+</ul>
+</div>
+</body>
+</html>
--- /dev/null
+\documentclass[a4paper,russian]{article}
+% generated by Docutils <http://docutils.sourceforge.net/>
+\usepackage{cmap} % fix search and cut-and-paste in Acrobat
+\usepackage{ifthen}
+\usepackage[T1,T2A]{fontenc}
+\usepackage[utf8]{inputenc}
+\usepackage[english,russian]{babel}
+\setcounter{secnumdepth}{0}
+
+%%% Custom LaTeX preamble
+% PDF Standard Fonts
+\usepackage{mathptmx} % Times
+\usepackage[scaled=.90]{helvet}
+\usepackage{courier}
+
+%%% User specified packages and stylesheets
+\usepackage{cmlgc}
+
+%%% Fallback definitions for Docutils-specific commands
+
+% titlereference role
+\providecommand*{\DUroletitlereference}[1]{\textsl{#1}}
+
+% hyperlinks:
+\ifthenelse{\isundefined{\hypersetup}}{
+ \usepackage[colorlinks=true,linkcolor=blue,urlcolor=blue,unicode=true]{hyperref}
+ \usepackage{bookmark}
+ \urlstyle{same} % normal text font (alternatives: tt, rm, sf)
+}{}
+
+%%% Body
+\begin{document}
+
+
+\section{Заголовок%
+ \label{section-1}%
+}
+
+первый пример: «Здравствуй, мир!»
+
+
+\section{Title%
+ \label{title}%
+}
+
+\foreignlanguage{english}{first example: “Hello world”.}
+
+
+\section{Notes%
+ \label{notes}%
+}
+
+\foreignlanguage{english}{This example tests rendering of Latin and Cyrillic characters by the LaTeX
+and XeTeX writers. Check the compiled PDF for garbage characters in text and
+bookmarks.}
+
+\foreignlanguage{english}{To work around a problem with Cyrillic in PDF-bookmarks in \DUroletitlereference{hyperref}
+versions older than v6.79g 2009/11/20, the test caller \texttt{latex\_cyrillic.py}
+sets \texttt{hyperref\_options} to \texttt{'unicode=true'} while \texttt{xetex\_cyrillic.py}
+sets it to \texttt{'unicode=false'}. The recommended option for current
+(2011-08-24) hyperref versions is \texttt{'pdfencoding=auto'}.}
+
+\end{document}
--- /dev/null
+<?xml version="1.0" encoding="utf-8" ?>
+<!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">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<meta name="generator" content="Docutils 0.16: http://docutils.sourceforge.net/" />
+<title>dangerous.txt</title>
+<link rel="stylesheet" href="../input/data/html4css1.css" type="text/css" />
+</head>
+<body>
+<div class="document">
+
+
+<p>Potentially dangerous features (security holes):</p>
+<div class="system-message">
+<p class="system-message-title">System Message: WARNING/2 (<tt class="docutils">functional/input/dangerous.txt</tt>, line 3)</p>
+<p>"include" directive disabled.</p>
+<pre class="literal-block">
+.. include:: /etc/passwd
+</pre>
+</div>
+<div class="system-message">
+<p class="system-message-title">System Message: WARNING/2 (<tt class="docutils">functional/input/dangerous.txt</tt>, line 4)</p>
+<p>"raw" directive disabled.</p>
+<pre class="literal-block">
+.. raw:: html
+ :file: /etc/passwd
+</pre>
+</div>
+<div class="system-message">
+<p class="system-message-title">System Message: WARNING/2 (<tt class="docutils">functional/input/dangerous.txt</tt>, line 6)</p>
+<p>"raw" directive disabled.</p>
+<pre class="literal-block">
+.. raw:: html
+ :url: file:///etc/passwd
+</pre>
+</div>
+<div class="system-message">
+<p class="system-message-title">System Message: WARNING/2 (<tt class="docutils">functional/input/dangerous.txt</tt>, line 8)</p>
+<p>"raw" directive disabled.</p>
+<pre class="literal-block">
+.. raw:: html
+
+ <script>
+ that does something really nasty
+ </script>
+</pre>
+</div>
+<div class="system-message">
+<p class="system-message-title">System Message: WARNING/2 (<tt class="docutils">functional/input/dangerous.txt</tt>, line 13)</p>
+<p>File and URL access deactivated; ignoring "csv-table" directive.</p>
+<pre class="literal-block">
+.. csv-table:: :file: /etc/passwd
+</pre>
+</div>
+<div class="system-message">
+<p class="system-message-title">System Message: WARNING/2 (<tt class="docutils">functional/input/dangerous.txt</tt>, line 14)</p>
+<p>File and URL access deactivated; ignoring "csv-table" directive.</p>
+<pre class="literal-block">
+.. csv-table:: :url: file:///etc/passwd
+</pre>
+</div>
+<div class="figure">
+<img alt="picture.png" src="picture.png" />
+</div>
+</div>
+</body>
+</html>
--- /dev/null
+<?xml version="1.0" encoding="utf-8" ?>
+<!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">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<meta name="generator" content="Docutils 0.16: http://docutils.sourceforge.net/" />
+<title>field_list.txt</title>
+<link rel="stylesheet" href="../input/data/html4css1.css" type="text/css" />
+</head>
+<body>
+<div class="document">
+
+
+<table class="docutils field-list" frame="void" rules="none">
+<col class="field-name" />
+<col class="field-body" />
+<tbody valign="top">
+<tr class="field"><th class="field-name">short:</th><td class="field-body">This field's name is short.</td>
+</tr>
+<tr class="field"><th class="field-name">medium-length:</th><td class="field-body">This field's name is medium-length.</td>
+</tr>
+<tr class="field"><th class="field-name">long field name:</th><td class="field-body">This field's name is long.</td>
+</tr>
+<tr class="field"><th class="field-name">very very long field name:</th><td class="field-body">This field's name is quite long.</td>
+</tr>
+</tbody>
+</table>
+</div>
+</body>
+</html>
--- /dev/null
+<!DOCTYPE html>
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+<meta charset="utf-8"/>
+<meta name="generator" content="Docutils 0.16: http://docutils.sourceforge.net/" />
+<title>Test footnote and citation rendering</title>
+<link rel="stylesheet" href="../input/data/minimal.css" type="text/css" />
+<link rel="stylesheet" href="../input/data/plain.css" type="text/css" />
+</head>
+<body>
+<div class="document" id="test-footnote-and-citation-rendering">
+<h1 class="title">Test footnote and citation rendering</h1>
+
+<p>Paragraphs may contain footnote references (manually numbered<a class="footnote-reference superscript" href="#footnote-1" id="footnote-reference-1">1</a>, anonymous auto-numbered<a class="footnote-reference superscript" href="#footnote-2" id="footnote-reference-2">3</a>, labeled auto-numbered<a class="footnote-reference superscript" href="#label" id="footnote-reference-3">2</a>, or
+symbolic<a class="footnote-reference superscript" href="#footnote-3" id="footnote-reference-4">*</a>) or citation references (<a class="citation-reference" href="#cit2002" id="citation-reference-1">[CIT2002]</a>, <a class="citation-reference" href="#du2015" id="citation-reference-2">[DU2015]</a>).</p>
+<dl class="footnote superscript">
+<dt class="label" id="footnote-1"><span class="superscript">1</span><span class="fn-backref">(<a href="#footnote-reference-1">1</a>,<a href="#footnote-reference-5">2</a>)</span></dt>
+<dd><p>A footnote contains body elements, consistently indented by at
+least 3 spaces.</p>
+<p>This is the footnote's second paragraph.</p>
+</dd>
+<dt class="label" id="label"><span class="superscript">2</span><span class="fn-backref">(<a href="#footnote-reference-3">1</a>,<a href="#footnote-reference-6">2</a>)</span></dt>
+<dd><p>Footnotes may be numbered, either manually (as in<a class="footnote-reference superscript" href="#footnote-1" id="footnote-reference-5">1</a>) or
+automatically using a "#"-prefixed label. This footnote has a
+label so it can be referred to from multiple places, both as a
+footnote reference (<a class="footnote-reference superscript" href="#label" id="footnote-reference-6">2</a>) and as a <a class="reference internal" href="#label">hyperlink reference</a>.</p>
+</dd>
+<dt class="label" id="footnote-2"><span class="superscript"><a class="fn-backref" href="#footnote-reference-2">3</a></span></dt>
+<dd><p>This footnote is numbered automatically and anonymously using a
+label of "#" only.</p>
+<p>This is the second paragraph.</p>
+<p>And this is the third paragraph.</p>
+</dd>
+<dt class="label" id="footnote-3"><span class="superscript"><a class="fn-backref" href="#footnote-reference-4">*</a></span></dt>
+<dd><p>Footnotes may also use symbols, specified with a "*" label.
+Here's a reference to the next footnote:<a class="footnote-reference superscript" href="#footnote-4" id="footnote-reference-7">†</a>.</p>
+</dd>
+<dt class="label" id="footnote-4"><span class="superscript"><a class="fn-backref" href="#footnote-reference-7">†</a></span></dt>
+<dd><p>This footnote shows the next symbol in the sequence.</p>
+</dd>
+<dt class="label" id="footnote-5"><span class="superscript">4</span></dt>
+<dd><p>Here's an unreferenced footnote, with a reference to a
+nonexistent footnote:<a class="footnote-reference superscript" href="#footnote-6" id="footnote-reference-8">5</a>.</p>
+</dd>
+</dl>
+<div class="section" id="citations">
+<h1>Citations</h1>
+<dl class="citation">
+<dt class="label" id="cit2002"><span class="brackets">CIT2002</span><span class="fn-backref">(<a href="#citation-reference-1">1</a>,<a href="#citation-reference-3">2</a>)</span></dt>
+<dd><p>Citations are text-labeled footnotes. They may be
+rendered separately and differently from footnotes.</p>
+</dd>
+<dt class="label" id="du2015"><span class="brackets"><a class="fn-backref" href="#citation-reference-2">DU2015</a></span></dt>
+<dd><p><cite>Example document</cite>, Hometown: 2015.</p>
+</dd>
+</dl>
+<p>Here's a reference to the above, <a class="citation-reference" href="#cit2002" id="citation-reference-3">[CIT2002]</a>.</p>
+<dl class="footnote superscript">
+<dt class="label" id="footnote-6"><span class="superscript"><a class="fn-backref" href="#footnote-reference-8">5</a></span></dt>
+<dd><p>this footnote is missing in the standard example document.</p>
+</dd>
+</dl>
+</div>
+</div>
+</body>
+</html>
--- /dev/null
+\documentclass[a4paper]{article}
+% generated by Docutils <http://docutils.sourceforge.net/>
+\usepackage{cmap} % fix search and cut-and-paste in Acrobat
+\usepackage{ifthen}
+\usepackage[T1]{fontenc}
+\usepackage[utf8]{inputenc}
+\usepackage[basque,esperanto,estonian,galician,ngerman,english]{babel}
+\AtBeginDocument{\shorthandoff{.<>}}
+\deactivatetilden % restore ~ in Galician
+\makeatletter
+ \addto\extrasestonian{\bbl@deactivate{~}}
+\makeatother
+\makeatletter
+ \addto\extrasbasque{\bbl@deactivate{~}}
+\makeatother
+
+%%% Custom LaTeX preamble
+% PDF Standard Fonts
+\usepackage{mathptmx} % Times
+\usepackage[scaled=.90]{helvet}
+\usepackage{courier}
+
+%%% User specified packages and stylesheets
+
+%%% Fallback definitions for Docutils-specific commands
+
+% hyperlinks:
+\ifthenelse{\isundefined{\hypersetup}}{
+ \usepackage[colorlinks=true,linkcolor=blue,urlcolor=blue]{hyperref}
+ \usepackage{bookmark}
+ \urlstyle{same} % normal text font (alternatives: tt, rm, sf)
+}{}
+
+%%% Body
+\begin{document}
+
+The \href{http://www.ctan.org/packages/babel}{babel} package introduces the concept of \textquotedbl{}shorthands\textquotedbl{}: additional
+characters that introduce a latex macro. Most common is the active double
+quote (\textquotedbl{}). Problematic is the tilde character (\textasciitilde{}) which is regularely used
+for no-break spaces but redefined by some language definition files:
+
+English: 'an' \textquotedbl{}active\textquotedbl{}-quote, \textasciicircum{}circumflex, and no-break spaces
+
+\foreignlanguage{basque}{Basque: 'an' \textquotedbl{}active\textquotedbl{}-quote, \textasciicircum{}circumflex, and no-break spaces}
+
+\foreignlanguage{esperanto}{Esperanto: 'an' \textquotedbl{}active\textquotedbl{}-quote, \textasciicircum{}circumflex, and no-break spaces}
+
+\foreignlanguage{estonian}{Estonian: 'an' \textquotedbl{}active\textquotedbl{}-quote, \textasciicircum{}circumflex, and no-break spaces}
+
+\foreignlanguage{galician}{Galician: 'an' \textquotedbl{}active\textquotedbl{}-quote, \textasciicircum{}circumflex, and no-break spaces}
+
+\foreignlanguage{ngerman}{German: 'an' \textquotedbl{}active\textquotedbl{}-quote, \textasciicircum{}circumflex, and no-break spaces}
+
+Spanish: option clash with Galician!
+
+% .. class:: language-es
+%
+% Spanish: 'an' "active"-quote, ^circumflex, and no-break spaces
+
+\end{document}
--- /dev/null
+\documentclass[a4paper]{article}
+% generated by Docutils <http://docutils.sourceforge.net/>
+\usepackage{cmap} % fix search and cut-and-paste in Acrobat
+\usepackage{ifthen}
+\usepackage[T1]{fontenc}
+\usepackage[utf8]{inputenc}
+\usepackage{graphicx}
+\usepackage{multirow}
+\setcounter{secnumdepth}{0}
+\usepackage{longtable,ltcaption,array}
+\setlength{\extrarowheight}{2pt}
+\newlength{\DUtablewidth} % internal use in tables
+
+%%% Custom LaTeX preamble
+% PDF Standard Fonts
+\usepackage{mathptmx} % Times
+\usepackage[scaled=.90]{helvet}
+\usepackage{courier}
+
+%%% User specified packages and stylesheets
+
+%%% Fallback definitions for Docutils-specific commands
+
+% transition (break, fancybreak, anonymous section)
+\providecommand*{\DUtransition}{%
+ \hspace*{\fill}\hrulefill\hspace*{\fill}
+ \vskip 0.5\baselineskip
+}
+
+% hyperlinks:
+\ifthenelse{\isundefined{\hypersetup}}{
+ \usepackage[colorlinks=true,linkcolor=blue,urlcolor=blue]{hyperref}
+ \usepackage{bookmark}
+ \urlstyle{same} % normal text font (alternatives: tt, rm, sf)
+}{}
+\hypersetup{
+ pdftitle={Some Tests for the LaTeX Writer},
+}
+
+%%% Body
+\begin{document}
+\title{Some Tests for the LaTeX Writer%
+ \label{some-tests-for-the-latex-writer}}
+\author{}
+\date{}
+\maketitle
+
+These tests contain unusual combinations of syntax elements which may cause
+trouble for the LaTeX writer but do not need to be tested with other writers.
+
+
+\section{Block Quotes%
+ \label{block-quotes}%
+}
+
+\begin{quote}
+This block quote comes directly after the section heading and is
+followed by a paragraph.
+
+This is the second paragraph of the block quote and it contains
+some more text filling up some space which would otherwise be
+empty.
+\nopagebreak
+
+\raggedleft —Attribution
+\end{quote}
+
+This is a paragraph.
+
+\begin{quote}
+This block quote does not have an attribution.
+\end{quote}
+
+This is another paragraph.
+
+\begin{quote}
+Another block quote at the end of the section.
+\end{quote}
+
+
+\section{More Block Quotes%
+ \label{more-block-quotes}%
+}
+
+\begin{quote}
+Block quote followed by a transition.
+\end{quote}
+
+%___________________________________________________________________________
+\DUtransition
+
+\begin{quote}
+Another block quote.
+\end{quote}
+
+
+\section{Images%
+ \label{images}%
+}
+
+Image with 20\% width:
+
+\includegraphics[width=0.200\linewidth]{../../../docs/user/rst/images/title.png}
+
+Image with 100\% width:
+
+\includegraphics[width=1.000\linewidth]{../../../docs/user/rst/images/title.png}
+
+
+\section{Rowspanning tables%
+ \label{rowspanning-tables}%
+}
+
+Several rowspanning cells in a table.
+
+Problem:
+
+In LaTeX, \textquotedbl{}overwritten\textquotedbl{} cells need to be defined as empty cells.
+
+Docutils (similarily to HTML) uses is the \textquotedbl{}Exchange Table Model\textquotedbl{} (also known
+as CALS tables, see docs/ref/soextblx.dtd) which defines only the remaining
+cells in a row \textquotedbl{}affected\textquotedbl{} by multirow cells.
+
+Therefore, visit\_entry() is only called for the remaining cells and the
+LaTeX writer needs bookkeeping to write out the required number of extra
+'\&'s.
+
+\setlength{\DUtablewidth}{\linewidth}
+\begin{longtable*}[c]{|p{0.075\DUtablewidth}|p{0.133\DUtablewidth}|p{0.133\DUtablewidth}|p{0.086\DUtablewidth}|}
+\hline
+
+11
+ &
+12
+ &
+13
+ &
+14
+ \\
+\hline
+
+21
+ & \multirow{2}{0.13\DUtablewidth}{%
+2/3 2
+} & \multirow{3}{0.13\DUtablewidth}{%
+2…4 3
+} &
+24
+ \\
+\cline{1-1}
+\cline{4-4}
+
+31
+ & & &
+34
+ \\
+\cline{1-1}
+\cline{2-2}
+\cline{4-4}
+
+41
+ &
+42
+ & &
+14
+ \\
+\hline
+\end{longtable*}
+
+\setlength{\DUtablewidth}{\linewidth}
+\begin{longtable*}[c]{|p{0.098\DUtablewidth}|p{0.098\DUtablewidth}|p{0.063\DUtablewidth}|}
+\hline
+
+11
+ &
+12
+ &
+13
+ \\
+\hline
+\multirow{2}{0.10\DUtablewidth}{%
+2/3 1
+} & \multirow{2}{0.10\DUtablewidth}{%
+2/3 2
+} &
+23
+ \\
+\cline{3-3}
+ & &
+33
+ \\
+\hline
+\end{longtable*}
+
+\setlength{\DUtablewidth}{\linewidth}
+\begin{longtable*}[c]{|p{0.098\DUtablewidth}|p{0.063\DUtablewidth}|}
+\hline
+
+11
+ &
+12
+ \\
+\hline
+\multirow{2}{0.10\DUtablewidth}{%
+2/3 1
+} &
+22
+ \\
+\cline{2-2}
+ &
+32
+ \\
+\hline
+\end{longtable*}
+
+\setlength{\DUtablewidth}{\linewidth}
+\begin{longtable*}[c]{|p{0.063\DUtablewidth}|p{0.110\DUtablewidth}|p{0.063\DUtablewidth}|}
+\hline
+
+11
+ &
+12
+ &
+13
+ \\
+\hline
+
+21
+ & \multirow{2}{0.11\DUtablewidth}{%
+2/3 2
+} &
+23
+ \\
+\cline{1-1}
+\cline{3-3}
+
+31
+ & &
+33
+ \\
+\hline
+\end{longtable*}
+
+\setlength{\DUtablewidth}{\linewidth}
+\begin{longtable*}[c]{|p{0.063\DUtablewidth}|p{0.110\DUtablewidth}|}
+\hline
+
+11
+ &
+12
+ \\
+\hline
+
+21
+ & \multirow{2}{0.11\DUtablewidth}{%
+2/3 1
+} \\
+\cline{1-1}
+
+31
+ & \\
+\hline
+\end{longtable*}
+
+\setlength{\DUtablewidth}{\linewidth}
+\begin{longtable*}[c]{|p{0.063\DUtablewidth}|p{0.110\DUtablewidth}|}
+\hline
+
+11
+ & \multirow{2}{0.11\DUtablewidth}{%
+1/2 1
+} \\
+\cline{1-1}
+
+21
+ & \\
+\hline
+
+31
+ &
+32
+ \\
+\hline
+\end{longtable*}
+
+\setlength{\DUtablewidth}{\linewidth}
+\begin{longtable*}[c]{|p{0.063\DUtablewidth}|p{0.156\DUtablewidth}|p{0.110\DUtablewidth}|}
+\hline
+
+11
+ & \multirow{2}{0.16\DUtablewidth}{%
+1/2 2
+} & \multirow{2}{0.11\DUtablewidth}{%
+1/2 3
+} \\
+\cline{1-1}
+
+21
+ & & \\
+\hline
+\end{longtable*}
+
+\setlength{\DUtablewidth}{\linewidth}
+\begin{longtable*}[c]{|p{0.098\DUtablewidth}|p{0.063\DUtablewidth}|p{0.110\DUtablewidth}|}
+\hline
+\multirow{2}{0.10\DUtablewidth}{%
+1/2 3
+} &
+12
+ & \multirow{2}{0.11\DUtablewidth}{%
+1/2 3
+} \\
+\cline{2-2}
+ &
+22
+ & \\
+\hline
+\end{longtable*}
+
+\setlength{\DUtablewidth}{\linewidth}
+\begin{longtable*}[c]{|p{0.098\DUtablewidth}|p{0.063\DUtablewidth}|}
+\hline
+\multirow{2}{0.10\DUtablewidth}{%
+1/2 3
+} &
+12
+ \\
+\cline{2-2}
+ &
+22
+ \\
+\hline
+
+31
+ &
+32
+ \\
+\hline
+\end{longtable*}
+
+\end{document}
--- /dev/null
+\documentclass[a4paper]{article}
+% generated by Docutils <http://docutils.sourceforge.net/>
+\usepackage{cmap} % fix search and cut-and-paste in Acrobat
+\usepackage{ifthen}
+\usepackage[T1]{fontenc}
+\usepackage[utf8]{inputenc}
+
+%%% Custom LaTeX preamble
+% PDF Standard Fonts
+\usepackage{mathptmx} % Times
+\usepackage[scaled=.90]{helvet}
+\usepackage{courier}
+
+%%% User specified packages and stylesheets
+
+%%% Fallback definitions for Docutils-specific commands
+
+% hyperlinks:
+\ifthenelse{\isundefined{\hypersetup}}{
+ \usepackage[colorlinks=true,linkcolor=blue,urlcolor=blue]{hyperref}
+ \usepackage{bookmark}
+ \urlstyle{same} % normal text font (alternatives: tt, rm, sf)
+}{}
+\hypersetup{
+ pdfauthor={Foo Fred;Bar Barney}
+}
+
+%%% Body
+\begin{document}
+\title{}
+\author{Foo Fred\\
+Food Foomatics \& Friends\\
+foo@food.example.info\\
+Fox St 13\\
+Foowood \and
+Bar Barney\\
+Bar-BQ Bar\\
+1-800-BARBQBAR\\
+Barbara St 16\\
+South Barwell}
+\date{}
+\maketitle
+
+\end{document}
--- /dev/null
+\documentclass[a4paper]{article}
+% generated by Docutils <http://docutils.sourceforge.net/>
+\usepackage{cmap} % fix search and cut-and-paste in Acrobat
+\usepackage{ifthen}
+\usepackage[T1]{fontenc}
+\usepackage[utf8]{inputenc}
+\usepackage{alltt}
+\usepackage{amsmath}
+\usepackage{graphicx}
+\usepackage{longtable,ltcaption,array}
+\setlength{\extrarowheight}{2pt}
+\newlength{\DUtablewidth} % internal use in tables
+
+%%% Custom LaTeX preamble
+% PDF Standard Fonts
+\usepackage{mathptmx} % Times
+\usepackage[scaled=.90]{helvet}
+\usepackage{courier}
+
+%%% User specified packages and stylesheets
+
+%%% Fallback definitions for Docutils-specific commands
+
+% 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]%
+ {\def\DocutilsClassFunctionName{DUCLASS#1}% arg cannot be used in end-part of environment.
+ \csname \DocutilsClassFunctionName \endcsname}%
+ {\csname end\DocutilsClassFunctionName \endcsname}%
+\fi
+
+% admonition (specially marked topic)
+\providecommand{\DUadmonition}[2][class-arg]{%
+ % try \DUadmonition#1{#2}:
+ \ifcsname DUadmonition#1\endcsname%
+ \csname DUadmonition#1\endcsname{#2}%
+ \else
+ \begin{center}
+ \fbox{\parbox{0.9\linewidth}{#2}}
+ \end{center}
+ \fi
+}
+% numeric or symbol footnotes with hyperlinks
+\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 markup (custom roles)
+% \DUrole{#1}{#2} tries \DUrole#1{#2}
+\providecommand*{\DUrole}[2]{%
+ \ifcsname DUrole#1\endcsname%
+ \csname DUrole#1\endcsname{#2}%
+ \else
+ % backwards compatibility: try \docutilsrole#1{#2}
+ \ifcsname docutilsrole#1\endcsname%
+ \PackageWarningNoLine{docutils}{Command prefix "docutilsrole" is
+ deprecated, \MessageBreak use `\protect\DUrole #1`}
+ \csname docutilsrole#1\endcsname{#2}%
+ \else%
+ #2%
+ \fi%
+ \fi%
+}
+
+% text mode subscript
+\ifx\textsubscript\undefined
+ \usepackage{fixltx2e} % since 2015 loaded by default
+\fi
+
+% title for topics, admonitions, unsupported section levels, and sidebar
+\providecommand*{\DUtitle}[2][class-arg]{%
+ % call \DUtitle#1{#2} if it exists:
+ \ifcsname DUtitle#1\endcsname%
+ \csname DUtitle#1\endcsname{#2}%
+ \else
+ \smallskip\noindent\textbf{#2}\smallskip%
+ \fi
+}
+
+% titlereference role
+\providecommand*{\DUroletitlereference}[1]{\textsl{#1}}
+
+% character width in monospaced font
+\newlength{\ttemwidth}
+\settowidth{\ttemwidth}{\ttfamily M}
+
+% hyperlinks:
+\ifthenelse{\isundefined{\hypersetup}}{
+ \usepackage[colorlinks=true,linkcolor=blue,urlcolor=blue]{hyperref}
+ \usepackage{bookmark}
+ \urlstyle{same} % normal text font (alternatives: tt, rm, sf)
+}{}
+
+%%% Body
+\begin{document}
+
+In LaTeX, literal blocks can be customized with the \textquotedbl{}literal-block-env\textquotedbl{}
+setting. This test file exists to check if the LaTeX writer output compiles
+and looks as expected.
+
+Start with a plain literal block:
+
+\begin{quote}
+\begin{alltt}
+$\textbackslash{}sin^2(x)$ and $\textbackslash{}cos^2(x)$ equals one:
+
+\textbackslash{}[
+ \textbackslash{}sin^2(x) + \textbackslash{}cos^2(x) = 1 % for all x
+\textbackslash{}]
+\end{alltt}
+\end{quote}
+
+A latex \textquotedbl{}code-block\textquotedbl{} (set with \textquotedbl{}literal-block-env\textquotedbl{}, if syntax
+highlight is \textquotedbl{}none\textquotedbl{}):
+
+\begin{DUclass}{code}
+\begin{DUclass}{latex}
+\begin{quote}
+\begin{alltt}
+$\textbackslash{}sin^2(x)$ and $\textbackslash{}cos^2(x)$ equals one:
+
+\textbackslash{}[
+ \textbackslash{}sin^2(x) + \textbackslash{}cos^2(x) = 1 % for all x
+\textbackslash{}]
+\end{alltt}
+\end{quote}
+\end{DUclass}
+\end{DUclass}
+
+A literal block in a table:
+
+\setlength{\DUtablewidth}{\linewidth}
+\begin{longtable*}[c]{|p{0.063\DUtablewidth}|p{0.145\DUtablewidth}|p{0.063\DUtablewidth}|}
+\hline
+
+test
+ &
+\begin{minipage}{8\ttemwidth}
+\begin{alltt}
+\textbackslash{}sin^2 x
+\end{alltt}
+\end{minipage}
+ &
+test
+ \\
+\hline
+\end{longtable*}
+
+A literal block in a table with auto-width columns:
+
+\begin{longtable*}[c]{|l|l|l|}
+\hline
+test &
+\ttfamily\raggedright
+\textbackslash{}sin\textasciicircum{}2~x
+ & test \\
+\hline
+\end{longtable*}
+
+\DUadmonition[note]{
+\DUtitle[note]{Note}
+
+A literal block in an admonition:
+
+\begin{quote}
+\ttfamily\raggedright
+\textbackslash{}sin\textasciicircum{}2~x
+\end{quote}
+}
+
+Parsed literal block with inline markup and leading whitespace:
+
+\begin{quote}
+\ttfamily\raggedright
+~~~\emph{emphasis},~\textbf{strong~emphasis},~\texttt{inline~literals},\\
+standalone~hyperlinks~(\url{http://www.python.org}),\\
+\hyperref[internal]{internal}~and~\href{http://www.python.org/}{external}~hyperlinks,\\
+%
+\phantomsection\label{internal}internal~hyperlink~targets,\\
+images~via~substitution~references~(\includegraphics{../../../docs/user/rst/images/biohazard.png}),\\
+footnote~references\DUfootnotemark{footnote-reference-1}{footnote-1}{*},\\
+citation~references~(\hyperlink{cit2002}{[CIT2002]}),~and~more.\\
+~\\
+~~~Here~are~some~explicit~interpreted~text~roles:\\
+a~PEP~reference~(\href{http://www.python.org/dev/peps/pep-0287}{PEP~287}),\\
+an~RFC~reference~(\href{http://tools.ietf.org/html/rfc2822.html}{RFC~2822}),\\
+an~abbreviation~(\DUrole{abbreviation}{abb.}),~an~acronym~(\DUrole{acronym}{reST}),\\
+code~(\texttt{\DUrole{code}{print~\textquotedbl{}hello~world\textquotedbl{}}}),\\
+maths~$\sin^2(x)$,\\
+\textsubscript{subscript}~and~\textsuperscript{superscript},\\
+\DUrole{custom}{custom}~\DUrole{custom-role}{roles},~and~explicit~roles~for\\
+\DUroletitlereference{Docutils}'~\emph{standard}~\textbf{inline}~\texttt{markup}.
+\end{quote}
+%
+\DUfootnotetext{footnote-1}{footnote-reference-1}{*}{%
+This footnote is referenced in a \DUroletitlereference{parsed literal} block.
+
+It contains a literal block:
+
+\begin{quote}
+\ttfamily\raggedright
+\textbackslash{}sin\textasciicircum{}2~x
+\end{quote}
+}
+\begin{figure}[b]\raisebox{1em}{\hypertarget{cit2002}{}}[CIT2002]
+Sample Citation, 2017.
+\end{figure}
+
+\end{document}
--- /dev/null
+\documentclass[a4paper]{article}
+% generated by Docutils <http://docutils.sourceforge.net/>
+\usepackage{cmap} % fix search and cut-and-paste in Acrobat
+\usepackage{ifthen}
+\usepackage[T1]{fontenc}
+\usepackage[utf8]{inputenc}
+\usepackage{amsmath}
+\usepackage{graphicx}
+\usepackage{fancyvrb}
+\usepackage{longtable,ltcaption,array}
+\setlength{\extrarowheight}{2pt}
+\newlength{\DUtablewidth} % internal use in tables
+
+%%% Custom LaTeX preamble
+% PDF Standard Fonts
+\usepackage{mathptmx} % Times
+\usepackage[scaled=.90]{helvet}
+\usepackage{courier}
+
+%%% User specified packages and stylesheets
+
+%%% Fallback definitions for Docutils-specific commands
+
+% 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]%
+ {\def\DocutilsClassFunctionName{DUCLASS#1}% arg cannot be used in end-part of environment.
+ \csname \DocutilsClassFunctionName \endcsname}%
+ {\csname end\DocutilsClassFunctionName \endcsname}%
+\fi
+
+% admonition (specially marked topic)
+\providecommand{\DUadmonition}[2][class-arg]{%
+ % try \DUadmonition#1{#2}:
+ \ifcsname DUadmonition#1\endcsname%
+ \csname DUadmonition#1\endcsname{#2}%
+ \else
+ \begin{center}
+ \fbox{\parbox{0.9\linewidth}{#2}}
+ \end{center}
+ \fi
+}
+% numeric or symbol footnotes with hyperlinks
+\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 markup (custom roles)
+% \DUrole{#1}{#2} tries \DUrole#1{#2}
+\providecommand*{\DUrole}[2]{%
+ \ifcsname DUrole#1\endcsname%
+ \csname DUrole#1\endcsname{#2}%
+ \else
+ % backwards compatibility: try \docutilsrole#1{#2}
+ \ifcsname docutilsrole#1\endcsname%
+ \PackageWarningNoLine{docutils}{Command prefix "docutilsrole" is
+ deprecated, \MessageBreak use `\protect\DUrole #1`}
+ \csname docutilsrole#1\endcsname{#2}%
+ \else%
+ #2%
+ \fi%
+ \fi%
+}
+
+% text mode subscript
+\ifx\textsubscript\undefined
+ \usepackage{fixltx2e} % since 2015 loaded by default
+\fi
+
+% title for topics, admonitions, unsupported section levels, and sidebar
+\providecommand*{\DUtitle}[2][class-arg]{%
+ % call \DUtitle#1{#2} if it exists:
+ \ifcsname DUtitle#1\endcsname%
+ \csname DUtitle#1\endcsname{#2}%
+ \else
+ \smallskip\noindent\textbf{#2}\smallskip%
+ \fi
+}
+
+% titlereference role
+\providecommand*{\DUroletitlereference}[1]{\textsl{#1}}
+
+% character width in monospaced font
+\newlength{\ttemwidth}
+\settowidth{\ttemwidth}{\ttfamily M}
+
+% hyperlinks:
+\ifthenelse{\isundefined{\hypersetup}}{
+ \usepackage[colorlinks=true,linkcolor=blue,urlcolor=blue]{hyperref}
+ \usepackage{bookmark}
+ \urlstyle{same} % normal text font (alternatives: tt, rm, sf)
+}{}
+
+%%% Body
+\begin{document}
+
+In LaTeX, literal blocks can be customized with the \textquotedbl{}literal-block-env\textquotedbl{}
+setting. This test file exists to check if the LaTeX writer output compiles
+and looks as expected.
+
+Start with a plain literal block:
+
+\begin{quote}
+\begin{Verbatim}
+$\sin^2(x)$ and $\cos^2(x)$ equals one:
+
+\[
+ \sin^2(x) + \cos^2(x) = 1 % for all x
+\]
+\end{Verbatim}
+\end{quote}
+
+A latex \textquotedbl{}code-block\textquotedbl{} (set with \textquotedbl{}literal-block-env\textquotedbl{}, if syntax
+highlight is \textquotedbl{}none\textquotedbl{}):
+
+\begin{DUclass}{code}
+\begin{DUclass}{latex}
+\begin{quote}
+\begin{Verbatim}
+$\sin^2(x)$ and $\cos^2(x)$ equals one:
+
+\[
+ \sin^2(x) + \cos^2(x) = 1 % for all x
+\]
+\end{Verbatim}
+\end{quote}
+\end{DUclass}
+\end{DUclass}
+
+A literal block in a table:
+
+\setlength{\DUtablewidth}{\linewidth}
+\begin{longtable*}[c]{|p{0.063\DUtablewidth}|p{0.145\DUtablewidth}|p{0.063\DUtablewidth}|}
+\hline
+
+test
+ &
+\begin{minipage}{8\ttemwidth}
+\begin{Verbatim}
+\sin^2 x
+\end{Verbatim}
+\end{minipage}
+ &
+test
+ \\
+\hline
+\end{longtable*}
+
+A literal block in a table with auto-width columns:
+
+\begin{longtable*}[c]{|l|l|l|}
+\hline
+test &
+\ttfamily\raggedright
+\textbackslash{}sin\textasciicircum{}2~x
+ & test \\
+\hline
+\end{longtable*}
+
+\DUadmonition[note]{
+\DUtitle[note]{Note}
+
+A literal block in an admonition:
+
+\begin{quote}
+\ttfamily\raggedright
+\textbackslash{}sin\textasciicircum{}2~x
+\end{quote}
+}
+
+Parsed literal block with inline markup and leading whitespace:
+
+\begin{quote}
+\ttfamily\raggedright
+~~~\emph{emphasis},~\textbf{strong~emphasis},~\texttt{inline~literals},\\
+standalone~hyperlinks~(\url{http://www.python.org}),\\
+\hyperref[internal]{internal}~and~\href{http://www.python.org/}{external}~hyperlinks,\\
+%
+\phantomsection\label{internal}internal~hyperlink~targets,\\
+images~via~substitution~references~(\includegraphics{../../../docs/user/rst/images/biohazard.png}),\\
+footnote~references\DUfootnotemark{footnote-reference-1}{footnote-1}{*},\\
+citation~references~(\hyperlink{cit2002}{[CIT2002]}),~and~more.\\
+~\\
+~~~Here~are~some~explicit~interpreted~text~roles:\\
+a~PEP~reference~(\href{http://www.python.org/dev/peps/pep-0287}{PEP~287}),\\
+an~RFC~reference~(\href{http://tools.ietf.org/html/rfc2822.html}{RFC~2822}),\\
+an~abbreviation~(\DUrole{abbreviation}{abb.}),~an~acronym~(\DUrole{acronym}{reST}),\\
+code~(\texttt{\DUrole{code}{print~\textquotedbl{}hello~world\textquotedbl{}}}),\\
+maths~$\sin^2(x)$,\\
+\textsubscript{subscript}~and~\textsuperscript{superscript},\\
+\DUrole{custom}{custom}~\DUrole{custom-role}{roles},~and~explicit~roles~for\\
+\DUroletitlereference{Docutils}'~\emph{standard}~\textbf{inline}~\texttt{markup}.
+\end{quote}
+%
+\DUfootnotetext{footnote-1}{footnote-reference-1}{*}{%
+This footnote is referenced in a \DUroletitlereference{parsed literal} block.
+
+It contains a literal block:
+
+\begin{quote}
+\ttfamily\raggedright
+\textbackslash{}sin\textasciicircum{}2~x
+\end{quote}
+}
+\begin{figure}[b]\raisebox{1em}{\hypertarget{cit2002}{}}[CIT2002]
+Sample Citation, 2017.
+\end{figure}
+
+\end{document}
--- /dev/null
+\documentclass[a4paper]{article}
+% generated by Docutils <http://docutils.sourceforge.net/>
+\usepackage{cmap} % fix search and cut-and-paste in Acrobat
+\usepackage{ifthen}
+\usepackage[T1]{fontenc}
+\usepackage[utf8]{inputenc}
+\usepackage{amsmath}
+\usepackage{graphicx}
+\usepackage{listings}
+\lstset{xleftmargin=\leftmargin}
+\usepackage{longtable,ltcaption,array}
+\setlength{\extrarowheight}{2pt}
+\newlength{\DUtablewidth} % internal use in tables
+
+%%% Custom LaTeX preamble
+
+% PDF Standard Fonts
+\usepackage{mathptmx} % Times
+\usepackage[scaled=.90]{helvet}
+\usepackage{courier}
+% LaTeX syntax highlight with "listings":
+\lstloadlanguages{[LaTeX]TeX} % comma separated list of languages
+\newcommand{\DUCLASSlatex}{\lstset{language=[LaTeX]TeX}}
+
+
+%%% User specified packages and stylesheets
+
+%%% Fallback definitions for Docutils-specific commands
+
+% 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]%
+ {\def\DocutilsClassFunctionName{DUCLASS#1}% arg cannot be used in end-part of environment.
+ \csname \DocutilsClassFunctionName \endcsname}%
+ {\csname end\DocutilsClassFunctionName \endcsname}%
+\fi
+
+% admonition (specially marked topic)
+\providecommand{\DUadmonition}[2][class-arg]{%
+ % try \DUadmonition#1{#2}:
+ \ifcsname DUadmonition#1\endcsname%
+ \csname DUadmonition#1\endcsname{#2}%
+ \else
+ \begin{center}
+ \fbox{\parbox{0.9\linewidth}{#2}}
+ \end{center}
+ \fi
+}
+% numeric or symbol footnotes with hyperlinks
+\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 markup (custom roles)
+% \DUrole{#1}{#2} tries \DUrole#1{#2}
+\providecommand*{\DUrole}[2]{%
+ \ifcsname DUrole#1\endcsname%
+ \csname DUrole#1\endcsname{#2}%
+ \else
+ % backwards compatibility: try \docutilsrole#1{#2}
+ \ifcsname docutilsrole#1\endcsname%
+ \PackageWarningNoLine{docutils}{Command prefix "docutilsrole" is
+ deprecated, \MessageBreak use `\protect\DUrole #1`}
+ \csname docutilsrole#1\endcsname{#2}%
+ \else%
+ #2%
+ \fi%
+ \fi%
+}
+
+% text mode subscript
+\ifx\textsubscript\undefined
+ \usepackage{fixltx2e} % since 2015 loaded by default
+\fi
+
+% title for topics, admonitions, unsupported section levels, and sidebar
+\providecommand*{\DUtitle}[2][class-arg]{%
+ % call \DUtitle#1{#2} if it exists:
+ \ifcsname DUtitle#1\endcsname%
+ \csname DUtitle#1\endcsname{#2}%
+ \else
+ \smallskip\noindent\textbf{#2}\smallskip%
+ \fi
+}
+
+% titlereference role
+\providecommand*{\DUroletitlereference}[1]{\textsl{#1}}
+
+% character width in monospaced font
+\newlength{\ttemwidth}
+\settowidth{\ttemwidth}{\ttfamily M}
+
+% hyperlinks:
+\ifthenelse{\isundefined{\hypersetup}}{
+ \usepackage[colorlinks=true,linkcolor=blue,urlcolor=blue]{hyperref}
+ \usepackage{bookmark}
+ \urlstyle{same} % normal text font (alternatives: tt, rm, sf)
+}{}
+
+%%% Body
+\begin{document}
+
+In LaTeX, literal blocks can be customized with the \textquotedbl{}literal-block-env\textquotedbl{}
+setting. This test file exists to check if the LaTeX writer output compiles
+and looks as expected.
+
+Start with a plain literal block:
+
+\begin{lstlisting}
+$\sin^2(x)$ and $\cos^2(x)$ equals one:
+
+\[
+ \sin^2(x) + \cos^2(x) = 1 % for all x
+\]
+\end{lstlisting}
+
+A latex \textquotedbl{}code-block\textquotedbl{} (set with \textquotedbl{}literal-block-env\textquotedbl{}, if syntax
+highlight is \textquotedbl{}none\textquotedbl{}):
+
+\begin{DUclass}{code}
+\begin{DUclass}{latex}
+\begin{lstlisting}
+$\sin^2(x)$ and $\cos^2(x)$ equals one:
+
+\[
+ \sin^2(x) + \cos^2(x) = 1 % for all x
+\]
+\end{lstlisting}
+\end{DUclass}
+\end{DUclass}
+
+A literal block in a table:
+
+\setlength{\DUtablewidth}{\linewidth}
+\begin{longtable*}[c]{|p{0.063\DUtablewidth}|p{0.145\DUtablewidth}|p{0.063\DUtablewidth}|}
+\hline
+
+test
+ &
+\begin{minipage}{8\ttemwidth}
+\lstset{xleftmargin=0pt}
+\begin{lstlisting}
+\sin^2 x
+\end{lstlisting}
+\end{minipage}
+ &
+test
+ \\
+\hline
+\end{longtable*}
+
+A literal block in a table with auto-width columns:
+
+\begin{longtable*}[c]{|l|l|l|}
+\hline
+test &
+\lstset{xleftmargin=0pt}
+\begin{lstlisting}
+\sin^2 x
+\end{lstlisting}
+ & test \\
+\hline
+\end{longtable*}
+
+\DUadmonition[note]{
+\DUtitle[note]{Note}
+
+A literal block in an admonition:
+
+\begin{quote}
+\ttfamily\raggedright
+\textbackslash{}sin\textasciicircum{}2~x
+\end{quote}
+}
+
+Parsed literal block with inline markup and leading whitespace:
+
+\begin{quote}
+\ttfamily\raggedright
+~~~\emph{emphasis},~\textbf{strong~emphasis},~\texttt{inline~literals},\\
+standalone~hyperlinks~(\url{http://www.python.org}),\\
+\hyperref[internal]{internal}~and~\href{http://www.python.org/}{external}~hyperlinks,\\
+%
+\phantomsection\label{internal}internal~hyperlink~targets,\\
+images~via~substitution~references~(\includegraphics{../../../docs/user/rst/images/biohazard.png}),\\
+footnote~references\DUfootnotemark{footnote-reference-1}{footnote-1}{*},\\
+citation~references~(\hyperlink{cit2002}{[CIT2002]}),~and~more.\\
+~\\
+~~~Here~are~some~explicit~interpreted~text~roles:\\
+a~PEP~reference~(\href{http://www.python.org/dev/peps/pep-0287}{PEP~287}),\\
+an~RFC~reference~(\href{http://tools.ietf.org/html/rfc2822.html}{RFC~2822}),\\
+an~abbreviation~(\DUrole{abbreviation}{abb.}),~an~acronym~(\DUrole{acronym}{reST}),\\
+code~(\texttt{\DUrole{code}{print~\textquotedbl{}hello~world\textquotedbl{}}}),\\
+maths~$\sin^2(x)$,\\
+\textsubscript{subscript}~and~\textsuperscript{superscript},\\
+\DUrole{custom}{custom}~\DUrole{custom-role}{roles},~and~explicit~roles~for\\
+\DUroletitlereference{Docutils}'~\emph{standard}~\textbf{inline}~\texttt{markup}.
+\end{quote}
+%
+\DUfootnotetext{footnote-1}{footnote-reference-1}{*}{%
+This footnote is referenced in a \DUroletitlereference{parsed literal} block.
+
+It contains a literal block:
+
+\begin{quote}
+\ttfamily\raggedright
+\textbackslash{}sin\textasciicircum{}2~x
+\end{quote}
+}
+\begin{figure}[b]\raisebox{1em}{\hypertarget{cit2002}{}}[CIT2002]
+Sample Citation, 2017.
+\end{figure}
+
+\end{document}
--- /dev/null
+\documentclass[a4paper]{article}
+% generated by Docutils <http://docutils.sourceforge.net/>
+\usepackage{cmap} % fix search and cut-and-paste in Acrobat
+\usepackage{ifthen}
+\usepackage[T1]{fontenc}
+\usepackage[utf8]{inputenc}
+\usepackage{amsmath}
+\usepackage{graphicx}
+\usepackage{longtable,ltcaption,array}
+\setlength{\extrarowheight}{2pt}
+\newlength{\DUtablewidth} % internal use in tables
+
+%%% Custom LaTeX preamble
+% PDF Standard Fonts
+\usepackage{mathptmx} % Times
+\usepackage[scaled=.90]{helvet}
+\usepackage{courier}
+
+%%% User specified packages and stylesheets
+
+%%% Fallback definitions for Docutils-specific commands
+
+% 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]%
+ {\def\DocutilsClassFunctionName{DUCLASS#1}% arg cannot be used in end-part of environment.
+ \csname \DocutilsClassFunctionName \endcsname}%
+ {\csname end\DocutilsClassFunctionName \endcsname}%
+\fi
+
+% admonition (specially marked topic)
+\providecommand{\DUadmonition}[2][class-arg]{%
+ % try \DUadmonition#1{#2}:
+ \ifcsname DUadmonition#1\endcsname%
+ \csname DUadmonition#1\endcsname{#2}%
+ \else
+ \begin{center}
+ \fbox{\parbox{0.9\linewidth}{#2}}
+ \end{center}
+ \fi
+}
+% numeric or symbol footnotes with hyperlinks
+\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 markup (custom roles)
+% \DUrole{#1}{#2} tries \DUrole#1{#2}
+\providecommand*{\DUrole}[2]{%
+ \ifcsname DUrole#1\endcsname%
+ \csname DUrole#1\endcsname{#2}%
+ \else
+ % backwards compatibility: try \docutilsrole#1{#2}
+ \ifcsname docutilsrole#1\endcsname%
+ \PackageWarningNoLine{docutils}{Command prefix "docutilsrole" is
+ deprecated, \MessageBreak use `\protect\DUrole #1`}
+ \csname docutilsrole#1\endcsname{#2}%
+ \else%
+ #2%
+ \fi%
+ \fi%
+}
+
+% text mode subscript
+\ifx\textsubscript\undefined
+ \usepackage{fixltx2e} % since 2015 loaded by default
+\fi
+
+% title for topics, admonitions, unsupported section levels, and sidebar
+\providecommand*{\DUtitle}[2][class-arg]{%
+ % call \DUtitle#1{#2} if it exists:
+ \ifcsname DUtitle#1\endcsname%
+ \csname DUtitle#1\endcsname{#2}%
+ \else
+ \smallskip\noindent\textbf{#2}\smallskip%
+ \fi
+}
+
+% titlereference role
+\providecommand*{\DUroletitlereference}[1]{\textsl{#1}}
+
+% character width in monospaced font
+\newlength{\ttemwidth}
+\settowidth{\ttemwidth}{\ttfamily M}
+
+% hyperlinks:
+\ifthenelse{\isundefined{\hypersetup}}{
+ \usepackage[colorlinks=true,linkcolor=blue,urlcolor=blue]{hyperref}
+ \usepackage{bookmark}
+ \urlstyle{same} % normal text font (alternatives: tt, rm, sf)
+}{}
+
+%%% Body
+\begin{document}
+
+In LaTeX, literal blocks can be customized with the \textquotedbl{}literal-block-env\textquotedbl{}
+setting. This test file exists to check if the LaTeX writer output compiles
+and looks as expected.
+
+Start with a plain literal block:
+
+\begin{quote}
+\begin{verbatim}
+$\sin^2(x)$ and $\cos^2(x)$ equals one:
+
+\[
+ \sin^2(x) + \cos^2(x) = 1 % for all x
+\]
+\end{verbatim}
+\end{quote}
+
+A latex \textquotedbl{}code-block\textquotedbl{} (set with \textquotedbl{}literal-block-env\textquotedbl{}, if syntax
+highlight is \textquotedbl{}none\textquotedbl{}):
+
+\begin{DUclass}{code}
+\begin{DUclass}{latex}
+\begin{quote}
+\begin{verbatim}
+$\sin^2(x)$ and $\cos^2(x)$ equals one:
+
+\[
+ \sin^2(x) + \cos^2(x) = 1 % for all x
+\]
+\end{verbatim}
+\end{quote}
+\end{DUclass}
+\end{DUclass}
+
+A literal block in a table:
+
+\setlength{\DUtablewidth}{\linewidth}
+\begin{longtable*}[c]{|p{0.063\DUtablewidth}|p{0.145\DUtablewidth}|p{0.063\DUtablewidth}|}
+\hline
+
+test
+ &
+\begin{minipage}{8\ttemwidth}
+\begin{verbatim}
+\sin^2 x
+\end{verbatim}
+\end{minipage}
+ &
+test
+ \\
+\hline
+\end{longtable*}
+
+A literal block in a table with auto-width columns:
+
+\begin{longtable*}[c]{|l|l|l|}
+\hline
+test &
+\ttfamily\raggedright
+\textbackslash{}sin\textasciicircum{}2~x
+ & test \\
+\hline
+\end{longtable*}
+
+\DUadmonition[note]{
+\DUtitle[note]{Note}
+
+A literal block in an admonition:
+
+\begin{quote}
+\ttfamily\raggedright
+\textbackslash{}sin\textasciicircum{}2~x
+\end{quote}
+}
+
+Parsed literal block with inline markup and leading whitespace:
+
+\begin{quote}
+\ttfamily\raggedright
+~~~\emph{emphasis},~\textbf{strong~emphasis},~\texttt{inline~literals},\\
+standalone~hyperlinks~(\url{http://www.python.org}),\\
+\hyperref[internal]{internal}~and~\href{http://www.python.org/}{external}~hyperlinks,\\
+%
+\phantomsection\label{internal}internal~hyperlink~targets,\\
+images~via~substitution~references~(\includegraphics{../../../docs/user/rst/images/biohazard.png}),\\
+footnote~references\DUfootnotemark{footnote-reference-1}{footnote-1}{*},\\
+citation~references~(\hyperlink{cit2002}{[CIT2002]}),~and~more.\\
+~\\
+~~~Here~are~some~explicit~interpreted~text~roles:\\
+a~PEP~reference~(\href{http://www.python.org/dev/peps/pep-0287}{PEP~287}),\\
+an~RFC~reference~(\href{http://tools.ietf.org/html/rfc2822.html}{RFC~2822}),\\
+an~abbreviation~(\DUrole{abbreviation}{abb.}),~an~acronym~(\DUrole{acronym}{reST}),\\
+code~(\texttt{\DUrole{code}{print~\textquotedbl{}hello~world\textquotedbl{}}}),\\
+maths~$\sin^2(x)$,\\
+\textsubscript{subscript}~and~\textsuperscript{superscript},\\
+\DUrole{custom}{custom}~\DUrole{custom-role}{roles},~and~explicit~roles~for\\
+\DUroletitlereference{Docutils}'~\emph{standard}~\textbf{inline}~\texttt{markup}.
+\end{quote}
+%
+\DUfootnotetext{footnote-1}{footnote-reference-1}{*}{%
+This footnote is referenced in a \DUroletitlereference{parsed literal} block.
+
+It contains a literal block:
+
+\begin{quote}
+\ttfamily\raggedright
+\textbackslash{}sin\textasciicircum{}2~x
+\end{quote}
+}
+\begin{figure}[b]\raisebox{1em}{\hypertarget{cit2002}{}}[CIT2002]
+Sample Citation, 2017.
+\end{figure}
+
+\end{document}
--- /dev/null
+\documentclass[a4paper]{article}
+% generated by Docutils <http://docutils.sourceforge.net/>
+\usepackage{cmap} % fix search and cut-and-paste in Acrobat
+\usepackage{ifthen}
+\usepackage[T1]{fontenc}
+\usepackage[utf8]{inputenc}
+\usepackage{amsmath}
+\usepackage{graphicx}
+\usepackage{moreverb}
+\usepackage{longtable,ltcaption,array}
+\setlength{\extrarowheight}{2pt}
+\newlength{\DUtablewidth} % internal use in tables
+
+%%% Custom LaTeX preamble
+% PDF Standard Fonts
+\usepackage{mathptmx} % Times
+\usepackage[scaled=.90]{helvet}
+\usepackage{courier}
+
+%%% User specified packages and stylesheets
+
+%%% Fallback definitions for Docutils-specific commands
+
+% 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]%
+ {\def\DocutilsClassFunctionName{DUCLASS#1}% arg cannot be used in end-part of environment.
+ \csname \DocutilsClassFunctionName \endcsname}%
+ {\csname end\DocutilsClassFunctionName \endcsname}%
+\fi
+
+% admonition (specially marked topic)
+\providecommand{\DUadmonition}[2][class-arg]{%
+ % try \DUadmonition#1{#2}:
+ \ifcsname DUadmonition#1\endcsname%
+ \csname DUadmonition#1\endcsname{#2}%
+ \else
+ \begin{center}
+ \fbox{\parbox{0.9\linewidth}{#2}}
+ \end{center}
+ \fi
+}
+% numeric or symbol footnotes with hyperlinks
+\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 markup (custom roles)
+% \DUrole{#1}{#2} tries \DUrole#1{#2}
+\providecommand*{\DUrole}[2]{%
+ \ifcsname DUrole#1\endcsname%
+ \csname DUrole#1\endcsname{#2}%
+ \else
+ % backwards compatibility: try \docutilsrole#1{#2}
+ \ifcsname docutilsrole#1\endcsname%
+ \PackageWarningNoLine{docutils}{Command prefix "docutilsrole" is
+ deprecated, \MessageBreak use `\protect\DUrole #1`}
+ \csname docutilsrole#1\endcsname{#2}%
+ \else%
+ #2%
+ \fi%
+ \fi%
+}
+
+% text mode subscript
+\ifx\textsubscript\undefined
+ \usepackage{fixltx2e} % since 2015 loaded by default
+\fi
+
+% title for topics, admonitions, unsupported section levels, and sidebar
+\providecommand*{\DUtitle}[2][class-arg]{%
+ % call \DUtitle#1{#2} if it exists:
+ \ifcsname DUtitle#1\endcsname%
+ \csname DUtitle#1\endcsname{#2}%
+ \else
+ \smallskip\noindent\textbf{#2}\smallskip%
+ \fi
+}
+
+% titlereference role
+\providecommand*{\DUroletitlereference}[1]{\textsl{#1}}
+
+% character width in monospaced font
+\newlength{\ttemwidth}
+\settowidth{\ttemwidth}{\ttfamily M}
+
+% hyperlinks:
+\ifthenelse{\isundefined{\hypersetup}}{
+ \usepackage[colorlinks=true,linkcolor=blue,urlcolor=blue]{hyperref}
+ \usepackage{bookmark}
+ \urlstyle{same} % normal text font (alternatives: tt, rm, sf)
+}{}
+
+%%% Body
+\begin{document}
+
+In LaTeX, literal blocks can be customized with the \textquotedbl{}literal-block-env\textquotedbl{}
+setting. This test file exists to check if the LaTeX writer output compiles
+and looks as expected.
+
+Start with a plain literal block:
+
+\begin{quote}
+\begin{verbatimtab}
+$\sin^2(x)$ and $\cos^2(x)$ equals one:
+
+\[
+ \sin^2(x) + \cos^2(x) = 1 % for all x
+\]
+\end{verbatimtab}
+\end{quote}
+
+A latex \textquotedbl{}code-block\textquotedbl{} (set with \textquotedbl{}literal-block-env\textquotedbl{}, if syntax
+highlight is \textquotedbl{}none\textquotedbl{}):
+
+\begin{DUclass}{code}
+\begin{DUclass}{latex}
+\begin{quote}
+\begin{verbatimtab}
+$\sin^2(x)$ and $\cos^2(x)$ equals one:
+
+\[
+ \sin^2(x) + \cos^2(x) = 1 % for all x
+\]
+\end{verbatimtab}
+\end{quote}
+\end{DUclass}
+\end{DUclass}
+
+A literal block in a table:
+
+\setlength{\DUtablewidth}{\linewidth}
+\begin{longtable*}[c]{|p{0.063\DUtablewidth}|p{0.145\DUtablewidth}|p{0.063\DUtablewidth}|}
+\hline
+
+test
+ &
+\begin{minipage}{8\ttemwidth}
+\begin{verbatimtab}
+\sin^2 x
+\end{verbatimtab}
+\end{minipage}
+ &
+test
+ \\
+\hline
+\end{longtable*}
+
+A literal block in a table with auto-width columns:
+
+\begin{longtable*}[c]{|l|l|l|}
+\hline
+test &
+\ttfamily\raggedright
+\textbackslash{}sin\textasciicircum{}2~x
+ & test \\
+\hline
+\end{longtable*}
+
+\DUadmonition[note]{
+\DUtitle[note]{Note}
+
+A literal block in an admonition:
+
+\begin{quote}
+\ttfamily\raggedright
+\textbackslash{}sin\textasciicircum{}2~x
+\end{quote}
+}
+
+Parsed literal block with inline markup and leading whitespace:
+
+\begin{quote}
+\ttfamily\raggedright
+~~~\emph{emphasis},~\textbf{strong~emphasis},~\texttt{inline~literals},\\
+standalone~hyperlinks~(\url{http://www.python.org}),\\
+\hyperref[internal]{internal}~and~\href{http://www.python.org/}{external}~hyperlinks,\\
+%
+\phantomsection\label{internal}internal~hyperlink~targets,\\
+images~via~substitution~references~(\includegraphics{../../../docs/user/rst/images/biohazard.png}),\\
+footnote~references\DUfootnotemark{footnote-reference-1}{footnote-1}{*},\\
+citation~references~(\hyperlink{cit2002}{[CIT2002]}),~and~more.\\
+~\\
+~~~Here~are~some~explicit~interpreted~text~roles:\\
+a~PEP~reference~(\href{http://www.python.org/dev/peps/pep-0287}{PEP~287}),\\
+an~RFC~reference~(\href{http://tools.ietf.org/html/rfc2822.html}{RFC~2822}),\\
+an~abbreviation~(\DUrole{abbreviation}{abb.}),~an~acronym~(\DUrole{acronym}{reST}),\\
+code~(\texttt{\DUrole{code}{print~\textquotedbl{}hello~world\textquotedbl{}}}),\\
+maths~$\sin^2(x)$,\\
+\textsubscript{subscript}~and~\textsuperscript{superscript},\\
+\DUrole{custom}{custom}~\DUrole{custom-role}{roles},~and~explicit~roles~for\\
+\DUroletitlereference{Docutils}'~\emph{standard}~\textbf{inline}~\texttt{markup}.
+\end{quote}
+%
+\DUfootnotetext{footnote-1}{footnote-reference-1}{*}{%
+This footnote is referenced in a \DUroletitlereference{parsed literal} block.
+
+It contains a literal block:
+
+\begin{quote}
+\ttfamily\raggedright
+\textbackslash{}sin\textasciicircum{}2~x
+\end{quote}
+}
+\begin{figure}[b]\raisebox{1em}{\hypertarget{cit2002}{}}[CIT2002]
+Sample Citation, 2017.
+\end{figure}
+
+\end{document}
--- /dev/null
+<?xml version="1.0" encoding="utf-8" ?>
+<!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">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<meta name="generator" content="Docutils 0.16: http://docutils.sourceforge.net/" />
+<title>Mathematics</title>
+<link rel="stylesheet" href="../input/data/html4css1.css" type="text/css" />
+<link rel="stylesheet" href="../input/data/math.css" type="text/css" />
+</head>
+<body>
+<div class="document" id="mathematics">
+<h1 class="title">Mathematics</h1>
+
+<p>Docutils supports inline math with the prefix or postfix <tt class="docutils literal">:math:</tt>
+role specificator, <span class="formula"><i>n</i>! + sin(<i>x</i><span class="scripts"><sup class="script">2</sup><sub class="script"><i>n</i></sub></span>)</span> and <span class="formula"><i>A</i><sub><span class="text">c</span></sub> = <span class="fraction"><span class="ignored">(</span><span class="numerator"><i>π</i></span><span class="ignored">)/(</span><span class="denominator">4</span><span class="ignored">)</span></span><i>d</i><sup>2</sup></span>, as well as displayed math via the
+<cite>math</cite> directive:</p>
+<div class="formula">
+<i>f</i>(<i>ϵ</i>) = <span class="fraction"><span class="ignored">(</span><span class="numerator">1</span><span class="ignored">)/(</span><span class="denominator">1 + exp<span class="array"><span class="arrayrow"><span class="bracket align-left">⎛</span></span><span class="arrayrow"><span class="bracket align-left">⎝</span></span></span><span class="fraction"><span class="ignored">(</span><span class="numerator"><i>ε</i></span><span class="ignored">)/(</span><span class="denominator"><i>k</i><sub><span class="text">B</span></sub><i>T</i></span><span class="ignored">)</span></span><span class="array"><span class="arrayrow"><span class="bracket align-right">⎞</span></span><span class="arrayrow"><span class="bracket align-right">⎠</span></span></span></span><span class="ignored">)</span></span>
+</div>
+<p>Content may start on the first line of the directive, e.g.</p>
+<div class="formula">
+<i>N</i> = <span class="fraction"><span class="ignored">(</span><span class="numerator"><span class="text">number of apples</span></span><span class="ignored">)/(</span><span class="denominator">7</span><span class="ignored">)</span></span>
+</div>
+<p>Equations can be labeled with a reference name using the <tt class="docutils literal">:name:</tt> option.
+See <a class="reference internal" href="#eq-m">eq:M</a> and <a class="reference internal" href="#eq-schrodinger">eq:schrödinger</a> below.</p>
+<p>The determinant of the matrix</p>
+<div class="formula" id="eq-m">
+<b>M</b> = <span class="array"><span class="arrayrow"><span class="bracket align-left">⎛</span></span><span class="arrayrow"><span class="bracket align-left">⎜</span></span><span class="arrayrow"><span class="bracket align-left">⎝</span></span></span><span class="array"><span class="arrayrow">
+<span class="arraycell align-c">
+<i>a</i>
+</span>
+<span class="arraycell align-c">
+<i>b</i>
+</span>
+
+</span>
+<span class="arrayrow">
+<span class="arraycell align-c">
+
+</span>
+<span class="arraycell align-c">
+
+</span>
+
+</span>
+<span class="arrayrow">
+<span class="arraycell align-c">
+<i>c</i>
+</span>
+<span class="arraycell align-c">
+<i>d</i>
+</span>
+
+</span>
+</span><span class="array"><span class="arrayrow"><span class="bracket align-right">⎞</span></span><span class="arrayrow"><span class="bracket align-right">⎟</span></span><span class="arrayrow"><span class="bracket align-right">⎠</span></span></span>
+</div>
+<p>is <span class="formula">|<b>M</b>| = <i>ad</i> − <i>bc</i></span>.</p>
+<p>More than one display math block can be put in one math directive.
+For example, the following sum and integral with limits:</p>
+<div class="formula">
+<span class="limits"><sup class="limit">1</sup><span class="limit">⌠</span><span class="limit">⌡</span><sub class="limit">0</sub></span><i>x</i><sup><i>n</i></sup><i>dx</i> = <span class="fraction"><span class="ignored">(</span><span class="numerator">1</span><span class="ignored">)/(</span><span class="denominator"><i>n</i> + 1</span><span class="ignored">)</span></span>
+</div>
+<div class="formula">
+<span class="limits"><sup class="limit"><i>m</i></sup><span class="limit">⎲</span><span class="limit">⎳</span><sub class="limit"><i>n</i> = 1</sub></span><i>n</i> = <span class="fraction"><span class="ignored">(</span><span class="numerator"><i>m</i>(<i>m</i> + 1)</span><span class="ignored">)/(</span><span class="denominator">2</span><span class="ignored">)</span></span>
+</div>
+<p>LaTeX-supported Unicode math symbols can be used in math roles and
+directives:</p>
+<p>The Schrödinger equation</p>
+<div class="formula" id="eq-schrodinger">
+<i>i</i>ℏ<span class="fraction"><span class="ignored">(</span><span class="numerator">∂</span><span class="ignored">)/(</span><span class="denominator">∂<i>t</i></span><span class="ignored">)</span></span>Ψ = <i>Ĥ</i>Ψ,
+</div>
+<p>with the <em>wave function</em> <span class="formula">Ψ</span>, describes how the quantum state of a
+physical system changes in time.</p>
+<dl class="docutils">
+<dt>Math-Accents:</dt>
+<dd><table border="1" class="colwidths-given borderless first last docutils">
+<colgroup>
+<col width="33%" />
+<col width="33%" />
+<col width="33%" />
+</colgroup>
+<tbody valign="top">
+<tr><td><span class="formula"><i>á</i></span> <tt class="docutils literal">\acute{a}</tt></td>
+<td><span class="formula"><i>ṫ</i></span> <tt class="docutils literal">\dot{t}</tt></td>
+<td><span class="formula"><i>γ̂</i></span> <tt class="docutils literal"><span class="pre">\hat{\gamma}</span></tt></td>
+</tr>
+<tr><td><span class="formula"><i>à</i></span> <tt class="docutils literal">\grave{a}</tt></td>
+<td><span class="formula"><i>ẗ</i></span> <tt class="docutils literal">\ddot{t}</tt></td>
+<td><span class="formula"><i>α̃</i></span> <tt class="docutils literal"><span class="pre">\tilde{\alpha}</span></tt></td>
+</tr>
+<tr><td><span class="formula"><i>x̆</i></span> <tt class="docutils literal">\breve{x}</tt></td>
+<td><span class="formula"><i>t⃛</i></span> <tt class="docutils literal">\dddot{t}</tt></td>
+<td><span class="formula"><i>ı⃗</i></span> <tt class="docutils literal"><span class="pre">\vec{\imath}</span></tt></td>
+</tr>
+<tr><td><span class="formula"><i>ǎ</i></span> <tt class="docutils literal">\check{a}</tt></td>
+<td><span class="formula"><span class="bar"><i>a</i></span></span> <tt class="docutils literal">\bar{a}</tt></td>
+<td><span class="formula"><i>R⃗</i></span> <tt class="docutils literal">\vec{R}</tt></td>
+</tr>
+</tbody>
+</table>
+</dd>
+</dl>
+<!-- \widetilde{xxx}
+\widehat{xxx} -->
+<p>Modulation Transfer Function:</p>
+<div class="formula">
+<span class="text">MTF</span> = <span class="array"><span class="arrayrow"><span class="bracket align-left">|</span></span><span class="arrayrow"><span class="bracket align-left">|</span></span></span><span class="fraction"><span class="ignored">(</span><span class="numerator">ℱ{<i>s</i>(<i>x</i>)}</span><span class="ignored">)/(</span><span class="denominator">ℱ{<i>s</i>(<i>x</i>)}|<sub><i>ω</i><sub><i>x</i></sub> = 0</sub></span><span class="ignored">)</span></span><span class="array"><span class="arrayrow"><span class="bracket align-right">|</span></span><span class="arrayrow"><span class="bracket align-right">|</span></span></span> = <span class="mathrm"> abs</span><span class="array"><span class="arrayrow"><span class="bracket align-left">⎛</span></span><span class="arrayrow"><span class="bracket align-left">⎝</span></span></span><span class="fraction"><span class="ignored">(</span><span class="numerator"><span class="limits"><span class="limit">⌠</span><span class="limit">⌡</span></span><span class="scripts"><sup class="script">∞</sup><sub class="script"> − ∞</sub></span><i>s</i>(<i>x</i>)<span class="mathrm">e</span><sup><span class="mathrm">i</span><i>ω</i><sub><i>x</i></sub><i>x</i></sup><span class="mathrm">d</span><i>x</i></span><span class="ignored">)/(</span><span class="denominator"><span class="limits"><span class="limit">⌠</span><span class="limit">⌡</span></span><span class="scripts"><sup class="script">∞</sup><sub class="script"> − ∞</sub></span><i>s</i>(<i>x</i>)<span class="mathrm">d</span><i>x</i></span><span class="ignored">)</span></span><span class="array"><span class="arrayrow"><span class="bracket align-right">⎞</span></span><span class="arrayrow"><span class="bracket align-right">⎠</span></span></span>.
+</div>
+<p>Math split over two lines: If a double backslash is detected outside a
+<tt class="docutils literal"><span class="pre">\begin{...}</span> <span class="pre">\end{...}</span></tt> pair, the math code is wrapped in an <a class="reference external" href="ftp://ftp.ams.org/ams/doc/amsmath/short-math-guide.pdf">AMSmath</a>
+<tt class="docutils literal">align</tt> environment:</p>
+<div class="formula">
+<span class="environment"><span class="arrayrow">
+<span class="arraycell align-r">
+<i>s</i><sub><span class="mathrm">out</span></sub>(<i>x</i>)
+</span>
+<span class="arraycell align-l">
+ = <i>s</i><sub><span class="mathrm">in</span></sub>(<i>x</i>’)*<i>s</i><sub><i>δ</i></sub>(<i>x</i> − <i>x</i>’)
+</span>
+
+</span>
+<span class="arrayrow">
+<span class="arraycell align-r">
+
+</span>
+<span class="arraycell align-l">
+
+</span>
+
+</span>
+<span class="arrayrow">
+<span class="arraycell align-r">
+
+</span>
+<span class="arraycell align-l">
+ = <span class="limits"><span class="limit">⌠</span><span class="limit">⌡</span></span><i>s</i><sub><span class="mathrm">in</span></sub>(<i>x</i>’)<i>s</i><sub><i>δ</i></sub>(<i>x</i> − <i>x</i>’)<span class="mathrm">d</span><i>x</i>’
+</span>
+
+</span>
+</span>
+</div>
+<p>Cases ("manually", with <tt class="docutils literal">matrix</tt> environment):</p>
+<div class="formula">
+<span class="mathrm">sgn</span>(<i>x</i>) = <span class="array"><span class="arrayrow"><span class="bracket align-left">⎧</span></span><span class="arrayrow"><span class="bracket align-left">⎨</span></span><span class="arrayrow"><span class="bracket align-left">⎩</span></span></span><span class="array"><span class="arrayrow">
+<span class="arraycell align-c">
+ − 1
+</span>
+<span class="arraycell align-c">
+<i>x</i> < 0
+</span>
+
+</span>
+<span class="arrayrow">
+<span class="arraycell align-c">
+
+</span>
+<span class="arraycell align-c">
+
+</span>
+
+</span>
+<span class="arrayrow">
+<span class="arraycell align-c">
+1
+</span>
+<span class="arraycell align-c">
+<i>x</i> > 0
+</span>
+
+</span>
+</span><span class="emptydot"></span>
+</div>
+<p>Cases with the <a class="reference external" href="ftp://ftp.ams.org/ams/doc/amsmath/short-math-guide.pdf">AMSmath</a> <tt class="docutils literal">cases</tt> environment (not (yet) supported by
+HTML writers with <tt class="docutils literal"><span class="pre">--math-output=MathML</span></tt>):</p>
+<div class="formula">
+<span class="mathrm">sgn</span>(<i>x</i>) = <span class="array"><span class="arrayrow"><span class="bracket align-l">⎧</span></span><span class="arrayrow"><span class="bracket align-l">⎨</span></span><span class="arrayrow"><span class="bracket align-l">⎩</span></span></span><span class="bracketcases">
+<span class="arrayrow">
+<span class="case align-l">
+ − 1
+</span>
+<span class="case align-l">
+<i>x</i> < 0
+</span>
+
+</span>
+<span class="arrayrow">
+<span class="case align-l">
+
+</span>
+<span class="case align-l">
+
+</span>
+
+</span>
+<span class="arrayrow">
+<span class="case align-l">
+1
+</span>
+<span class="case align-l">
+<i>x</i> > 0
+</span>
+
+</span>
+
+</span>
+
+</div>
+</div>
+</body>
+</html>
--- /dev/null
+<?xml version="1.0" encoding="utf-8" ?>
+<!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">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<meta name="generator" content="Docutils 0.16: http://docutils.sourceforge.net/" />
+<title>Mathematics</title>
+<link rel="stylesheet" href="../input/data/html4css1.css" type="text/css" />
+</head>
+<body>
+<div class="document" id="mathematics">
+<h1 class="title">Mathematics</h1>
+
+<p>Docutils supports inline math with the prefix or postfix <tt class="docutils literal">:math:</tt>
+role specificator, <tt class="math">n! + \sin(x_n^2)</tt> and <tt class="math">A_\text{c} =
+\frac{\pi}{4} d^2</tt>, as well as displayed math via the
+<cite>math</cite> directive:</p>
+<pre class="math">
+f(\epsilon) = \frac{1}{1 + \exp\left(\frac{\varepsilon}{k_\text{B}T}\right)}
+</pre>
+<p>Content may start on the first line of the directive, e.g.</p>
+<pre class="math">
+N = \frac{\text{number of apples}}{7}
+</pre>
+<p>Equations can be labeled with a reference name using the <tt class="docutils literal">:name:</tt> option.
+See <a class="reference internal" href="#eq-m">eq:M</a> and <a class="reference internal" href="#eq-schrodinger">eq:schrödinger</a> below.</p>
+<p>The determinant of the matrix</p>
+<pre class="math" id="eq-m">
+\mathbf{M} = \left(\begin{matrix}a&b\\c&d\end{matrix}\right)
+</pre>
+<p>is <tt class="math">|\mathbf{M}| = ad - bc</tt>.</p>
+<p>More than one display math block can be put in one math directive.
+For example, the following sum and integral with limits:</p>
+<pre class="math">
+\int_0^1 x^n dx = \frac{1}{n + 1}
+</pre>
+<pre class="math">
+\sum_{n=1}^m n = \frac{m(m+1)}{2}
+</pre>
+<p>LaTeX-supported Unicode math symbols can be used in math roles and
+directives:</p>
+<p>The Schrödinger equation</p>
+<pre class="math" id="eq-schrodinger">
+i\hbar \frac{\partial }{\partial t}\Psi = \hat{H}\Psi ,
+</pre>
+<p>with the <em>wave function</em> <tt class="math">\Psi </tt>, describes how the quantum state of a
+physical system changes in time.</p>
+<dl class="docutils">
+<dt>Math-Accents:</dt>
+<dd><table border="1" class="colwidths-given borderless first last docutils">
+<colgroup>
+<col width="33%" />
+<col width="33%" />
+<col width="33%" />
+</colgroup>
+<tbody valign="top">
+<tr><td><tt class="math">\acute{a}</tt> <tt class="docutils literal">\acute{a}</tt></td>
+<td><tt class="math">\dot{t}</tt> <tt class="docutils literal">\dot{t}</tt></td>
+<td><tt class="math">\hat{\gamma}</tt> <tt class="docutils literal"><span class="pre">\hat{\gamma}</span></tt></td>
+</tr>
+<tr><td><tt class="math">\grave{a}</tt> <tt class="docutils literal">\grave{a}</tt></td>
+<td><tt class="math">\ddot{t}</tt> <tt class="docutils literal">\ddot{t}</tt></td>
+<td><tt class="math">\tilde{\alpha}</tt> <tt class="docutils literal"><span class="pre">\tilde{\alpha}</span></tt></td>
+</tr>
+<tr><td><tt class="math">\breve{x}</tt> <tt class="docutils literal">\breve{x}</tt></td>
+<td><tt class="math">\dddot{t}</tt> <tt class="docutils literal">\dddot{t}</tt></td>
+<td><tt class="math">\vec{\imath}</tt> <tt class="docutils literal"><span class="pre">\vec{\imath}</span></tt></td>
+</tr>
+<tr><td><tt class="math">\check{a}</tt> <tt class="docutils literal">\check{a}</tt></td>
+<td><tt class="math">\bar{a}</tt> <tt class="docutils literal">\bar{a}</tt></td>
+<td><tt class="math">\vec{R}</tt> <tt class="docutils literal">\vec{R}</tt></td>
+</tr>
+</tbody>
+</table>
+</dd>
+</dl>
+<!-- \widetilde{xxx}
+\widehat{xxx} -->
+<p>Modulation Transfer Function:</p>
+<pre class="math">
+\text{MTF} = \left|\frac{\mathcal{F}\{s(x)\}}
+ {\mathcal{F}\{ s(x)\} |_{\omega _{x}=0}}\right|
+ = \mathrm{abs}\left(\frac
+ {\int _{-\infty }^{\infty }s(x) \mathrm{e}^{\mathrm{i}\omega _{x}x}\mathrm{d}{x}}
+ {\int _{-\infty }^{\infty }s(x)\mathrm{d}{x}}
+ \right).
+</pre>
+<p>Math split over two lines: If a double backslash is detected outside a
+<tt class="docutils literal"><span class="pre">\begin{...}</span> <span class="pre">\end{...}</span></tt> pair, the math code is wrapped in an <a class="reference external" href="ftp://ftp.ams.org/ams/doc/amsmath/short-math-guide.pdf">AMSmath</a>
+<tt class="docutils literal">align</tt> environment:</p>
+<pre class="math">
+s_{\mathrm{out}}(x) & = s_{\mathrm{in}}(x') * s_\delta (x-x') \\
+ & = \int s_{\mathrm{in}}(x')s_\delta (x-x')\mathrm{d}x'
+</pre>
+<p>Cases ("manually", with <tt class="docutils literal">matrix</tt> environment):</p>
+<pre class="math">
+\mathrm{sgn}(x) = \left\{\begin{matrix}
+ -1 & x<0\\
+ 1 & x>0
+ \end{matrix}\right.
+</pre>
+<p>Cases with the <a class="reference external" href="ftp://ftp.ams.org/ams/doc/amsmath/short-math-guide.pdf">AMSmath</a> <tt class="docutils literal">cases</tt> environment (not (yet) supported by
+HTML writers with <tt class="docutils literal"><span class="pre">--math-output=MathML</span></tt>):</p>
+<pre class="math">
+\mathrm{sgn}(x) = \begin{cases}
+ -1 & x<0\\
+ 1 & x>0
+ \end{cases}
+</pre>
+</div>
+</body>
+</html>
--- /dev/null
+<?xml version="1.0" encoding="utf-8" ?>
+<!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">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<meta name="generator" content="Docutils 0.16: http://docutils.sourceforge.net/" />
+<title>Mathematics</title>
+<script type="text/javascript" src="/usr/share/javascript/mathjax/MathJax.js?config=TeX-AMS_CHTML"></script>
+<link rel="stylesheet" href="../input/data/html4css1.css" type="text/css" />
+</head>
+<body>
+<div class="document" id="mathematics">
+<h1 class="title">Mathematics</h1>
+
+<p>Docutils supports inline math with the prefix or postfix <tt class="docutils literal">:math:</tt>
+role specificator, <span class="math">\(n! + \sin(x_n^2)\)</span> and <span class="math">\(A_\text{c} =
+\frac{\pi}{4} d^2\)</span>, as well as displayed math via the
+<cite>math</cite> directive:</p>
+<div class="math">
+\begin{equation*}
+f(\epsilon) = \frac{1}{1 + \exp\left(\frac{\varepsilon}{k_\text{B}T}\right)}
+\end{equation*}
+</div>
+<p>Content may start on the first line of the directive, e.g.</p>
+<div class="math">
+\begin{equation*}
+N = \frac{\text{number of apples}}{7}
+\end{equation*}
+</div>
+<p>Equations can be labeled with a reference name using the <tt class="docutils literal">:name:</tt> option.
+See <a class="reference internal" href="#eq-m">eq:M</a> and <a class="reference internal" href="#eq-schrodinger">eq:schrödinger</a> below.</p>
+<p>The determinant of the matrix</p>
+<div class="math" id="eq-m">
+\begin{equation*}
+\mathbf{M} = \left(\begin{matrix}a&b\\c&d\end{matrix}\right)
+\end{equation*}
+</div>
+<p>is <span class="math">\(|\mathbf{M}| = ad - bc\)</span>.</p>
+<p>More than one display math block can be put in one math directive.
+For example, the following sum and integral with limits:</p>
+<div class="math">
+\begin{equation*}
+\int_0^1 x^n dx = \frac{1}{n + 1}
+\end{equation*}
+</div>
+<div class="math">
+\begin{equation*}
+\sum_{n=1}^m n = \frac{m(m+1)}{2}
+\end{equation*}
+</div>
+<p>LaTeX-supported Unicode math symbols can be used in math roles and
+directives:</p>
+<p>The Schrödinger equation</p>
+<div class="math" id="eq-schrodinger">
+\begin{equation*}
+i\hbar \frac{\partial }{\partial t}\Psi = \hat{H}\Psi ,
+\end{equation*}
+</div>
+<p>with the <em>wave function</em> <span class="math">\(\Psi \)</span>, describes how the quantum state of a
+physical system changes in time.</p>
+<dl class="docutils">
+<dt>Math-Accents:</dt>
+<dd><table border="1" class="colwidths-given borderless first last docutils">
+<colgroup>
+<col width="33%" />
+<col width="33%" />
+<col width="33%" />
+</colgroup>
+<tbody valign="top">
+<tr><td><span class="math">\(\acute{a}\)</span> <tt class="docutils literal">\acute{a}</tt></td>
+<td><span class="math">\(\dot{t}\)</span> <tt class="docutils literal">\dot{t}</tt></td>
+<td><span class="math">\(\hat{\gamma}\)</span> <tt class="docutils literal"><span class="pre">\hat{\gamma}</span></tt></td>
+</tr>
+<tr><td><span class="math">\(\grave{a}\)</span> <tt class="docutils literal">\grave{a}</tt></td>
+<td><span class="math">\(\ddot{t}\)</span> <tt class="docutils literal">\ddot{t}</tt></td>
+<td><span class="math">\(\tilde{\alpha}\)</span> <tt class="docutils literal"><span class="pre">\tilde{\alpha}</span></tt></td>
+</tr>
+<tr><td><span class="math">\(\breve{x}\)</span> <tt class="docutils literal">\breve{x}</tt></td>
+<td><span class="math">\(\dddot{t}\)</span> <tt class="docutils literal">\dddot{t}</tt></td>
+<td><span class="math">\(\vec{\imath}\)</span> <tt class="docutils literal"><span class="pre">\vec{\imath}</span></tt></td>
+</tr>
+<tr><td><span class="math">\(\check{a}\)</span> <tt class="docutils literal">\check{a}</tt></td>
+<td><span class="math">\(\bar{a}\)</span> <tt class="docutils literal">\bar{a}</tt></td>
+<td><span class="math">\(\vec{R}\)</span> <tt class="docutils literal">\vec{R}</tt></td>
+</tr>
+</tbody>
+</table>
+</dd>
+</dl>
+<!-- \widetilde{xxx}
+\widehat{xxx} -->
+<p>Modulation Transfer Function:</p>
+<div class="math">
+\begin{equation*}
+\text{MTF} = \left|\frac{\mathcal{F}\{s(x)\}}
+ {\mathcal{F}\{ s(x)\} |_{\omega _{x}=0}}\right|
+ = \mathrm{abs}\left(\frac
+ {\int _{-\infty }^{\infty }s(x) \mathrm{e}^{\mathrm{i}\omega _{x}x}\mathrm{d}{x}}
+ {\int _{-\infty }^{\infty }s(x)\mathrm{d}{x}}
+ \right).
+\end{equation*}
+</div>
+<p>Math split over two lines: If a double backslash is detected outside a
+<tt class="docutils literal"><span class="pre">\begin{...}</span> <span class="pre">\end{...}</span></tt> pair, the math code is wrapped in an <a class="reference external" href="ftp://ftp.ams.org/ams/doc/amsmath/short-math-guide.pdf">AMSmath</a>
+<tt class="docutils literal">align</tt> environment:</p>
+<div class="math">
+\begin{align*}
+s_{\mathrm{out}}(x) & = s_{\mathrm{in}}(x') * s_\delta (x-x') \\
+ & = \int s_{\mathrm{in}}(x')s_\delta (x-x')\mathrm{d}x'
+\end{align*}
+</div>
+<p>Cases ("manually", with <tt class="docutils literal">matrix</tt> environment):</p>
+<div class="math">
+\begin{equation*}
+\mathrm{sgn}(x) = \left\{\begin{matrix}
+ -1 & x<0\\
+ 1 & x>0
+ \end{matrix}\right.
+\end{equation*}
+</div>
+<p>Cases with the <a class="reference external" href="ftp://ftp.ams.org/ams/doc/amsmath/short-math-guide.pdf">AMSmath</a> <tt class="docutils literal">cases</tt> environment (not (yet) supported by
+HTML writers with <tt class="docutils literal"><span class="pre">--math-output=MathML</span></tt>):</p>
+<div class="math">
+\begin{equation*}
+\mathrm{sgn}(x) = \begin{cases}
+ -1 & x<0\\
+ 1 & x>0
+ \end{cases}
+\end{equation*}
+</div>
+</div>
+</body>
+</html>
--- /dev/null
+<!DOCTYPE html>
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+<meta charset="utf-8"/>
+<meta name="generator" content="Docutils 0.16: http://docutils.sourceforge.net/" />
+<title>Mathematics</title>
+<link rel="stylesheet" href="../input/data/minimal.css" type="text/css" />
+<link rel="stylesheet" href="../input/data/plain.css" type="text/css" />
+</head>
+<body>
+<div class="document" id="mathematics">
+<h1 class="title">Mathematics</h1>
+
+<p>Docutils supports inline math with the prefix or postfix <span class="docutils literal">:math:</span>
+role specificator, <math xmlns="http://www.w3.org/1998/Math/MathML">
+<mrow><mi>n</mi><mo>!</mo><mo>+</mo><mo>sin</mo><mo>(</mo><msubsup><mi>x</mi><mi>n</mi><mn>2</mn></msubsup><mo>)</mo></mrow></math> and <math xmlns="http://www.w3.org/1998/Math/MathML">
+<mrow><msub><mi>A</mi><mtext>c</mtext></msub><mo>=</mo><mfrac>
+<mrow><mi>π</mi></mrow>
+<mrow><mn>4</mn></mrow></mfrac><msup><mi>d</mi><mn>2</mn></msup></mrow></math>, as well as displayed math via the
+<cite>math</cite> directive:</p>
+<div>
+<math xmlns="http://www.w3.org/1998/Math/MathML" mode="display">
+<mtable>
+<mtr>
+<mtd><mi>f</mi><mo>(</mo><mi>ϵ</mi><mo>)</mo><mo>=</mo><mfrac>
+<mrow><mn>1</mn></mrow>
+<mrow><mn>1</mn><mo>+</mo><mo>exp</mo><mfenced open="(" close=")">
+<mrow><mfrac>
+<mrow><mi>ε</mi></mrow>
+<mrow><msub><mi>k</mi><mtext>B</mtext></msub><mi>T</mi></mrow></mfrac></mrow></mfenced></mrow></mfrac></mtd></mtr></mtable></math>
+</div>
+<p>Content may start on the first line of the directive, e.g.</p>
+<div>
+<math xmlns="http://www.w3.org/1998/Math/MathML" mode="display">
+<mtable>
+<mtr>
+<mtd><mi>N</mi><mo>=</mo><mfrac>
+<mrow><mtext>number of apples</mtext></mrow>
+<mrow><mn>7</mn></mrow></mfrac></mtd></mtr></mtable></math>
+</div>
+<p>Equations can be labeled with a reference name using the <span class="docutils literal">:name:</span> option.
+See <a class="reference internal" href="#eq-m">eq:M</a> and <a class="reference internal" href="#eq-schrodinger">eq:schrödinger</a> below.</p>
+<p>The determinant of the matrix</p>
+<div id="eq-m">
+<math xmlns="http://www.w3.org/1998/Math/MathML" mode="display">
+<mtable>
+<mtr>
+<mtd><mstyle fontweight="bold">
+<mrow><mi>M</mi></mrow></mstyle><mo>=</mo><mfenced open="(" close=")">
+<mrow>
+<mtable>
+<mtr>
+<mtd><mi>a</mi></mtd>
+<mtd><mi>b</mi></mtd></mtr>
+<mtr>
+<mtd><mi>c</mi></mtd>
+<mtd><mi>d</mi></mtd></mtr></mtable></mrow></mfenced></mtd></mtr></mtable></math>
+</div>
+<p>is <math xmlns="http://www.w3.org/1998/Math/MathML">
+<mrow><mo>|</mo><mstyle fontweight="bold">
+<mrow><mi>M</mi></mrow></mstyle><mo>|</mo><mo>=</mo><mi>a</mi><mi>d</mi><mo>-</mo><mi>b</mi><mi>c</mi></mrow></math>.</p>
+<p>More than one display math block can be put in one math directive.
+For example, the following sum and integral with limits:</p>
+<div>
+<math xmlns="http://www.w3.org/1998/Math/MathML" mode="display">
+<mtable>
+<mtr>
+<mtd><munderover><mo>∫</mo><mn>0</mn><mn>1</mn></munderover><msup><mi>x</mi><mi>n</mi></msup><mi>d</mi><mi>x</mi><mo>=</mo><mfrac>
+<mrow><mn>1</mn></mrow>
+<mrow><mi>n</mi><mo>+</mo><mn>1</mn></mrow></mfrac></mtd></mtr></mtable></math>
+</div>
+<div>
+<math xmlns="http://www.w3.org/1998/Math/MathML" mode="display">
+<mtable>
+<mtr>
+<mtd><munderover><mo>∑</mo>
+<mrow><mi>n</mi><mo>=</mo><mn>1</mn></mrow><mi>m</mi></munderover><mi>n</mi><mo>=</mo><mfrac>
+<mrow><mi>m</mi><mo>(</mo><mi>m</mi><mo>+</mo><mn>1</mn><mo>)</mo></mrow>
+<mrow><mn>2</mn></mrow></mfrac></mtd></mtr></mtable></math>
+</div>
+<p>LaTeX-supported Unicode math symbols can be used in math roles and
+directives:</p>
+<p>The Schrödinger equation</p>
+<div id="eq-schrodinger">
+<math xmlns="http://www.w3.org/1998/Math/MathML" mode="display">
+<mtable>
+<mtr>
+<mtd><mi>i</mi><mi>ℏ</mi><mfrac>
+<mrow><mo>∂</mo></mrow>
+<mrow><mo>∂</mo><mi>t</mi></mrow></mfrac><mo>Ψ</mo><mo>=</mo><mover>
+<mrow><mi>H</mi></mrow><mo>^</mo></mover><mo>Ψ</mo><mo>,</mo></mtd></mtr></mtable></math>
+</div>
+<p>with the <em>wave function</em> <math xmlns="http://www.w3.org/1998/Math/MathML">
+<mrow><mo>Ψ</mo></mrow></math>, describes how the quantum state of a
+physical system changes in time.</p>
+<dl>
+<dt>Math-Accents:</dt>
+<dd><table class="colwidths-given borderless">
+<colgroup>
+<col style="width: 33%" />
+<col style="width: 33%" />
+<col style="width: 33%" />
+</colgroup>
+<tbody>
+<tr><td><p><math xmlns="http://www.w3.org/1998/Math/MathML">
+<mrow><mover>
+<mrow><mi>a</mi></mrow><mo>´</mo></mover></mrow></math> <span class="docutils literal">\acute{a}</span></p></td>
+<td><p><math xmlns="http://www.w3.org/1998/Math/MathML">
+<mrow><mover>
+<mrow><mi>t</mi></mrow><mo>˙</mo></mover></mrow></math> <span class="docutils literal">\dot{t}</span></p></td>
+<td><p><math xmlns="http://www.w3.org/1998/Math/MathML">
+<mrow><mover>
+<mrow><mi>γ</mi></mrow><mo>^</mo></mover></mrow></math> <span class="docutils literal"><span class="pre">\hat{\gamma}</span></span></p></td>
+</tr>
+<tr><td><p><math xmlns="http://www.w3.org/1998/Math/MathML">
+<mrow><mover>
+<mrow><mi>a</mi></mrow><mo>`</mo></mover></mrow></math> <span class="docutils literal">\grave{a}</span></p></td>
+<td><p><math xmlns="http://www.w3.org/1998/Math/MathML">
+<mrow><mover>
+<mrow><mi>t</mi></mrow><mo>¨</mo></mover></mrow></math> <span class="docutils literal">\ddot{t}</span></p></td>
+<td><p><math xmlns="http://www.w3.org/1998/Math/MathML">
+<mrow><mover>
+<mrow><mi>α</mi></mrow><mo>˜</mo></mover></mrow></math> <span class="docutils literal"><span class="pre">\tilde{\alpha}</span></span></p></td>
+</tr>
+<tr><td><p><math xmlns="http://www.w3.org/1998/Math/MathML">
+<mrow><mover>
+<mrow><mi>x</mi></mrow><mo>˘</mo></mover></mrow></math> <span class="docutils literal">\breve{x}</span></p></td>
+<td><p><math xmlns="http://www.w3.org/1998/Math/MathML">
+<mrow><mover>
+<mrow><mi>t</mi></mrow><mo>⃛</mo></mover></mrow></math> <span class="docutils literal">\dddot{t}</span></p></td>
+<td><p><math xmlns="http://www.w3.org/1998/Math/MathML">
+<mrow><mover>
+<mrow><mi>ı</mi></mrow><mo>⃗</mo></mover></mrow></math> <span class="docutils literal"><span class="pre">\vec{\imath}</span></span></p></td>
+</tr>
+<tr><td><p><math xmlns="http://www.w3.org/1998/Math/MathML">
+<mrow><mover>
+<mrow><mi>a</mi></mrow><mo>ˇ</mo></mover></mrow></math> <span class="docutils literal">\check{a}</span></p></td>
+<td><p><math xmlns="http://www.w3.org/1998/Math/MathML">
+<mrow><mover>
+<mrow><mi>a</mi></mrow><mo>¯</mo></mover></mrow></math> <span class="docutils literal">\bar{a}</span></p></td>
+<td><p><math xmlns="http://www.w3.org/1998/Math/MathML">
+<mrow><mover>
+<mrow><mi>R</mi></mrow><mo>⃗</mo></mover></mrow></math> <span class="docutils literal">\vec{R}</span></p></td>
+</tr>
+</tbody>
+</table>
+</dd>
+</dl>
+<!-- \widetilde{xxx}
+\widehat{xxx} -->
+<p>Modulation Transfer Function:</p>
+<div>
+<math xmlns="http://www.w3.org/1998/Math/MathML" mode="display">
+<mtable>
+<mtr>
+<mtd><mtext>MTF</mtext><mo>=</mo><mfenced open="|" close="|">
+<mrow><mfrac>
+<mrow><mi>ℱ</mi><mo>{</mo><mi>s</mi><mo>(</mo><mi>x</mi><mo>)</mo><mo>}</mo></mrow>
+<mrow><mi>ℱ</mi><mo>{</mo><mi>s</mi><mo>(</mo><mi>x</mi><mo>)</mo><mo>}</mo><msub><mo>|</mo>
+<mrow><msub><mi>ω</mi>
+<mrow><mi>x</mi></mrow></msub><mo>=</mo><mn>0</mn></mrow></msub></mrow></mfrac></mrow></mfenced><mo>=</mo><mtext>abs</mtext><mfenced open="(" close=")">
+<mrow><mfrac>
+<mrow><munderover><mo>∫</mo>
+<mrow><mo>-</mo><mo>∞</mo></mrow>
+<mrow><mo>∞</mo></mrow></munderover><mi>s</mi><mo>(</mo><mi>x</mi><mo>)</mo><msup><mtext>e</mtext>
+<mrow><mtext>i</mtext><msub><mi>ω</mi>
+<mrow><mi>x</mi></mrow></msub><mi>x</mi></mrow></msup><mtext>d</mtext>
+<mrow><mi>x</mi></mrow></mrow>
+<mrow><munderover><mo>∫</mo>
+<mrow><mo>-</mo><mo>∞</mo></mrow>
+<mrow><mo>∞</mo></mrow></munderover><mi>s</mi><mo>(</mo><mi>x</mi><mo>)</mo><mtext>d</mtext>
+<mrow><mi>x</mi></mrow></mrow></mfrac></mrow></mfenced><mo>.</mo></mtd></mtr></mtable></math>
+</div>
+<p>Math split over two lines: If a double backslash is detected outside a
+<span class="docutils literal"><span class="pre">\begin{...}</span> <span class="pre">\end{...}</span></span> pair, the math code is wrapped in an <a class="reference external" href="ftp://ftp.ams.org/ams/doc/amsmath/short-math-guide.pdf">AMSmath</a>
+<span class="docutils literal">align</span> environment:</p>
+<div>
+<math xmlns="http://www.w3.org/1998/Math/MathML" mode="display">
+<mtable>
+<mtr>
+<mtd><msub><mi>s</mi>
+<mrow><mtext>out</mtext></mrow></msub><mo>(</mo><mi>x</mi><mo>)</mo></mtd>
+<mtd><mo>=</mo><msub><mi>s</mi>
+<mrow><mtext>in</mtext></mrow></msub><mo>(</mo><mi>x</mi><mo>'</mo><mo>)</mo><mo>*</mo><msub><mi>s</mi><mi>δ</mi></msub><mo>(</mo><mi>x</mi><mo>-</mo><mi>x</mi><mo>'</mo><mo>)</mo></mtd></mtr>
+<mtr>
+<mtd></mtd>
+<mtd><mo>=</mo><mo>∫</mo><msub><mi>s</mi>
+<mrow><mtext>in</mtext></mrow></msub><mo>(</mo><mi>x</mi><mo>'</mo><mo>)</mo><msub><mi>s</mi><mi>δ</mi></msub><mo>(</mo><mi>x</mi><mo>-</mo><mi>x</mi><mo>'</mo><mo>)</mo><mtext>d</mtext><mi>x</mi><mo>'</mo></mtd></mtr></mtable></math>
+</div>
+<p>Cases ("manually", with <span class="docutils literal">matrix</span> environment):</p>
+<div>
+<math xmlns="http://www.w3.org/1998/Math/MathML" mode="display">
+<mtable>
+<mtr>
+<mtd><mtext>sgn</mtext><mo>(</mo><mi>x</mi><mo>)</mo><mo>=</mo><mfenced open="{" close="">
+<mrow>
+<mtable>
+<mtr>
+<mtd><mo>-</mo><mn>1</mn></mtd>
+<mtd><mi>x</mi><mo><</mo><mn>0</mn></mtd></mtr>
+<mtr>
+<mtd><mn>1</mn></mtd>
+<mtd><mi>x</mi><mo>></mo><mn>0</mn></mtd></mtr></mtable></mrow></mfenced></mtd></mtr></mtable></math>
+</div>
+<p>Cases with the <a class="reference external" href="ftp://ftp.ams.org/ams/doc/amsmath/short-math-guide.pdf">AMSmath</a> <span class="docutils literal">cases</span> environment (not (yet) supported by
+HTML writers with <span class="docutils literal"><span class="pre">--math-output=MathML</span></span>):</p>
+<div class="system-message">
+<p class="system-message-title">System Message: ERROR/3 (<span class="docutils literal">functional/input/data/math.txt</span>, line 108)</p>
+<p>
+Environment not supported! Supported environment: "matrix".</p>
+<pre class="literal-block">
+\mathrm{sgn}(x) = \begin{cases}
+ -1 & x<0\\
+ 1 & x>0
+ \end{cases}
+</pre>
+</div>
+</div>
+</body>
+</html>
--- /dev/null
+<?xml version="1.0" encoding="utf-8" ?>
+<!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">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<meta name="generator" content="Docutils 0.16: http://docutils.sourceforge.net/" />
+<title>link_in_substitution.txt</title>
+<link rel="stylesheet" href="foo&bar.css" type="text/css" />
+</head>
+<body>
+<div class="document">
+
+
+<p>Test the interaction of transforms.references.Substitutions and
+transforms.references.ExternalLinks.</p>
+<p><a class="reference external" href="http://docutils.sourceforge.net/rst.html">reStructuredText</a> is cool!</p>
+<p>There is a preferred alternative:</p>
+<p><a class="reference external" href="http://docutils.sourceforge.net/rst.html">reStructuredText</a> is cool!</p>
+<p>This only works for the case where the entire substitution is a
+reference, not when the reference is embedded as part of the
+substitution:</p>
+<p>unstructured <a class="reference external" href="http://docutils.sourceforge.net/rst.html">reStructuredText</a> is uncool!</p>
+</div>
+</body>
+</html>
--- /dev/null
+<?xml version="1.0" encoding="utf-8" ?>
+<!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://www.python.org/dev/peps/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=utf-8" />
+ <meta name="generator" content="Docutils 0.16: http://docutils.sourceforge.net/" />
+ <title>PEP 100 -- Test PEP</title>
+ <link rel="stylesheet" href="../input/data/html4css1.css" type="text/css" />
+</head>
+<body bgcolor="white">
+<table class="navigation" cellpadding="0" cellspacing="0"
+ width="100%" border="0">
+<tr><td class="navicon" width="150" height="35">
+<a href="http://www.python.org/" title="Python Home Page">
+<img src="http://www.python.org/pics/PyBanner000.gif" alt="[Python]"
+ border="0" width="150" height="35" /></a></td>
+<td class="textlinks" align="left">
+[<b><a href="http://www.python.org/">Python Home</a></b>]
+[<b><a href="http://www.python.org/dev/peps/">PEP Index</a></b>]
+[<b><a href="http://www.python.org/peps/pep-0100.txt">PEP Source</a></b>]
+</td></tr></table>
+<div class="document">
+<table class="rfc2822 docutils field-list" frame="void" rules="none">
+<col class="field-name" />
+<col class="field-body" />
+<tbody valign="top">
+<tr class="field"><th class="field-name">PEP:</th><td class="field-body">100</td>
+</tr>
+<tr class="field"><th class="field-name">Title:</th><td class="field-body">Test PEP</td>
+</tr>
+<tr class="field"><th class="field-name">Version:</th><td class="field-body">42</td>
+</tr>
+<tr class="field"><th class="field-name">Last-Modified:</th><td class="field-body"><a class="reference external" href="http://hg.python.org/peps/file/default/pep-0100.txt">A long time ago.</a></td>
+</tr>
+<tr class="field"><th class="field-name">Author:</th><td class="field-body">John Doe <john at example.org></td>
+</tr>
+<tr class="field"><th class="field-name">Discussions-To:</th><td class="field-body"><<a class="reference external" href="mailto:devnull%40example.org?subject=PEP%20100">devnull at example.org</a>></td>
+</tr>
+<tr class="field"><th class="field-name">Status:</th><td class="field-body">Draft</td>
+</tr>
+<tr class="field"><th class="field-name">Type:</th><td class="field-body">Standards Track</td>
+</tr>
+<tr class="field"><th class="field-name">Content-Type:</th><td class="field-body"><a class="reference external" href="http://www.python.org/dev/peps/pep-0012">text/x-rst</a></td>
+</tr>
+<tr class="field"><th class="field-name">Created:</th><td class="field-body">01-Jun-2001</td>
+</tr>
+<tr class="field"><th class="field-name">Post-History:</th><td class="field-body">13-Jun-2001</td>
+</tr>
+</tbody>
+</table>
+<hr />
+<div class="contents topic" id="contents">
+<p class="topic-title">Contents</p>
+<ul class="simple">
+<li><a class="reference internal" href="#abstract" id="toc-entry-1">Abstract</a></li>
+<li><a class="reference internal" href="#copyright" id="toc-entry-2">Copyright</a></li>
+<li><a class="reference internal" href="#references-and-footnotes" id="toc-entry-3">References and Footnotes</a></li>
+</ul>
+</div>
+<div class="section" id="abstract">
+<h1><a class="toc-backref" href="#toc-entry-1">Abstract</a></h1>
+<p>This is just a test <a class="footnote-reference" href="#footnote-1" id="footnote-reference-1">[1]</a>. See the <a class="reference external" href="http://www.python.org/peps/">PEP repository</a> <a class="footnote-reference" href="#footnote-2" id="footnote-reference-2">[2]</a> for the real
+thing.</p>
+</div>
+<div class="section" id="copyright">
+<h1><a class="toc-backref" href="#toc-entry-2">Copyright</a></h1>
+<p>This document has been placed in the public domain.</p>
+</div>
+<div class="section" id="references-and-footnotes">
+<h1><a class="toc-backref" href="#toc-entry-3">References and Footnotes</a></h1>
+<table class="docutils footnote" frame="void" id="footnote-1" rules="none">
+<colgroup><col class="label" /><col /></colgroup>
+<tbody valign="top">
+<tr><td class="label"><a class="fn-backref" href="#footnote-reference-1">[1]</a></td><td>PEP editors: <a class="reference external" href="mailto:peps%40python.org">peps<span>@</span>python<span>.</span>org</a></td></tr>
+</tbody>
+</table>
+<table class="docutils footnote" frame="void" id="footnote-2" rules="none">
+<colgroup><col class="label" /><col /></colgroup>
+<tbody valign="top">
+<tr><td class="label"><a class="fn-backref" href="#footnote-reference-2">[2]</a></td><td><a class="reference external" href="http://www.python.org/peps/">http://www.python.org/peps/</a></td></tr>
+</tbody>
+</table>
+</div>
+
+</div>
+</body>
+</html>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE document PUBLIC "+//IDN docutils.sourceforge.net//DTD Docutils Generic//EN//XML" "http://docutils.sourceforge.net/docs/ref/docutils.dtd">
+<!-- Generated by Docutils 0.16 -->
+<document ids="restructuredtext-test-document doctitle" names="restructuredtext\ test\ document doctitle" source="functional/input/standalone_rst_docutils_xml.txt" title="reStructuredText Test Document">
+ <title>reStructuredText Test Document</title>
+ <subtitle ids="examples-of-syntax-constructs subtitle" names="examples\ of\ syntax\ constructs subtitle">Examples of Syntax Constructs</subtitle>
+ <decoration>
+ <header>
+ <paragraph>Document header</paragraph>
+ </header>
+ <footer>
+ <paragraph>Document footer</paragraph>
+ </footer>
+ </decoration>
+ <docinfo>
+ <author>David Goodger</author>
+ <address xml:space="preserve">123 Example Street
+Example, EX Canada
+A1B 2C3</address>
+ <contact><reference refuri="mailto:goodger@python.org">goodger@python.org</reference></contact>
+ <authors>
+ <author>Me</author>
+ <author>Myself</author>
+ <author>I</author>
+ </authors>
+ <organization>humankind</organization>
+ <date>Now, or yesterday. Or maybe even <emphasis>before</emphasis> yesterday.</date>
+ <status>This is a "work in progress"</status>
+ <revision>is managed by a version control system.</revision>
+ <version>1</version>
+ <copyright>This document has been placed in the public domain. You
+ may do with it as you wish. You may copy, modify,
+ redistribute, reattribute, sell, buy, rent, lease,
+ destroy, or improve it, quote it at length, excerpt,
+ incorporate, collate, fold, staple, or mutilate it, or do
+ anything else to it that your or anyone else's heart
+ desires.</copyright>
+ <field classes="field-name">
+ <field_name>field name</field_name>
+ <field_body>
+ <paragraph>This is a "generic bibliographic field".</paragraph>
+ </field_body>
+ </field>
+ <field classes="field-name-2">
+ <field_name>field name "2"</field_name>
+ <field_body>
+ <paragraph>Generic bibliographic fields may contain multiple body elements.</paragraph>
+ <paragraph>Like this.</paragraph>
+ </field_body>
+ </field>
+ </docinfo>
+ <topic classes="dedication">
+ <title>Dedication</title>
+ <paragraph>For Docutils users & co-developers.</paragraph>
+ </topic>
+ <topic classes="abstract">
+ <title>Abstract</title>
+ <paragraph>This is a test document, containing at least one example of each
+ reStructuredText construct.</paragraph>
+ </topic>
+ <comment xml:space="preserve">This is a comment. Note how any initial comments are moved by
+transforms to after the document title, subtitle, and docinfo.</comment>
+ <target refid="doctitle"></target>
+ <comment xml:space="preserve">Above is the document title, and below is the subtitle.
+They are transformed from section titles after parsing.</comment>
+ <target refid="subtitle"></target>
+ <comment xml:space="preserve">bibliographic fields (which also require a transform):</comment>
+ <raw format="latex" xml:space="preserve">\pagebreak[4] % start ToC on new page</raw>
+ <topic classes="contents" ids="table-of-contents" names="table\ of\ contents">
+ <title>Table of Contents</title>
+ <bullet_list classes="auto-toc">
+ <list_item>
+ <paragraph><reference ids="toc-entry-1" refid="structural-elements"><generated classes="sectnum">1 </generated>Structural Elements</reference></paragraph>
+ <bullet_list classes="auto-toc">
+ <list_item>
+ <paragraph><reference ids="toc-entry-2" refid="section-title"><generated classes="sectnum">1.1 </generated>Section Title</reference></paragraph>
+ </list_item>
+ <list_item>
+ <paragraph><reference ids="toc-entry-3" refid="empty-section"><generated classes="sectnum">1.2 </generated>Empty Section</reference></paragraph>
+ </list_item>
+ <list_item>
+ <paragraph><reference ids="toc-entry-4" refid="transitions"><generated classes="sectnum">1.3 </generated>Transitions</reference></paragraph>
+ </list_item>
+ </bullet_list>
+ </list_item>
+ <list_item>
+ <paragraph><reference ids="toc-entry-5" refid="body-elements"><generated classes="sectnum">2 </generated>Body Elements</reference></paragraph>
+ <bullet_list classes="auto-toc">
+ <list_item>
+ <paragraph><reference ids="toc-entry-6" refid="paragraphs"><generated classes="sectnum">2.1 </generated>Paragraphs</reference></paragraph>
+ <bullet_list classes="auto-toc">
+ <list_item>
+ <paragraph><reference ids="toc-entry-7" refid="inline-markup"><generated classes="sectnum">2.1.1 </generated>Inline Markup</reference></paragraph>
+ </list_item>
+ </bullet_list>
+ </list_item>
+ <list_item>
+ <paragraph><reference ids="toc-entry-8" refid="bullet-lists"><generated classes="sectnum">2.2 </generated>Bullet Lists</reference></paragraph>
+ </list_item>
+ <list_item>
+ <paragraph><reference ids="toc-entry-9" refid="enumerated-lists"><generated classes="sectnum">2.3 </generated>Enumerated Lists</reference></paragraph>
+ </list_item>
+ <list_item>
+ <paragraph><reference ids="toc-entry-10" refid="definition-lists"><generated classes="sectnum">2.4 </generated>Definition Lists</reference></paragraph>
+ </list_item>
+ <list_item>
+ <paragraph><reference ids="toc-entry-11" refid="field-lists"><generated classes="sectnum">2.5 </generated>Field Lists</reference></paragraph>
+ </list_item>
+ <list_item>
+ <paragraph><reference ids="toc-entry-12" refid="option-lists"><generated classes="sectnum">2.6 </generated>Option Lists</reference></paragraph>
+ </list_item>
+ <list_item>
+ <paragraph><reference ids="toc-entry-13" refid="literal-blocks"><generated classes="sectnum">2.7 </generated>Literal Blocks</reference></paragraph>
+ </list_item>
+ <list_item>
+ <paragraph><reference ids="toc-entry-14" refid="line-blocks"><generated classes="sectnum">2.8 </generated>Line Blocks</reference></paragraph>
+ </list_item>
+ <list_item>
+ <paragraph><reference ids="toc-entry-15" refid="block-quotes"><generated classes="sectnum">2.9 </generated>Block Quotes</reference></paragraph>
+ </list_item>
+ <list_item>
+ <paragraph><reference ids="toc-entry-16" refid="doctest-blocks"><generated classes="sectnum">2.10 </generated>Doctest Blocks</reference></paragraph>
+ </list_item>
+ <list_item>
+ <paragraph><reference ids="toc-entry-17" refid="footnotes"><generated classes="sectnum">2.11 </generated>Footnotes</reference></paragraph>
+ </list_item>
+ <list_item>
+ <paragraph><reference ids="toc-entry-18" refid="citations"><generated classes="sectnum">2.12 </generated>Citations</reference></paragraph>
+ </list_item>
+ <list_item>
+ <paragraph><reference ids="toc-entry-19" refid="targets"><generated classes="sectnum">2.13 </generated>Targets</reference></paragraph>
+ <bullet_list classes="auto-toc">
+ <list_item>
+ <paragraph><reference ids="toc-entry-20" refid="duplicate-target-names"><generated classes="sectnum">2.13.1 </generated>Duplicate Target Names</reference></paragraph>
+ </list_item>
+ <list_item>
+ <paragraph><reference ids="toc-entry-21" refid="duplicate-target-names-1"><generated classes="sectnum">2.13.2 </generated>Duplicate Target Names</reference></paragraph>
+ </list_item>
+ </bullet_list>
+ </list_item>
+ <list_item>
+ <paragraph><reference ids="toc-entry-22" refid="directives"><generated classes="sectnum">2.14 </generated>Directives</reference></paragraph>
+ <bullet_list classes="auto-toc">
+ <list_item>
+ <paragraph><reference ids="toc-entry-23" refid="document-parts"><generated classes="sectnum">2.14.1 </generated>Document Parts</reference></paragraph>
+ </list_item>
+ <list_item>
+ <paragraph><reference ids="toc-entry-24" refid="images-and-figures"><generated classes="sectnum">2.14.2 </generated>Images and Figures</reference></paragraph>
+ </list_item>
+ <list_item>
+ <paragraph><reference ids="toc-entry-25" refid="admonitions"><generated classes="sectnum">2.14.3 </generated>Admonitions</reference></paragraph>
+ </list_item>
+ <list_item>
+ <paragraph><reference ids="toc-entry-26" refid="topics-sidebars-and-rubrics"><generated classes="sectnum">2.14.4 </generated>Topics, Sidebars, and Rubrics</reference></paragraph>
+ </list_item>
+ <list_item>
+ <paragraph><reference ids="toc-entry-27" refid="target-footnotes"><generated classes="sectnum">2.14.5 </generated>Target Footnotes</reference></paragraph>
+ </list_item>
+ <list_item>
+ <paragraph><reference ids="toc-entry-28" refid="replacement-text"><generated classes="sectnum">2.14.6 </generated>Replacement Text</reference></paragraph>
+ </list_item>
+ <list_item>
+ <paragraph><reference ids="toc-entry-29" refid="compound-paragraph"><generated classes="sectnum">2.14.7 </generated>Compound Paragraph</reference></paragraph>
+ </list_item>
+ <list_item>
+ <paragraph><reference ids="toc-entry-30" refid="parsed-literal-blocks"><generated classes="sectnum">2.14.8 </generated>Parsed Literal Blocks</reference></paragraph>
+ </list_item>
+ <list_item>
+ <paragraph><reference ids="toc-entry-31" refid="code"><generated classes="sectnum">2.14.9 </generated>Code</reference></paragraph>
+ </list_item>
+ </bullet_list>
+ </list_item>
+ <list_item>
+ <paragraph><reference ids="toc-entry-32" refid="substitution-definitions"><generated classes="sectnum">2.15 </generated>Substitution Definitions</reference></paragraph>
+ </list_item>
+ <list_item>
+ <paragraph><reference ids="toc-entry-33" refid="comments"><generated classes="sectnum">2.16 </generated>Comments</reference></paragraph>
+ </list_item>
+ <list_item>
+ <paragraph><reference ids="toc-entry-34" refid="raw-text"><generated classes="sectnum">2.17 </generated>Raw text</reference></paragraph>
+ </list_item>
+ <list_item>
+ <paragraph><reference ids="toc-entry-35" refid="container"><generated classes="sectnum">2.18 </generated>Container</reference></paragraph>
+ </list_item>
+ <list_item>
+ <paragraph><reference ids="toc-entry-36" refid="colspanning-tables"><generated classes="sectnum">2.19 </generated>Colspanning tables</reference></paragraph>
+ </list_item>
+ <list_item>
+ <paragraph><reference ids="toc-entry-37" refid="rowspanning-tables"><generated classes="sectnum">2.20 </generated>Rowspanning tables</reference></paragraph>
+ </list_item>
+ <list_item>
+ <paragraph><reference ids="toc-entry-38" refid="complex-tables"><generated classes="sectnum">2.21 </generated>Complex tables</reference></paragraph>
+ </list_item>
+ <list_item>
+ <paragraph><reference ids="toc-entry-39" refid="list-tables"><generated classes="sectnum">2.22 </generated>List Tables</reference></paragraph>
+ </list_item>
+ </bullet_list>
+ </list_item>
+ <list_item>
+ <paragraph><reference ids="toc-entry-40" refid="error-handling"><generated classes="sectnum">3 </generated>Error Handling</reference></paragraph>
+ </list_item>
+ </bullet_list>
+ </topic>
+ <section ids="structural-elements" names="structural\ elements">
+ <title auto="1" refid="toc-entry-1"><generated classes="sectnum">1 </generated>Structural Elements</title>
+ <section ids="section-title" names="section\ title">
+ <title auto="1" refid="toc-entry-2"><generated classes="sectnum">1.1 </generated>Section Title</title>
+ <subtitle ids="section-subtitle" names="section\ subtitle">Section Subtitle</subtitle>
+ <paragraph>Lone subsections are converted to a section subtitle by a transform
+ activated with the <literal>--section-subtitles</literal> command line option or the
+ <literal>sectsubtitle-xform</literal> configuration value.</paragraph>
+ </section>
+ <section ids="empty-section" names="empty\ section">
+ <title auto="1" refid="toc-entry-3"><generated classes="sectnum">1.2 </generated>Empty Section</title>
+ </section>
+ <section ids="transitions" names="transitions">
+ <title auto="1" refid="toc-entry-4"><generated classes="sectnum">1.3 </generated>Transitions</title>
+ <paragraph>Here's a transition:</paragraph>
+ <transition></transition>
+ <paragraph>It divides the section. Transitions may also occur between sections:</paragraph>
+ </section>
+ </section>
+ <transition></transition>
+ <section ids="body-elements" names="body\ elements">
+ <title auto="1" refid="toc-entry-5"><generated classes="sectnum">2 </generated>Body Elements</title>
+ <section ids="paragraphs" names="paragraphs">
+ <title auto="1" refid="toc-entry-6"><generated classes="sectnum">2.1 </generated>Paragraphs</title>
+ <paragraph>A paragraph.</paragraph>
+ <section ids="inline-markup" names="inline\ markup">
+ <title auto="1" refid="toc-entry-7"><generated classes="sectnum">2.1.1 </generated>Inline Markup</title>
+ <paragraph>Paragraphs contain text and may contain inline markup: <emphasis>emphasis</emphasis>,
+ <strong>strong emphasis</strong>, <literal>inline literals</literal>, standalone hyperlinks
+ (<reference refuri="http://www.python.org">http://www.python.org</reference>), external hyperlinks (<reference name="Python" refuri="http://www.python.org/">Python</reference> <footnote_reference auto="1" ids="footnote-reference-10" refid="footnote-6">5</footnote_reference>), internal
+ cross-references (<reference name="example" refid="example">example</reference>), external hyperlinks with embedded URIs
+ (<reference name="Python web site" refuri="http://www.python.org">Python web site</reference>), <reference anonymous="1" name="anonymous hyperlink references" refuri="http://www.python.org/">anonymous hyperlink
+ references</reference> <footnote_reference auto="1" ids="footnote-reference-14" refid="footnote-6">5</footnote_reference> (<reference anonymous="1" name="a second reference" refuri="http://docutils.sourceforge.net/">a second reference</reference> <footnote_reference auto="1" ids="footnote-reference-15" refid="footnote-8">7</footnote_reference>), footnote references (manually
+ numbered <footnote_reference ids="footnote-reference-1" refid="footnote-1">1</footnote_reference>, anonymous auto-numbered <footnote_reference auto="1" ids="footnote-reference-2" refid="footnote-2">3</footnote_reference>, labeled auto-numbered
+ <footnote_reference auto="1" ids="footnote-reference-3" refid="label">2</footnote_reference>, or symbolic <footnote_reference auto="*" ids="footnote-reference-4" refid="footnote-3">*</footnote_reference>), citation references (<citation_reference ids="citation-reference-1" refid="cit2002">CIT2002</citation_reference>),
+ substitution references (<image alt="EXAMPLE" uri="../../../docs/user/rst/images/biohazard.png"></image> &
+ a <emphasis>trimmed heart</emphasis> <literal>(U+2665):</literal>♥), and <target ids="inline-hyperlink-targets" names="inline\ hyperlink\ targets">inline hyperlink targets</target>
+ (see <reference name="Targets" refid="targets">Targets</reference> below for a reference back to here). Character-level
+ inline markup is also possible (although exceedingly ugly!) in <emphasis>re</emphasis><literal>Structured</literal><emphasis>Text</emphasis>. Problems are indicated by <problematic ids="problematic-1" refid="system-message-1">|problematic|</problematic> text
+ (generated by processing errors; this one is intentional). Here is a
+ reference to the <reference name="doctitle" refid="doctitle">doctitle</reference> and the <reference name="subtitle" refid="subtitle">subtitle</reference>.</paragraph>
+ <target anonymous="1" ids="target-1" refuri="http://www.python.org/"></target>
+ <target anonymous="1" ids="target-2" refuri="http://docutils.sourceforge.net/"></target>
+ <paragraph>The default role for interpreted text is <title_reference>Title Reference</title_reference>. Here are
+ some explicit interpreted text roles: a PEP reference (<reference refuri="http://www.python.org/dev/peps/pep-0287">PEP 287</reference>); an
+ RFC reference (<reference refuri="http://tools.ietf.org/html/rfc2822.html">RFC 2822</reference>); an abbreviation (<abbreviation>abb.</abbreviation>), an acronym
+ (<acronym>reST</acronym>), code (<literal classes="code">print "hello world"</literal>); a <subscript>subscript</subscript>;
+ a <superscript>superscript</superscript> and explicit roles for <title_reference>Docutils</title_reference>'
+ <emphasis>standard</emphasis> <strong>inline</strong> <literal>markup</literal>.</paragraph>
+ <comment xml:space="preserve">DO NOT RE-WRAP THE FOLLOWING PARAGRAPH!</comment>
+ <paragraph>Let's test wrapping and whitespace significance in inline literals:
+ <literal>This is an example of --inline-literal --text, --including some--
+strangely--hyphenated-words. Adjust-the-width-of-your-browser-window
+to see how the text is wrapped. -- ---- -------- Now note the
+spacing between the words of this sentence (words
+should be grouped in pairs).</literal></paragraph>
+ <paragraph>If the <literal>--pep-references</literal> option was supplied, there should be a
+ live link to PEP 258 here.</paragraph>
+ </section>
+ </section>
+ <section ids="bullet-lists" names="bullet\ lists">
+ <title auto="1" refid="toc-entry-8"><generated classes="sectnum">2.2 </generated>Bullet Lists</title>
+ <bullet_list bullet="-">
+ <list_item>
+ <paragraph>A bullet list</paragraph>
+ <bullet_list bullet="+">
+ <list_item>
+ <paragraph>Nested bullet list.</paragraph>
+ </list_item>
+ <list_item>
+ <paragraph>Nested item 2.</paragraph>
+ </list_item>
+ </bullet_list>
+ </list_item>
+ <list_item>
+ <paragraph>Item 2.</paragraph>
+ <paragraph>Paragraph 2 of item 2.</paragraph>
+ <bullet_list bullet="*">
+ <list_item>
+ <paragraph>Nested bullet list.</paragraph>
+ </list_item>
+ <list_item>
+ <paragraph>Nested item 2.</paragraph>
+ <bullet_list bullet="-">
+ <list_item>
+ <paragraph>Third level.</paragraph>
+ </list_item>
+ <list_item>
+ <paragraph>Item 2.</paragraph>
+ </list_item>
+ </bullet_list>
+ </list_item>
+ <list_item>
+ <paragraph>Nested item 3.</paragraph>
+ </list_item>
+ <list_item>
+ <paragraph>This nested list should be compacted by the HTML writer.</paragraph>
+ <target ids="target" names="target"></target>
+ <comment xml:space="preserve">Even if this item contains a target and a comment.</comment>
+ </list_item>
+ </bullet_list>
+ </list_item>
+ </bullet_list>
+ </section>
+ <section ids="enumerated-lists" names="enumerated\ lists">
+ <title auto="1" refid="toc-entry-9"><generated classes="sectnum">2.3 </generated>Enumerated Lists</title>
+ <enumerated_list enumtype="arabic" prefix="" suffix=".">
+ <list_item>
+ <paragraph>Arabic numerals.</paragraph>
+ <enumerated_list enumtype="loweralpha" prefix="" suffix=")">
+ <list_item>
+ <paragraph>lower alpha)</paragraph>
+ <enumerated_list enumtype="lowerroman" prefix="(" suffix=")">
+ <list_item>
+ <paragraph>(lower roman)</paragraph>
+ <enumerated_list enumtype="upperalpha" prefix="" suffix=".">
+ <list_item>
+ <paragraph>upper alpha.</paragraph>
+ <enumerated_list enumtype="upperroman" prefix="" suffix=")">
+ <list_item>
+ <paragraph>upper roman)</paragraph>
+ </list_item>
+ </enumerated_list>
+ </list_item>
+ </enumerated_list>
+ </list_item>
+ </enumerated_list>
+ </list_item>
+ </enumerated_list>
+ </list_item>
+ <list_item>
+ <paragraph>Lists that don't start at 1:</paragraph>
+ <enumerated_list enumtype="arabic" prefix="" start="3" suffix=".">
+ <list_item>
+ <paragraph>Three</paragraph>
+ </list_item>
+ <list_item>
+ <paragraph>Four</paragraph>
+ </list_item>
+ </enumerated_list>
+ <system_message level="1" line="8" source="functional/input/data/standard.txt" type="INFO">
+ <paragraph>Enumerated list start value not ordinal-1: "3" (ordinal 3)</paragraph>
+ </system_message>
+ <enumerated_list enumtype="upperalpha" prefix="" start="3" suffix=".">
+ <list_item>
+ <paragraph>C</paragraph>
+ </list_item>
+ <list_item>
+ <paragraph>D</paragraph>
+ </list_item>
+ </enumerated_list>
+ <system_message level="1" line="8" source="functional/input/data/standard.txt" type="INFO">
+ <paragraph>Enumerated list start value not ordinal-1: "C" (ordinal 3)</paragraph>
+ </system_message>
+ <enumerated_list enumtype="lowerroman" prefix="" start="3" suffix=".">
+ <list_item>
+ <paragraph>iii</paragraph>
+ </list_item>
+ <list_item>
+ <paragraph>iv</paragraph>
+ </list_item>
+ </enumerated_list>
+ <system_message level="1" line="8" source="functional/input/data/standard.txt" type="INFO">
+ <paragraph>Enumerated list start value not ordinal-1: "iii" (ordinal 3)</paragraph>
+ </system_message>
+ </list_item>
+ </enumerated_list>
+ </section>
+ <section ids="definition-lists" names="definition\ lists">
+ <title auto="1" refid="toc-entry-10"><generated classes="sectnum">2.4 </generated>Definition Lists</title>
+ <definition_list>
+ <definition_list_item>
+ <term>Term</term>
+ <definition>
+ <paragraph>Definition</paragraph>
+ </definition>
+ </definition_list_item>
+ <definition_list_item>
+ <term>Term</term>
+ <classifier>classifier</classifier>
+ <definition>
+ <paragraph>Definition paragraph 1.</paragraph>
+ <paragraph>Definition paragraph 2.</paragraph>
+ </definition>
+ </definition_list_item>
+ <definition_list_item>
+ <term>Term</term>
+ <definition>
+ <paragraph>Definition</paragraph>
+ </definition>
+ </definition_list_item>
+ <definition_list_item>
+ <term>Term</term>
+ <classifier>classifier one</classifier>
+ <classifier>classifier two</classifier>
+ <definition>
+ <paragraph>Definition</paragraph>
+ </definition>
+ </definition_list_item>
+ </definition_list>
+ </section>
+ <section ids="field-lists" names="field\ lists">
+ <title auto="1" refid="toc-entry-11"><generated classes="sectnum">2.5 </generated>Field Lists</title>
+ <field_list>
+ <field>
+ <field_name>what</field_name>
+ <field_body>
+ <paragraph>Field lists map field names to field bodies, like database
+ records. They are often part of an extension syntax. They are
+ an unambiguous variant of RFC 2822 fields.</paragraph>
+ </field_body>
+ </field>
+ <field>
+ <field_name>how arg1 arg2</field_name>
+ <field_body>
+ <paragraph>The field marker is a colon, the field name, and a colon.</paragraph>
+ <paragraph>The field body may contain one or more body elements, indented
+ relative to the field marker.</paragraph>
+ </field_body>
+ </field>
+ <field>
+ <field_name>credits</field_name>
+ <field_body>
+ <paragraph classes="credits">This paragraph has the <title_reference>credits</title_reference> class set. (This is actually not
+ about credits but just for ensuring that the class attribute
+ doesn't get stripped away.)</paragraph>
+ </field_body>
+ </field>
+ </field_list>
+ </section>
+ <section ids="option-lists" names="option\ lists">
+ <title auto="1" refid="toc-entry-12"><generated classes="sectnum">2.6 </generated>Option Lists</title>
+ <paragraph>For listing command-line options:</paragraph>
+ <option_list>
+ <option_list_item>
+ <option_group>
+ <option>
+ <option_string>-a</option_string>
+ </option>
+ </option_group>
+ <description>
+ <paragraph>command-line option "a"</paragraph>
+ </description>
+ </option_list_item>
+ <option_list_item>
+ <option_group>
+ <option>
+ <option_string>-b</option_string>
+ <option_argument delimiter=" ">file</option_argument>
+ </option>
+ </option_group>
+ <description>
+ <paragraph>options can have arguments
+ and long descriptions</paragraph>
+ </description>
+ </option_list_item>
+ <option_list_item>
+ <option_group>
+ <option>
+ <option_string>--long</option_string>
+ </option>
+ </option_group>
+ <description>
+ <paragraph>options can be long also</paragraph>
+ </description>
+ </option_list_item>
+ <option_list_item>
+ <option_group>
+ <option>
+ <option_string>--input</option_string>
+ <option_argument delimiter="=">file</option_argument>
+ </option>
+ </option_group>
+ <description>
+ <paragraph>long options can also have
+ arguments</paragraph>
+ </description>
+ </option_list_item>
+ <option_list_item>
+ <option_group>
+ <option>
+ <option_string>--very-long-option</option_string>
+ </option>
+ </option_group>
+ <description>
+ <paragraph>The description can also start on the next line.</paragraph>
+ <paragraph>The description may contain multiple body elements,
+ regardless of where it starts.</paragraph>
+ </description>
+ </option_list_item>
+ <option_list_item>
+ <option_group>
+ <option>
+ <option_string>-x</option_string>
+ </option>
+ <option>
+ <option_string>-y</option_string>
+ </option>
+ <option>
+ <option_string>-z</option_string>
+ </option>
+ </option_group>
+ <description>
+ <paragraph>Multiple options are an "option group".</paragraph>
+ </description>
+ </option_list_item>
+ <option_list_item>
+ <option_group>
+ <option>
+ <option_string>-v</option_string>
+ </option>
+ <option>
+ <option_string>--verbose</option_string>
+ </option>
+ </option_group>
+ <description>
+ <paragraph>Commonly-seen: short & long options.</paragraph>
+ </description>
+ </option_list_item>
+ <option_list_item>
+ <option_group>
+ <option>
+ <option_string>-1</option_string>
+ <option_argument delimiter=" ">file</option_argument>
+ </option>
+ <option>
+ <option_string>--one</option_string>
+ <option_argument delimiter="=">file</option_argument>
+ </option>
+ <option>
+ <option_string>--two</option_string>
+ <option_argument delimiter=" ">file</option_argument>
+ </option>
+ </option_group>
+ <description>
+ <paragraph>Multiple options with arguments.</paragraph>
+ </description>
+ </option_list_item>
+ <option_list_item>
+ <option_group>
+ <option>
+ <option_string>/V</option_string>
+ </option>
+ </option_group>
+ <description>
+ <paragraph>DOS/VMS-style options too</paragraph>
+ </description>
+ </option_list_item>
+ </option_list>
+ <paragraph>There must be at least two spaces between the option and the
+ description.</paragraph>
+ </section>
+ <section ids="literal-blocks" names="literal\ blocks">
+ <title auto="1" refid="toc-entry-13"><generated classes="sectnum">2.7 </generated>Literal Blocks</title>
+ <paragraph>Literal blocks are indicated with a double-colon ("::") at the end of
+ the preceding paragraph (over there <literal>--></literal>). They can be indented:</paragraph>
+ <literal_block xml:space="preserve">if literal_block:
+ text = 'is left as-is'
+ spaces_and_linebreaks = 'are preserved'
+ markup_processing = None</literal_block>
+ <paragraph>Or they can be quoted without indentation:</paragraph>
+ <literal_block xml:space="preserve">>> Great idea!
+>
+> Why didn't I think of that?</literal_block>
+ </section>
+ <section ids="line-blocks" names="line\ blocks">
+ <title auto="1" refid="toc-entry-14"><generated classes="sectnum">2.8 </generated>Line Blocks</title>
+ <paragraph>This section tests line blocks. Line blocks are body elements which
+ consist of lines and other line blocks. Nested line blocks cause
+ indentation.</paragraph>
+ <line_block>
+ <line>This is a line block. It ends with a blank line.</line>
+ <line_block>
+ <line>New lines begin with a vertical bar ("|").</line>
+ <line>Line breaks and initial indent are significant, and preserved.</line>
+ <line_block>
+ <line>Continuation lines are also possible. A long line that is intended
+ to wrap should begin with a space in place of the vertical bar.</line>
+ </line_block>
+ <line>The left edge of a continuation line need not be aligned with
+ the left edge of the text above it.</line>
+ </line_block>
+ </line_block>
+ <line_block>
+ <line>This is a second line block.</line>
+ <line></line>
+ <line>Blank lines are permitted internally, but they must begin with a "|".</line>
+ </line_block>
+ <paragraph>Another line block, surrounded by paragraphs:</paragraph>
+ <line_block>
+ <line>And it's no good waiting by the window</line>
+ <line>It's no good waiting for the sun</line>
+ <line>Please believe me, the things you dream of</line>
+ <line>They don't fall in the lap of no-one</line>
+ </line_block>
+ <paragraph>Take it away, Eric the Orchestra Leader!</paragraph>
+ <block_quote>
+ <line_block>
+ <line>A one, two, a one two three four</line>
+ <line></line>
+ <line>Half a bee, philosophically,</line>
+ <line_block>
+ <line>must, <emphasis>ipso facto</emphasis>, half not be.</line>
+ </line_block>
+ <line>But half the bee has got to be,</line>
+ <line_block>
+ <line><emphasis>vis a vis</emphasis> its entity. D'you see?</line>
+ <line></line>
+ </line_block>
+ <line>But can a bee be said to be</line>
+ <line_block>
+ <line>or not to be an entire bee,</line>
+ <line_block>
+ <line>when half the bee is not a bee,</line>
+ <line_block>
+ <line>due to some ancient injury?</line>
+ <line></line>
+ </line_block>
+ </line_block>
+ </line_block>
+ <line>Singing...</line>
+ </line_block>
+ </block_quote>
+ <paragraph>A line block, like the following poem by Christian Morgenstern, can
+ also be centre-aligned:</paragraph>
+ <line_block classes="language-de align-center">
+ <line><strong>Die Trichter</strong></line>
+ <line></line>
+ <line>Zwei Trichter wandeln durch die Nacht.</line>
+ <line>Durch ihres Rumpfs verengten Schacht</line>
+ <line>fließt weißes Mondlicht</line>
+ <line>still und heiter</line>
+ <line>auf ihren</line>
+ <line>Waldweg</line>
+ <line>u. s.</line>
+ <line>w.</line>
+ <line></line>
+ </line_block>
+ </section>
+ <section ids="block-quotes" names="block\ quotes">
+ <title auto="1" refid="toc-entry-15"><generated classes="sectnum">2.9 </generated>Block Quotes</title>
+ <paragraph>Block quotes consist of indented body elements:</paragraph>
+ <block_quote>
+ <paragraph>My theory by A. Elk. Brackets Miss, brackets. This theory goes
+ as follows and begins now. All brontosauruses are thin at one
+ end, much much thicker in the middle and then thin again at the
+ far end. That is my theory, it is mine, and belongs to me and I
+ own it, and what it is too.</paragraph>
+ <attribution>Anne Elk (Miss)</attribution>
+ </block_quote>
+ <paragraph>The language of a quote (like any other object) can be specified by
+ a class attribute:</paragraph>
+ <comment xml:space="preserve"></comment>
+ <block_quote classes="language-fr">
+ <paragraph>ReStructuredText est un langage de balisage léger utilisé
+ notamment dans la documentation du langage Python.</paragraph>
+ </block_quote>
+ </section>
+ <section ids="doctest-blocks" names="doctest\ blocks">
+ <title auto="1" refid="toc-entry-16"><generated classes="sectnum">2.10 </generated>Doctest Blocks</title>
+ <doctest_block xml:space="preserve">>>> print 'Python-specific usage examples; begun with ">>>"'
+Python-specific usage examples; begun with ">>>"
+>>> print '(cut and pasted from interactive Python sessions)'
+(cut and pasted from interactive Python sessions)</doctest_block>
+ </section>
+ <section ids="footnotes" names="footnotes">
+ <title auto="1" refid="toc-entry-17"><generated classes="sectnum">2.11 </generated>Footnotes</title>
+ <footnote backrefs="footnote-reference-1 footnote-reference-5 footnote-reference-9" ids="footnote-1" names="1">
+ <label>1</label>
+ <paragraph>A footnote contains body elements, consistently indented by at
+ least 3 spaces.</paragraph>
+ <paragraph>This is the footnote's second paragraph.</paragraph>
+ </footnote>
+ <footnote auto="1" backrefs="footnote-reference-3 footnote-reference-6" ids="label" names="label">
+ <label>2</label>
+ <paragraph>Footnotes may be numbered, either manually (as in <footnote_reference ids="footnote-reference-5" refid="footnote-1">1</footnote_reference>) or
+ automatically using a "#"-prefixed label. This footnote has a
+ label so it can be referred to from multiple places, both as a
+ footnote reference (<footnote_reference auto="1" ids="footnote-reference-6" refid="label">2</footnote_reference>) and as a <reference anonymous="1" name="hyperlink reference" refid="label">hyperlink reference</reference>.</paragraph>
+ <target anonymous="1" ids="target-3" refid="label"></target>
+ </footnote>
+ <footnote auto="1" backrefs="footnote-reference-2" ids="footnote-2" names="3">
+ <label>3</label>
+ <paragraph>This footnote is numbered automatically and anonymously using a
+ label of "#" only.</paragraph>
+ <paragraph>This is the second paragraph.</paragraph>
+ <paragraph>And this is the third paragraph.</paragraph>
+ </footnote>
+ <footnote auto="*" backrefs="footnote-reference-4" ids="footnote-3">
+ <label>*</label>
+ <paragraph>Footnotes may also use symbols, specified with a "*" label.
+ Here's a reference to the next footnote: <footnote_reference auto="*" ids="footnote-reference-7" refid="footnote-4">†</footnote_reference>.</paragraph>
+ </footnote>
+ <footnote auto="*" backrefs="footnote-reference-7" ids="footnote-4">
+ <label>†</label>
+ <paragraph>This footnote shows the next symbol in the sequence.</paragraph>
+ </footnote>
+ <footnote ids="footnote-5" names="4">
+ <label>4</label>
+ <paragraph>Here's an unreferenced footnote, with a reference to a
+ nonexistent footnote: <problematic ids="footnote-reference-8" refid="system-message-2">[5]_</problematic>.</paragraph>
+ </footnote>
+ </section>
+ <section ids="citations" names="citations">
+ <title auto="1" refid="toc-entry-18"><generated classes="sectnum">2.12 </generated>Citations</title>
+ <citation backrefs="citation-reference-1 citation-reference-2" ids="cit2002" names="cit2002">
+ <label>CIT2002</label>
+ <paragraph>Citations are text-labeled footnotes. They may be
+ rendered separately and differently from footnotes.</paragraph>
+ </citation>
+ <paragraph>Here's a reference to the above, <citation_reference ids="citation-reference-2" refid="cit2002">CIT2002</citation_reference>, and a <problematic ids="citation-reference-3" refid="system-message-3">[nonexistent]_</problematic>
+ citation.</paragraph>
+ <target refid="another-target"></target>
+ </section>
+ <section ids="targets another-target" names="targets another\ target">
+ <title auto="1" refid="toc-entry-19"><generated classes="sectnum">2.13 </generated>Targets</title>
+ <target refid="example"></target>
+ <paragraph ids="example" names="example">This paragraph is pointed to by the explicit "example" target. A
+ reference can be found under <reference name="Inline Markup" refid="inline-markup">Inline Markup</reference>, above. <reference name="Inline hyperlink targets" refid="inline-hyperlink-targets">Inline
+ hyperlink targets</reference> are also possible.</paragraph>
+ <paragraph>Section headers are implicit targets, referred to by name. See
+ <reference name="Targets" refid="targets">Targets</reference>, which is a subsection of <reference name="Body Elements" refid="body-elements">Body Elements</reference>.</paragraph>
+ <paragraph>Explicit external targets are interpolated into references such as
+ "<reference name="Python" refuri="http://www.python.org/">Python</reference> <footnote_reference auto="1" ids="footnote-reference-11" refid="footnote-6">5</footnote_reference>".</paragraph>
+ <target ids="python" names="python" refuri="http://www.python.org/"></target>
+ <paragraph>Targets may be indirect and anonymous. Thus <reference anonymous="1" name="this phrase" refid="targets">this phrase</reference> may also
+ refer to the <reference name="Targets" refid="targets">Targets</reference> section.</paragraph>
+ <target anonymous="1" ids="target-4" refid="targets"></target>
+ <paragraph>Here's a <problematic ids="problematic-2" refid="system-message-4">`hyperlink reference without a target`_</problematic>, which generates an
+ error.</paragraph>
+ <section dupnames="duplicate\ target\ names" ids="duplicate-target-names">
+ <title auto="1" refid="toc-entry-20"><generated classes="sectnum">2.13.1 </generated>Duplicate Target Names</title>
+ <paragraph>Duplicate names in section headers or other implicit targets will
+ generate "info" (level-1) system messages. Duplicate names in
+ explicit targets will generate "warning" (level-2) system messages.</paragraph>
+ </section>
+ <section dupnames="duplicate\ target\ names" ids="duplicate-target-names-1">
+ <title auto="1" refid="toc-entry-21"><generated classes="sectnum">2.13.2 </generated>Duplicate Target Names</title>
+ <system_message backrefs="duplicate-target-names-1" level="1" line="439" source="functional/input/data/standard.txt" type="INFO">
+ <paragraph>Duplicate implicit target name: "duplicate target names".</paragraph>
+ </system_message>
+ <paragraph>Since there are two "Duplicate Target Names" section headers, we
+ cannot uniquely refer to either of them by name. If we try to (like
+ this: <problematic ids="problematic-3" refid="system-message-5">`Duplicate Target Names`_</problematic>), an error is generated.</paragraph>
+ </section>
+ </section>
+ <section ids="directives" names="directives">
+ <title auto="1" refid="toc-entry-22"><generated classes="sectnum">2.14 </generated>Directives</title>
+ <topic classes="contents local" ids="contents" names="contents">
+ <bullet_list classes="auto-toc">
+ <list_item>
+ <paragraph><reference ids="toc-entry-41" refid="document-parts"><generated classes="sectnum">2.14.1 </generated>Document Parts</reference></paragraph>
+ </list_item>
+ <list_item>
+ <paragraph><reference ids="toc-entry-42" refid="images-and-figures"><generated classes="sectnum">2.14.2 </generated>Images and Figures</reference></paragraph>
+ </list_item>
+ <list_item>
+ <paragraph><reference ids="toc-entry-43" refid="admonitions"><generated classes="sectnum">2.14.3 </generated>Admonitions</reference></paragraph>
+ </list_item>
+ <list_item>
+ <paragraph><reference ids="toc-entry-44" refid="topics-sidebars-and-rubrics"><generated classes="sectnum">2.14.4 </generated>Topics, Sidebars, and Rubrics</reference></paragraph>
+ </list_item>
+ <list_item>
+ <paragraph><reference ids="toc-entry-45" refid="target-footnotes"><generated classes="sectnum">2.14.5 </generated>Target Footnotes</reference></paragraph>
+ </list_item>
+ <list_item>
+ <paragraph><reference ids="toc-entry-46" refid="replacement-text"><generated classes="sectnum">2.14.6 </generated>Replacement Text</reference></paragraph>
+ </list_item>
+ <list_item>
+ <paragraph><reference ids="toc-entry-47" refid="compound-paragraph"><generated classes="sectnum">2.14.7 </generated>Compound Paragraph</reference></paragraph>
+ </list_item>
+ <list_item>
+ <paragraph><reference ids="toc-entry-48" refid="parsed-literal-blocks"><generated classes="sectnum">2.14.8 </generated>Parsed Literal Blocks</reference></paragraph>
+ </list_item>
+ <list_item>
+ <paragraph><reference ids="toc-entry-49" refid="code"><generated classes="sectnum">2.14.9 </generated>Code</reference></paragraph>
+ </list_item>
+ </bullet_list>
+ </topic>
+ <paragraph>These are just a sample of the many reStructuredText Directives. For
+ others, please see
+ <reference refuri="http://docutils.sourceforge.net/docs/ref/rst/directives.html">http://docutils.sourceforge.net/docs/ref/rst/directives.html</reference>.</paragraph>
+ <section ids="document-parts" names="document\ parts">
+ <title auto="1" refid="toc-entry-41"><generated classes="sectnum">2.14.1 </generated>Document Parts</title>
+ <paragraph>An example of the "contents" directive can be seen above this section
+ (a local, untitled table of <reference name="contents" refid="contents">contents</reference>) and at the beginning of the
+ document (a document-wide <reference name="table of contents" refid="table-of-contents">table of contents</reference>).</paragraph>
+ </section>
+ <section ids="images-and-figures" names="images\ and\ figures">
+ <title auto="1" refid="toc-entry-42"><generated classes="sectnum">2.14.2 </generated>Images and Figures</title>
+ <paragraph>An image directive (also clickable -- a hyperlink reference):</paragraph>
+ <reference name="directives" refid="directives"><image classes="class1 class2" uri="../../../docs/user/rst/images/title.png"></image></reference>
+ <paragraph>Image with multiple IDs:</paragraph>
+ <target refid="image-target-1"></target>
+ <target refid="image-target-2"></target>
+ <target refid="image-target-3"></target>
+ <image ids="image-target-3 image-target-2 image-target-1" names="image\ target\ 3 image\ target\ 2 image\ target\ 1" uri="../../../docs/user/rst/images/title.png"></image>
+ <paragraph>A centered image:</paragraph>
+ <image align="center" uri="../../../docs/user/rst/images/biohazard.png"></image>
+ <paragraph>A left-aligned image:</paragraph>
+ <image align="left" uri="../../../docs/user/rst/images/biohazard.png"></image>
+ <paragraph>This paragraph might flow around the image.
+ The specific behavior depends upon the style sheet and
+ the browser or rendering software used.</paragraph>
+ <paragraph>A right-aligned image:</paragraph>
+ <image align="right" uri="../../../docs/user/rst/images/biohazard.png"></image>
+ <paragraph>This paragraph might flow around the image.
+ The specific behavior depends upon the style sheet and
+ the browser or rendering software used.</paragraph>
+ <paragraph>For inline images see <reference name="Substitution Definitions" refid="substitution-definitions">Substitution Definitions</reference>.</paragraph>
+ <paragraph>Image size:</paragraph>
+ <paragraph>An image 2 em wide:</paragraph>
+ <image uri="../../../docs/user/rst/images/biohazard.png" width="2em"></image>
+ <paragraph>An image 2 em wide and 15 pixel high:</paragraph>
+ <image height="15px" uri="../../../docs/user/rst/images/biohazard.png" width="2em"></image>
+ <paragraph>An image occupying 50% of the line width:</paragraph>
+ <image uri="../../../docs/user/rst/images/title.png" width="50%"></image>
+ <paragraph>An image 2 cm high:</paragraph>
+ <image height="2cm" uri="../../../docs/user/rst/images/biohazard.png"></image>
+ <paragraph>A <emphasis>figure</emphasis> is an image with a caption and/or a legend. With page-based output
+ media, figures might float to a different position if this helps the page
+ layout.</paragraph>
+ <figure classes="figclass1 figclass2">
+ <image alt="reStructuredText, the markup syntax" classes="class1 class2" uri="../../../docs/user/rst/images/title.png" width="258"></image>
+ <caption>Plaintext markup syntax and parser system.</caption>
+ <legend>
+ <table>
+ <tgroup cols="2">
+ <colspec colwidth="12"></colspec>
+ <colspec colwidth="47"></colspec>
+ <tbody>
+ <row>
+ <entry>
+ <paragraph>re</paragraph>
+ </entry>
+ <entry>
+ <paragraph>Revised, revisited, based on 're' module.</paragraph>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <paragraph>Structured</paragraph>
+ </entry>
+ <entry>
+ <paragraph>Structure-enhanced text, structuredtext.</paragraph>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <paragraph>Text</paragraph>
+ </entry>
+ <entry>
+ <paragraph>Well it is, isn't it?</paragraph>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ <paragraph>This paragraph is also part of the legend.</paragraph>
+ </legend>
+ </figure>
+ <paragraph>A left-aligned figure:</paragraph>
+ <figure align="left" classes="figclass1 figclass2" width="70%">
+ <image alt="reStructuredText, the markup syntax" classes="class1 class2" uri="../../../docs/user/rst/images/biohazard.png" width="40px"></image>
+ <caption>This is the caption.</caption>
+ <legend>
+ <paragraph>This is the legend.</paragraph>
+ <paragraph>The legend may consist of several paragraphs.</paragraph>
+ </legend>
+ </figure>
+ <paragraph>This paragraph might flow around the figure.</paragraph>
+ <paragraph>The specific behavior depends upon the style sheet and the browser or
+ rendering software used.</paragraph>
+ <paragraph>A centered figure:</paragraph>
+ <figure align="center">
+ <image uri="../../../docs/user/rst/images/biohazard.png" width="40px"></image>
+ <caption>This is the caption.</caption>
+ <legend>
+ <paragraph>This is the legend.</paragraph>
+ <paragraph>The legend may consist of several paragraphs.</paragraph>
+ </legend>
+ </figure>
+ <paragraph>This paragraph might flow around the figure.</paragraph>
+ <paragraph>The specific behavior depends upon the style sheet and the browser or
+ rendering software used.</paragraph>
+ <paragraph>A right-aligned figure:</paragraph>
+ <figure align="right">
+ <image uri="../../../docs/user/rst/images/biohazard.png" width="40px"></image>
+ <caption>This is the caption.</caption>
+ <legend>
+ <paragraph>This is the legend.</paragraph>
+ <paragraph>The legend may consist of several paragraphs.</paragraph>
+ </legend>
+ </figure>
+ <paragraph>This paragraph might flow around the figure. The specific behavior depends
+ upon the style sheet and the browser or rendering software used.</paragraph>
+ <paragraph>Tables may be given titles and additional arguments with the <emphasis>table</emphasis>
+ directive:</paragraph>
+ <table align="left">
+ <title>left-aligned table</title>
+ <tgroup cols="2">
+ <colspec colwidth="5"></colspec>
+ <colspec colwidth="5"></colspec>
+ <thead>
+ <row>
+ <entry>
+ <paragraph>A</paragraph>
+ </entry>
+ <entry>
+ <paragraph>not A</paragraph>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <paragraph>False</paragraph>
+ </entry>
+ <entry>
+ <paragraph>True</paragraph>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <paragraph>True</paragraph>
+ </entry>
+ <entry>
+ <paragraph>False</paragraph>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ <table align="center">
+ <title>center-aligned table</title>
+ <tgroup cols="2">
+ <colspec colwidth="5"></colspec>
+ <colspec colwidth="5"></colspec>
+ <thead>
+ <row>
+ <entry>
+ <paragraph>A</paragraph>
+ </entry>
+ <entry>
+ <paragraph>not A</paragraph>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <paragraph>False</paragraph>
+ </entry>
+ <entry>
+ <paragraph>True</paragraph>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <paragraph>True</paragraph>
+ </entry>
+ <entry>
+ <paragraph>False</paragraph>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ <table align="right">
+ <title>right-aligned table</title>
+ <tgroup cols="2">
+ <colspec colwidth="5"></colspec>
+ <colspec colwidth="5"></colspec>
+ <thead>
+ <row>
+ <entry>
+ <paragraph>A</paragraph>
+ </entry>
+ <entry>
+ <paragraph>not A</paragraph>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <paragraph>False</paragraph>
+ </entry>
+ <entry>
+ <paragraph>True</paragraph>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <paragraph>True</paragraph>
+ </entry>
+ <entry>
+ <paragraph>False</paragraph>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ <paragraph>With the "widths" argument "auto" (or "class" value "colwidths-auto"),
+ column widths are determined by the backend (if supported by the
+ writer/backend).</paragraph>
+ <target refid="target1"></target>
+ <target refid="target2"></target>
+ <table classes="colwidths-auto" ids="target2 target1" names="target2 target1">
+ <tgroup cols="3">
+ <colspec colwidth="7"></colspec>
+ <colspec colwidth="7"></colspec>
+ <colspec colwidth="10"></colspec>
+ <thead>
+ <row>
+ <entry>
+ <paragraph>A</paragraph>
+ </entry>
+ <entry>
+ <paragraph>B</paragraph>
+ </entry>
+ <entry>
+ <paragraph>A or B</paragraph>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <paragraph>False</paragraph>
+ </entry>
+ <entry>
+ <paragraph>False</paragraph>
+ </entry>
+ <entry>
+ <paragraph>False</paragraph>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <paragraph>True</paragraph>
+ </entry>
+ <entry>
+ <paragraph>False</paragraph>
+ </entry>
+ <entry>
+ <paragraph>True</paragraph>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <paragraph>False</paragraph>
+ </entry>
+ <entry>
+ <paragraph>True</paragraph>
+ </entry>
+ <entry>
+ <paragraph>True</paragraph>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <paragraph>True</paragraph>
+ </entry>
+ <entry>
+ <paragraph>True</paragraph>
+ </entry>
+ <entry>
+ <paragraph>True</paragraph>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ </section>
+ <section ids="admonitions" names="admonitions">
+ <title auto="1" refid="toc-entry-43"><generated classes="sectnum">2.14.3 </generated>Admonitions</title>
+ <attention>
+ <paragraph>Directives at large.</paragraph>
+ </attention>
+ <caution>
+ <paragraph>Don't take any wooden nickels.</paragraph>
+ </caution>
+ <danger>
+ <paragraph>Mad scientist at work!</paragraph>
+ </danger>
+ <error>
+ <paragraph>Does not compute.</paragraph>
+ </error>
+ <hint>
+ <paragraph>It's bigger than a bread box.</paragraph>
+ </hint>
+ <important>
+ <bullet_list bullet="-">
+ <list_item>
+ <paragraph>Wash behind your ears.</paragraph>
+ </list_item>
+ <list_item>
+ <paragraph>Clean up your room.</paragraph>
+ </list_item>
+ <list_item>
+ <paragraph>Call your mother.</paragraph>
+ </list_item>
+ <list_item>
+ <paragraph>Back up your data.</paragraph>
+ </list_item>
+ </bullet_list>
+ </important>
+ <note>
+ <paragraph>This is a note.</paragraph>
+ </note>
+ <tip>
+ <paragraph>15% if the service is good.</paragraph>
+ </tip>
+ <warning>
+ <paragraph>Strong prose may provoke extreme mental exertion.
+ Reader discretion is strongly advised.</paragraph>
+ </warning>
+ <admonition classes="admonition-and-by-the-way">
+ <title>And, by the way...</title>
+ <paragraph>You can make up your own admonition too.</paragraph>
+ <target ids="docutils" names="docutils" refuri="http://docutils.sourceforge.net/"></target>
+ </admonition>
+ </section>
+ <section ids="topics-sidebars-and-rubrics" names="topics,\ sidebars,\ and\ rubrics">
+ <title auto="1" refid="toc-entry-44"><generated classes="sectnum">2.14.4 </generated>Topics, Sidebars, and Rubrics</title>
+ <paragraph><emphasis>Sidebars</emphasis> are like miniature, parallel documents.</paragraph>
+ <sidebar>
+ <title>Sidebar Title</title>
+ <subtitle>Optional Subtitle</subtitle>
+ <paragraph>This is a sidebar. It is for text outside the flow of the main
+ text.</paragraph>
+ <rubric>This is a rubric inside a sidebar</rubric>
+ <paragraph>Sidebars often appear beside the main text with a border and a different
+ background or font color.</paragraph>
+ </sidebar>
+ <paragraph>A <emphasis>topic</emphasis> is like a block quote with a title, or a self-contained section
+ with no subsections.</paragraph>
+ <topic>
+ <title>Topic Title</title>
+ <paragraph>This is a topic.</paragraph>
+ </topic>
+ <paragraph>A <emphasis>rubric</emphasis> is like an informal heading that doesn't correspond to the
+ document's structure. It is typically highlighted in red (hence the name).</paragraph>
+ <rubric>This is a rubric</rubric>
+ <paragraph>Topics and rubrics can be used at places where a <reference name="section title" refid="section-title">section title</reference> is not
+ allowed (e.g. inside a directive).</paragraph>
+ </section>
+ <section ids="target-footnotes" names="target\ footnotes">
+ <title auto="1" refid="toc-entry-45"><generated classes="sectnum">2.14.5 </generated>Target Footnotes</title>
+ <footnote auto="1" backrefs="footnote-reference-10 footnote-reference-11 footnote-reference-12 footnote-reference-14" ids="footnote-6" names="TARGET_NOTE:\ footnote-6">
+ <label>5</label>
+ <paragraph><reference refuri="http://www.python.org/">http://www.python.org/</reference></paragraph>
+ </footnote>
+ <footnote auto="1" backrefs="footnote-reference-13" ids="footnote-7" names="TARGET_NOTE:\ footnote-7">
+ <label>6</label>
+ <paragraph><reference refuri="http://pygments.org/">http://pygments.org/</reference></paragraph>
+ </footnote>
+ <footnote auto="1" backrefs="footnote-reference-15" ids="footnote-8" names="TARGET_NOTE:\ footnote-8">
+ <label>7</label>
+ <paragraph><reference refuri="http://docutils.sourceforge.net/">http://docutils.sourceforge.net/</reference></paragraph>
+ </footnote>
+ </section>
+ <section ids="replacement-text" names="replacement\ text">
+ <title auto="1" refid="toc-entry-46"><generated classes="sectnum">2.14.6 </generated>Replacement Text</title>
+ <paragraph>I recommend you try <reference refuri="http://www.python.org/">Python, <emphasis>the</emphasis> best language around</reference> <footnote_reference auto="1" ids="footnote-reference-12" refid="footnote-6">5</footnote_reference>.</paragraph>
+ <substitution_definition names="Python">Python, <emphasis>the</emphasis> best language around</substitution_definition>
+ </section>
+ <section ids="compound-paragraph" names="compound\ paragraph">
+ <title auto="1" refid="toc-entry-47"><generated classes="sectnum">2.14.7 </generated>Compound Paragraph</title>
+ <paragraph>The <emphasis>compound</emphasis> directive is used to create a "compound paragraph", which
+ is a single logical paragraph containing multiple physical body
+ elements. For example:</paragraph>
+ <compound>
+ <paragraph>The 'rm' command is very dangerous. If you are logged
+ in as root and enter</paragraph>
+ <literal_block xml:space="preserve">cd /
+rm -rf *</literal_block>
+ <paragraph>you will erase the entire contents of your file system.</paragraph>
+ </compound>
+ <paragraph>Test the handling and display of compound paragraphs:</paragraph>
+ <compound classes="some-class">
+ <paragraph>Compound 2, paragraph 1,</paragraph>
+ <paragraph>compound 2, paragraph 2,</paragraph>
+ <bullet_list bullet="*">
+ <list_item>
+ <paragraph>list item 1,</paragraph>
+ </list_item>
+ <list_item>
+ <paragraph>list item 2,</paragraph>
+ </list_item>
+ </bullet_list>
+ <paragraph>compound 2, paragraph 3.</paragraph>
+ </compound>
+ <compound>
+ <paragraph>Compound 3, only consisting of one paragraph.</paragraph>
+ </compound>
+ <compound>
+ <literal_block xml:space="preserve">Compound 4.
+This one starts with a literal block.</literal_block>
+ <paragraph>Compound 4, paragraph following the literal block.</paragraph>
+ </compound>
+ <paragraph>Now something <emphasis>really</emphasis> perverted -- a nested compound block. This is
+ just to test that it works at all; the results don't have to be
+ meaningful.</paragraph>
+ <compound>
+ <paragraph>Compound 5, block 1 (a paragraph).</paragraph>
+ <compound>
+ <paragraph>Compound 6 is block 2 in compound 5.</paragraph>
+ <paragraph>Compound 6, another paragraph.</paragraph>
+ </compound>
+ <paragraph>Compound 5, block 3 (a paragraph).</paragraph>
+ </compound>
+ <compound>
+ <paragraph>Compound 7, tests the inclusion of various block-level
+ elements in one logical paragraph. First a table,</paragraph>
+ <table>
+ <tgroup cols="3">
+ <colspec colwidth="20"></colspec>
+ <colspec colwidth="20"></colspec>
+ <colspec colwidth="20"></colspec>
+ <tbody>
+ <row>
+ <entry>
+ <paragraph>Left cell, first
+ paragraph.</paragraph>
+ <paragraph>Left cell, second
+ paragraph.</paragraph>
+ </entry>
+ <entry>
+ <paragraph>Middle cell,
+ consisting of
+ exactly one
+ paragraph.</paragraph>
+ </entry>
+ <entry>
+ <paragraph>Right cell.</paragraph>
+ <paragraph>Paragraph 2.</paragraph>
+ <paragraph>Paragraph 3.</paragraph>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ <paragraph>followed by a paragraph. This physical paragraph is
+ actually a continuation of the paragraph before the table. It is followed
+ by</paragraph>
+ <block_quote>
+ <paragraph>a quote and</paragraph>
+ </block_quote>
+ <enumerated_list enumtype="arabic" prefix="" suffix=".">
+ <list_item>
+ <paragraph>an enumerated list,</paragraph>
+ </list_item>
+ </enumerated_list>
+ <paragraph>a paragraph,</paragraph>
+ <option_list>
+ <option_list_item>
+ <option_group>
+ <option>
+ <option_string>--an</option_string>
+ </option>
+ </option_group>
+ <description>
+ <paragraph>option list,</paragraph>
+ </description>
+ </option_list_item>
+ </option_list>
+ <paragraph>a paragraph,</paragraph>
+ <field_list>
+ <field>
+ <field_name>a field</field_name>
+ <field_body>
+ <paragraph>list,</paragraph>
+ </field_body>
+ </field>
+ </field_list>
+ <paragraph>a paragraph,</paragraph>
+ <definition_list>
+ <definition_list_item>
+ <term>a definition</term>
+ <definition>
+ <paragraph>list,</paragraph>
+ </definition>
+ </definition_list_item>
+ </definition_list>
+ <paragraph>a paragraph, an image:</paragraph>
+ <image uri="../../../docs/user/rst/images/biohazard.png"></image>
+ <paragraph>a paragraph,</paragraph>
+ <line_block>
+ <line>a line</line>
+ <line>block,</line>
+ </line_block>
+ <paragraph>a paragraph followed by a comment,</paragraph>
+ <comment xml:space="preserve">this is a comment</comment>
+ <paragraph>a paragraph, a</paragraph>
+ <note>
+ <paragraph>with content</paragraph>
+ </note>
+ <paragraph>and the final paragraph of the compound 7.</paragraph>
+ </compound>
+ </section>
+ <section ids="parsed-literal-blocks" names="parsed\ literal\ blocks">
+ <title auto="1" refid="toc-entry-48"><generated classes="sectnum">2.14.8 </generated>Parsed Literal Blocks</title>
+ <literal_block xml:space="preserve">This is a parsed literal block.
+ This line is indented. The next line is blank.
+
+Inline markup is supported, e.g. <emphasis>emphasis</emphasis>, <strong>strong</strong>, <literal>literal
+text</literal>, <subscript>sub-</subscript> and <superscript>super</superscript>scripts,
+inline formulas: <math>A = 2 \pi r^2</math>,
+footnotes <footnote_reference ids="footnote-reference-9" refid="footnote-1">1</footnote_reference>, <target ids="hyperlink-targets" names="hyperlink\ targets">hyperlink targets</target>, and <reference name="references" refuri="http://www.python.org/">references</reference><target ids="references" names="references" refuri="http://www.python.org/"></target>.</literal_block>
+ </section>
+ <section ids="code" names="code">
+ <title auto="1" refid="toc-entry-49"><generated classes="sectnum">2.14.9 </generated>Code</title>
+ <paragraph>Blocks of source code can be set with the <title_reference>code</title_reference> directive. If the code
+ language is specified, the content is parsed and tagged by the <reference name="Pygments" refuri="http://pygments.org/">Pygments</reference> <footnote_reference auto="1" ids="footnote-reference-13" refid="footnote-7">6</footnote_reference>
+ syntax highlighter and can be formatted with a style sheet. (Code parsing
+ is turned off using the <literal>syntax-highlight</literal> config setting in the test
+ conversions in order to get identical results with/without installed
+ Pygments highlighter.)</paragraph>
+ <literal_block classes="code python" xml:space="preserve">print 'This is Python code.'</literal_block>
+ <paragraph>The <literal>:number-lines:</literal> option (with optional start value) generates line
+ numbers:</paragraph>
+ <literal_block classes="code python" xml:space="preserve"><inline classes="ln"> 8 </inline># print integers from 0 to 9:
+<inline classes="ln"> 9 </inline>for i in range(10):
+<inline classes="ln">10 </inline> print i</literal_block>
+ <paragraph>For inline code snippets, there is the <title_reference>code</title_reference> role, which can be used
+ directly (the code will not be parsed/tagged, as the language is not known)
+ or as base for special code roles, e.g. the LaTeX code in the next
+ paragraph.</paragraph>
+ <paragraph>Docutils uses LaTeX syntax for math directives and roles:
+ <literal classes="code tex">\alpha = f(x)</literal> prints <math>\alpha = f(x)</math>.</paragraph>
+ <paragraph>The <literal>:code:</literal> option of the <title_reference>include</title_reference> directive sets the included content
+ as a code block, here the rst file <literal>header_footer.txt</literal> with line numbers:</paragraph>
+ <literal_block classes="code rst" source="functional/input/data/header_footer.txt" xml:space="preserve"><inline classes="ln">1 </inline>.. header:: Document header
+<inline classes="ln">2 </inline>.. footer:: Document footer</literal_block>
+ <target ids="pygments" names="pygments" refuri="http://pygments.org/"></target>
+ </section>
+ </section>
+ <section ids="substitution-definitions" names="substitution\ definitions">
+ <title auto="1" refid="toc-entry-32"><generated classes="sectnum">2.15 </generated>Substitution Definitions</title>
+ <paragraph>An inline image (<image alt="EXAMPLE" uri="../../../docs/user/rst/images/biohazard.png"></image>) example:</paragraph>
+ <substitution_definition names="EXAMPLE"><image alt="EXAMPLE" uri="../../../docs/user/rst/images/biohazard.png"></image></substitution_definition>
+ <paragraph>A Unicode example:</paragraph>
+ <substitution_definition ltrim="1" names="heart" rtrim="1">♥</substitution_definition>
+ <paragraph>(Substitution definitions are not visible in the HTML source.)</paragraph>
+ </section>
+ <section ids="comments" names="comments">
+ <title auto="1" refid="toc-entry-33"><generated classes="sectnum">2.16 </generated>Comments</title>
+ <paragraph>Here's one:</paragraph>
+ <comment xml:space="preserve">Comments begin with two dots and a space. Anything may
+follow, except for the syntax of footnotes, hyperlink
+targets, directives, or substitution definitions.
+
+Double-dashes -- "--" -- must be escaped somehow in HTML output.
+
+Comments may contain non-ASCII characters: ä ö ü æ ø å</comment>
+ <paragraph>(View the HTML source to see the comment.)</paragraph>
+ </section>
+ <section ids="raw-text" names="raw\ text">
+ <title auto="1" refid="toc-entry-34"><generated classes="sectnum">2.17 </generated>Raw text</title>
+ <paragraph>This does not necessarily look nice, because there may be missing white space.</paragraph>
+ <paragraph>It's just there to freeze the behavior.</paragraph>
+ <raw format="html latex" xml:space="preserve">A test.</raw>
+ <raw format="html latex" xml:space="preserve">Second test.</raw>
+ <raw classes="myclass" format="html latex" xml:space="preserve">Another test with myclass set.</raw>
+ <paragraph>This is the <raw classes="myrawroleclass" format="html latex" xml:space="preserve">fourth test</raw> with myrawroleclass set.</paragraph>
+ <raw format="html" xml:space="preserve">Fifth test in HTML.<br />Line two.</raw>
+ <raw format="latex" xml:space="preserve">Fifth test in LaTeX.\\Line two.</raw>
+ </section>
+ <section ids="container" names="container">
+ <title auto="1" refid="toc-entry-35"><generated classes="sectnum">2.18 </generated>Container</title>
+ <container classes="custom">
+ <paragraph>paragraph 1</paragraph>
+ <paragraph>paragraph 2</paragraph>
+ </container>
+ </section>
+ <section ids="colspanning-tables" names="colspanning\ tables">
+ <title auto="1" refid="toc-entry-36"><generated classes="sectnum">2.19 </generated>Colspanning tables</title>
+ <paragraph>This table has a cell spanning two columns:</paragraph>
+ <table>
+ <tgroup cols="3">
+ <colspec colwidth="5"></colspec>
+ <colspec colwidth="5"></colspec>
+ <colspec colwidth="6"></colspec>
+ <thead>
+ <row>
+ <entry morecols="1">
+ <paragraph>Inputs</paragraph>
+ </entry>
+ <entry>
+ <paragraph>Output</paragraph>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <paragraph>A</paragraph>
+ </entry>
+ <entry>
+ <paragraph>B</paragraph>
+ </entry>
+ <entry>
+ <paragraph>A or B</paragraph>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <paragraph>False</paragraph>
+ </entry>
+ <entry>
+ <paragraph>False</paragraph>
+ </entry>
+ <entry>
+ <paragraph>False</paragraph>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <paragraph>True</paragraph>
+ </entry>
+ <entry>
+ <paragraph>False</paragraph>
+ </entry>
+ <entry>
+ <paragraph>True</paragraph>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <paragraph>False</paragraph>
+ </entry>
+ <entry>
+ <paragraph>True</paragraph>
+ </entry>
+ <entry>
+ <paragraph>True</paragraph>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <paragraph>True</paragraph>
+ </entry>
+ <entry>
+ <paragraph>True</paragraph>
+ </entry>
+ <entry>
+ <paragraph>True</paragraph>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ </section>
+ <section ids="rowspanning-tables" names="rowspanning\ tables">
+ <title auto="1" refid="toc-entry-37"><generated classes="sectnum">2.20 </generated>Rowspanning tables</title>
+ <paragraph>Here's a table with cells spanning several rows:</paragraph>
+ <table>
+ <tgroup cols="3">
+ <colspec colwidth="24"></colspec>
+ <colspec colwidth="12"></colspec>
+ <colspec colwidth="18"></colspec>
+ <thead>
+ <row>
+ <entry>
+ <paragraph>Header row, column 1
+ (header rows optional)</paragraph>
+ </entry>
+ <entry>
+ <paragraph>Header 2</paragraph>
+ </entry>
+ <entry>
+ <paragraph>Header 3</paragraph>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <paragraph>body row 1, column 1</paragraph>
+ </entry>
+ <entry>
+ <paragraph>column 2</paragraph>
+ </entry>
+ <entry>
+ <paragraph>column 3</paragraph>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <paragraph>body row 2</paragraph>
+ </entry>
+ <entry morerows="1">
+ <paragraph>Cells may
+ span rows.</paragraph>
+ </entry>
+ <entry morerows="1">
+ <paragraph>Another
+ rowspanning
+ cell.</paragraph>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <paragraph>body row 3</paragraph>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ </section>
+ <section ids="complex-tables" names="complex\ tables">
+ <title auto="1" refid="toc-entry-38"><generated classes="sectnum">2.21 </generated>Complex tables</title>
+ <paragraph>Here's a complex table, which should test all features.</paragraph>
+ <table>
+ <tgroup cols="4">
+ <colspec colwidth="24"></colspec>
+ <colspec colwidth="12"></colspec>
+ <colspec colwidth="10"></colspec>
+ <colspec colwidth="10"></colspec>
+ <thead>
+ <row>
+ <entry>
+ <paragraph>Header row, column 1
+ (header rows optional)</paragraph>
+ </entry>
+ <entry>
+ <paragraph>Header 2</paragraph>
+ </entry>
+ <entry>
+ <paragraph>Header 3</paragraph>
+ </entry>
+ <entry>
+ <paragraph>Header 4</paragraph>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <paragraph>body row 1, column 1</paragraph>
+ </entry>
+ <entry>
+ <paragraph>column 2</paragraph>
+ </entry>
+ <entry>
+ <paragraph>column 3</paragraph>
+ </entry>
+ <entry>
+ <paragraph>column 4</paragraph>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <paragraph>body row 2</paragraph>
+ </entry>
+ <entry morecols="2">
+ <paragraph>Cells may span columns.</paragraph>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <paragraph>body row 3</paragraph>
+ </entry>
+ <entry morerows="1">
+ <paragraph>Cells may
+ span rows.</paragraph>
+ <paragraph>Paragraph.</paragraph>
+ </entry>
+ <entry morecols="1" morerows="1">
+ <bullet_list bullet="-">
+ <list_item>
+ <paragraph>Table cells</paragraph>
+ </list_item>
+ <list_item>
+ <paragraph>contain</paragraph>
+ </list_item>
+ <list_item>
+ <paragraph>body elements.</paragraph>
+ </list_item>
+ </bullet_list>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <paragraph>body row 4</paragraph>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <paragraph>body row 5</paragraph>
+ </entry>
+ <entry morecols="1">
+ <paragraph>Cells may also be
+ empty: <literal>--></literal></paragraph>
+ </entry>
+ <entry>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ </section>
+ <section ids="list-tables" names="list\ tables">
+ <title auto="1" refid="toc-entry-39"><generated classes="sectnum">2.22 </generated>List Tables</title>
+ <paragraph>Here's a list table exercising all features:</paragraph>
+ <table classes="colwidths-given test" width="40em">
+ <title>list table with integral header</title>
+ <tgroup cols="3">
+ <colspec colwidth="10" stub="1"></colspec>
+ <colspec colwidth="20"></colspec>
+ <colspec colwidth="30"></colspec>
+ <thead>
+ <row>
+ <entry>
+ <paragraph>Treat</paragraph>
+ </entry>
+ <entry>
+ <paragraph>Quantity</paragraph>
+ </entry>
+ <entry>
+ <paragraph>Description</paragraph>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <paragraph>Albatross</paragraph>
+ </entry>
+ <entry>
+ <paragraph>2.99</paragraph>
+ </entry>
+ <entry>
+ <paragraph>On a stick!</paragraph>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <paragraph>Crunchy Frog</paragraph>
+ </entry>
+ <entry>
+ <paragraph>1.49</paragraph>
+ </entry>
+ <entry>
+ <paragraph>If we took the bones out, it wouldn't be
+ crunchy, now would it?</paragraph>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <paragraph>Gannet Ripple</paragraph>
+ </entry>
+ <entry>
+ <paragraph>1.99</paragraph>
+ </entry>
+ <entry>
+ <paragraph>On a stick!</paragraph>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ <table align="center" classes="colwidths-auto">
+ <title>center aligned list table</title>
+ <tgroup cols="2">
+ <colspec colwidth="50"></colspec>
+ <colspec colwidth="50"></colspec>
+ <tbody>
+ <row>
+ <entry>
+ <paragraph>Albatross</paragraph>
+ </entry>
+ <entry>
+ <paragraph>2.99</paragraph>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <paragraph>Crunchy Frog</paragraph>
+ </entry>
+ <entry>
+ <paragraph>1.49</paragraph>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <paragraph>Gannet Ripple</paragraph>
+ </entry>
+ <entry>
+ <paragraph>1.99</paragraph>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ </section>
+ </section>
+ <section ids="error-handling" names="error\ handling">
+ <title auto="1" refid="toc-entry-40"><generated classes="sectnum">3 </generated>Error Handling</title>
+ <paragraph>Any errors caught during processing will generate system messages.</paragraph>
+ <paragraph>There should be five messages in the following, auto-generated
+ section, "Docutils System Messages":</paragraph>
+ <comment xml:space="preserve">section should be added by Docutils automatically</comment>
+ </section>
+ <section classes="system-messages">
+ <title>Docutils System Messages</title>
+ <system_message backrefs="problematic-1" ids="system-message-1" level="3" line="104" source="functional/input/data/standard.txt" type="ERROR">
+ <paragraph>Undefined substitution referenced: "problematic".</paragraph>
+ </system_message>
+ <system_message backrefs="footnote-reference-8" ids="system-message-2" level="3" line="392" source="functional/input/data/standard.txt" type="ERROR">
+ <paragraph>Unknown target name: "5".</paragraph>
+ </system_message>
+ <system_message backrefs="citation-reference-3" ids="system-message-3" level="3" line="401" source="functional/input/data/standard.txt" type="ERROR">
+ <paragraph>Unknown target name: "nonexistent".</paragraph>
+ </system_message>
+ <system_message backrefs="problematic-2" ids="system-message-4" level="3" line="428" source="functional/input/data/standard.txt" type="ERROR">
+ <paragraph>Unknown target name: "hyperlink reference without a target".</paragraph>
+ </system_message>
+ <system_message backrefs="problematic-3" ids="system-message-5" level="3" line="441" source="functional/input/data/standard.txt" type="ERROR">
+ <paragraph>Duplicate target name, cannot be used as a unique reference: "duplicate target names".</paragraph>
+ </system_message>
+ <system_message level="1" line="164" source="functional/input/data/standard.txt" type="INFO">
+ <paragraph>Hyperlink target "target" is not referenced.</paragraph>
+ </system_message>
+ <system_message level="1" line="406" source="functional/input/data/standard.txt" type="INFO">
+ <paragraph>Hyperlink target "another-target" is not referenced.</paragraph>
+ </system_message>
+ <system_message level="1" line="474" source="functional/input/data/standard.txt" type="INFO">
+ <paragraph>Hyperlink target "image-target-1" is not referenced.</paragraph>
+ </system_message>
+ <system_message level="1" line="475" source="functional/input/data/standard.txt" type="INFO">
+ <paragraph>Hyperlink target "image-target-2" is not referenced.</paragraph>
+ </system_message>
+ <system_message level="1" line="476" source="functional/input/data/standard.txt" type="INFO">
+ <paragraph>Hyperlink target "image-target-3" is not referenced.</paragraph>
+ </system_message>
+ <system_message level="1" line="640" source="functional/input/data/standard.txt" type="INFO">
+ <paragraph>Hyperlink target "target1" is not referenced.</paragraph>
+ </system_message>
+ <system_message level="1" line="641" source="functional/input/data/standard.txt" type="INFO">
+ <paragraph>Hyperlink target "target2" is not referenced.</paragraph>
+ </system_message>
+ <system_message level="1" line="686" source="functional/input/data/standard.txt" type="INFO">
+ <paragraph>Hyperlink target "docutils" is not referenced.</paragraph>
+ </system_message>
+ <system_message level="1" line="852" source="functional/input/data/standard.txt" type="INFO">
+ <paragraph>Hyperlink target "hyperlink targets" is not referenced.</paragraph>
+ </system_message>
+ </section>
+</document>
--- /dev/null
+<?xml version="1.0" encoding="utf-8" ?>
+<!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">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<meta name="generator" content="Docutils 0.16: http://docutils.sourceforge.net/" />
+<title>reStructuredText Test Document</title>
+<meta name="author" content="David Goodger" />
+<meta name="authors" content="Me Myself I" />
+<meta name="organization" content="humankind" />
+<meta name="date" content="Now, or yesterday. Or maybe even before yesterday." />
+<meta name="copyright" content="This document has been placed in the public domain. You may do with it as you wish. You may copy, modify, redistribute, reattribute, sell, buy, rent, lease, destroy, or improve it, quote it at length, excerpt, incorporate, collate, fold, staple, or mutilate it, or do anything else to it that your or anyone else's heart desires." />
+<meta content="reStructuredText, test, parser" name="keywords" />
+<meta content="A test document, containing at least one example of each reStructuredText construct." lang="en" name="description" />
+<link rel="stylesheet" href="../input/data/html4css1.css" type="text/css" />
+<link rel="stylesheet" href="../input/data/math.css" type="text/css" />
+</head>
+<body>
+<div class="header">
+Document header
+<hr class="header"/>
+</div>
+<div class="document" id="restructuredtext-test-document">
+<span id="doctitle"></span>
+<h1 class="title">reStructuredText Test Document</h1>
+<h2 class="subtitle" id="examples-of-syntax-constructs"><span id="subtitle"></span>Examples of Syntax Constructs</h2>
+<table class="docinfo" frame="void" rules="none">
+<col class="docinfo-name" />
+<col class="docinfo-content" />
+<tbody valign="top">
+<tr><th class="docinfo-name">Author:</th>
+<td>David Goodger</td></tr>
+<tr><th class="docinfo-name">Address:</th>
+<td><pre class="address">
+123 Example Street
+Example, EX Canada
+A1B 2C3
+</pre>
+</td></tr>
+<tr><th class="docinfo-name">Contact:</th>
+<td><a class="first last reference external" href="mailto:goodger@python.org">goodger@python.org</a></td></tr>
+<tr><th class="docinfo-name">Authors:</th>
+<td>Me
+<br />Myself
+<br />I</td></tr>
+<tr><th class="docinfo-name">Organization:</th>
+<td>humankind</td></tr>
+<tr><th class="docinfo-name">Date:</th>
+<td>Now, or yesterday. Or maybe even <em>before</em> yesterday.</td></tr>
+<tr><th class="docinfo-name">Status:</th>
+<td>This is a "work in progress"</td></tr>
+<tr><th class="docinfo-name">Revision:</th>
+<td>is managed by a version control system.</td></tr>
+<tr><th class="docinfo-name">Version:</th>
+<td>1</td></tr>
+<tr><th class="docinfo-name">Copyright:</th>
+<td>This document has been placed in the public domain. You
+may do with it as you wish. You may copy, modify,
+redistribute, reattribute, sell, buy, rent, lease,
+destroy, or improve it, quote it at length, excerpt,
+incorporate, collate, fold, staple, or mutilate it, or do
+anything else to it that your or anyone else's heart
+desires.</td></tr>
+<tr class="field-name field"><th class="docinfo-name">field name:</th><td class="field-body">This is a "generic bibliographic field".</td>
+</tr>
+<tr class="field-name-2 field"><th class="docinfo-name">field name "2":</th><td class="field-body"><p class="first">Generic bibliographic fields may contain multiple body elements.</p>
+<p class="last">Like this.</p>
+</td>
+</tr>
+</tbody>
+</table>
+<div class="dedication topic">
+<p class="topic-title">Dedication</p>
+<p>For Docutils users & co-developers.</p>
+</div>
+<div class="abstract topic">
+<p class="topic-title">Abstract</p>
+<p>This is a test document, containing at least one example of each
+reStructuredText construct.</p>
+</div>
+<!-- This is a comment. Note how any initial comments are moved by
+transforms to after the document title, subtitle, and docinfo. -->
+<!-- Above is the document title, and below is the subtitle.
+They are transformed from section titles after parsing. -->
+<!-- bibliographic fields (which also require a transform): -->
+<div class="contents topic" id="table-of-contents">
+<p class="topic-title">Table of Contents</p>
+<ul class="auto-toc simple">
+<li><a class="reference internal" href="#structural-elements" id="toc-entry-1">1 Structural Elements</a><ul class="auto-toc">
+<li><a class="reference internal" href="#section-title" id="toc-entry-2">1.1 Section Title</a></li>
+<li><a class="reference internal" href="#empty-section" id="toc-entry-3">1.2 Empty Section</a></li>
+<li><a class="reference internal" href="#transitions" id="toc-entry-4">1.3 Transitions</a></li>
+</ul>
+</li>
+<li><a class="reference internal" href="#body-elements" id="toc-entry-5">2 Body Elements</a><ul class="auto-toc">
+<li><a class="reference internal" href="#paragraphs" id="toc-entry-6">2.1 Paragraphs</a><ul class="auto-toc">
+<li><a class="reference internal" href="#inline-markup" id="toc-entry-7">2.1.1 Inline Markup</a></li>
+</ul>
+</li>
+<li><a class="reference internal" href="#bullet-lists" id="toc-entry-8">2.2 Bullet Lists</a></li>
+<li><a class="reference internal" href="#enumerated-lists" id="toc-entry-9">2.3 Enumerated Lists</a></li>
+<li><a class="reference internal" href="#definition-lists" id="toc-entry-10">2.4 Definition Lists</a></li>
+<li><a class="reference internal" href="#field-lists" id="toc-entry-11">2.5 Field Lists</a></li>
+<li><a class="reference internal" href="#option-lists" id="toc-entry-12">2.6 Option Lists</a></li>
+<li><a class="reference internal" href="#literal-blocks" id="toc-entry-13">2.7 Literal Blocks</a></li>
+<li><a class="reference internal" href="#line-blocks" id="toc-entry-14">2.8 Line Blocks</a></li>
+<li><a class="reference internal" href="#block-quotes" id="toc-entry-15">2.9 Block Quotes</a></li>
+<li><a class="reference internal" href="#doctest-blocks" id="toc-entry-16">2.10 Doctest Blocks</a></li>
+<li><a class="reference internal" href="#footnotes" id="toc-entry-17">2.11 Footnotes</a></li>
+<li><a class="reference internal" href="#citations" id="toc-entry-18">2.12 Citations</a></li>
+<li><a class="reference internal" href="#targets" id="toc-entry-19">2.13 Targets</a><ul class="auto-toc">
+<li><a class="reference internal" href="#duplicate-target-names" id="toc-entry-20">2.13.1 Duplicate Target Names</a></li>
+<li><a class="reference internal" href="#duplicate-target-names-1" id="toc-entry-21">2.13.2 Duplicate Target Names</a></li>
+</ul>
+</li>
+<li><a class="reference internal" href="#directives" id="toc-entry-22">2.14 Directives</a><ul class="auto-toc">
+<li><a class="reference internal" href="#document-parts" id="toc-entry-23">2.14.1 Document Parts</a></li>
+<li><a class="reference internal" href="#images-and-figures" id="toc-entry-24">2.14.2 Images and Figures</a></li>
+<li><a class="reference internal" href="#admonitions" id="toc-entry-25">2.14.3 Admonitions</a></li>
+<li><a class="reference internal" href="#topics-sidebars-and-rubrics" id="toc-entry-26">2.14.4 Topics, Sidebars, and Rubrics</a></li>
+<li><a class="reference internal" href="#target-footnotes" id="toc-entry-27">2.14.5 Target Footnotes</a></li>
+<li><a class="reference internal" href="#replacement-text" id="toc-entry-28">2.14.6 Replacement Text</a></li>
+<li><a class="reference internal" href="#compound-paragraph" id="toc-entry-29">2.14.7 Compound Paragraph</a></li>
+<li><a class="reference internal" href="#parsed-literal-blocks" id="toc-entry-30">2.14.8 Parsed Literal Blocks</a></li>
+<li><a class="reference internal" href="#code" id="toc-entry-31">2.14.9 Code</a></li>
+</ul>
+</li>
+<li><a class="reference internal" href="#substitution-definitions" id="toc-entry-32">2.15 Substitution Definitions</a></li>
+<li><a class="reference internal" href="#comments" id="toc-entry-33">2.16 Comments</a></li>
+<li><a class="reference internal" href="#raw-text" id="toc-entry-34">2.17 Raw text</a></li>
+<li><a class="reference internal" href="#container" id="toc-entry-35">2.18 Container</a></li>
+<li><a class="reference internal" href="#colspanning-tables" id="toc-entry-36">2.19 Colspanning tables</a></li>
+<li><a class="reference internal" href="#rowspanning-tables" id="toc-entry-37">2.20 Rowspanning tables</a></li>
+<li><a class="reference internal" href="#complex-tables" id="toc-entry-38">2.21 Complex tables</a></li>
+<li><a class="reference internal" href="#list-tables" id="toc-entry-39">2.22 List Tables</a></li>
+<li><a class="reference internal" href="#custom-roles" id="toc-entry-40">2.23 Custom Roles</a></li>
+<li><a class="reference internal" href="#svg-images" id="toc-entry-41">2.24 SVG Images</a></li>
+<li><a class="reference internal" href="#swf-images" id="toc-entry-42">2.25 SWF Images</a></li>
+</ul>
+</li>
+<li><a class="reference internal" href="#error-handling" id="toc-entry-43">3 Error Handling</a></li>
+</ul>
+</div>
+<div class="section" id="structural-elements">
+<h1><a class="toc-backref" href="#toc-entry-1">1 Structural Elements</a></h1>
+<div class="section" id="section-title">
+<h2 class="with-subtitle"><a class="toc-backref" href="#toc-entry-2">1.1 Section Title</a></h2>
+<h2 class="section-subtitle" id="section-subtitle"><span class="section-subtitle">Section Subtitle</span></h2>
+<p>Lone subsections are converted to a section subtitle by a transform
+activated with the <tt class="docutils literal"><span class="pre">--section-subtitles</span></tt> command line option or the
+<tt class="docutils literal"><span class="pre">sectsubtitle-xform</span></tt> configuration value.</p>
+</div>
+<div class="section" id="empty-section">
+<h2><a class="toc-backref" href="#toc-entry-3">1.2 Empty Section</a></h2>
+</div>
+<div class="section" id="transitions">
+<h2><a class="toc-backref" href="#toc-entry-4">1.3 Transitions</a></h2>
+<p>Here's a transition:</p>
+<hr class="docutils" />
+<p>It divides the section. Transitions may also occur between sections:</p>
+</div>
+</div>
+<hr class="docutils" />
+<div class="section" id="body-elements">
+<h1><a class="toc-backref" href="#toc-entry-5">2 Body Elements</a></h1>
+<div class="section" id="paragraphs">
+<h2><a class="toc-backref" href="#toc-entry-6">2.1 Paragraphs</a></h2>
+<p>A paragraph.</p>
+<div class="section" id="inline-markup">
+<h3><a class="toc-backref" href="#toc-entry-7">2.1.1 Inline Markup</a></h3>
+<p>Paragraphs contain text and may contain inline markup: <em>emphasis</em>,
+<strong>strong emphasis</strong>, <tt class="docutils literal">inline literals</tt>, standalone hyperlinks
+(<a class="reference external" href="http://www.python.org">http://www.python.org</a>), external hyperlinks (<a class="reference external" href="http://www.python.org/">Python</a> <a class="footnote-reference" href="#footnote-6" id="footnote-reference-10">[5]</a>), internal
+cross-references (<a class="reference internal" href="#example">example</a>), external hyperlinks with embedded URIs
+(<a class="reference external" href="http://www.python.org">Python web site</a>), <a class="reference external" href="http://www.python.org/">anonymous hyperlink
+references</a> <a class="footnote-reference" href="#footnote-6" id="footnote-reference-14">[5]</a> (<a class="reference external" href="http://docutils.sourceforge.net/">a second reference</a> <a class="footnote-reference" href="#footnote-8" id="footnote-reference-15">[7]</a>), footnote references (manually
+numbered <a class="footnote-reference" href="#footnote-1" id="footnote-reference-1">[1]</a>, anonymous auto-numbered <a class="footnote-reference" href="#footnote-2" id="footnote-reference-2">[3]</a>, labeled auto-numbered
+<a class="footnote-reference" href="#label" id="footnote-reference-3">[2]</a>, or symbolic <a class="footnote-reference" href="#footnote-3" id="footnote-reference-4">[*]</a>), citation references (<a class="citation-reference" href="#cit2002" id="citation-reference-1">[CIT2002]</a>),
+substitution references (<img alt="EXAMPLE" src="../../../docs/user/rst/images/biohazard.png" /> &
+a <em>trimmed heart</em> <tt class="docutils literal">(U+2665):</tt>♥), and <span class="target" id="inline-hyperlink-targets">inline hyperlink targets</span>
+(see <a class="reference internal" href="#targets">Targets</a> below for a reference back to here). Character-level
+inline markup is also possible (although exceedingly ugly!) in <em>re</em><tt class="docutils literal">Structured</tt><em>Text</em>. Problems are indicated by <a href="#system-message-1"><span class="problematic" id="problematic-1">|problematic|</span></a> text
+(generated by processing errors; this one is intentional). Here is a
+reference to the <a class="reference internal" href="#doctitle">doctitle</a> and the <a class="reference internal" href="#subtitle">subtitle</a>.</p>
+<p>The default role for interpreted text is <cite>Title Reference</cite>. Here are
+some explicit interpreted text roles: a PEP reference (<a class="reference external" href="http://www.python.org/dev/peps/pep-0287">PEP 287</a>); an
+RFC reference (<a class="reference external" href="http://tools.ietf.org/html/rfc2822.html">RFC 2822</a>); an abbreviation (<abbr>abb.</abbr>), an acronym
+(<acronym>reST</acronym>), code (<code>print "hello world"</code>); a <sub>subscript</sub>;
+a <sup>superscript</sup> and explicit roles for <cite>Docutils</cite>'
+<em>standard</em> <strong>inline</strong> <tt class="docutils literal">markup</tt>.</p>
+<!-- DO NOT RE-WRAP THE FOLLOWING PARAGRAPH! -->
+<p>Let's test wrapping and whitespace significance in inline literals:
+<tt class="docutils literal">This is an example of <span class="pre">--inline-literal</span> <span class="pre">--text,</span> <span class="pre">--including</span> <span class="pre">some--</span>
+<span class="pre">strangely--hyphenated-words.</span> <span class="pre">Adjust-the-width-of-your-browser-window</span>
+to see how the text is wrapped. <span class="pre">--</span> <span class="pre">----</span> <span class="pre">--------</span> Now note the
+spacing between the words of this sentence (words
+should be grouped in pairs).</tt></p>
+<p>If the <tt class="docutils literal"><span class="pre">--pep-references</span></tt> option was supplied, there should be a
+live link to PEP 258 here.</p>
+</div>
+</div>
+<div class="section" id="bullet-lists">
+<h2><a class="toc-backref" href="#toc-entry-8">2.2 Bullet Lists</a></h2>
+<ul>
+<li><p class="first">A bullet list</p>
+<ul class="simple">
+<li>Nested bullet list.</li>
+<li>Nested item 2.</li>
+</ul>
+</li>
+<li><p class="first">Item 2.</p>
+<p>Paragraph 2 of item 2.</p>
+<ul class="simple">
+<li>Nested bullet list.</li>
+<li>Nested item 2.<ul>
+<li>Third level.</li>
+<li>Item 2.</li>
+</ul>
+</li>
+<li>Nested item 3.</li>
+<li>This nested list should be compacted by the HTML writer.<span class="target" id="target"></span><!-- Even if this item contains a target and a comment. -->
+</li>
+</ul>
+</li>
+</ul>
+</div>
+<div class="section" id="enumerated-lists">
+<h2><a class="toc-backref" href="#toc-entry-9">2.3 Enumerated Lists</a></h2>
+<ol class="arabic">
+<li><p class="first">Arabic numerals.</p>
+<ol class="loweralpha simple">
+<li>lower alpha)<ol class="lowerroman">
+<li>(lower roman)<ol class="upperalpha">
+<li>upper alpha.<ol class="upperroman">
+<li>upper roman)</li>
+</ol>
+</li>
+</ol>
+</li>
+</ol>
+</li>
+</ol>
+</li>
+<li><p class="first">Lists that don't start at 1:</p>
+<ol class="arabic simple" start="3">
+<li>Three</li>
+<li>Four</li>
+</ol>
+<ol class="upperalpha simple" start="3">
+<li>C</li>
+<li>D</li>
+</ol>
+<ol class="lowerroman simple" start="3">
+<li>iii</li>
+<li>iv</li>
+</ol>
+</li>
+</ol>
+</div>
+<div class="section" id="definition-lists">
+<h2><a class="toc-backref" href="#toc-entry-10">2.4 Definition Lists</a></h2>
+<dl class="docutils">
+<dt>Term</dt>
+<dd>Definition</dd>
+<dt>Term <span class="classifier-delimiter">:</span> <span class="classifier">classifier</span></dt>
+<dd><p class="first">Definition paragraph 1.</p>
+<p class="last">Definition paragraph 2.</p>
+</dd>
+<dt>Term</dt>
+<dd>Definition</dd>
+<dt>Term <span class="classifier-delimiter">:</span> <span class="classifier">classifier one</span> <span class="classifier-delimiter">:</span> <span class="classifier">classifier two</span></dt>
+<dd>Definition</dd>
+</dl>
+</div>
+<div class="section" id="field-lists">
+<h2><a class="toc-backref" href="#toc-entry-11">2.5 Field Lists</a></h2>
+<table class="docutils field-list" frame="void" rules="none">
+<col class="field-name" />
+<col class="field-body" />
+<tbody valign="top">
+<tr class="field"><th class="field-name">what:</th><td class="field-body"><p class="first">Field lists map field names to field bodies, like database
+records. They are often part of an extension syntax. They are
+an unambiguous variant of RFC 2822 fields.</p>
+</td>
+</tr>
+<tr class="field"><th class="field-name">how arg1 arg2:</th><td class="field-body"><p class="first">The field marker is a colon, the field name, and a colon.</p>
+<p>The field body may contain one or more body elements, indented
+relative to the field marker.</p>
+</td>
+</tr>
+<tr class="field"><th class="field-name">credits:</th><td class="field-body"><p class="credits first last">This paragraph has the <cite>credits</cite> class set. (This is actually not
+about credits but just for ensuring that the class attribute
+doesn't get stripped away.)</p>
+</td>
+</tr>
+</tbody>
+</table>
+</div>
+<div class="section" id="option-lists">
+<h2><a class="toc-backref" href="#toc-entry-12">2.6 Option Lists</a></h2>
+<p>For listing command-line options:</p>
+<table class="docutils option-list" frame="void" rules="none">
+<col class="option" />
+<col class="description" />
+<tbody valign="top">
+<tr><td class="option-group">
+<kbd><span class="option">-a</span></kbd></td>
+<td>command-line option "a"</td></tr>
+<tr><td class="option-group">
+<kbd><span class="option">-b <var>file</var></span></kbd></td>
+<td>options can have arguments
+and long descriptions</td></tr>
+<tr><td class="option-group">
+<kbd><span class="option">--long</span></kbd></td>
+<td>options can be long also</td></tr>
+<tr><td class="option-group">
+<kbd><span class="option">--input=<var>file</var></span></kbd></td>
+<td>long options can also have
+arguments</td></tr>
+<tr><td class="option-group" colspan="2">
+<kbd><span class="option">--very-long-option</span></kbd></td>
+</tr>
+<tr><td> </td><td><p class="first">The description can also start on the next line.</p>
+<p class="last">The description may contain multiple body elements,
+regardless of where it starts.</p>
+</td></tr>
+<tr><td class="option-group">
+<kbd><span class="option">-x</span>, <span class="option">-y</span>, <span class="option">-z</span></kbd></td>
+<td>Multiple options are an "option group".</td></tr>
+<tr><td class="option-group">
+<kbd><span class="option">-v</span>, <span class="option">--verbose</span></kbd></td>
+<td>Commonly-seen: short & long options.</td></tr>
+<tr><td class="option-group" colspan="2">
+<kbd><span class="option">-1 <var>file</var></span>, <span class="option">--one=<var>file</var></span>, <span class="option">--two <var>file</var></span></kbd></td>
+</tr>
+<tr><td> </td><td>Multiple options with arguments.</td></tr>
+<tr><td class="option-group">
+<kbd><span class="option">/V</span></kbd></td>
+<td>DOS/VMS-style options too</td></tr>
+</tbody>
+</table>
+<p>There must be at least two spaces between the option and the
+description.</p>
+</div>
+<div class="section" id="literal-blocks">
+<h2><a class="toc-backref" href="#toc-entry-13">2.7 Literal Blocks</a></h2>
+<p>Literal blocks are indicated with a double-colon ("::") at the end of
+the preceding paragraph (over there <tt class="docutils literal"><span class="pre">--></span></tt>). They can be indented:</p>
+<pre class="literal-block">
+if literal_block:
+ text = 'is left as-is'
+ spaces_and_linebreaks = 'are preserved'
+ markup_processing = None
+</pre>
+<p>Or they can be quoted without indentation:</p>
+<pre class="literal-block">
+>> Great idea!
+>
+> Why didn't I think of that?
+</pre>
+</div>
+<div class="section" id="line-blocks">
+<h2><a class="toc-backref" href="#toc-entry-14">2.8 Line Blocks</a></h2>
+<p>This section tests line blocks. Line blocks are body elements which
+consist of lines and other line blocks. Nested line blocks cause
+indentation.</p>
+<div class="line-block">
+<div class="line">This is a line block. It ends with a blank line.</div>
+<div class="line-block">
+<div class="line">New lines begin with a vertical bar ("|").</div>
+<div class="line">Line breaks and initial indent are significant, and preserved.</div>
+<div class="line-block">
+<div class="line">Continuation lines are also possible. A long line that is intended
+to wrap should begin with a space in place of the vertical bar.</div>
+</div>
+<div class="line">The left edge of a continuation line need not be aligned with
+the left edge of the text above it.</div>
+</div>
+</div>
+<div class="line-block">
+<div class="line">This is a second line block.</div>
+<div class="line"><br /></div>
+<div class="line">Blank lines are permitted internally, but they must begin with a "|".</div>
+</div>
+<p>Another line block, surrounded by paragraphs:</p>
+<div class="line-block">
+<div class="line">And it's no good waiting by the window</div>
+<div class="line">It's no good waiting for the sun</div>
+<div class="line">Please believe me, the things you dream of</div>
+<div class="line">They don't fall in the lap of no-one</div>
+</div>
+<p>Take it away, Eric the Orchestra Leader!</p>
+<blockquote>
+<div class="line-block">
+<div class="line">A one, two, a one two three four</div>
+<div class="line"><br /></div>
+<div class="line">Half a bee, philosophically,</div>
+<div class="line-block">
+<div class="line">must, <em>ipso facto</em>, half not be.</div>
+</div>
+<div class="line">But half the bee has got to be,</div>
+<div class="line-block">
+<div class="line"><em>vis a vis</em> its entity. D'you see?</div>
+<div class="line"><br /></div>
+</div>
+<div class="line">But can a bee be said to be</div>
+<div class="line-block">
+<div class="line">or not to be an entire bee,</div>
+<div class="line-block">
+<div class="line">when half the bee is not a bee,</div>
+<div class="line-block">
+<div class="line">due to some ancient injury?</div>
+<div class="line"><br /></div>
+</div>
+</div>
+</div>
+<div class="line">Singing...</div>
+</div>
+</blockquote>
+<p>A line block, like the following poem by Christian Morgenstern, can
+also be centre-aligned:</p>
+<div class="align-center line-block" lang="de">
+<div class="line"><strong>Die Trichter</strong></div>
+<div class="line"><br /></div>
+<div class="line">Zwei Trichter wandeln durch die Nacht.</div>
+<div class="line">Durch ihres Rumpfs verengten Schacht</div>
+<div class="line">fließt weißes Mondlicht</div>
+<div class="line">still und heiter</div>
+<div class="line">auf ihren</div>
+<div class="line">Waldweg</div>
+<div class="line">u. s.</div>
+<div class="line">w.</div>
+<div class="line"><br /></div>
+</div>
+</div>
+<div class="section" id="block-quotes">
+<h2><a class="toc-backref" href="#toc-entry-15">2.9 Block Quotes</a></h2>
+<p>Block quotes consist of indented body elements:</p>
+<blockquote>
+<p>My theory by A. Elk. Brackets Miss, brackets. This theory goes
+as follows and begins now. All brontosauruses are thin at one
+end, much much thicker in the middle and then thin again at the
+far end. That is my theory, it is mine, and belongs to me and I
+own it, and what it is too.</p>
+<p class="attribution">—Anne Elk (Miss)</p>
+</blockquote>
+<p>The language of a quote (like any other object) can be specified by
+a class attribute:</p>
+<!-- -->
+<blockquote lang="fr">
+ReStructuredText est un langage de balisage léger utilisé
+notamment dans la documentation du langage Python.</blockquote>
+</div>
+<div class="section" id="doctest-blocks">
+<h2><a class="toc-backref" href="#toc-entry-16">2.10 Doctest Blocks</a></h2>
+<pre class="doctest-block">
+>>> print 'Python-specific usage examples; begun with ">>>"'
+Python-specific usage examples; begun with ">>>"
+>>> print '(cut and pasted from interactive Python sessions)'
+(cut and pasted from interactive Python sessions)
+</pre>
+</div>
+<div class="section" id="footnotes">
+<h2><a class="toc-backref" href="#toc-entry-17">2.11 Footnotes</a></h2>
+<table class="docutils footnote" frame="void" id="footnote-1" rules="none">
+<colgroup><col class="label" /><col /></colgroup>
+<tbody valign="top">
+<tr><td class="label">[1]</td><td><em>(<a class="fn-backref" href="#footnote-reference-1">1</a>, <a class="fn-backref" href="#footnote-reference-5">2</a>, <a class="fn-backref" href="#footnote-reference-9">3</a>)</em> <p>A footnote contains body elements, consistently indented by at
+least 3 spaces.</p>
+<p class="last">This is the footnote's second paragraph.</p>
+</td></tr>
+</tbody>
+</table>
+<table class="docutils footnote" frame="void" id="label" rules="none">
+<colgroup><col class="label" /><col /></colgroup>
+<tbody valign="top">
+<tr><td class="label">[2]</td><td><em>(<a class="fn-backref" href="#footnote-reference-3">1</a>, <a class="fn-backref" href="#footnote-reference-6">2</a>)</em> Footnotes may be numbered, either manually (as in <a class="footnote-reference" href="#footnote-1" id="footnote-reference-5">[1]</a>) or
+automatically using a "#"-prefixed label. This footnote has a
+label so it can be referred to from multiple places, both as a
+footnote reference (<a class="footnote-reference" href="#label" id="footnote-reference-6">[2]</a>) and as a <a class="reference internal" href="#label">hyperlink reference</a>.</td></tr>
+</tbody>
+</table>
+<table class="docutils footnote" frame="void" id="footnote-2" rules="none">
+<colgroup><col class="label" /><col /></colgroup>
+<tbody valign="top">
+<tr><td class="label"><a class="fn-backref" href="#footnote-reference-2">[3]</a></td><td><p class="first">This footnote is numbered automatically and anonymously using a
+label of "#" only.</p>
+<p>This is the second paragraph.</p>
+<p class="last">And this is the third paragraph.</p>
+</td></tr>
+</tbody>
+</table>
+<table class="docutils footnote" frame="void" id="footnote-3" rules="none">
+<colgroup><col class="label" /><col /></colgroup>
+<tbody valign="top">
+<tr><td class="label"><a class="fn-backref" href="#footnote-reference-4">[*]</a></td><td>Footnotes may also use symbols, specified with a "*" label.
+Here's a reference to the next footnote: <a class="footnote-reference" href="#footnote-4" id="footnote-reference-7">[†]</a>.</td></tr>
+</tbody>
+</table>
+<table class="docutils footnote" frame="void" id="footnote-4" rules="none">
+<colgroup><col class="label" /><col /></colgroup>
+<tbody valign="top">
+<tr><td class="label"><a class="fn-backref" href="#footnote-reference-7">[†]</a></td><td>This footnote shows the next symbol in the sequence.</td></tr>
+</tbody>
+</table>
+<table class="docutils footnote" frame="void" id="footnote-5" rules="none">
+<colgroup><col class="label" /><col /></colgroup>
+<tbody valign="top">
+<tr><td class="label">[4]</td><td>Here's an unreferenced footnote, with a reference to a
+nonexistent footnote: <a href="#system-message-2"><span class="problematic" id="footnote-reference-8">[5]_</span></a>.</td></tr>
+</tbody>
+</table>
+</div>
+<div class="section" id="citations">
+<h2><a class="toc-backref" href="#toc-entry-18">2.12 Citations</a></h2>
+<table class="docutils citation" frame="void" id="cit2002" rules="none">
+<colgroup><col class="label" /><col /></colgroup>
+<tbody valign="top">
+<tr><td class="label">[CIT2002]</td><td><em>(<a class="fn-backref" href="#citation-reference-1">1</a>, <a class="fn-backref" href="#citation-reference-2">2</a>)</em> Citations are text-labeled footnotes. They may be
+rendered separately and differently from footnotes.</td></tr>
+</tbody>
+</table>
+<p>Here's a reference to the above, <a class="citation-reference" href="#cit2002" id="citation-reference-2">[CIT2002]</a>, and a <a href="#system-message-3"><span class="problematic" id="citation-reference-3">[nonexistent]_</span></a>
+citation.</p>
+</div>
+<div class="section" id="targets">
+<span id="another-target"></span><h2><a class="toc-backref" href="#toc-entry-19">2.13 Targets</a></h2>
+<p id="example">This paragraph is pointed to by the explicit "example" target. A
+reference can be found under <a class="reference internal" href="#inline-markup">Inline Markup</a>, above. <a class="reference internal" href="#inline-hyperlink-targets">Inline
+hyperlink targets</a> are also possible.</p>
+<p>Section headers are implicit targets, referred to by name. See
+<a class="reference internal" href="#targets">Targets</a>, which is a subsection of <a class="reference internal" href="#body-elements">Body Elements</a>.</p>
+<p>Explicit external targets are interpolated into references such as
+"<a class="reference external" href="http://www.python.org/">Python</a> <a class="footnote-reference" href="#footnote-6" id="footnote-reference-11">[5]</a>".</p>
+<p>Targets may be indirect and anonymous. Thus <a class="reference internal" href="#targets">this phrase</a> may also
+refer to the <a class="reference internal" href="#targets">Targets</a> section.</p>
+<p>Here's a <a href="#system-message-4"><span class="problematic" id="problematic-2">`hyperlink reference without a target`_</span></a>, which generates an
+error.</p>
+<div class="section" id="duplicate-target-names">
+<h3><a class="toc-backref" href="#toc-entry-20">2.13.1 Duplicate Target Names</a></h3>
+<p>Duplicate names in section headers or other implicit targets will
+generate "info" (level-1) system messages. Duplicate names in
+explicit targets will generate "warning" (level-2) system messages.</p>
+</div>
+<div class="section" id="duplicate-target-names-1">
+<h3><a class="toc-backref" href="#toc-entry-21">2.13.2 Duplicate Target Names</a></h3>
+<p>Since there are two "Duplicate Target Names" section headers, we
+cannot uniquely refer to either of them by name. If we try to (like
+this: <a href="#system-message-5"><span class="problematic" id="problematic-3">`Duplicate Target Names`_</span></a>), an error is generated.</p>
+</div>
+</div>
+<div class="section" id="directives">
+<h2><a class="toc-backref" href="#toc-entry-22">2.14 Directives</a></h2>
+<div class="contents local topic" id="contents">
+<ul class="auto-toc simple">
+<li><a class="reference internal" href="#document-parts" id="toc-entry-44">2.14.1 Document Parts</a></li>
+<li><a class="reference internal" href="#images-and-figures" id="toc-entry-45">2.14.2 Images and Figures</a></li>
+<li><a class="reference internal" href="#admonitions" id="toc-entry-46">2.14.3 Admonitions</a></li>
+<li><a class="reference internal" href="#topics-sidebars-and-rubrics" id="toc-entry-47">2.14.4 Topics, Sidebars, and Rubrics</a></li>
+<li><a class="reference internal" href="#target-footnotes" id="toc-entry-48">2.14.5 Target Footnotes</a></li>
+<li><a class="reference internal" href="#replacement-text" id="toc-entry-49">2.14.6 Replacement Text</a></li>
+<li><a class="reference internal" href="#compound-paragraph" id="toc-entry-50">2.14.7 Compound Paragraph</a></li>
+<li><a class="reference internal" href="#parsed-literal-blocks" id="toc-entry-51">2.14.8 Parsed Literal Blocks</a></li>
+<li><a class="reference internal" href="#code" id="toc-entry-52">2.14.9 Code</a></li>
+</ul>
+</div>
+<p>These are just a sample of the many reStructuredText Directives. For
+others, please see
+<a class="reference external" href="http://docutils.sourceforge.net/docs/ref/rst/directives.html">http://docutils.sourceforge.net/docs/ref/rst/directives.html</a>.</p>
+<div class="section" id="document-parts">
+<h3><a class="toc-backref" href="#toc-entry-44">2.14.1 Document Parts</a></h3>
+<p>An example of the "contents" directive can be seen above this section
+(a local, untitled table of <a class="reference internal" href="#contents">contents</a>) and at the beginning of the
+document (a document-wide <a class="reference internal" href="#table-of-contents">table of contents</a>).</p>
+</div>
+<div class="section" id="images-and-figures">
+<h3><a class="toc-backref" href="#toc-entry-45">2.14.2 Images and Figures</a></h3>
+<p>An image directive (also clickable -- a hyperlink reference):</p>
+<a class="reference internal image-reference" href="#directives"><img alt="../../../docs/user/rst/images/title.png" class="class1 class2" src="../../../docs/user/rst/images/title.png" /></a>
+<p>Image with multiple IDs:</p>
+<span id="image-target-2"></span><span id="image-target-1"></span><img alt="../../../docs/user/rst/images/title.png" id="image-target-3" src="../../../docs/user/rst/images/title.png" />
+<p>A centered image:</p>
+<img alt="../../../docs/user/rst/images/biohazard.png" class="align-center" src="../../../docs/user/rst/images/biohazard.png" />
+<p>A left-aligned image:</p>
+<img alt="../../../docs/user/rst/images/biohazard.png" class="align-left" src="../../../docs/user/rst/images/biohazard.png" />
+<p>This paragraph might flow around the image.
+The specific behavior depends upon the style sheet and
+the browser or rendering software used.</p>
+<p>A right-aligned image:</p>
+<img alt="../../../docs/user/rst/images/biohazard.png" class="align-right" src="../../../docs/user/rst/images/biohazard.png" />
+<p>This paragraph might flow around the image.
+The specific behavior depends upon the style sheet and
+the browser or rendering software used.</p>
+<p>For inline images see <a class="reference internal" href="#substitution-definitions">Substitution Definitions</a>.</p>
+<p>Image size:</p>
+<p>An image 2 em wide:</p>
+<img alt="../../../docs/user/rst/images/biohazard.png" src="../../../docs/user/rst/images/biohazard.png" style="width: 2em;" />
+<p>An image 2 em wide and 15 pixel high:</p>
+<img alt="../../../docs/user/rst/images/biohazard.png" src="../../../docs/user/rst/images/biohazard.png" style="width: 2em; height: 15px;" />
+<p>An image occupying 50% of the line width:</p>
+<img alt="../../../docs/user/rst/images/title.png" src="../../../docs/user/rst/images/title.png" style="width: 50%;" />
+<p>An image 2 cm high:</p>
+<img alt="../../../docs/user/rst/images/biohazard.png" src="../../../docs/user/rst/images/biohazard.png" style="height: 2cm;" />
+<p>A <em>figure</em> is an image with a caption and/or a legend. With page-based output
+media, figures might float to a different position if this helps the page
+layout.</p>
+<div class="figclass1 figclass2 figure">
+<img alt="reStructuredText, the markup syntax" class="class1 class2" src="../../../docs/user/rst/images/title.png" style="width: 258px;" />
+<p class="caption">Plaintext markup syntax and parser system.</p>
+<div class="legend">
+<table border="1" class="docutils">
+<colgroup>
+<col width="20%" />
+<col width="80%" />
+</colgroup>
+<tbody valign="top">
+<tr><td>re</td>
+<td>Revised, revisited, based on 're' module.</td>
+</tr>
+<tr><td>Structured</td>
+<td>Structure-enhanced text, structuredtext.</td>
+</tr>
+<tr><td>Text</td>
+<td>Well it is, isn't it?</td>
+</tr>
+</tbody>
+</table>
+<p>This paragraph is also part of the legend.</p>
+</div>
+</div>
+<p>A left-aligned figure:</p>
+<div class="figclass1 figclass2 figure align-left" style="width: 70%">
+<img alt="reStructuredText, the markup syntax" class="class1 class2" src="../../../docs/user/rst/images/biohazard.png" style="width: 40px;" />
+<p class="caption">This is the caption.</p>
+<div class="legend">
+<p>This is the legend.</p>
+<p>The legend may consist of several paragraphs.</p>
+</div>
+</div>
+<p>This paragraph might flow around the figure.</p>
+<p>The specific behavior depends upon the style sheet and the browser or
+rendering software used.</p>
+<p>A centered figure:</p>
+<div class="figure align-center">
+<img alt="../../../docs/user/rst/images/biohazard.png" src="../../../docs/user/rst/images/biohazard.png" style="width: 40px;" />
+<p class="caption">This is the caption.</p>
+<div class="legend">
+<p>This is the legend.</p>
+<p>The legend may consist of several paragraphs.</p>
+</div>
+</div>
+<p>This paragraph might flow around the figure.</p>
+<p>The specific behavior depends upon the style sheet and the browser or
+rendering software used.</p>
+<p>A right-aligned figure:</p>
+<div class="figure align-right">
+<img alt="../../../docs/user/rst/images/biohazard.png" src="../../../docs/user/rst/images/biohazard.png" style="width: 40px;" />
+<p class="caption">This is the caption.</p>
+<div class="legend">
+<p>This is the legend.</p>
+<p>The legend may consist of several paragraphs.</p>
+</div>
+</div>
+<p>This paragraph might flow around the figure. The specific behavior depends
+upon the style sheet and the browser or rendering software used.</p>
+<p>Tables may be given titles and additional arguments with the <em>table</em>
+directive:</p>
+<table border="1" class="docutils align-left">
+<caption>left-aligned table</caption>
+<colgroup>
+<col width="50%" />
+<col width="50%" />
+</colgroup>
+<thead valign="bottom">
+<tr><th class="head">A</th>
+<th class="head">not A</th>
+</tr>
+</thead>
+<tbody valign="top">
+<tr><td>False</td>
+<td>True</td>
+</tr>
+<tr><td>True</td>
+<td>False</td>
+</tr>
+</tbody>
+</table>
+<table border="1" class="docutils align-center">
+<caption>center-aligned table</caption>
+<colgroup>
+<col width="50%" />
+<col width="50%" />
+</colgroup>
+<thead valign="bottom">
+<tr><th class="head">A</th>
+<th class="head">not A</th>
+</tr>
+</thead>
+<tbody valign="top">
+<tr><td>False</td>
+<td>True</td>
+</tr>
+<tr><td>True</td>
+<td>False</td>
+</tr>
+</tbody>
+</table>
+<table border="1" class="docutils align-right">
+<caption>right-aligned table</caption>
+<colgroup>
+<col width="50%" />
+<col width="50%" />
+</colgroup>
+<thead valign="bottom">
+<tr><th class="head">A</th>
+<th class="head">not A</th>
+</tr>
+</thead>
+<tbody valign="top">
+<tr><td>False</td>
+<td>True</td>
+</tr>
+<tr><td>True</td>
+<td>False</td>
+</tr>
+</tbody>
+</table>
+<p>With the "widths" argument "auto" (or "class" value "colwidths-auto"),
+column widths are determined by the backend (if supported by the
+writer/backend).</p>
+<span id="target1"></span><table border="1" class="colwidths-auto docutils" id="target2">
+<thead valign="bottom">
+<tr><th class="head">A</th>
+<th class="head">B</th>
+<th class="head">A or B</th>
+</tr>
+</thead>
+<tbody valign="top">
+<tr><td>False</td>
+<td>False</td>
+<td>False</td>
+</tr>
+<tr><td>True</td>
+<td>False</td>
+<td>True</td>
+</tr>
+<tr><td>False</td>
+<td>True</td>
+<td>True</td>
+</tr>
+<tr><td>True</td>
+<td>True</td>
+<td>True</td>
+</tr>
+</tbody>
+</table>
+</div>
+<div class="section" id="admonitions">
+<h3><a class="toc-backref" href="#toc-entry-46">2.14.3 Admonitions</a></h3>
+<div class="admonition attention">
+<p class="first admonition-title">Attention!</p>
+<p class="last">Directives at large.</p>
+</div>
+<div class="admonition caution">
+<p class="first admonition-title">Caution!</p>
+<p class="last">Don't take any wooden nickels.</p>
+</div>
+<div class="admonition danger">
+<p class="first admonition-title">!DANGER!</p>
+<p class="last">Mad scientist at work!</p>
+</div>
+<div class="admonition error">
+<p class="first admonition-title">Error</p>
+<p class="last">Does not compute.</p>
+</div>
+<div class="admonition hint">
+<p class="first admonition-title">Hint</p>
+<p class="last">It's bigger than a bread box.</p>
+</div>
+<div class="admonition important">
+<p class="first admonition-title">Important</p>
+<ul class="last simple">
+<li>Wash behind your ears.</li>
+<li>Clean up your room.</li>
+<li>Call your mother.</li>
+<li>Back up your data.</li>
+</ul>
+</div>
+<div class="admonition note">
+<p class="first admonition-title">Note</p>
+<p class="last">This is a note.</p>
+</div>
+<div class="admonition tip">
+<p class="first admonition-title">Tip</p>
+<p class="last">15% if the service is good.</p>
+</div>
+<div class="admonition warning">
+<p class="first admonition-title">Warning</p>
+<p class="last">Strong prose may provoke extreme mental exertion.
+Reader discretion is strongly advised.</p>
+</div>
+<div class="admonition admonition-and-by-the-way">
+<p class="first admonition-title">And, by the way...</p>
+<p class="last">You can make up your own admonition too.</p>
+</div>
+</div>
+<div class="section" id="topics-sidebars-and-rubrics">
+<h3><a class="toc-backref" href="#toc-entry-47">2.14.4 Topics, Sidebars, and Rubrics</a></h3>
+<p><em>Sidebars</em> are like miniature, parallel documents.</p>
+<div class="sidebar">
+<p class="first sidebar-title">Sidebar Title</p>
+<p class="sidebar-subtitle">Optional Subtitle</p>
+<p>This is a sidebar. It is for text outside the flow of the main
+text.</p>
+<p class="rubric">This is a rubric inside a sidebar</p>
+<p class="last">Sidebars often appear beside the main text with a border and a different
+background or font color.</p>
+</div>
+<p>A <em>topic</em> is like a block quote with a title, or a self-contained section
+with no subsections.</p>
+<div class="topic">
+<p class="topic-title">Topic Title</p>
+<p>This is a topic.</p>
+</div>
+<p>A <em>rubric</em> is like an informal heading that doesn't correspond to the
+document's structure. It is typically highlighted in red (hence the name).</p>
+<p class="rubric">This is a rubric</p>
+<p>Topics and rubrics can be used at places where a <a class="reference internal" href="#section-title">section title</a> is not
+allowed (e.g. inside a directive).</p>
+</div>
+<div class="section" id="target-footnotes">
+<h3><a class="toc-backref" href="#toc-entry-48">2.14.5 Target Footnotes</a></h3>
+<table class="docutils footnote" frame="void" id="footnote-6" rules="none">
+<colgroup><col class="label" /><col /></colgroup>
+<tbody valign="top">
+<tr><td class="label">[5]</td><td><em>(<a class="fn-backref" href="#footnote-reference-10">1</a>, <a class="fn-backref" href="#footnote-reference-11">2</a>, <a class="fn-backref" href="#footnote-reference-12">3</a>, <a class="fn-backref" href="#footnote-reference-14">4</a>)</em> <a class="reference external" href="http://www.python.org/">http://www.python.org/</a></td></tr>
+</tbody>
+</table>
+<table class="docutils footnote" frame="void" id="footnote-7" rules="none">
+<colgroup><col class="label" /><col /></colgroup>
+<tbody valign="top">
+<tr><td class="label"><a class="fn-backref" href="#footnote-reference-13">[6]</a></td><td><a class="reference external" href="http://pygments.org/">http://pygments.org/</a></td></tr>
+</tbody>
+</table>
+<table class="docutils footnote" frame="void" id="footnote-8" rules="none">
+<colgroup><col class="label" /><col /></colgroup>
+<tbody valign="top">
+<tr><td class="label"><a class="fn-backref" href="#footnote-reference-15">[7]</a></td><td><a class="reference external" href="http://docutils.sourceforge.net/">http://docutils.sourceforge.net/</a></td></tr>
+</tbody>
+</table>
+</div>
+<div class="section" id="replacement-text">
+<h3><a class="toc-backref" href="#toc-entry-49">2.14.6 Replacement Text</a></h3>
+<p>I recommend you try <a class="reference external" href="http://www.python.org/">Python, <em>the</em> best language around</a> <a class="footnote-reference" href="#footnote-6" id="footnote-reference-12">[5]</a>.</p>
+</div>
+<div class="section" id="compound-paragraph">
+<h3><a class="toc-backref" href="#toc-entry-50">2.14.7 Compound Paragraph</a></h3>
+<p>The <em>compound</em> directive is used to create a "compound paragraph", which
+is a single logical paragraph containing multiple physical body
+elements. For example:</p>
+<div class="compound">
+<p class="compound-first">The 'rm' command is very dangerous. If you are logged
+in as root and enter</p>
+<pre class="compound-middle literal-block">
+cd /
+rm -rf *
+</pre>
+<p class="compound-last">you will erase the entire contents of your file system.</p>
+</div>
+<p>Test the handling and display of compound paragraphs:</p>
+<div class="some-class compound">
+<p class="compound-first">Compound 2, paragraph 1,</p>
+<p class="compound-middle">compound 2, paragraph 2,</p>
+<ul class="compound-middle simple">
+<li>list item 1,</li>
+<li>list item 2,</li>
+</ul>
+<p class="compound-last">compound 2, paragraph 3.</p>
+</div>
+<div class="compound">
+<p>Compound 3, only consisting of one paragraph.</p>
+</div>
+<div class="compound">
+<pre class="compound-first literal-block">
+Compound 4.
+This one starts with a literal block.
+</pre>
+<p class="compound-last">Compound 4, paragraph following the literal block.</p>
+</div>
+<p>Now something <em>really</em> perverted -- a nested compound block. This is
+just to test that it works at all; the results don't have to be
+meaningful.</p>
+<div class="compound">
+<p class="compound-first">Compound 5, block 1 (a paragraph).</p>
+<div class="compound-middle compound">
+<p class="compound-first">Compound 6 is block 2 in compound 5.</p>
+<p class="compound-last">Compound 6, another paragraph.</p>
+</div>
+<p class="compound-last">Compound 5, block 3 (a paragraph).</p>
+</div>
+<div class="compound">
+<p class="compound-first">Compound 7, tests the inclusion of various block-level
+elements in one logical paragraph. First a table,</p>
+<table border="1" class="compound-middle docutils">
+<colgroup>
+<col width="33%" />
+<col width="33%" />
+<col width="33%" />
+</colgroup>
+<tbody valign="top">
+<tr><td><p class="first">Left cell, first
+paragraph.</p>
+<p class="last">Left cell, second
+paragraph.</p>
+</td>
+<td>Middle cell,
+consisting of
+exactly one
+paragraph.</td>
+<td><p class="first">Right cell.</p>
+<p>Paragraph 2.</p>
+<p class="last">Paragraph 3.</p>
+</td>
+</tr>
+</tbody>
+</table>
+<p class="compound-middle">followed by a paragraph. This physical paragraph is
+actually a continuation of the paragraph before the table. It is followed
+by</p>
+<blockquote class="compound-middle">
+a quote and</blockquote>
+<ol class="compound-middle arabic simple">
+<li>an enumerated list,</li>
+</ol>
+<p class="compound-middle">a paragraph,</p>
+<table class="compound-middle docutils option-list" frame="void" rules="none">
+<col class="option" />
+<col class="description" />
+<tbody valign="top">
+<tr><td class="option-group">
+<kbd><span class="option">--an</span></kbd></td>
+<td>option list,</td></tr>
+</tbody>
+</table>
+<p class="compound-middle">a paragraph,</p>
+<table class="compound-middle docutils field-list" frame="void" rules="none">
+<col class="field-name" />
+<col class="field-body" />
+<tbody valign="top">
+<tr class="field"><th class="field-name">a field:</th><td class="field-body">list,</td>
+</tr>
+</tbody>
+</table>
+<p class="compound-middle">a paragraph,</p>
+<dl class="compound-middle docutils">
+<dt>a definition</dt>
+<dd>list,</dd>
+</dl>
+<p class="compound-middle">a paragraph, an image:</p>
+<img alt="../../../docs/user/rst/images/biohazard.png" class="compound-middle" src="../../../docs/user/rst/images/biohazard.png" />
+<p class="compound-middle">a paragraph,</p>
+<div class="compound-middle line-block">
+<div class="line">a line</div>
+<div class="line">block,</div>
+</div>
+<p class="compound-middle">a paragraph followed by a comment,</p>
+<!-- this is a comment -->
+<p class="compound-middle">a paragraph, a</p>
+<div class="admonition note compound-middle">
+<p class="first admonition-title">Note</p>
+<p class="last">with content</p>
+</div>
+<p class="compound-last">and the final paragraph of the compound 7.</p>
+</div>
+</div>
+<div class="section" id="parsed-literal-blocks">
+<h3><a class="toc-backref" href="#toc-entry-51">2.14.8 Parsed Literal Blocks</a></h3>
+<pre class="literal-block">
+This is a parsed literal block.
+ This line is indented. The next line is blank.
+
+Inline markup is supported, e.g. <em>emphasis</em>, <strong>strong</strong>, <tt class="docutils literal">literal
+text</tt>, <span class="subscript">sub-</span> and <span class="superscript">super</span>scripts,
+inline formulas: <span class="formula"><i>A</i> = 2<i>π</i><i>r</i><sup>2</sup></span>,
+footnotes <a class="footnote-reference" href="#footnote-1" id="footnote-reference-9">[1]</a>, <span class="target" id="hyperlink-targets">hyperlink targets</span>, and <a class="reference external" href="http://www.python.org/">references</a>.
+</pre>
+</div>
+<div class="section" id="code">
+<h3><a class="toc-backref" href="#toc-entry-52">2.14.9 Code</a></h3>
+<p>Blocks of source code can be set with the <cite>code</cite> directive. If the code
+language is specified, the content is parsed and tagged by the <a class="reference external" href="http://pygments.org/">Pygments</a> <a class="footnote-reference" href="#footnote-7" id="footnote-reference-13">[6]</a>
+syntax highlighter and can be formatted with a style sheet. (Code parsing
+is turned off using the <tt class="docutils literal"><span class="pre">syntax-highlight</span></tt> config setting in the test
+conversions in order to get identical results with/without installed
+Pygments highlighter.)</p>
+<pre class="code python literal-block">
+print 'This is Python code.'
+</pre>
+<p>The <tt class="docutils literal"><span class="pre">:number-lines:</span></tt> option (with optional start value) generates line
+numbers:</p>
+<pre class="code python literal-block">
+<span class="ln"> 8 </span># print integers from 0 to 9:
+<span class="ln"> 9 </span>for i in range(10):
+<span class="ln">10 </span> print i
+</pre>
+<p>For inline code snippets, there is the <cite>code</cite> role, which can be used
+directly (the code will not be parsed/tagged, as the language is not known)
+or as base for special code roles, e.g. the LaTeX code in the next
+paragraph.</p>
+<p>Docutils uses LaTeX syntax for math directives and roles:
+<code class="tex">\alpha = f(x)</code> prints <span class="formula"><i>α</i> = <i>f</i>(<i>x</i>)</span>.</p>
+<p>The <tt class="docutils literal">:code:</tt> option of the <cite>include</cite> directive sets the included content
+as a code block, here the rst file <tt class="docutils literal">header_footer.txt</tt> with line numbers:</p>
+<pre class="code rst literal-block">
+<span class="ln">1 </span>.. header:: Document header
+<span class="ln">2 </span>.. footer:: Document footer
+</pre>
+</div>
+</div>
+<div class="section" id="substitution-definitions">
+<h2><a class="toc-backref" href="#toc-entry-32">2.15 Substitution Definitions</a></h2>
+<p>An inline image (<img alt="EXAMPLE" src="../../../docs/user/rst/images/biohazard.png" />) example:</p>
+<p>A Unicode example:</p>
+<p>(Substitution definitions are not visible in the HTML source.)</p>
+</div>
+<div class="section" id="comments">
+<h2><a class="toc-backref" href="#toc-entry-33">2.16 Comments</a></h2>
+<p>Here's one:</p>
+<!-- Comments begin with two dots and a space. Anything may
+follow, except for the syntax of footnotes, hyperlink
+targets, directives, or substitution definitions.
+
+Double-dashes - - "- -" - - must be escaped somehow in HTML output.
+
+Comments may contain non-ASCII characters: ä ö ü æ ø å -->
+<p>(View the HTML source to see the comment.)</p>
+</div>
+<div class="section" id="raw-text">
+<h2><a class="toc-backref" href="#toc-entry-34">2.17 Raw text</a></h2>
+<p>This does not necessarily look nice, because there may be missing white space.</p>
+<p>It's just there to freeze the behavior.</p>
+A test.Second test.<div class="myclass">Another test with myclass set.</div><p>This is the <span class="myrawroleclass">fourth test</span> with myrawroleclass set.</p>
+Fifth test in HTML.<br />Line two.</div>
+<div class="section" id="container">
+<h2><a class="toc-backref" href="#toc-entry-35">2.18 Container</a></h2>
+<div class="custom docutils container">
+<p>paragraph 1</p>
+<p>paragraph 2</p>
+</div>
+</div>
+<div class="section" id="colspanning-tables">
+<h2><a class="toc-backref" href="#toc-entry-36">2.19 Colspanning tables</a></h2>
+<p>This table has a cell spanning two columns:</p>
+<table border="1" class="docutils">
+<colgroup>
+<col width="31%" />
+<col width="31%" />
+<col width="38%" />
+</colgroup>
+<thead valign="bottom">
+<tr><th class="head" colspan="2">Inputs</th>
+<th class="head">Output</th>
+</tr>
+<tr><th class="head">A</th>
+<th class="head">B</th>
+<th class="head">A or B</th>
+</tr>
+</thead>
+<tbody valign="top">
+<tr><td>False</td>
+<td>False</td>
+<td>False</td>
+</tr>
+<tr><td>True</td>
+<td>False</td>
+<td>True</td>
+</tr>
+<tr><td>False</td>
+<td>True</td>
+<td>True</td>
+</tr>
+<tr><td>True</td>
+<td>True</td>
+<td>True</td>
+</tr>
+</tbody>
+</table>
+</div>
+<div class="section" id="rowspanning-tables">
+<h2><a class="toc-backref" href="#toc-entry-37">2.20 Rowspanning tables</a></h2>
+<p>Here's a table with cells spanning several rows:</p>
+<table border="1" class="docutils">
+<colgroup>
+<col width="44%" />
+<col width="22%" />
+<col width="33%" />
+</colgroup>
+<thead valign="bottom">
+<tr><th class="head">Header row, column 1
+(header rows optional)</th>
+<th class="head">Header 2</th>
+<th class="head">Header 3</th>
+</tr>
+</thead>
+<tbody valign="top">
+<tr><td>body row 1, column 1</td>
+<td>column 2</td>
+<td>column 3</td>
+</tr>
+<tr><td>body row 2</td>
+<td rowspan="2">Cells may
+span rows.</td>
+<td rowspan="2">Another
+rowspanning
+cell.</td>
+</tr>
+<tr><td>body row 3</td>
+</tr>
+</tbody>
+</table>
+</div>
+<div class="section" id="complex-tables">
+<h2><a class="toc-backref" href="#toc-entry-38">2.21 Complex tables</a></h2>
+<p>Here's a complex table, which should test all features.</p>
+<table border="1" class="docutils">
+<colgroup>
+<col width="43%" />
+<col width="21%" />
+<col width="18%" />
+<col width="18%" />
+</colgroup>
+<thead valign="bottom">
+<tr><th class="head">Header row, column 1
+(header rows optional)</th>
+<th class="head">Header 2</th>
+<th class="head">Header 3</th>
+<th class="head">Header 4</th>
+</tr>
+</thead>
+<tbody valign="top">
+<tr><td>body row 1, column 1</td>
+<td>column 2</td>
+<td>column 3</td>
+<td>column 4</td>
+</tr>
+<tr><td>body row 2</td>
+<td colspan="3">Cells may span columns.</td>
+</tr>
+<tr><td>body row 3</td>
+<td rowspan="2"><p class="first">Cells may
+span rows.</p>
+<p class="last">Paragraph.</p>
+</td>
+<td colspan="2" rowspan="2"><ul class="first last simple">
+<li>Table cells</li>
+<li>contain</li>
+<li>body elements.</li>
+</ul>
+</td>
+</tr>
+<tr><td>body row 4</td>
+</tr>
+<tr><td>body row 5</td>
+<td colspan="2">Cells may also be
+empty: <tt class="docutils literal"><span class="pre">--></span></tt></td>
+<td> </td>
+</tr>
+</tbody>
+</table>
+</div>
+<div class="section" id="list-tables">
+<h2><a class="toc-backref" href="#toc-entry-39">2.22 List Tables</a></h2>
+<p>Here's a list table exercising all features:</p>
+<table border="1" class="colwidths-given test docutils" style="width: 40em">
+<caption>list table with integral header</caption>
+<colgroup>
+<col width="17%" />
+<col width="33%" />
+<col width="50%" />
+</colgroup>
+<thead valign="bottom">
+<tr><th class="head stub">Treat</th>
+<th class="head">Quantity</th>
+<th class="head">Description</th>
+</tr>
+</thead>
+<tbody valign="top">
+<tr><th class="stub">Albatross</th>
+<td>2.99</td>
+<td>On a stick!</td>
+</tr>
+<tr><th class="stub">Crunchy Frog</th>
+<td>1.49</td>
+<td>If we took the bones out, it wouldn't be
+crunchy, now would it?</td>
+</tr>
+<tr><th class="stub">Gannet Ripple</th>
+<td>1.99</td>
+<td>On a stick!</td>
+</tr>
+</tbody>
+</table>
+<table border="1" class="colwidths-auto docutils align-center">
+<caption>center aligned list table</caption>
+<tbody valign="top">
+<tr><td>Albatross</td>
+<td>2.99</td>
+</tr>
+<tr><td>Crunchy Frog</td>
+<td>1.49</td>
+</tr>
+<tr><td>Gannet Ripple</td>
+<td>1.99</td>
+</tr>
+</tbody>
+</table>
+</div>
+<div class="section" id="custom-roles">
+<h2><a class="toc-backref" href="#toc-entry-40">2.23 Custom Roles</a></h2>
+<ul>
+<li><p class="first">A role based on an existing role.</p>
+<p><tt class="custom docutils literal">one</tt> <tt class="custom docutils literal">two</tt> <tt class="custom docutils literal">three</tt></p>
+</li>
+<li><p class="first">A new role.</p>
+<p><span class="customnew">one two three</span></p>
+</li>
+<li><p class="first">A role with class attribute.</p>
+<p><span class="special">interpreted text</span></p>
+</li>
+<li><p class="first">A language-switching role:</p>
+<p>Let's count in German <span lang="de">eins zwei drei</span>.</p>
+</li>
+<li><p class="first">A role with multiple class attributes, styled with raw directives:</p>
+<p>The following works in most browsers but does not validate
+(<tt class="docutils literal"><style></tt> is only allowed in the document head):</p>
+<pre class="literal-block">
+.. raw:: html
+
+ <style type="text/css"><!--
+ .green {color: green;}
+ .sc {font-variant: small-caps;}
+ --></style>
+</pre>
+<p><span class="green sc" lang="en-gb">British colourful text in small-caps</span>.</p>
+</li>
+</ul>
+</div>
+<div class="section" id="svg-images">
+<h2><a class="toc-backref" href="#toc-entry-41">2.24 SVG Images</a></h2>
+<object class="align-left" data="../../../docs/user/rst/images/biohazard.svg" style="width: 48px; height: 48px;" type="image/svg+xml">
+../../../docs/user/rst/images/biohazard.svg</object>
+<p>Scalable vector graphics (SVG) images are the only standards-compliable way
+to include vector graphics in HTML documents. However, they are not
+supported by all backends/output formats. (E.g., LaTeX supports the
+PDF or Postscript formats for vector graphics instead.)</p>
+<p>Rendering behaviour varies, depending on</p>
+<ol class="loweralpha">
+<li><p class="first">The SVG image itself, e.g. fixed-size vs. scaling:</p>
+<pre class="literal-block">
+width="280" viewBox="0 0 280 27"
+height="27" width="100%"
+ height="100%"
+</pre>
+</li>
+<li><p class="first">The method used to put the image in the document.</p>
+<p>For HTML, there are several alternatives including:</p>
+<ul class="simple">
+<li>using the HTML <tt class="docutils literal"><img></tt> tag (not for interactive/animated SVG),</li>
+<li>using the HTML <tt class="docutils literal"><object></tt> tag,</li>
+<li>including within SVG using the SVG <tt class="docutils literal"><image></tt> tag,</li>
+<li>embedd the SVG code within HTML (inlining).</li>
+</ul>
+<p>The <cite>html4css1</cite> writer uses <tt class="docutils literal"><object></tt> tags, the <cite>html5</cite>
+writer uses <tt class="docutils literal"><img></tt> tags.</p>
+<!-- cf. http://edutechwiki.unige.ch/en/Using_SVG_with_HTML5_tutorial -->
+</li>
+<li><p class="first">The viewing agent.</p>
+<p>All up-to-date HTML browsers support SVG, however not all do this fully
+and in the same manner. Many older versions, especially IE < 9, have
+deficiencies or require plug-ins (i.e. don't support the <tt class="docutils literal"><img></tt> tag).</p>
+</li>
+</ol>
+<p>If the image is wrapped in <tt class="docutils literal"><object></tt> or <tt class="docutils literal"><svg></tt> tags, it depends on the
+<tt class="docutils literal">viewBox</tt> declaration inside the images root <tt class="docutils literal"><svg></tt> element whether an
+SVG image is scaled or clipped/padded. Images wrapped in <tt class="docutils literal"><img></tt> are
+always scaled.</p>
+<ul>
+<li><object class="first align-right" data="../../../docs/user/rst/images/title-scaling.svg" style="width: 50%;" type="image/svg+xml">
+../../../docs/user/rst/images/title-scaling.svg</object>
+<p>A scaling image (scales with the browser window), occupying 50% of the line
+width. The <tt class="docutils literal">viewBox</tt> setting in the image file enables auto-scaling also in
+<tt class="docutils literal"><object></tt> tags and embedded SVG (if width and hight are set to 100% in the
+SVG <image> tag).</p>
+</li>
+<li><object class="first align-right" data="../../../docs/user/rst/images/title.svg" style="width: 50%; height: 15px;" type="image/svg+xml">
+../../../docs/user/rst/images/title.svg</object>
+<p>A fixed-size image in a box 50% wide and 15 pixles high. This image is
+scaled, if wrapped in an <tt class="docutils literal"><img></tt> tag but clipped in an <tt class="docutils literal"><object></tt> tag
+or within SVG.</p>
+</li>
+<li><object class="first align-right" data="../../../docs/user/rst/images/title-scaling.svg" style="width: 50%; height: 1.5em;" type="image/svg+xml">
+../../../docs/user/rst/images/title-scaling.svg</object>
+<p>A right aligned, scaling image 50% wide and 1.5 em high. (This SVG image
+keeps the aspect ratio.)</p>
+</li>
+<li><p class="first">An inline image <object data="../../../docs/user/rst/images/biohazard-scaling.svg" style="height: 0.8em;" type="image/svg+xml">inline-svg</object> scaled to a height of 0.8 em.</p>
+</li>
+<li><object class="first align-right" data="../../../docs/user/rst/images/biohazard-scaling.svg" style="height: 1em;" type="image/svg+xml">
+../../../docs/user/rst/images/biohazard-scaling.svg</object>
+<p>A scaling image 1 em high, right aligned:</p>
+</li>
+<li><p class="first">A scaling image 5 mm x 5 mm, centered, with hyperlink reference:</p>
+<a class="reference internal image-reference" href="#svg-images"><object class="align-center" data="../../../docs/user/rst/images/biohazard-scaling.svg" style="width: 5mm; height: 5mm;" type="image/svg+xml">../../../docs/user/rst/images/biohazard-scaling.svg</object></a>
+</li>
+<li><object class="first align-right" data="../../../docs/user/rst/images/biohazard.svg" style="width: 4cm; height: 2em;" type="image/svg+xml">
+../../../docs/user/rst/images/biohazard.svg</object>
+<p>A fixed-size image in a 4 cm x 2 em box.</p>
+</li>
+</ul>
+<p>Older versions of <cite>webkit</cite> based browsers (chromium, safari, midori,
+konqueror) support the <tt class="docutils literal"><img></tt> tag but don't display contained bitmap
+images in this case.</p>
+<ul>
+<li><object class="first align-right" data="../../../docs/user/rst/images/biohazard-bitmap.svg" style="width: 3em;" type="image/svg+xml">
+../../../docs/user/rst/images/biohazard-bitmap.svg</object>
+<p>A small, fixed-size SVG image with embedded bitmap, The <tt class="docutils literal">:width:</tt> is
+set to 3 em in the rST source. Does not scale if wrapped in <tt class="docutils literal"><object></tt>
+tags.</p>
+</li>
+<li><object class="first align-right" data="../../../docs/user/rst/images/biohazard-bitmap-scaling.svg" style="width: 3em;" type="image/svg+xml">
+../../../docs/user/rst/images/biohazard-bitmap-scaling.svg</object>
+<p>A scaling SVG image with embedded bitmap, 3 em wide.</p>
+</li>
+</ul>
+<p>SVG images can also be put in figures:</p>
+<blockquote>
+<div class="figure align-center">
+<object data="../../../docs/user/rst/images/title.svg" style="width: 290px; height: 28px;" type="image/svg+xml">
+reStructuredText, the markup syntax</object>
+<p class="caption"><strong>Figure:</strong> SVG image in a figure.</p>
+</div>
+</blockquote>
+</div>
+<div class="section" id="swf-images">
+<h2><a class="toc-backref" href="#toc-entry-42">2.25 SWF Images</a></h2>
+<p>Shockwave Flash is an image/movie format that most modern web browsers
+support via a plugin. It is sometimes blocked due to privacy/security
+concerns.</p>
+<p>Images with extension <tt class="docutils literal">.swf</tt> are placed inside <object> elements.
+For complete control over display options use raw HTML.</p>
+<object class="align-left" data="../../../docs/user/rst/images/biohazard.swf" style="width: 4cm; height: 2em;" type="application/x-shockwave-flash">
+[biohazard.swf]</object>
+<p>An SWF image in a 4 cm x 2 em box, left aligned.</p>
+<p>An inline SWF image <object data="../../../docs/user/rst/images/biohazard.swf" style="width: 0.8em; height: 0.8em;" type="application/x-shockwave-flash">inline-swf</object> scaled to 0.8 em x 0.8 em.</p>
+</div>
+</div>
+<div class="section" id="error-handling">
+<h1><a class="toc-backref" href="#toc-entry-43">3 Error Handling</a></h1>
+<p>Any errors caught during processing will generate system messages.</p>
+<p>There should be five messages in the following, auto-generated
+section, "Docutils System Messages":</p>
+<!-- section should be added by Docutils automatically -->
+</div>
+<div class="system-messages section">
+<h1>Docutils System Messages</h1>
+<div class="system-message" id="system-message-1">
+<p class="system-message-title">System Message: ERROR/3 (<tt class="docutils">functional/input/data/standard.txt</tt>, line 104); <em><a href="#problematic-1">backlink</a></em></p>
+Undefined substitution referenced: "problematic".</div>
+<div class="system-message" id="system-message-2">
+<p class="system-message-title">System Message: ERROR/3 (<tt class="docutils">functional/input/data/standard.txt</tt>, line 392); <em><a href="#footnote-reference-8">backlink</a></em></p>
+Unknown target name: "5".</div>
+<div class="system-message" id="system-message-3">
+<p class="system-message-title">System Message: ERROR/3 (<tt class="docutils">functional/input/data/standard.txt</tt>, line 401); <em><a href="#citation-reference-3">backlink</a></em></p>
+Unknown target name: "nonexistent".</div>
+<div class="system-message" id="system-message-4">
+<p class="system-message-title">System Message: ERROR/3 (<tt class="docutils">functional/input/data/standard.txt</tt>, line 428); <em><a href="#problematic-2">backlink</a></em></p>
+Unknown target name: "hyperlink reference without a target".</div>
+<div class="system-message" id="system-message-5">
+<p class="system-message-title">System Message: ERROR/3 (<tt class="docutils">functional/input/data/standard.txt</tt>, line 441); <em><a href="#problematic-3">backlink</a></em></p>
+Duplicate target name, cannot be used as a unique reference: "duplicate target names".</div>
+</div>
+</div>
+<div class="footer">
+<hr class="footer" />
+<p>Document footer</p>
+<p><a class="reference external" href="http://validator.w3.org/check?uri=referer"><img alt="Valid XHTML 1.0!" src="http://www.w3.org/Icons/valid-xhtml10" style="width: 88px; height: 31px;" /></a> <a class="reference external" href="http://jigsaw.w3.org/css-validator/check/referer"><img alt="Valid CSS 2.1!" src="http://jigsaw.w3.org/css-validator/images/vcss" style="width: 88px; height: 31px;" /></a></p>
+
+</div>
+</body>
+</html>
--- /dev/null
+<!DOCTYPE html>
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+<meta charset="utf-8"/>
+<meta name="generator" content="Docutils 0.16: http://docutils.sourceforge.net/" />
+<title>reStructuredText Test Document</title>
+<meta name="author" content="David Goodger" />
+<meta name="author" content="Me" />
+<meta name="author" content="Myself" />
+<meta name="author" content="I" />
+<meta name="dcterms.date" content="Now, or yesterday. Or maybe even before yesterday." />
+<meta name="dcterms.rights" content="This document has been placed in the public domain. You may do with it as you wish. You may copy, modify, redistribute, reattribute, sell, buy, rent, lease, destroy, or improve it, quote it at length, excerpt, incorporate, collate, fold, staple, or mutilate it, or do anything else to it that your or anyone else's heart desires." />
+<meta content="reStructuredText, test, parser" name="keywords" />
+<meta content="A test document, containing at least one example of each reStructuredText construct." lang="en" name="description" xml:lang="en" />
+<link rel="schema.dcterms" href="http://purl.org/dc/terms/">
+<link rel="stylesheet" href="../input/data/minimal.css" type="text/css" />
+<link rel="stylesheet" href="../input/data/plain.css" type="text/css" />
+<link rel="stylesheet" href="../input/data/math.css" type="text/css" />
+</head>
+<body>
+<div class="header">
+<p>Document header</p>
+
+<hr class="header"/>
+</div>
+<div class="document" id="restructuredtext-test-document">
+<span id="doctitle"></span>
+<h1 class="title">reStructuredText Test Document</h1>
+<p class="subtitle" id="examples-of-syntax-constructs"><span id="subtitle"></span>Examples of Syntax Constructs</p>
+<dl class="docinfo">
+<dt class="author">Author</dt>
+<dd class="author"><p>David Goodger</p></dd>
+<dt class="address">Address</dt>
+<dd class="address"><pre class="address">123 Example Street
+Example, EX Canada
+A1B 2C3
+</pre>
+</dd>
+<dt class="contact">Contact</dt>
+<dd class="contact"><a class="reference external" href="mailto:goodger@python.org">goodger@python.org</a></dd>
+<dt class="authors">Authors</dt>
+<dd class="authors"><p>Me</p>
+<p>Myself</p>
+<p>I</p>
+</dd>
+<dt class="organization">Organization</dt>
+<dd class="organization">humankind</dd>
+<dt class="date">Date</dt>
+<dd class="date">Now, or yesterday. Or maybe even <em>before</em> yesterday.</dd>
+<dt class="status">Status</dt>
+<dd class="status">This is a "work in progress"</dd>
+<dt class="revision">Revision</dt>
+<dd class="revision">is managed by a version control system.</dd>
+<dt class="version">Version</dt>
+<dd class="version">1</dd>
+<dt class="copyright">Copyright</dt>
+<dd class="copyright">This document has been placed in the public domain. You
+may do with it as you wish. You may copy, modify,
+redistribute, reattribute, sell, buy, rent, lease,
+destroy, or improve it, quote it at length, excerpt,
+incorporate, collate, fold, staple, or mutilate it, or do
+anything else to it that your or anyone else's heart
+desires.</dd>
+<dt class="field-name">field name</dt>
+<dd class="field-name"><p>This is a "generic bibliographic field".</p>
+</dd>
+<dt class="field-name-2">field name "2"</dt>
+<dd class="field-name-2"><p>Generic bibliographic fields may contain multiple body elements.</p>
+<p>Like this.</p>
+</dd>
+</dl>
+<div class="dedication topic">
+<p class="topic-title">Dedication</p>
+<p>For Docutils users & co-developers.</p>
+</div>
+<div class="abstract topic">
+<p class="topic-title">Abstract</p>
+<p>This is a test document, containing at least one example of each
+reStructuredText construct.</p>
+</div>
+<!-- This is a comment. Note how any initial comments are moved by
+transforms to after the document title, subtitle, and docinfo. -->
+<!-- Above is the document title, and below is the subtitle.
+They are transformed from section titles after parsing. -->
+<!-- bibliographic fields (which also require a transform): -->
+<div class="contents topic" id="table-of-contents">
+<p class="topic-title">Table of Contents</p>
+<ul class="auto-toc simple">
+<li><p><a class="reference internal" href="#structural-elements" id="toc-entry-1"><span class="sectnum">1</span> Structural Elements</a></p>
+<ul class="auto-toc">
+<li><p><a class="reference internal" href="#section-title" id="toc-entry-2"><span class="sectnum">1.1</span> Section Title</a></p></li>
+<li><p><a class="reference internal" href="#empty-section" id="toc-entry-3"><span class="sectnum">1.2</span> Empty Section</a></p></li>
+<li><p><a class="reference internal" href="#transitions" id="toc-entry-4"><span class="sectnum">1.3</span> Transitions</a></p></li>
+</ul>
+</li>
+<li><p><a class="reference internal" href="#body-elements" id="toc-entry-5"><span class="sectnum">2</span> Body Elements</a></p>
+<ul class="auto-toc">
+<li><p><a class="reference internal" href="#paragraphs" id="toc-entry-6"><span class="sectnum">2.1</span> Paragraphs</a></p>
+<ul class="auto-toc">
+<li><p><a class="reference internal" href="#inline-markup" id="toc-entry-7"><span class="sectnum">2.1.1</span> Inline Markup</a></p></li>
+</ul>
+</li>
+<li><p><a class="reference internal" href="#bullet-lists" id="toc-entry-8"><span class="sectnum">2.2</span> Bullet Lists</a></p></li>
+<li><p><a class="reference internal" href="#enumerated-lists" id="toc-entry-9"><span class="sectnum">2.3</span> Enumerated Lists</a></p></li>
+<li><p><a class="reference internal" href="#definition-lists" id="toc-entry-10"><span class="sectnum">2.4</span> Definition Lists</a></p></li>
+<li><p><a class="reference internal" href="#field-lists" id="toc-entry-11"><span class="sectnum">2.5</span> Field Lists</a></p></li>
+<li><p><a class="reference internal" href="#option-lists" id="toc-entry-12"><span class="sectnum">2.6</span> Option Lists</a></p></li>
+<li><p><a class="reference internal" href="#literal-blocks" id="toc-entry-13"><span class="sectnum">2.7</span> Literal Blocks</a></p></li>
+<li><p><a class="reference internal" href="#line-blocks" id="toc-entry-14"><span class="sectnum">2.8</span> Line Blocks</a></p></li>
+<li><p><a class="reference internal" href="#block-quotes" id="toc-entry-15"><span class="sectnum">2.9</span> Block Quotes</a></p></li>
+<li><p><a class="reference internal" href="#doctest-blocks" id="toc-entry-16"><span class="sectnum">2.10</span> Doctest Blocks</a></p></li>
+<li><p><a class="reference internal" href="#footnotes" id="toc-entry-17"><span class="sectnum">2.11</span> Footnotes</a></p></li>
+<li><p><a class="reference internal" href="#citations" id="toc-entry-18"><span class="sectnum">2.12</span> Citations</a></p></li>
+<li><p><a class="reference internal" href="#targets" id="toc-entry-19"><span class="sectnum">2.13</span> Targets</a></p>
+<ul class="auto-toc">
+<li><p><a class="reference internal" href="#duplicate-target-names" id="toc-entry-20"><span class="sectnum">2.13.1</span> Duplicate Target Names</a></p></li>
+<li><p><a class="reference internal" href="#duplicate-target-names-1" id="toc-entry-21"><span class="sectnum">2.13.2</span> Duplicate Target Names</a></p></li>
+</ul>
+</li>
+<li><p><a class="reference internal" href="#directives" id="toc-entry-22"><span class="sectnum">2.14</span> Directives</a></p>
+<ul class="auto-toc">
+<li><p><a class="reference internal" href="#document-parts" id="toc-entry-23"><span class="sectnum">2.14.1</span> Document Parts</a></p></li>
+<li><p><a class="reference internal" href="#images-and-figures" id="toc-entry-24"><span class="sectnum">2.14.2</span> Images and Figures</a></p></li>
+<li><p><a class="reference internal" href="#admonitions" id="toc-entry-25"><span class="sectnum">2.14.3</span> Admonitions</a></p></li>
+<li><p><a class="reference internal" href="#topics-sidebars-and-rubrics" id="toc-entry-26"><span class="sectnum">2.14.4</span> Topics, Sidebars, and Rubrics</a></p></li>
+<li><p><a class="reference internal" href="#target-footnotes" id="toc-entry-27"><span class="sectnum">2.14.5</span> Target Footnotes</a></p></li>
+<li><p><a class="reference internal" href="#replacement-text" id="toc-entry-28"><span class="sectnum">2.14.6</span> Replacement Text</a></p></li>
+<li><p><a class="reference internal" href="#compound-paragraph" id="toc-entry-29"><span class="sectnum">2.14.7</span> Compound Paragraph</a></p></li>
+<li><p><a class="reference internal" href="#parsed-literal-blocks" id="toc-entry-30"><span class="sectnum">2.14.8</span> Parsed Literal Blocks</a></p></li>
+<li><p><a class="reference internal" href="#code" id="toc-entry-31"><span class="sectnum">2.14.9</span> Code</a></p></li>
+</ul>
+</li>
+<li><p><a class="reference internal" href="#substitution-definitions" id="toc-entry-32"><span class="sectnum">2.15</span> Substitution Definitions</a></p></li>
+<li><p><a class="reference internal" href="#comments" id="toc-entry-33"><span class="sectnum">2.16</span> Comments</a></p></li>
+<li><p><a class="reference internal" href="#raw-text" id="toc-entry-34"><span class="sectnum">2.17</span> Raw text</a></p></li>
+<li><p><a class="reference internal" href="#container" id="toc-entry-35"><span class="sectnum">2.18</span> Container</a></p></li>
+<li><p><a class="reference internal" href="#colspanning-tables" id="toc-entry-36"><span class="sectnum">2.19</span> Colspanning tables</a></p></li>
+<li><p><a class="reference internal" href="#rowspanning-tables" id="toc-entry-37"><span class="sectnum">2.20</span> Rowspanning tables</a></p></li>
+<li><p><a class="reference internal" href="#complex-tables" id="toc-entry-38"><span class="sectnum">2.21</span> Complex tables</a></p></li>
+<li><p><a class="reference internal" href="#list-tables" id="toc-entry-39"><span class="sectnum">2.22</span> List Tables</a></p></li>
+<li><p><a class="reference internal" href="#custom-roles" id="toc-entry-40"><span class="sectnum">2.23</span> Custom Roles</a></p></li>
+</ul>
+</li>
+<li><p><a class="reference internal" href="#html-specific" id="toc-entry-41"><span class="sectnum">3</span> HTML specific</a></p>
+<ul class="auto-toc">
+<li><p><a class="reference internal" href="#svg-images" id="toc-entry-42"><span class="sectnum">3.1</span> SVG Images</a></p></li>
+<li><p><a class="reference internal" href="#swf-images" id="toc-entry-43"><span class="sectnum">3.2</span> SWF Images</a></p></li>
+<li><p><a class="reference internal" href="#text-level-semantics" id="toc-entry-44"><span class="sectnum">3.3</span> Text-level semantics</a></p></li>
+<li><p><a class="reference internal" href="#indicating-edits" id="toc-entry-45"><span class="sectnum">3.4</span> Indicating Edits</a></p></li>
+</ul>
+</li>
+<li><p><a class="reference internal" href="#changes-to-the-html4css1-writer" id="toc-entry-46"><span class="sectnum">4</span> Changes to the html4css1 writer</a></p>
+<ul class="auto-toc">
+<li><p><a class="reference internal" href="#field-list-handling" id="toc-entry-47"><span class="sectnum">4.1</span> Field list handling</a></p></li>
+<li><p><a class="reference internal" href="#styling-with-class-arguments" id="toc-entry-48"><span class="sectnum">4.2</span> Styling with class arguments</a></p>
+<ul class="auto-toc">
+<li><p><a class="reference internal" href="#description-lists" id="toc-entry-49"><span class="sectnum">4.2.1</span> Description lists</a></p></li>
+<li><p><a class="reference internal" href="#field-list-variants" id="toc-entry-50"><span class="sectnum">4.2.2</span> Field list variants</a></p></li>
+<li><p><a class="reference internal" href="#table-variants" id="toc-entry-51"><span class="sectnum">4.2.3</span> Table variants</a></p></li>
+</ul>
+</li>
+</ul>
+</li>
+<li><p><a class="reference internal" href="#error-handling" id="toc-entry-52"><span class="sectnum">5</span> Error Handling</a></p></li>
+</ul>
+</div>
+<div class="section" id="structural-elements">
+<h1><a class="toc-backref" href="#toc-entry-1"><span class="sectnum">1</span> Structural Elements</a></h1>
+<div class="section" id="section-title">
+<h2 class="with-subtitle"><a class="toc-backref" href="#toc-entry-2"><span class="sectnum">1.1</span> Section Title</a></h2>
+<p class="section-subtitle" id="section-subtitle">Section Subtitle</p>
+<p>Lone subsections are converted to a section subtitle by a transform
+activated with the <span class="docutils literal"><span class="pre">--section-subtitles</span></span> command line option or the
+<span class="docutils literal"><span class="pre">sectsubtitle-xform</span></span> configuration value.</p>
+</div>
+<div class="section" id="empty-section">
+<h2><a class="toc-backref" href="#toc-entry-3"><span class="sectnum">1.2</span> Empty Section</a></h2>
+</div>
+<div class="section" id="transitions">
+<h2><a class="toc-backref" href="#toc-entry-4"><span class="sectnum">1.3</span> Transitions</a></h2>
+<p>Here's a transition:</p>
+<hr class="docutils" />
+<p>It divides the section. Transitions may also occur between sections:</p>
+</div>
+</div>
+<hr class="docutils" />
+<div class="section" id="body-elements">
+<h1><a class="toc-backref" href="#toc-entry-5"><span class="sectnum">2</span> Body Elements</a></h1>
+<div class="section" id="paragraphs">
+<h2><a class="toc-backref" href="#toc-entry-6"><span class="sectnum">2.1</span> Paragraphs</a></h2>
+<p>A paragraph.</p>
+<div class="section" id="inline-markup">
+<h3><a class="toc-backref" href="#toc-entry-7"><span class="sectnum">2.1.1</span> Inline Markup</a></h3>
+<p>Paragraphs contain text and may contain inline markup: <em>emphasis</em>,
+<strong>strong emphasis</strong>, <span class="docutils literal">inline literals</span>, standalone hyperlinks
+(<a class="reference external" href="http://www.python.org">http://www.python.org</a>), external hyperlinks (<a class="reference external" href="http://www.python.org/">Python</a> <a class="footnote-reference brackets" href="#footnote-7" id="footnote-reference-18">7</a>), internal
+cross-references (<a class="reference internal" href="#example">example</a>), external hyperlinks with embedded URIs
+(<a class="reference external" href="http://www.python.org">Python web site</a>), <a class="reference external" href="http://www.python.org/">anonymous hyperlink
+references</a> <a class="footnote-reference brackets" href="#footnote-7" id="footnote-reference-25">7</a> (<a class="reference external" href="http://docutils.sourceforge.net/">a second reference</a> <a class="footnote-reference brackets" href="#footnote-12" id="footnote-reference-26">12</a>), footnote references (manually
+numbered <a class="footnote-reference brackets" href="#footnote-1" id="footnote-reference-1">1</a>, anonymous auto-numbered <a class="footnote-reference brackets" href="#footnote-2" id="footnote-reference-2">3</a>, labeled auto-numbered
+<a class="footnote-reference brackets" href="#label" id="footnote-reference-3">2</a>, or symbolic <a class="footnote-reference brackets" href="#footnote-3" id="footnote-reference-4">*</a>), citation references (<a class="citation-reference" href="#cit2002" id="citation-reference-1">[CIT2002]</a>),
+substitution references (<img alt="EXAMPLE" src="../../../docs/user/rst/images/biohazard.png" /> &
+a <em>trimmed heart</em> <span class="docutils literal">(U+2665):</span>♥), and <span class="target" id="inline-hyperlink-targets">inline hyperlink targets</span>
+(see <a class="reference internal" href="#targets">Targets</a> below for a reference back to here). Character-level
+inline markup is also possible (although exceedingly ugly!) in <em>re</em><span class="docutils literal">Structured</span><em>Text</em>. Problems are indicated by <a href="#system-message-1"><span class="problematic" id="problematic-1">|problematic|</span></a> text
+(generated by processing errors; this one is intentional). Here is a
+reference to the <a class="reference internal" href="#doctitle">doctitle</a> and the <a class="reference internal" href="#subtitle">subtitle</a>.</p>
+<p>The default role for interpreted text is <cite>Title Reference</cite>. Here are
+some explicit interpreted text roles: a PEP reference (<a class="reference external" href="http://www.python.org/dev/peps/pep-0287">PEP 287</a>); an
+RFC reference (<a class="reference external" href="http://tools.ietf.org/html/rfc2822.html">RFC 2822</a>); an abbreviation (<abbr>abb.</abbr>), an acronym
+(<abbr>reST</abbr>), code (<code>print "hello world"</code>); a <sub>subscript</sub>;
+a <sup>superscript</sup> and explicit roles for <cite>Docutils</cite>'
+<em>standard</em> <strong>inline</strong> <span class="docutils literal">markup</span>.</p>
+<!-- DO NOT RE-WRAP THE FOLLOWING PARAGRAPH! -->
+<p>Let's test wrapping and whitespace significance in inline literals:
+<span class="docutils literal">This is an example of <span class="pre">--inline-literal</span> <span class="pre">--text,</span> <span class="pre">--including</span> <span class="pre">some--</span> <span class="pre">strangely--hyphenated-words.</span> <span class="pre">Adjust-the-width-of-your-browser-window</span> to see how the text is wrapped. <span class="pre">--</span> <span class="pre">----</span> <span class="pre">--------</span> Now note the spacing between the words of this sentence (words should be grouped in pairs).</span></p>
+<p>If the <span class="docutils literal"><span class="pre">--pep-references</span></span> option was supplied, there should be a
+live link to PEP 258 here.</p>
+</div>
+</div>
+<div class="section" id="bullet-lists">
+<h2><a class="toc-backref" href="#toc-entry-8"><span class="sectnum">2.2</span> Bullet Lists</a></h2>
+<ul>
+<li><p>A bullet list</p>
+<ul class="simple">
+<li><p>Nested bullet list.</p></li>
+<li><p>Nested item 2.</p></li>
+</ul>
+</li>
+<li><p>Item 2.</p>
+<p>Paragraph 2 of item 2.</p>
+<ul class="simple">
+<li><p>Nested bullet list.</p></li>
+<li><p>Nested item 2.</p>
+<ul>
+<li><p>Third level.</p></li>
+<li><p>Item 2.</p></li>
+</ul>
+</li>
+<li><p>Nested item 3.</p></li>
+<li><p>This nested list should be compacted by the HTML writer.</p>
+<span class="target" id="target"></span><!-- Even if this item contains a target and a comment. -->
+</li>
+</ul>
+</li>
+</ul>
+</div>
+<div class="section" id="enumerated-lists">
+<h2><a class="toc-backref" href="#toc-entry-9"><span class="sectnum">2.3</span> Enumerated Lists</a></h2>
+<ol class="arabic">
+<li><p>Arabic numerals.</p>
+<ol class="loweralpha simple">
+<li><p>lower alpha)</p>
+<ol class="lowerroman simple">
+<li><p>(lower roman)</p>
+<ol class="upperalpha simple">
+<li><p>upper alpha.</p>
+<ol class="upperroman simple">
+<li><p>upper roman)</p></li>
+</ol>
+</li>
+</ol>
+</li>
+</ol>
+</li>
+</ol>
+</li>
+<li><p>Lists that don't start at 1:</p>
+<ol class="arabic simple" start="3">
+<li><p>Three</p></li>
+<li><p>Four</p></li>
+</ol>
+<ol class="upperalpha simple" start="3">
+<li><p>C</p></li>
+<li><p>D</p></li>
+</ol>
+<ol class="lowerroman simple" start="3">
+<li><p>iii</p></li>
+<li><p>iv</p></li>
+</ol>
+</li>
+</ol>
+</div>
+<div class="section" id="definition-lists">
+<h2><a class="toc-backref" href="#toc-entry-10"><span class="sectnum">2.4</span> Definition Lists</a></h2>
+<dl>
+<dt>Term</dt>
+<dd><p>Definition</p>
+</dd>
+<dt>Term<span class="classifier">classifier</span></dt>
+<dd><p>Definition paragraph 1.</p>
+<p>Definition paragraph 2.</p>
+</dd>
+<dt>Term</dt>
+<dd><p>Definition</p>
+</dd>
+<dt>Term<span class="classifier">classifier one</span><span class="classifier">classifier two</span></dt>
+<dd><p>Definition</p>
+</dd>
+</dl>
+</div>
+<div class="section" id="field-lists">
+<h2><a class="toc-backref" href="#toc-entry-11"><span class="sectnum">2.5</span> Field Lists</a></h2>
+<dl class="field-list">
+<dt>what</dt>
+<dd><p>Field lists map field names to field bodies, like database
+records. They are often part of an extension syntax. They are
+an unambiguous variant of RFC 2822 fields.</p>
+</dd>
+<dt>how arg1 arg2</dt>
+<dd><p>The field marker is a colon, the field name, and a colon.</p>
+<p>The field body may contain one or more body elements, indented
+relative to the field marker.</p>
+</dd>
+<dt>credits</dt>
+<dd><p class="credits">This paragraph has the <cite>credits</cite> class set. (This is actually not
+about credits but just for ensuring that the class attribute
+doesn't get stripped away.)</p>
+</dd>
+</dl>
+</div>
+<div class="section" id="option-lists">
+<h2><a class="toc-backref" href="#toc-entry-12"><span class="sectnum">2.6</span> Option Lists</a></h2>
+<p>For listing command-line options:</p>
+<dl class="option-list">
+<dt><kbd><span class="option">-a</span></kbd></dt>
+<dd><p>command-line option "a"</p>
+</dd>
+<dt><kbd><span class="option">-b <var>file</var></span></kbd></dt>
+<dd><p>options can have arguments
+and long descriptions</p>
+</dd>
+<dt><kbd><span class="option">--long</span></kbd></dt>
+<dd><p>options can be long also</p>
+</dd>
+<dt><kbd><span class="option">--input=<var>file</var></span></kbd></dt>
+<dd><p>long options can also have
+arguments</p>
+</dd>
+<dt><kbd><span class="option">--very-long-option</span></kbd></dt>
+<dd><p>The description can also start on the next line.</p>
+<p>The description may contain multiple body elements,
+regardless of where it starts.</p>
+</dd>
+<dt><kbd><span class="option">-x</span>, <span class="option">-y</span>, <span class="option">-z</span></kbd></dt>
+<dd><p>Multiple options are an "option group".</p>
+</dd>
+<dt><kbd><span class="option">-v</span>, <span class="option">--verbose</span></kbd></dt>
+<dd><p>Commonly-seen: short & long options.</p>
+</dd>
+<dt><kbd><span class="option">-1 <var>file</var></span>, <span class="option">--one=<var>file</var></span>, <span class="option">--two <var>file</var></span></kbd></dt>
+<dd><p>Multiple options with arguments.</p>
+</dd>
+<dt><kbd><span class="option">/V</span></kbd></dt>
+<dd><p>DOS/VMS-style options too</p>
+</dd>
+</dl>
+<p>There must be at least two spaces between the option and the
+description.</p>
+</div>
+<div class="section" id="literal-blocks">
+<h2><a class="toc-backref" href="#toc-entry-13"><span class="sectnum">2.7</span> Literal Blocks</a></h2>
+<p>Literal blocks are indicated with a double-colon ("::") at the end of
+the preceding paragraph (over there <span class="docutils literal"><span class="pre">--></span></span>). They can be indented:</p>
+<pre class="literal-block">if literal_block:
+ text = 'is left as-is'
+ spaces_and_linebreaks = 'are preserved'
+ markup_processing = None</pre>
+<p>Or they can be quoted without indentation:</p>
+<pre class="literal-block">>> Great idea!
+>
+> Why didn't I think of that?</pre>
+</div>
+<div class="section" id="line-blocks">
+<h2><a class="toc-backref" href="#toc-entry-14"><span class="sectnum">2.8</span> Line Blocks</a></h2>
+<p>This section tests line blocks. Line blocks are body elements which
+consist of lines and other line blocks. Nested line blocks cause
+indentation.</p>
+<div class="line-block">
+<div class="line">This is a line block. It ends with a blank line.</div>
+<div class="line-block">
+<div class="line">New lines begin with a vertical bar ("|").</div>
+<div class="line">Line breaks and initial indent are significant, and preserved.</div>
+<div class="line-block">
+<div class="line">Continuation lines are also possible. A long line that is intended
+to wrap should begin with a space in place of the vertical bar.</div>
+</div>
+<div class="line">The left edge of a continuation line need not be aligned with
+the left edge of the text above it.</div>
+</div>
+</div>
+<div class="line-block">
+<div class="line">This is a second line block.</div>
+<div class="line"><br /></div>
+<div class="line">Blank lines are permitted internally, but they must begin with a "|".</div>
+</div>
+<p>Another line block, surrounded by paragraphs:</p>
+<div class="line-block">
+<div class="line">And it's no good waiting by the window</div>
+<div class="line">It's no good waiting for the sun</div>
+<div class="line">Please believe me, the things you dream of</div>
+<div class="line">They don't fall in the lap of no-one</div>
+</div>
+<p>Take it away, Eric the Orchestra Leader!</p>
+<blockquote>
+<div class="line-block">
+<div class="line">A one, two, a one two three four</div>
+<div class="line"><br /></div>
+<div class="line">Half a bee, philosophically,</div>
+<div class="line-block">
+<div class="line">must, <em>ipso facto</em>, half not be.</div>
+</div>
+<div class="line">But half the bee has got to be,</div>
+<div class="line-block">
+<div class="line"><em>vis a vis</em> its entity. D'you see?</div>
+<div class="line"><br /></div>
+</div>
+<div class="line">But can a bee be said to be</div>
+<div class="line-block">
+<div class="line">or not to be an entire bee,</div>
+<div class="line-block">
+<div class="line">when half the bee is not a bee,</div>
+<div class="line-block">
+<div class="line">due to some ancient injury?</div>
+<div class="line"><br /></div>
+</div>
+</div>
+</div>
+<div class="line">Singing...</div>
+</div>
+</blockquote>
+<p>A line block, like the following poem by Christian Morgenstern, can
+also be centre-aligned:</p>
+<div class="align-center line-block" lang="de">
+<div class="line"><strong>Die Trichter</strong></div>
+<div class="line"><br /></div>
+<div class="line">Zwei Trichter wandeln durch die Nacht.</div>
+<div class="line">Durch ihres Rumpfs verengten Schacht</div>
+<div class="line">fließt weißes Mondlicht</div>
+<div class="line">still und heiter</div>
+<div class="line">auf ihren</div>
+<div class="line">Waldweg</div>
+<div class="line">u. s.</div>
+<div class="line">w.</div>
+<div class="line"><br /></div>
+</div>
+</div>
+<div class="section" id="block-quotes">
+<h2><a class="toc-backref" href="#toc-entry-15"><span class="sectnum">2.9</span> Block Quotes</a></h2>
+<p>Block quotes consist of indented body elements:</p>
+<blockquote>
+<p>My theory by A. Elk. Brackets Miss, brackets. This theory goes
+as follows and begins now. All brontosauruses are thin at one
+end, much much thicker in the middle and then thin again at the
+far end. That is my theory, it is mine, and belongs to me and I
+own it, and what it is too.</p>
+<p class="attribution">—Anne Elk (Miss)</p>
+</blockquote>
+<p>The language of a quote (like any other object) can be specified by
+a class attribute:</p>
+<!-- -->
+<blockquote lang="fr">
+<p>ReStructuredText est un langage de balisage léger utilisé
+notamment dans la documentation du langage Python.</p>
+</blockquote>
+</div>
+<div class="section" id="doctest-blocks">
+<h2><a class="toc-backref" href="#toc-entry-16"><span class="sectnum">2.10</span> Doctest Blocks</a></h2>
+<pre class="code python doctest">>>> print 'Python-specific usage examples; begun with ">>>"'
+Python-specific usage examples; begun with ">>>"
+>>> print '(cut and pasted from interactive Python sessions)'
+(cut and pasted from interactive Python sessions)
+</pre>
+</div>
+<div class="section" id="footnotes">
+<h2><a class="toc-backref" href="#toc-entry-17"><span class="sectnum">2.11</span> Footnotes</a></h2>
+<dl class="footnote brackets">
+<dt class="label" id="footnote-1"><span class="brackets">1</span><span class="fn-backref">(<a href="#footnote-reference-1">1</a>,<a href="#footnote-reference-5">2</a>,<a href="#footnote-reference-9">3</a>)</span></dt>
+<dd><p>A footnote contains body elements, consistently indented by at
+least 3 spaces.</p>
+<p>This is the footnote's second paragraph.</p>
+</dd>
+<dt class="label" id="label"><span class="brackets">2</span><span class="fn-backref">(<a href="#footnote-reference-3">1</a>,<a href="#footnote-reference-6">2</a>)</span></dt>
+<dd><p>Footnotes may be numbered, either manually (as in <a class="footnote-reference brackets" href="#footnote-1" id="footnote-reference-5">1</a>) or
+automatically using a "#"-prefixed label. This footnote has a
+label so it can be referred to from multiple places, both as a
+footnote reference (<a class="footnote-reference brackets" href="#label" id="footnote-reference-6">2</a>) and as a <a class="reference internal" href="#label">hyperlink reference</a>.</p>
+</dd>
+<dt class="label" id="footnote-2"><span class="brackets"><a class="fn-backref" href="#footnote-reference-2">3</a></span></dt>
+<dd><p>This footnote is numbered automatically and anonymously using a
+label of "#" only.</p>
+<p>This is the second paragraph.</p>
+<p>And this is the third paragraph.</p>
+</dd>
+<dt class="label" id="footnote-3"><span class="brackets"><a class="fn-backref" href="#footnote-reference-4">*</a></span></dt>
+<dd><p>Footnotes may also use symbols, specified with a "*" label.
+Here's a reference to the next footnote: <a class="footnote-reference brackets" href="#footnote-4" id="footnote-reference-7">†</a>.</p>
+</dd>
+<dt class="label" id="footnote-4"><span class="brackets"><a class="fn-backref" href="#footnote-reference-7">†</a></span></dt>
+<dd><p>This footnote shows the next symbol in the sequence.</p>
+</dd>
+<dt class="label" id="footnote-5"><span class="brackets">4</span></dt>
+<dd><p>Here's an unreferenced footnote, with a reference to a
+nonexistent footnote: <a href="#system-message-2"><span class="problematic" id="footnote-reference-8">[5]_</span></a>.</p>
+</dd>
+</dl>
+</div>
+<div class="section" id="citations">
+<h2><a class="toc-backref" href="#toc-entry-18"><span class="sectnum">2.12</span> Citations</a></h2>
+<dl class="citation">
+<dt class="label" id="cit2002"><span class="brackets">CIT2002</span><span class="fn-backref">(<a href="#citation-reference-1">1</a>,<a href="#citation-reference-2">2</a>)</span></dt>
+<dd><p>Citations are text-labeled footnotes. They may be
+rendered separately and differently from footnotes.</p>
+</dd>
+</dl>
+<p>Here's a reference to the above, <a class="citation-reference" href="#cit2002" id="citation-reference-2">[CIT2002]</a>, and a <a href="#system-message-3"><span class="problematic" id="citation-reference-3">[nonexistent]_</span></a>
+citation.</p>
+</div>
+<div class="section" id="targets">
+<span id="another-target"></span><h2><a class="toc-backref" href="#toc-entry-19"><span class="sectnum">2.13</span> Targets</a></h2>
+<p id="example">This paragraph is pointed to by the explicit "example" target. A
+reference can be found under <a class="reference internal" href="#inline-markup">Inline Markup</a>, above. <a class="reference internal" href="#inline-hyperlink-targets">Inline
+hyperlink targets</a> are also possible.</p>
+<p>Section headers are implicit targets, referred to by name. See
+<a class="reference internal" href="#targets">Targets</a>, which is a subsection of <a class="reference internal" href="#body-elements">Body Elements</a>.</p>
+<p>Explicit external targets are interpolated into references such as
+"<a class="reference external" href="http://www.python.org/">Python</a> <a class="footnote-reference brackets" href="#footnote-7" id="footnote-reference-19">7</a>".</p>
+<p>Targets may be indirect and anonymous. Thus <a class="reference internal" href="#targets">this phrase</a> may also
+refer to the <a class="reference internal" href="#targets">Targets</a> section.</p>
+<p>Here's a <a href="#system-message-4"><span class="problematic" id="problematic-2">`hyperlink reference without a target`_</span></a>, which generates an
+error.</p>
+<div class="section" id="duplicate-target-names">
+<h3><a class="toc-backref" href="#toc-entry-20"><span class="sectnum">2.13.1</span> Duplicate Target Names</a></h3>
+<p>Duplicate names in section headers or other implicit targets will
+generate "info" (level-1) system messages. Duplicate names in
+explicit targets will generate "warning" (level-2) system messages.</p>
+</div>
+<div class="section" id="duplicate-target-names-1">
+<h3><a class="toc-backref" href="#toc-entry-21"><span class="sectnum">2.13.2</span> Duplicate Target Names</a></h3>
+<p>Since there are two "Duplicate Target Names" section headers, we
+cannot uniquely refer to either of them by name. If we try to (like
+this: <a href="#system-message-5"><span class="problematic" id="problematic-3">`Duplicate Target Names`_</span></a>), an error is generated.</p>
+</div>
+</div>
+<div class="section" id="directives">
+<h2><a class="toc-backref" href="#toc-entry-22"><span class="sectnum">2.14</span> Directives</a></h2>
+<div class="contents local topic" id="contents">
+<ul class="auto-toc simple">
+<li><p><a class="reference internal" href="#document-parts" id="toc-entry-53"><span class="sectnum">2.14.1</span> Document Parts</a></p></li>
+<li><p><a class="reference internal" href="#images-and-figures" id="toc-entry-54"><span class="sectnum">2.14.2</span> Images and Figures</a></p></li>
+<li><p><a class="reference internal" href="#admonitions" id="toc-entry-55"><span class="sectnum">2.14.3</span> Admonitions</a></p></li>
+<li><p><a class="reference internal" href="#topics-sidebars-and-rubrics" id="toc-entry-56"><span class="sectnum">2.14.4</span> Topics, Sidebars, and Rubrics</a></p></li>
+<li><p><a class="reference internal" href="#target-footnotes" id="toc-entry-57"><span class="sectnum">2.14.5</span> Target Footnotes</a></p></li>
+<li><p><a class="reference internal" href="#replacement-text" id="toc-entry-58"><span class="sectnum">2.14.6</span> Replacement Text</a></p></li>
+<li><p><a class="reference internal" href="#compound-paragraph" id="toc-entry-59"><span class="sectnum">2.14.7</span> Compound Paragraph</a></p></li>
+<li><p><a class="reference internal" href="#parsed-literal-blocks" id="toc-entry-60"><span class="sectnum">2.14.8</span> Parsed Literal Blocks</a></p></li>
+<li><p><a class="reference internal" href="#code" id="toc-entry-61"><span class="sectnum">2.14.9</span> Code</a></p></li>
+</ul>
+</div>
+<p>These are just a sample of the many reStructuredText Directives. For
+others, please see
+<a class="reference external" href="http://docutils.sourceforge.net/docs/ref/rst/directives.html">http://docutils.sourceforge.net/docs/ref/rst/directives.html</a>.</p>
+<div class="section" id="document-parts">
+<h3><a class="toc-backref" href="#toc-entry-53"><span class="sectnum">2.14.1</span> Document Parts</a></h3>
+<p>An example of the "contents" directive can be seen above this section
+(a local, untitled table of <a class="reference internal" href="#contents">contents</a>) and at the beginning of the
+document (a document-wide <a class="reference internal" href="#table-of-contents">table of contents</a>).</p>
+</div>
+<div class="section" id="images-and-figures">
+<h3><a class="toc-backref" href="#toc-entry-54"><span class="sectnum">2.14.2</span> Images and Figures</a></h3>
+<p>An image directive (also clickable -- a hyperlink reference):</p>
+<a class="reference internal image-reference" href="#directives"><img alt="../../../docs/user/rst/images/title.png" class="class1 class2" src="../../../docs/user/rst/images/title.png" /></a>
+<p>Image with multiple IDs:</p>
+<span id="image-target-2"></span><span id="image-target-1"></span><img alt="../../../docs/user/rst/images/title.png" id="image-target-3" src="../../../docs/user/rst/images/title.png" />
+<p>A centered image:</p>
+<img alt="../../../docs/user/rst/images/biohazard.png" class="align-center" src="../../../docs/user/rst/images/biohazard.png" />
+<p>A left-aligned image:</p>
+<img alt="../../../docs/user/rst/images/biohazard.png" class="align-left" src="../../../docs/user/rst/images/biohazard.png" />
+<p>This paragraph might flow around the image.
+The specific behavior depends upon the style sheet and
+the browser or rendering software used.</p>
+<p>A right-aligned image:</p>
+<img alt="../../../docs/user/rst/images/biohazard.png" class="align-right" src="../../../docs/user/rst/images/biohazard.png" />
+<p>This paragraph might flow around the image.
+The specific behavior depends upon the style sheet and
+the browser or rendering software used.</p>
+<p>For inline images see <a class="reference internal" href="#substitution-definitions">Substitution Definitions</a>.</p>
+<p>Image size:</p>
+<p>An image 2 em wide:</p>
+<img alt="../../../docs/user/rst/images/biohazard.png" src="../../../docs/user/rst/images/biohazard.png" style="width: 2em;" />
+<p>An image 2 em wide and 15 pixel high:</p>
+<img alt="../../../docs/user/rst/images/biohazard.png" src="../../../docs/user/rst/images/biohazard.png" style="width: 2em; height: 15px;" />
+<p>An image occupying 50% of the line width:</p>
+<img alt="../../../docs/user/rst/images/title.png" src="../../../docs/user/rst/images/title.png" style="width: 50%;" />
+<p>An image 2 cm high:</p>
+<img alt="../../../docs/user/rst/images/biohazard.png" src="../../../docs/user/rst/images/biohazard.png" style="height: 2cm;" />
+<p>A <em>figure</em> is an image with a caption and/or a legend. With page-based output
+media, figures might float to a different position if this helps the page
+layout.</p>
+<div class="figclass1 figclass2 figure">
+<img alt="reStructuredText, the markup syntax" class="class1 class2" src="../../../docs/user/rst/images/title.png" style="width: 258px;" />
+<p class="caption">Plaintext markup syntax and parser system.</p>
+<div class="legend">
+<table>
+<colgroup>
+<col style="width: 20%" />
+<col style="width: 80%" />
+</colgroup>
+<tbody>
+<tr><td><p>re</p></td>
+<td><p>Revised, revisited, based on 're' module.</p></td>
+</tr>
+<tr><td><p>Structured</p></td>
+<td><p>Structure-enhanced text, structuredtext.</p></td>
+</tr>
+<tr><td><p>Text</p></td>
+<td><p>Well it is, isn't it?</p></td>
+</tr>
+</tbody>
+</table>
+<p>This paragraph is also part of the legend.</p>
+</div>
+</div>
+<p>A left-aligned figure:</p>
+<div class="figclass1 figclass2 figure align-left" style="width: 70%">
+<img alt="reStructuredText, the markup syntax" class="class1 class2" src="../../../docs/user/rst/images/biohazard.png" style="width: 40px;" />
+<p class="caption">This is the caption.</p>
+<div class="legend">
+<p>This is the legend.</p>
+<p>The legend may consist of several paragraphs.</p>
+</div>
+</div>
+<p>This paragraph might flow around the figure.</p>
+<p>The specific behavior depends upon the style sheet and the browser or
+rendering software used.</p>
+<p>A centered figure:</p>
+<div class="figure align-center">
+<img alt="../../../docs/user/rst/images/biohazard.png" src="../../../docs/user/rst/images/biohazard.png" style="width: 40px;" />
+<p class="caption">This is the caption.</p>
+<div class="legend">
+<p>This is the legend.</p>
+<p>The legend may consist of several paragraphs.</p>
+</div>
+</div>
+<p>This paragraph might flow around the figure.</p>
+<p>The specific behavior depends upon the style sheet and the browser or
+rendering software used.</p>
+<p>A right-aligned figure:</p>
+<div class="figure align-right">
+<img alt="../../../docs/user/rst/images/biohazard.png" src="../../../docs/user/rst/images/biohazard.png" style="width: 40px;" />
+<p class="caption">This is the caption.</p>
+<div class="legend">
+<p>This is the legend.</p>
+<p>The legend may consist of several paragraphs.</p>
+</div>
+</div>
+<p>This paragraph might flow around the figure. The specific behavior depends
+upon the style sheet and the browser or rendering software used.</p>
+<p>Tables may be given titles and additional arguments with the <em>table</em>
+directive:</p>
+<table class="align-left">
+<caption>left-aligned table</caption>
+<colgroup>
+<col style="width: 50%" />
+<col style="width: 50%" />
+</colgroup>
+<thead>
+<tr><th class="head"><p>A</p></th>
+<th class="head"><p>not A</p></th>
+</tr>
+</thead>
+<tbody>
+<tr><td><p>False</p></td>
+<td><p>True</p></td>
+</tr>
+<tr><td><p>True</p></td>
+<td><p>False</p></td>
+</tr>
+</tbody>
+</table>
+<table class="align-center">
+<caption>center-aligned table</caption>
+<colgroup>
+<col style="width: 50%" />
+<col style="width: 50%" />
+</colgroup>
+<thead>
+<tr><th class="head"><p>A</p></th>
+<th class="head"><p>not A</p></th>
+</tr>
+</thead>
+<tbody>
+<tr><td><p>False</p></td>
+<td><p>True</p></td>
+</tr>
+<tr><td><p>True</p></td>
+<td><p>False</p></td>
+</tr>
+</tbody>
+</table>
+<table class="align-right">
+<caption>right-aligned table</caption>
+<colgroup>
+<col style="width: 50%" />
+<col style="width: 50%" />
+</colgroup>
+<thead>
+<tr><th class="head"><p>A</p></th>
+<th class="head"><p>not A</p></th>
+</tr>
+</thead>
+<tbody>
+<tr><td><p>False</p></td>
+<td><p>True</p></td>
+</tr>
+<tr><td><p>True</p></td>
+<td><p>False</p></td>
+</tr>
+</tbody>
+</table>
+<p>With the "widths" argument "auto" (or "class" value "colwidths-auto"),
+column widths are determined by the backend (if supported by the
+writer/backend).</p>
+<span id="target1"></span><table class="colwidths-auto" id="target2">
+<thead>
+<tr><th class="head"><p>A</p></th>
+<th class="head"><p>B</p></th>
+<th class="head"><p>A or B</p></th>
+</tr>
+</thead>
+<tbody>
+<tr><td><p>False</p></td>
+<td><p>False</p></td>
+<td><p>False</p></td>
+</tr>
+<tr><td><p>True</p></td>
+<td><p>False</p></td>
+<td><p>True</p></td>
+</tr>
+<tr><td><p>False</p></td>
+<td><p>True</p></td>
+<td><p>True</p></td>
+</tr>
+<tr><td><p>True</p></td>
+<td><p>True</p></td>
+<td><p>True</p></td>
+</tr>
+</tbody>
+</table>
+</div>
+<div class="section" id="admonitions">
+<h3><a class="toc-backref" href="#toc-entry-55"><span class="sectnum">2.14.3</span> Admonitions</a></h3>
+<div class="admonition attention">
+<p class="admonition-title">Attention!</p>
+<p>Directives at large.</p>
+</div>
+<div class="admonition caution">
+<p class="admonition-title">Caution!</p>
+<p>Don't take any wooden nickels.</p>
+</div>
+<div class="admonition danger">
+<p class="admonition-title">!DANGER!</p>
+<p>Mad scientist at work!</p>
+</div>
+<div class="admonition error">
+<p class="admonition-title">Error</p>
+<p>Does not compute.</p>
+</div>
+<div class="admonition hint">
+<p class="admonition-title">Hint</p>
+<p>It's bigger than a bread box.</p>
+</div>
+<div class="admonition important">
+<p class="admonition-title">Important</p>
+<ul class="simple">
+<li><p>Wash behind your ears.</p></li>
+<li><p>Clean up your room.</p></li>
+<li><p>Call your mother.</p></li>
+<li><p>Back up your data.</p></li>
+</ul>
+</div>
+<div class="admonition note">
+<p class="admonition-title">Note</p>
+<p>This is a note.</p>
+</div>
+<div class="admonition tip">
+<p class="admonition-title">Tip</p>
+<p>15% if the service is good.</p>
+</div>
+<div class="admonition warning">
+<p class="admonition-title">Warning</p>
+<p>Strong prose may provoke extreme mental exertion.
+Reader discretion is strongly advised.</p>
+</div>
+<div class="admonition admonition-and-by-the-way">
+<p class="admonition-title">And, by the way...</p>
+<p>You can make up your own admonition too.</p>
+</div>
+</div>
+<div class="section" id="topics-sidebars-and-rubrics">
+<h3><a class="toc-backref" href="#toc-entry-56"><span class="sectnum">2.14.4</span> Topics, Sidebars, and Rubrics</a></h3>
+<p><em>Sidebars</em> are like miniature, parallel documents.</p>
+<div class="sidebar">
+<p class="sidebar-title">Sidebar Title</p>
+<p class="sidebar-subtitle">Optional Subtitle</p>
+<p>This is a sidebar. It is for text outside the flow of the main
+text.</p>
+<p class="rubric">This is a rubric inside a sidebar</p>
+<p>Sidebars often appear beside the main text with a border and a different
+background or font color.</p>
+</div>
+<p>A <em>topic</em> is like a block quote with a title, or a self-contained section
+with no subsections.</p>
+<div class="topic">
+<p class="topic-title">Topic Title</p>
+<p>This is a topic.</p>
+</div>
+<p>A <em>rubric</em> is like an informal heading that doesn't correspond to the
+document's structure. It is typically highlighted in red (hence the name).</p>
+<p class="rubric">This is a rubric</p>
+<p>Topics and rubrics can be used at places where a <a class="reference internal" href="#section-title">section title</a> is not
+allowed (e.g. inside a directive).</p>
+</div>
+<div class="section" id="target-footnotes">
+<h3><a class="toc-backref" href="#toc-entry-57"><span class="sectnum">2.14.5</span> Target Footnotes</a></h3>
+<dl class="footnote brackets">
+<dt class="label" id="footnote-7"><span class="brackets">7</span><span class="fn-backref">(<a href="#footnote-reference-18">1</a>,<a href="#footnote-reference-19">2</a>,<a href="#footnote-reference-20">3</a>,<a href="#footnote-reference-25">4</a>)</span></dt>
+<dd><p><a class="reference external" href="http://www.python.org/">http://www.python.org/</a></p>
+</dd>
+<dt class="label" id="footnote-8"><span class="brackets"><a class="fn-backref" href="#footnote-reference-21">8</a></span></dt>
+<dd><p><a class="reference external" href="http://pygments.org/">http://pygments.org/</a></p>
+</dd>
+<dt class="label" id="footnote-9"><span class="brackets"><a class="fn-backref" href="#footnote-reference-22">9</a></span></dt>
+<dd><p><a class="reference external" href="http://docutils.sourceforge.net/docs/dev/todo.html#interpreted-text">http://docutils.sourceforge.net/docs/dev/todo.html#interpreted-text</a></p>
+</dd>
+<dt class="label" id="footnote-10"><span class="brackets"><a class="fn-backref" href="#footnote-reference-23">10</a></span></dt>
+<dd><p><a class="reference external" href="http://docutils.sourceforge.net/docs/user/config.html#table-style">http://docutils.sourceforge.net/docs/user/config.html#table-style</a></p>
+</dd>
+<dt class="label" id="footnote-11"><span class="brackets"><a class="fn-backref" href="#footnote-reference-24">11</a></span></dt>
+<dd><p><a class="reference external" href="http://tug.ctan.org/tex-archive/macros/latex/contrib/booktabs/booktabs.pdf">http://tug.ctan.org/tex-archive/macros/latex/contrib/booktabs/booktabs.pdf</a></p>
+</dd>
+<dt class="label" id="footnote-12"><span class="brackets"><a class="fn-backref" href="#footnote-reference-26">12</a></span></dt>
+<dd><p><a class="reference external" href="http://docutils.sourceforge.net/">http://docutils.sourceforge.net/</a></p>
+</dd>
+<dt class="label" id="footnote-13"><span class="brackets"><a class="fn-backref" href="#footnote-reference-27">13</a></span></dt>
+<dd><p><a class="reference external" href="https://html.spec.whatwg.org/#text-level-semantics">https://html.spec.whatwg.org/#text-level-semantics</a></p>
+</dd>
+<dt class="label" id="footnote-14"><span class="brackets"><a class="fn-backref" href="#footnote-reference-28">14</a></span></dt>
+<dd><p><a class="reference external" href="https://html.spec.whatwg.org/multipage/edits.html">https://html.spec.whatwg.org/multipage/edits.html</a></p>
+</dd>
+</dl>
+</div>
+<div class="section" id="replacement-text">
+<h3><a class="toc-backref" href="#toc-entry-58"><span class="sectnum">2.14.6</span> Replacement Text</a></h3>
+<p>I recommend you try <a class="reference external" href="http://www.python.org/">Python, <em>the</em> best language around</a> <a class="footnote-reference brackets" href="#footnote-7" id="footnote-reference-20">7</a>.</p>
+</div>
+<div class="section" id="compound-paragraph">
+<h3><a class="toc-backref" href="#toc-entry-59"><span class="sectnum">2.14.7</span> Compound Paragraph</a></h3>
+<p>The <em>compound</em> directive is used to create a "compound paragraph", which
+is a single logical paragraph containing multiple physical body
+elements. For example:</p>
+<div class="compound">
+<p class="compound-first">The 'rm' command is very dangerous. If you are logged
+in as root and enter</p>
+<pre class="compound-middle literal-block">cd /
+rm -rf *</pre>
+<p class="compound-last">you will erase the entire contents of your file system.</p>
+</div>
+<p>Test the handling and display of compound paragraphs:</p>
+<div class="some-class compound">
+<p class="compound-first">Compound 2, paragraph 1,</p>
+<p class="compound-middle">compound 2, paragraph 2,</p>
+<ul class="compound-middle simple">
+<li><p>list item 1,</p></li>
+<li><p>list item 2,</p></li>
+</ul>
+<p class="compound-last">compound 2, paragraph 3.</p>
+</div>
+<div class="compound">
+<p>Compound 3, only consisting of one paragraph.</p>
+</div>
+<div class="compound">
+<pre class="compound-first literal-block">Compound 4.
+This one starts with a literal block.</pre>
+<p class="compound-last">Compound 4, paragraph following the literal block.</p>
+</div>
+<p>Now something <em>really</em> perverted -- a nested compound block. This is
+just to test that it works at all; the results don't have to be
+meaningful.</p>
+<div class="compound">
+<p class="compound-first">Compound 5, block 1 (a paragraph).</p>
+<div class="compound-middle compound">
+<p class="compound-first">Compound 6 is block 2 in compound 5.</p>
+<p class="compound-last">Compound 6, another paragraph.</p>
+</div>
+<p class="compound-last">Compound 5, block 3 (a paragraph).</p>
+</div>
+<div class="compound">
+<p class="compound-first">Compound 7, tests the inclusion of various block-level
+elements in one logical paragraph. First a table,</p>
+<table class="compound-middle">
+<colgroup>
+<col style="width: 33%" />
+<col style="width: 33%" />
+<col style="width: 33%" />
+</colgroup>
+<tbody>
+<tr><td><p>Left cell, first
+paragraph.</p>
+<p>Left cell, second
+paragraph.</p>
+</td>
+<td><p>Middle cell,
+consisting of
+exactly one
+paragraph.</p></td>
+<td><p>Right cell.</p>
+<p>Paragraph 2.</p>
+<p>Paragraph 3.</p>
+</td>
+</tr>
+</tbody>
+</table>
+<p class="compound-middle">followed by a paragraph. This physical paragraph is
+actually a continuation of the paragraph before the table. It is followed
+by</p>
+<blockquote class="compound-middle">
+<p>a quote and</p>
+</blockquote>
+<ol class="compound-middle arabic simple">
+<li><p>an enumerated list,</p></li>
+</ol>
+<p class="compound-middle">a paragraph,</p>
+<dl class="compound-middle option-list">
+<dt><kbd><span class="option">--an</span></kbd></dt>
+<dd><p>option list,</p>
+</dd>
+</dl>
+<p class="compound-middle">a paragraph,</p>
+<dl class="compound-middle field-list simple">
+<dt>a field</dt>
+<dd><p>list,</p>
+</dd>
+</dl>
+<p class="compound-middle">a paragraph,</p>
+<dl class="compound-middle simple">
+<dt>a definition</dt>
+<dd><p>list,</p>
+</dd>
+</dl>
+<p class="compound-middle">a paragraph, an image:</p>
+<img alt="../../../docs/user/rst/images/biohazard.png" class="compound-middle" src="../../../docs/user/rst/images/biohazard.png" />
+<p class="compound-middle">a paragraph,</p>
+<div class="compound-middle line-block">
+<div class="line">a line</div>
+<div class="line">block,</div>
+</div>
+<p class="compound-middle">a paragraph followed by a comment,</p>
+<!-- this is a comment -->
+<p class="compound-middle">a paragraph, a</p>
+<div class="admonition note compound-middle">
+<p class="admonition-title">Note</p>
+<p>with content</p>
+</div>
+<p class="compound-last">and the final paragraph of the compound 7.</p>
+</div>
+</div>
+<div class="section" id="parsed-literal-blocks">
+<h3><a class="toc-backref" href="#toc-entry-60"><span class="sectnum">2.14.8</span> Parsed Literal Blocks</a></h3>
+<pre class="literal-block">This is a parsed literal block.
+ This line is indented. The next line is blank.
+
+Inline markup is supported, e.g. <em>emphasis</em>, <strong>strong</strong>, <span class="docutils literal">literal
+text</span>, <sub>sub-</sub> and <sup>super</sup>scripts,
+inline formulas: <span class="formula"><i>A</i> = 2<i>π</i><i>r</i><sup>2</sup></span>,
+footnotes <a class="footnote-reference brackets" href="#footnote-1" id="footnote-reference-9">1</a>, <span class="target" id="hyperlink-targets">hyperlink targets</span>, and <a class="reference external" href="http://www.python.org/">references</a>.</pre>
+</div>
+<div class="section" id="code">
+<h3><a class="toc-backref" href="#toc-entry-61"><span class="sectnum">2.14.9</span> Code</a></h3>
+<p>Blocks of source code can be set with the <cite>code</cite> directive. If the code
+language is specified, the content is parsed and tagged by the <a class="reference external" href="http://pygments.org/">Pygments</a> <a class="footnote-reference brackets" href="#footnote-8" id="footnote-reference-21">8</a>
+syntax highlighter and can be formatted with a style sheet. (Code parsing
+is turned off using the <span class="docutils literal"><span class="pre">syntax-highlight</span></span> config setting in the test
+conversions in order to get identical results with/without installed
+Pygments highlighter.)</p>
+<pre class="code python literal-block"><code>print 'This is Python code.'</code></pre>
+<p>The <span class="docutils literal"><span class="pre">:number-lines:</span></span> option (with optional start value) generates line
+numbers:</p>
+<pre class="code python literal-block"><code><span class="ln"> 8 </span># print integers from 0 to 9:
+<span class="ln"> 9 </span>for i in range(10):
+<span class="ln">10 </span> print i</code></pre>
+<p>For inline code snippets, there is the <cite>code</cite> role, which can be used
+directly (the code will not be parsed/tagged, as the language is not known)
+or as base for special code roles, e.g. the LaTeX code in the next
+paragraph.</p>
+<p>Docutils uses LaTeX syntax for math directives and roles:
+<code class="tex">\alpha = f(x)</code> prints <span class="formula"><i>α</i> = <i>f</i>(<i>x</i>)</span>.</p>
+<p>The <span class="docutils literal">:code:</span> option of the <cite>include</cite> directive sets the included content
+as a code block, here the rst file <span class="docutils literal">header_footer.txt</span> with line numbers:</p>
+<pre class="code rst literal-block"><code><span class="ln">1 </span>.. header:: Document header
+<span class="ln">2 </span>.. footer:: Document footer</code></pre>
+</div>
+</div>
+<div class="section" id="substitution-definitions">
+<h2><a class="toc-backref" href="#toc-entry-32"><span class="sectnum">2.15</span> Substitution Definitions</a></h2>
+<p>An inline image (<img alt="EXAMPLE" src="../../../docs/user/rst/images/biohazard.png" />) example:</p>
+<p>A Unicode example:</p>
+<p>(Substitution definitions are not visible in the HTML source.)</p>
+</div>
+<div class="section" id="comments">
+<h2><a class="toc-backref" href="#toc-entry-33"><span class="sectnum">2.16</span> Comments</a></h2>
+<p>Here's one:</p>
+<!-- Comments begin with two dots and a space. Anything may
+follow, except for the syntax of footnotes, hyperlink
+targets, directives, or substitution definitions.
+
+Double-dashes - - "- -" - - must be escaped somehow in HTML output.
+
+Comments may contain non-ASCII characters: ä ö ü æ ø å -->
+<p>(View the HTML source to see the comment.)</p>
+</div>
+<div class="section" id="raw-text">
+<h2><a class="toc-backref" href="#toc-entry-34"><span class="sectnum">2.17</span> Raw text</a></h2>
+<p>This does not necessarily look nice, because there may be missing white space.</p>
+<p>It's just there to freeze the behavior.</p>
+A test.Second test.<div class="myclass">Another test with myclass set.</div><p>This is the <span class="myrawroleclass">fourth test</span> with myrawroleclass set.</p>
+Fifth test in HTML.<br />Line two.</div>
+<div class="section" id="container">
+<h2><a class="toc-backref" href="#toc-entry-35"><span class="sectnum">2.18</span> Container</a></h2>
+<div class="custom docutils container">
+<p>paragraph 1</p>
+<p>paragraph 2</p>
+</div>
+</div>
+<div class="section" id="colspanning-tables">
+<h2><a class="toc-backref" href="#toc-entry-36"><span class="sectnum">2.19</span> Colspanning tables</a></h2>
+<p>This table has a cell spanning two columns:</p>
+<table>
+<colgroup>
+<col style="width: 31%" />
+<col style="width: 31%" />
+<col style="width: 38%" />
+</colgroup>
+<thead>
+<tr><th class="head" colspan="2"><p>Inputs</p></th>
+<th class="head"><p>Output</p></th>
+</tr>
+<tr><th class="head"><p>A</p></th>
+<th class="head"><p>B</p></th>
+<th class="head"><p>A or B</p></th>
+</tr>
+</thead>
+<tbody>
+<tr><td><p>False</p></td>
+<td><p>False</p></td>
+<td><p>False</p></td>
+</tr>
+<tr><td><p>True</p></td>
+<td><p>False</p></td>
+<td><p>True</p></td>
+</tr>
+<tr><td><p>False</p></td>
+<td><p>True</p></td>
+<td><p>True</p></td>
+</tr>
+<tr><td><p>True</p></td>
+<td><p>True</p></td>
+<td><p>True</p></td>
+</tr>
+</tbody>
+</table>
+</div>
+<div class="section" id="rowspanning-tables">
+<h2><a class="toc-backref" href="#toc-entry-37"><span class="sectnum">2.20</span> Rowspanning tables</a></h2>
+<p>Here's a table with cells spanning several rows:</p>
+<table>
+<colgroup>
+<col style="width: 44%" />
+<col style="width: 22%" />
+<col style="width: 33%" />
+</colgroup>
+<thead>
+<tr><th class="head"><p>Header row, column 1
+(header rows optional)</p></th>
+<th class="head"><p>Header 2</p></th>
+<th class="head"><p>Header 3</p></th>
+</tr>
+</thead>
+<tbody>
+<tr><td><p>body row 1, column 1</p></td>
+<td><p>column 2</p></td>
+<td><p>column 3</p></td>
+</tr>
+<tr><td><p>body row 2</p></td>
+<td rowspan="2"><p>Cells may
+span rows.</p></td>
+<td rowspan="2"><p>Another
+rowspanning
+cell.</p></td>
+</tr>
+<tr><td><p>body row 3</p></td>
+</tr>
+</tbody>
+</table>
+</div>
+<div class="section" id="complex-tables">
+<h2><a class="toc-backref" href="#toc-entry-38"><span class="sectnum">2.21</span> Complex tables</a></h2>
+<p>Here's a complex table, which should test all features.</p>
+<table>
+<colgroup>
+<col style="width: 43%" />
+<col style="width: 21%" />
+<col style="width: 18%" />
+<col style="width: 18%" />
+</colgroup>
+<thead>
+<tr><th class="head"><p>Header row, column 1
+(header rows optional)</p></th>
+<th class="head"><p>Header 2</p></th>
+<th class="head"><p>Header 3</p></th>
+<th class="head"><p>Header 4</p></th>
+</tr>
+</thead>
+<tbody>
+<tr><td><p>body row 1, column 1</p></td>
+<td><p>column 2</p></td>
+<td><p>column 3</p></td>
+<td><p>column 4</p></td>
+</tr>
+<tr><td><p>body row 2</p></td>
+<td colspan="3"><p>Cells may span columns.</p></td>
+</tr>
+<tr><td><p>body row 3</p></td>
+<td rowspan="2"><p>Cells may
+span rows.</p>
+<p>Paragraph.</p>
+</td>
+<td colspan="2" rowspan="2"><ul class="simple">
+<li><p>Table cells</p></li>
+<li><p>contain</p></li>
+<li><p>body elements.</p></li>
+</ul>
+</td>
+</tr>
+<tr><td><p>body row 4</p></td>
+</tr>
+<tr><td><p>body row 5</p></td>
+<td colspan="2"><p>Cells may also be
+empty: <span class="docutils literal"><span class="pre">--></span></span></p></td>
+<td></td>
+</tr>
+</tbody>
+</table>
+</div>
+<div class="section" id="list-tables">
+<h2><a class="toc-backref" href="#toc-entry-39"><span class="sectnum">2.22</span> List Tables</a></h2>
+<p>Here's a list table exercising all features:</p>
+<table class="colwidths-given test" style="width: 40em">
+<caption>list table with integral header</caption>
+<colgroup>
+<col style="width: 17%" />
+<col style="width: 33%" />
+<col style="width: 50%" />
+</colgroup>
+<thead>
+<tr><th class="head stub"><p>Treat</p></th>
+<th class="head"><p>Quantity</p></th>
+<th class="head"><p>Description</p></th>
+</tr>
+</thead>
+<tbody>
+<tr><th class="stub"><p>Albatross</p></th>
+<td><p>2.99</p></td>
+<td><p>On a stick!</p></td>
+</tr>
+<tr><th class="stub"><p>Crunchy Frog</p></th>
+<td><p>1.49</p></td>
+<td><p>If we took the bones out, it wouldn't be
+crunchy, now would it?</p></td>
+</tr>
+<tr><th class="stub"><p>Gannet Ripple</p></th>
+<td><p>1.99</p></td>
+<td><p>On a stick!</p></td>
+</tr>
+</tbody>
+</table>
+<table class="colwidths-auto align-center">
+<caption>center aligned list table</caption>
+<tbody>
+<tr><td><p>Albatross</p></td>
+<td><p>2.99</p></td>
+</tr>
+<tr><td><p>Crunchy Frog</p></td>
+<td><p>1.49</p></td>
+</tr>
+<tr><td><p>Gannet Ripple</p></td>
+<td><p>1.99</p></td>
+</tr>
+</tbody>
+</table>
+</div>
+<div class="section" id="custom-roles">
+<h2><a class="toc-backref" href="#toc-entry-40"><span class="sectnum">2.23</span> Custom Roles</a></h2>
+<ul>
+<li><p>A role based on an existing role.</p>
+<p><span class="custom docutils literal">one</span> <span class="custom docutils literal">two</span> <span class="custom docutils literal">three</span></p>
+</li>
+<li><p>A new role.</p>
+<p><span class="customnew">one two three</span></p>
+</li>
+<li><p>A role with class attribute.</p>
+<p><span class="special">interpreted text</span></p>
+</li>
+<li><p>A language-switching role:</p>
+<p>Let's count in German <span lang="de">eins zwei drei</span>.</p>
+</li>
+<li><p>A role with multiple class attributes, styled with raw directives:</p>
+<p>The following works in most browsers but does not validate
+(<span class="docutils literal"><style></span> is only allowed in the document head):</p>
+<pre class="literal-block">.. raw:: html
+
+ <style type="text/css"><!--
+ .green {color: green;}
+ .sc {font-variant: small-caps;}
+ --></style></pre>
+<p><span class="green sc" lang="en-gb">British colourful text in small-caps</span>.</p>
+</li>
+</ul>
+</div>
+</div>
+<div class="section" id="html-specific">
+<h1><a class="toc-backref" href="#toc-entry-41"><span class="sectnum">3</span> HTML specific</a></h1>
+<div class="section" id="svg-images">
+<h2><a class="toc-backref" href="#toc-entry-42"><span class="sectnum">3.1</span> SVG Images</a></h2>
+<img alt="../../../docs/user/rst/images/biohazard.svg" class="align-left" src="../../../docs/user/rst/images/biohazard.svg" style="width: 48px; height: 48px;" />
+<p>Scalable vector graphics (SVG) images are the only standards-compliable way
+to include vector graphics in HTML documents. However, they are not
+supported by all backends/output formats. (E.g., LaTeX supports the
+PDF or Postscript formats for vector graphics instead.)</p>
+<p>Rendering behaviour varies, depending on</p>
+<ol class="loweralpha">
+<li><p>The SVG image itself, e.g. fixed-size vs. scaling:</p>
+<pre class="literal-block">width="280" viewBox="0 0 280 27"
+height="27" width="100%"
+ height="100%"</pre>
+</li>
+<li><p>The method used to put the image in the document.</p>
+<p>For HTML, there are several alternatives including:</p>
+<ul class="simple">
+<li><p>using the HTML <span class="docutils literal"><img></span> tag (not for interactive/animated SVG),</p></li>
+<li><p>using the HTML <span class="docutils literal"><object></span> tag,</p></li>
+<li><p>including within SVG using the SVG <span class="docutils literal"><image></span> tag,</p></li>
+<li><p>embedd the SVG code within HTML (inlining).</p></li>
+</ul>
+<p>The <cite>html4css1</cite> writer uses <span class="docutils literal"><object></span> tags, the <cite>html5</cite>
+writer uses <span class="docutils literal"><img></span> tags.</p>
+<!-- cf. http://edutechwiki.unige.ch/en/Using_SVG_with_HTML5_tutorial -->
+</li>
+<li><p>The viewing agent.</p>
+<p>All up-to-date HTML browsers support SVG, however not all do this fully
+and in the same manner. Many older versions, especially IE < 9, have
+deficiencies or require plug-ins (i.e. don't support the <span class="docutils literal"><img></span> tag).</p>
+</li>
+</ol>
+<p>If the image is wrapped in <span class="docutils literal"><object></span> or <span class="docutils literal"><svg></span> tags, it depends on the
+<span class="docutils literal">viewBox</span> declaration inside the images root <span class="docutils literal"><svg></span> element whether an
+SVG image is scaled or clipped/padded. Images wrapped in <span class="docutils literal"><img></span> are
+always scaled.</p>
+<ul>
+<li><img alt="../../../docs/user/rst/images/title-scaling.svg" class="align-right" src="../../../docs/user/rst/images/title-scaling.svg" style="width: 50%;" />
+<p>A scaling image (scales with the browser window), occupying 50% of the line
+width. The <span class="docutils literal">viewBox</span> setting in the image file enables auto-scaling also in
+<span class="docutils literal"><object></span> tags and embedded SVG (if width and hight are set to 100% in the
+SVG <image> tag).</p>
+</li>
+<li><img alt="../../../docs/user/rst/images/title.svg" class="align-right" src="../../../docs/user/rst/images/title.svg" style="width: 50%; height: 15px;" />
+<p>A fixed-size image in a box 50% wide and 15 pixles high. This image is
+scaled, if wrapped in an <span class="docutils literal"><img></span> tag but clipped in an <span class="docutils literal"><object></span> tag
+or within SVG.</p>
+</li>
+<li><img alt="../../../docs/user/rst/images/title-scaling.svg" class="align-right" src="../../../docs/user/rst/images/title-scaling.svg" style="width: 50%; height: 1.5em;" />
+<p>A right aligned, scaling image 50% wide and 1.5 em high. (This SVG image
+keeps the aspect ratio.)</p>
+</li>
+<li><p>An inline image <img alt="inline-svg" src="../../../docs/user/rst/images/biohazard-scaling.svg" style="height: 0.8em;" /> scaled to a height of 0.8 em.</p>
+</li>
+<li><img alt="../../../docs/user/rst/images/biohazard-scaling.svg" class="align-right" src="../../../docs/user/rst/images/biohazard-scaling.svg" style="height: 1em;" />
+<p>A scaling image 1 em high, right aligned:</p>
+</li>
+<li><p>A scaling image 5 mm x 5 mm, centered, with hyperlink reference:</p>
+<a class="reference internal image-reference" href="#svg-images"><img alt="../../../docs/user/rst/images/biohazard-scaling.svg" class="align-center" src="../../../docs/user/rst/images/biohazard-scaling.svg" style="width: 5mm; height: 5mm;" /></a>
+</li>
+<li><img alt="../../../docs/user/rst/images/biohazard.svg" class="align-right" src="../../../docs/user/rst/images/biohazard.svg" style="width: 4cm; height: 2em;" />
+<p>A fixed-size image in a 4 cm x 2 em box.</p>
+</li>
+</ul>
+<p>Older versions of <cite>webkit</cite> based browsers (chromium, safari, midori,
+konqueror) support the <span class="docutils literal"><img></span> tag but don't display contained bitmap
+images in this case.</p>
+<ul>
+<li><img alt="../../../docs/user/rst/images/biohazard-bitmap.svg" class="align-right" src="../../../docs/user/rst/images/biohazard-bitmap.svg" style="width: 3em;" />
+<p>A small, fixed-size SVG image with embedded bitmap, The <span class="docutils literal">:width:</span> is
+set to 3 em in the rST source. Does not scale if wrapped in <span class="docutils literal"><object></span>
+tags.</p>
+</li>
+<li><img alt="../../../docs/user/rst/images/biohazard-bitmap-scaling.svg" class="align-right" src="../../../docs/user/rst/images/biohazard-bitmap-scaling.svg" style="width: 3em;" />
+<p>A scaling SVG image with embedded bitmap, 3 em wide.</p>
+</li>
+</ul>
+<p>SVG images can also be put in figures:</p>
+<blockquote>
+<div class="figure align-center">
+<img alt="reStructuredText, the markup syntax" src="../../../docs/user/rst/images/title.svg" style="width: 290px; height: 28px;" />
+<p class="caption"><strong>Figure:</strong> SVG image in a figure.</p>
+</div>
+</blockquote>
+</div>
+<div class="section" id="swf-images">
+<h2><a class="toc-backref" href="#toc-entry-43"><span class="sectnum">3.2</span> SWF Images</a></h2>
+<p>Shockwave Flash is an image/movie format that most modern web browsers
+support via a plugin. It is sometimes blocked due to privacy/security
+concerns.</p>
+<p>Images with extension <span class="docutils literal">.swf</span> are placed inside <object> elements.
+For complete control over display options use raw HTML.</p>
+<object class="align-left" data="../../../docs/user/rst/images/biohazard.swf" style="width: 4cm; height: 2em;" type="application/x-shockwave-flash">
+[biohazard.swf]</object>
+<p>An SWF image in a 4 cm x 2 em box, left aligned.</p>
+<p>An inline SWF image <object data="../../../docs/user/rst/images/biohazard.swf" style="width: 0.8em; height: 0.8em;" type="application/x-shockwave-flash">inline-swf</object> scaled to 0.8 em x 0.8 em.</p>
+</div>
+<div class="section" id="text-level-semantics">
+<h2><a class="toc-backref" href="#toc-entry-44"><span class="sectnum">3.3</span> Text-level semantics</a></h2>
+<p><a class="reference external" href="https://html.spec.whatwg.org/#text-level-semantics">HTML 5 tags for representation of text-level semantics</a> <a class="footnote-reference brackets" href="#footnote-13" id="footnote-reference-27">13</a> and their
+reStructuredText equivalents.</p>
+<dl class="narrow field-list">
+<dt>a</dt>
+<dd><p>Hyperlinks</p>
+<blockquote>
+<p>Visit my <a class="reference external" href="example.org:drinks.html">drinks</a> page.</p>
+</blockquote>
+</dd>
+<dt>em</dt>
+<dd><p>Stress emphasis</p>
+<blockquote>
+<p>I must say I <em>adore</em> lemonade. I's <em>sooo</em> sweet.</p>
+</blockquote>
+</dd>
+<dt>strong</dt>
+<dd><p>Importance</p>
+<blockquote>
+<p><strong>Warning</strong>: This tea is <strong>very hot</strong>.</p>
+</blockquote>
+</dd>
+<dt>small</dt>
+<dd><p>Side comments</p>
+<blockquote>
+<p>These grapes are made into wine.
+<span class="small">Alcohol is addictive.</span></p>
+</blockquote>
+</dd>
+<dt>s</dt>
+<dd><p>Inaccurate text</p>
+<blockquote>
+<p>Price: <span class="s">£4.50</span> £2.00!</p>
+</blockquote>
+</dd>
+<dt>cite</dt>
+<dd><p>Titles of works</p>
+<blockquote>
+<p>The case <cite>Hugo v. Danielle</cite> is relevant here.
+I recommend reading <cite>Harry Potter</cite>.</p>
+</blockquote>
+</dd>
+<dt>q</dt>
+<dd><p>Quotations</p>
+<blockquote>
+<p>The judge said <span class="q">You can drink water from the fish tank</span>
+but advised against it.</p>
+</blockquote>
+</dd>
+<dt>dfn</dt>
+<dd><p>Defining instance</p>
+<blockquote>
+<p>The term <span class="dfn">organic food</span> refers to food produced without synthetic
+chemicals.</p>
+</blockquote>
+</dd>
+<dt>abbr</dt>
+<dd><p>Abbreviations <a class="footnote-reference brackets" href="#attribute-optional" id="footnote-reference-10">5</a></p>
+<blockquote>
+<p>Organic food in Ireland is certified by the <abbr>IOFGA</abbr> <a class="footnote-reference brackets" href="#footnote-6" id="footnote-reference-11">‡</a></p>
+</blockquote>
+<p>In rST there are separate roles for <cite>abbreviations</cite> <abbr>rsp.</abbr>
+<cite>acronymes</cite>. In HTML, the <acronym> tag is obsolete and authors are
+advised to use <abbr> instead. The HTML5 writer uses <abbr> for Docutil's
+<abbreviation> element.</p>
+<dl class="footnote brackets">
+<dt class="label" id="footnote-6"><span class="brackets"><a class="fn-backref" href="#footnote-reference-11">‡</a></span></dt>
+<dd><p>Irish Organic Farmers and Growers Association</p>
+</dd>
+</dl>
+</dd>
+<dt>ruby, rt, rp</dt>
+<dd><p>Ruby annotations</p>
+<p>Require inline nesting, currently not supported in rST.</p>
+<blockquote>
+<p><ruby> OJ <rp>(</rp><rt>Orange Juice</rt><rp>)</rp></ruby></p>
+</blockquote>
+</dd>
+<dt>data</dt>
+<dd><p>Machine-readable equivalent <a class="footnote-reference brackets" href="#attribute-required" id="footnote-reference-12">6</a></p>
+<blockquote>
+<p>Available starting today! <data value="UPC:022014640201">North Coast
+Organic Apple Cider</data></p>
+</blockquote>
+</dd>
+<dt>time</dt>
+<dd><p>Machine-readable equivalent of date- or time-related data <a class="footnote-reference brackets" href="#attribute-required" id="footnote-reference-13">6</a></p>
+<blockquote>
+<p>Available starting on <time datetime="2011-11-18">November 18th</time>!</p>
+</blockquote>
+</dd>
+<dt>code</dt>
+<dd><p>Computer code</p>
+<blockquote>
+<p>The <code>fruitdb</code> program can be used for tracking fruit production.</p>
+</blockquote>
+</dd>
+<dt>var</dt>
+<dd><p>Variables</p>
+<blockquote>
+<p>If there are <span class="var">n</span> fruit in the bowl, at least <span class="var">n</span>÷2 will be
+ripe.</p>
+</blockquote>
+</dd>
+<dt>samp</dt>
+<dd><p>Computer output</p>
+<blockquote>
+<p>The computer said <span class="samp docutils literal">Unknown error <span class="pre">-3</span></span>.</p>
+</blockquote>
+</dd>
+<dt>kbd</dt>
+<dd><p>User input</p>
+<blockquote>
+<p>Hit <span class="kbd">F1</span> to continue.</p>
+</blockquote>
+</dd>
+<dt>sub</dt>
+<dd><p>Subscripts</p>
+<blockquote>
+<p>Water is H<sub>2</sub>O.</p>
+</blockquote>
+</dd>
+<dt>sup</dt>
+<dd><p>Superscripts</p>
+<blockquote>
+<p>The Hydrogen in heavy water is usually <sup>2</sup>H.</p>
+</blockquote>
+</dd>
+<dt>i</dt>
+<dd><p>Alternative voice</p>
+<blockquote>
+<p>Lemonade consists primarily of <span class="i" lang="la">Citrus limon</span>.</p>
+</blockquote>
+</dd>
+<dt>b</dt>
+<dd><p>Keywords</p>
+<blockquote>
+<p>Take a <span class="b">lemon</span> and squeeze it with a <span class="b">juicer</span>.</p>
+</blockquote>
+</dd>
+<dt>u</dt>
+<dd><p>Annotations</p>
+<blockquote>
+<p>The mixture of apple juice and <span class="u spelling">eldeflower</span> juice is very
+pleasant.</p>
+</blockquote>
+</dd>
+<dt>mark</dt>
+<dd><p>Highlight</p>
+<blockquote>
+<p>Elderflower cordial, with one <span class="mark">part</span> cordial to ten
+<span class="mark">part</span>s water, stands a<span class="mark">part</span> from the rest.</p>
+</blockquote>
+</dd>
+<dt>bdi</dt>
+<dd><p>Text directionality isolation <a class="footnote-reference brackets" href="#attribute-optional" id="footnote-reference-14">5</a></p>
+<blockquote>
+<p>The recommended restaurant is <span class="bdi">My Juice Café (At The Beach)</span>.</p>
+</blockquote>
+<p>The <cite>dir</cite> global attribute defaults to "auto" (not "inherit") on this
+element.</p>
+</dd>
+<dt>bdo</dt>
+<dd><p>Text directionality formatting <a class="footnote-reference brackets" href="#attribute-required" id="footnote-reference-15">6</a></p>
+<blockquote>
+<p>The proposal is to write English, but in reverse order. "Juice" would
+become "<bdo dir=rtl>Juice</bdo>"></p>
+</blockquote>
+<p>Authors must specify the dir attribute on this element.</p>
+</dd>
+<dt>span</dt>
+<dd><p>Other</p>
+<blockquote>
+<p>In French we call it <span lang="fr">sirop de sureau</span>.</p>
+</blockquote>
+</dd>
+<dt>br</dt>
+<dd><p>Line break</p>
+<p>For complete paragraphs, use a line-block:</p>
+<blockquote>
+<div class="line-block">
+<div class="line">Simply Orange Juice Company</div>
+<div class="line">Apopka, FL 32703</div>
+<div class="line">U.S.A.</div>
+</div>
+</blockquote>
+<p>rST does not natively support an exceptional hard line break in a floating
+paragraph. You may use a HTML-only substitution.</p>
+<blockquote>
+<p>I want to break this line after the colon: <br /> but allow other
+linebreaks in this paragraph according to the width of the containing
+block.</p>
+</blockquote>
+</dd>
+<dt>wbr</dt>
+<dd><p>Line breaking opportunity</p>
+<p>Not supported by rST. You may use a ZWSP character (u200B), literal or via
+a substitution.</p>
+<blockquote>
+<p>www.simplyorangejuice.com</p>
+</blockquote>
+</dd>
+</dl>
+</div>
+<div class="section" id="indicating-edits">
+<h2><a class="toc-backref" href="#toc-entry-45"><span class="sectnum">3.4</span> Indicating Edits</a></h2>
+<p><a class="reference external" href="https://html.spec.whatwg.org/multipage/edits.html">HTML tags for representation of edits to the document</a> <a class="footnote-reference brackets" href="#footnote-14" id="footnote-reference-28">14</a> and their
+reStructuredText equivalents.</p>
+<dl class="field-list">
+<dt>ins</dt>
+<dd><p>Additions <a class="footnote-reference brackets" href="#attribute-optional" id="footnote-reference-16">5</a></p>
+<blockquote>
+<p>This text has "always" been here. <span class="ins">This text has been inserted.</span></p>
+<div class="ins docutils container">
+<p>This paragraph has been inserted.</p>
+</div>
+</blockquote>
+</dd>
+<dt>del</dt>
+<dd><p>Removed content <a class="footnote-reference brackets" href="#attribute-optional" id="footnote-reference-17">5</a></p>
+<blockquote>
+<p><span class="del">This text has been deleted</span>, here is the rest of the paragraph.</p>
+<div class="del docutils container">
+<p>This paragraph has been deleted.</p>
+</div>
+</blockquote>
+</dd>
+</dl>
+<dl class="footnote brackets">
+<dt class="label" id="attribute-optional"><span class="brackets">5</span><span class="fn-backref">(<a href="#footnote-reference-10">1</a>,<a href="#footnote-reference-14">2</a>,<a href="#footnote-reference-16">3</a>,<a href="#footnote-reference-17">4</a>)</span></dt>
+<dd><p>Would gain from support for attributes/arguments
+to inline roles. See <a class="reference external" href="http://docutils.sourceforge.net/docs/dev/todo.html#interpreted-text">TODO</a> <a class="footnote-reference brackets" href="#footnote-9" id="footnote-reference-22">9</a></p>
+</dd>
+<dt class="label" id="attribute-required"><span class="brackets">6</span><span class="fn-backref">(<a href="#footnote-reference-12">1</a>,<a href="#footnote-reference-13">2</a>,<a href="#footnote-reference-15">3</a>)</span></dt>
+<dd><p>Requires support for attributes to inline
+roles to make sense.</p>
+</dd>
+</dl>
+</div>
+</div>
+<div class="section" id="changes-to-the-html4css1-writer">
+<h1><a class="toc-backref" href="#toc-entry-46"><span class="sectnum">4</span> Changes to the html4css1 writer</a></h1>
+<ul class="simple">
+<li><p>Use only meta keywords recognized by HTML 5.</p></li>
+<li><p>Set table column widths with <style="width: ...">, not "width" argument.</p></li>
+<li><p>Horizontal alignment of table heads with CSS.</p></li>
+<li><p>Field lists as styled definition lists.</p></li>
+<li><p>Do not drop paragraph objects, use CSS rules to prevent unwanted vertical
+space.</p></li>
+<li><p>Put subtitles in <p> elements.</p></li>
+</ul>
+<div class="section" id="field-list-handling">
+<h2><a class="toc-backref" href="#toc-entry-47"><span class="sectnum">4.1</span> Field list handling</a></h2>
+<p>The following list demonstrates the problems with the html4css1
+approach: the <cite>field-name-limit</cite> setting is given in "number of
+characters" but the field name uses a proportional font.</p>
+<dl class="field-list simple">
+<dt>The field name</dt>
+<dd><p>is typeset on the same line, unless it is "long".</p>
+</dd>
+<dt>this field name</dt>
+<dd><p>is considered "long" in the html table rendering by
+the html4css1 writer with the default setting of
+<span class="docutils literal"><span class="pre">--field-name-limit=14</span></span>.</p>
+</dd>
+<dt>iiiiiiiiiiiiiii</dt>
+<dd><p>a field name that is considered "long" by html4css1
+with the default setting of <cite>field-name-limit: 14</cite>.</p>
+</dd>
+<dt>MMMMMMMMMMMMMM</dt>
+<dd><p>a field name that is actually longer than the
+previous one but regarded "short" by html4css1.</p>
+</dd>
+</dl>
+<p>With <span class="docutils literal">html_plain</span>, a <cite>field list</cite> is typeset as CSS-styled <cite>definition
+list</cite>. The default layout is similar to the look with <cite>html4css1</cite>:</p>
+<dl class="open field-list">
+<dt>A long field name</dt>
+<dd><p>sticks into the field body.</p>
+<p>The field body is pushed to the next line (you can suppress
+this behaviour with the <a class="reference internal" href="#run-in">run-in</a> class argument).</p>
+</dd>
+<dt>Customization</dt>
+<dd><p>of the field name width is possible with CSS instead
+of the <cite>field-name-limit</cite> configuration setting, for
+example:</p>
+<pre class="literal-block">dl.field-list > dd { margin-left: 6em; }</pre>
+</dd>
+<dt>Empty</dt>
+<dd><p></p></dd>
+<dt>fields</dt>
+<dd><p>must not lead to misalignment of the following content.</p>
+</dd>
+</dl>
+</div>
+<div class="section" id="styling-with-class-arguments">
+<h2><a class="toc-backref" href="#toc-entry-48"><span class="sectnum">4.2</span> Styling with class arguments</a></h2>
+<p>The <span class="docutils literal">plain.css</span> style sheet comes with some pre-defined style variants
+that can be choosen via a class argument.</p>
+<div class="section" id="description-lists">
+<h3><a class="toc-backref" href="#toc-entry-49"><span class="sectnum">4.2.1</span> Description lists</a></h3>
+<p>Definition lists with the "description" class argument:</p>
+<dl class="description simple">
+<dt>description lists</dt>
+<dd><p>Definition lists that are styled like in most dictionaries,
+encyclopedias etc. (as well as the LaTeX <cite>description</cite> environment).</p>
+</dd>
+<dt>label</dt>
+<dd><p>The term to be described. Put in boldface.</p>
+</dd>
+<dt>content</dt>
+<dd><p>Starts on the same line and has a hanging indent.</p>
+</dd>
+</dl>
+</div>
+<div class="section" id="field-list-variants">
+<h3><a class="toc-backref" href="#toc-entry-50"><span class="sectnum">4.2.2</span> Field list variants</a></h3>
+<p>For field lists, the "compact/open", "narrow" and "run-in" styles are defined
+in the style sheet <span class="docutils literal">plain.css</span>.</p>
+<dl class="simple">
+<dt><em>compact</em></dt>
+<dd><dl class="compact field-list simple">
+<dt>Feature</dt>
+<dd><p>No additional space between list items.</p>
+</dd>
+<dt>Option</dt>
+<dd><p>The <span class="docutils literal"><span class="pre">--compact-field-lists</span></span> command line option (and the
+corresponding configuration setting) set the <cite>compact</cite>
+class argument on all "simple" field lists, if not
+overridden with <cite>open</cite>.</p>
+</dd>
+<dt>Use</dt>
+<dd><p>For lists with short field body.</p>
+</dd>
+</dl>
+</dd>
+<dt><em>open</em></dt>
+<dd><dl class="open field-list">
+<dt>Feature</dt>
+<dd><p>Additional space between list items also in "simple" lists.
+(Overrides the <span class="docutils literal"><span class="pre">--compact-field-lists</span></span> command line
+option and the corresponding configuration setting)</p>
+</dd>
+<dt>Use</dt>
+<dd><p>For "simple" lists that should keep the space between list items.</p>
+</dd>
+</dl>
+</dd>
+<dt><em>narrow</em></dt>
+<dd><dl class="narrow field-list simple">
+<dt>Feature</dt>
+<dd><p>Less indented field body.</p>
+</dd>
+<dt>Use</dt>
+<dd><p>For lists with short field names.</p>
+</dd>
+<dt>A long field name</dt>
+<dd><p>sticks into the field body and the field body starts on a
+new line (if not combined with <a class="reference internal" href="#run-in">run-in</a>).</p>
+</dd>
+</dl>
+</dd>
+</dl>
+<dl class="simple" id="run-in">
+<dt><em>run-in</em></dt>
+<dd><dl class="run-in field-list simple">
+<dt>Feature</dt>
+<dd><p>Field body starts on the same line also after long field
+names.</p>
+</dd>
+<dt>A long field name</dt>
+<dd><p>sticks into the field body which continues on
+the same line.</p>
+</dd>
+<dt>The next field name</dt>
+<dd><p>and field body should align. Long text in the field
+body is wrapped and aligns with other fields.</p>
+</dd>
+</dl>
+</dd>
+</dl>
+</div>
+<div class="section" id="table-variants">
+<h3><a class="toc-backref" href="#toc-entry-51"><span class="sectnum">4.2.3</span> Table variants</a></h3>
+<p>The following styles can be applied to individual tables via a class
+argument or as document wide setting with the <a class="reference external" href="http://docutils.sourceforge.net/docs/user/config.html#table-style">table-style</a> <a class="footnote-reference brackets" href="#footnote-10" id="footnote-reference-23">10</a> configuration
+setting (or command line argument).</p>
+<ul>
+<li><p>Numbered tables can be achieved with the "numbered" class option:</p>
+<table class="numbered">
+<caption>truth values</caption>
+<colgroup>
+<col style="width: 29%" />
+<col style="width: 29%" />
+<col style="width: 42%" />
+</colgroup>
+<thead>
+<tr><th class="head"><p>A</p></th>
+<th class="head"><p>B</p></th>
+<th class="head"><p>A or B</p></th>
+</tr>
+</thead>
+<tbody>
+<tr><td><p>False</p></td>
+<td><p>False</p></td>
+<td><p>False</p></td>
+</tr>
+<tr><td><p>True</p></td>
+<td><p>False</p></td>
+<td><p>True</p></td>
+</tr>
+<tr><td><p>False</p></td>
+<td><p>True</p></td>
+<td><p>True</p></td>
+</tr>
+<tr><td><p>True</p></td>
+<td><p>True</p></td>
+<td><p>True</p></td>
+</tr>
+</tbody>
+</table>
+<p>Currently, referencing to the table by number is not supported. This is a
+common request and already on the <cite>TODO list</cite>.</p>
+</li>
+<li><p>A table with "booktabs" class value, is rendered similar to the style
+from the <a class="reference external" href="http://tug.ctan.org/tex-archive/macros/latex/contrib/booktabs/booktabs.pdf">booktabs</a> <a class="footnote-reference brackets" href="#footnote-11" id="footnote-reference-24">11</a> LaTeX package.</p>
+</li>
+</ul>
+<p>"Booktabs" style table, numbered, centre-aligned, with auto-sized columns:</p>
+<blockquote>
+<table class="booktabs numbered colwidths-auto align-center">
+<caption>I/O values</caption>
+<thead>
+<tr><th class="head" colspan="2"><p>Input</p></th>
+<th class="head"><p>Output</p></th>
+</tr>
+<tr><th class="head"><p>A</p></th>
+<th class="head"><p>B</p></th>
+<th class="head"><p>A or B</p></th>
+</tr>
+</thead>
+<tbody>
+<tr><td><p>False</p></td>
+<td><p>False</p></td>
+<td><p>False</p></td>
+</tr>
+<tr><td><p>True</p></td>
+<td><p>False</p></td>
+<td><p>True</p></td>
+</tr>
+<tr><td><p>False</p></td>
+<td><p>True</p></td>
+<td><p>True</p></td>
+</tr>
+<tr><td><p>True</p></td>
+<td><p>True</p></td>
+<td><p>True</p></td>
+</tr>
+</tbody>
+</table>
+</blockquote>
+</div>
+</div>
+</div>
+<div class="section" id="error-handling">
+<h1><a class="toc-backref" href="#toc-entry-52"><span class="sectnum">5</span> Error Handling</a></h1>
+<p>Any errors caught during processing will generate system messages.</p>
+<p>There should be five messages in the following, auto-generated
+section, "Docutils System Messages":</p>
+<!-- section should be added by Docutils automatically -->
+</div>
+<div class="system-messages section">
+<h1>Docutils System Messages</h1>
+<div class="system-message" id="system-message-1">
+<p class="system-message-title">System Message: ERROR/3 (<span class="docutils literal">functional/input/data/standard.txt</span>, line 104); <em><a href="#problematic-1">backlink</a></em></p>
+<p>Undefined substitution referenced: "problematic".</p>
+</div>
+<div class="system-message" id="system-message-2">
+<p class="system-message-title">System Message: ERROR/3 (<span class="docutils literal">functional/input/data/standard.txt</span>, line 392); <em><a href="#footnote-reference-8">backlink</a></em></p>
+<p>Unknown target name: "5".</p>
+</div>
+<div class="system-message" id="system-message-3">
+<p class="system-message-title">System Message: ERROR/3 (<span class="docutils literal">functional/input/data/standard.txt</span>, line 401); <em><a href="#citation-reference-3">backlink</a></em></p>
+<p>Unknown target name: "nonexistent".</p>
+</div>
+<div class="system-message" id="system-message-4">
+<p class="system-message-title">System Message: ERROR/3 (<span class="docutils literal">functional/input/data/standard.txt</span>, line 428); <em><a href="#problematic-2">backlink</a></em></p>
+<p>Unknown target name: "hyperlink reference without a target".</p>
+</div>
+<div class="system-message" id="system-message-5">
+<p class="system-message-title">System Message: ERROR/3 (<span class="docutils literal">functional/input/data/standard.txt</span>, line 441); <em><a href="#problematic-3">backlink</a></em></p>
+<p>Duplicate target name, cannot be used as a unique reference: "duplicate target names".</p>
+</div>
+</div>
+</div>
+<div class="footer">
+<hr class="footer" />
+<p>Document footer</p>
+<p><a class="reference external" href="http://www.w3.org/TR/html5/"><img alt="Conforms to HTML 5" src="http://www.w3.org/html/logo/badge/html5-badge-h-css3-semantics.png" style="width: 88px; height: 31px;" /></a> <a class="reference external" href="http://validator.w3.org/check?uri=referer"><img alt="Check validity!" src="https://www.w3.org/Icons/ValidatorSuite/vs-blue-190.png" style="width: 88px; height: 31px;" /></a> <a class="reference external" href="http://jigsaw.w3.org/css-validator/check/referer"><img alt="Valid CSS 2.1!" src="http://jigsaw.w3.org/css-validator/images/vcss" style="width: 88px; height: 31px;" /></a></p>
+
+</div>
+</body>
+</html>
--- /dev/null
+\documentclass[a4paper]{article}
+% generated by Docutils <http://docutils.sourceforge.net/>
+\usepackage{cmap} % fix search and cut-and-paste in Acrobat
+\usepackage{ifthen}
+\usepackage[T1]{fontenc}
+\usepackage[utf8]{inputenc}
+\DeclareUnicodeCharacter{21D4}{\ensuremath{\Leftrightarrow}}
+\DeclareUnicodeCharacter{2660}{\ensuremath{\spadesuit}}
+\DeclareUnicodeCharacter{2663}{\ensuremath{\clubsuit}}
+\usepackage{alltt}
+\usepackage{amsmath}
+\usepackage[british,french,ngerman,english]{babel}
+% Prevent side-effects if French hyphenation patterns are not loaded:
+\frenchbsetup{StandardLayout}
+\AtBeginDocument{\selectlanguage{english}\noextrasfrench}
+\usepackage{color}
+\usepackage{float} % float configuration
+\floatplacement{figure}{H} % place figures here definitely
+\usepackage{graphicx}
+\usepackage{multirow}
+\usepackage{pifont}
+\setcounter{secnumdepth}{0}
+\usepackage{longtable,ltcaption,array}
+\setlength{\extrarowheight}{2pt}
+\newlength{\DUtablewidth} % internal use in tables
+\usepackage{tabularx}
+\usepackage{textcomp} % text symbol macros
+
+%%% Custom LaTeX preamble
+% PDF Standard Fonts
+\usepackage{mathptmx} % Times
+\usepackage[scaled=.90]{helvet}
+\usepackage{courier}
+
+%%% User specified packages and stylesheets
+
+%%% Fallback definitions for Docutils-specific commands
+
+% 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]%
+ {\def\DocutilsClassFunctionName{DUCLASS#1}% arg cannot be used in end-part of environment.
+ \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}}{}
+}
+
+% abstract title
+\providecommand*{\DUtitleabstract}[1]{\centerline{\textbf{#1}}}
+
+% admonition (specially marked topic)
+\providecommand{\DUadmonition}[2][class-arg]{%
+ % try \DUadmonition#1{#2}:
+ \ifcsname DUadmonition#1\endcsname%
+ \csname DUadmonition#1\endcsname{#2}%
+ \else
+ \begin{center}
+ \fbox{\parbox{0.9\linewidth}{#2}}
+ \end{center}
+ \fi
+}
+
+% dedication topic
+\providecommand*{\DUCLASSdedication}{%
+ \renewenvironment{quote}{\begin{center}}{\end{center}}%
+}
+
+% docinfo (width of docinfo table)
+\DUprovidelength{\DUdocinfowidth}{0.9\linewidth}
+
+% subtitle (in document title)
+\providecommand*{\DUdocumentsubtitle}[1]{{\large #1}}
+\newcounter{enumv}
+
+% error admonition title
+\providecommand*{\DUtitleerror}[1]{\DUtitle{\color{red}#1}}
+
+% fieldlist environment
+\ifthenelse{\isundefined{\DUfieldlist}}{
+ \newenvironment{DUfieldlist}%
+ {\quote\description}
+ {\enddescription\endquote}
+}{}
+% numeric or symbol footnotes with hyperlinks
+\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 markup (custom roles)
+% \DUrole{#1}{#2} tries \DUrole#1{#2}
+\providecommand*{\DUrole}[2]{%
+ \ifcsname DUrole#1\endcsname%
+ \csname DUrole#1\endcsname{#2}%
+ \else
+ % backwards compatibility: try \docutilsrole#1{#2}
+ \ifcsname docutilsrole#1\endcsname%
+ \PackageWarningNoLine{docutils}{Command prefix "docutilsrole" is
+ deprecated, \MessageBreak use `\protect\DUrole #1`}
+ \csname docutilsrole#1\endcsname{#2}%
+ \else%
+ #2%
+ \fi%
+ \fi%
+}
+
+% legend environment
+\ifthenelse{\isundefined{\DUlegend}}{
+ \newenvironment{DUlegend}{\small}{}
+}{}
+
+% lineblock 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 environment
+\providecommand*{\DUoptionlistlabel}[1]{\bf #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}
+}
+
+% subtitle (for sidebar)
+\providecommand*{\DUsubtitle}[1]{\par\emph{#1}\smallskip}
+
+% text mode subscript
+\ifx\textsubscript\undefined
+ \usepackage{fixltx2e} % since 2015 loaded by default
+\fi
+
+% title for topics, admonitions, unsupported section levels, and sidebar
+\providecommand*{\DUtitle}[2][class-arg]{%
+ % call \DUtitle#1{#2} if it exists:
+ \ifcsname DUtitle#1\endcsname%
+ \csname DUtitle#1\endcsname{#2}%
+ \else
+ \smallskip\noindent\textbf{#2}\smallskip%
+ \fi
+}
+
+% titlereference role
+\providecommand*{\DUroletitlereference}[1]{\textsl{#1}}
+
+% transition (break, fancybreak, anonymous section)
+\providecommand*{\DUtransition}{%
+ \hspace*{\fill}\hrulefill\hspace*{\fill}
+ \vskip 0.5\baselineskip
+}
+
+% hyperlinks:
+\ifthenelse{\isundefined{\hypersetup}}{
+ \usepackage[colorlinks=true,linkcolor=blue,urlcolor=blue]{hyperref}
+ \usepackage{bookmark}
+ \urlstyle{same} % normal text font (alternatives: tt, rm, sf)
+}{}
+\hypersetup{
+ pdftitle={reStructuredText Test Document},
+ pdfauthor={David Goodger;Me;Myself;I}
+}
+
+%%% Body
+\begin{document}
+\title{reStructuredText Test Document%
+ \label{restructuredtext-test-document}%
+ \label{doctitle}%
+ \\%
+ \DUdocumentsubtitle{Examples of Syntax Constructs}%
+ \label{examples-of-syntax-constructs}%
+ \label{subtitle}}
+\author{}
+\date{}
+\maketitle
+
+% Docinfo
+\begin{center}
+\begin{tabularx}{\DUdocinfowidth}{lX}
+\textbf{Author}: &
+ David Goodger \\
+\textbf{Address}: &
+ {\raggedright
+123 Example Street\\
+Example, EX Canada\\
+A1B 2C3 } \\
+\textbf{Contact}: &
+ \href{mailto:goodger@python.org}{goodger@python.org} \\
+\textbf{Author}: &
+ Me \\
+\textbf{Author}: &
+ Myself \\
+\textbf{Author}: &
+ I \\
+\textbf{Organization}: &
+ humankind \\
+\textbf{Date}: &
+ Now, or yesterday. Or maybe even \emph{before} yesterday. \\
+\textbf{Status}: &
+ This is a “work in progress” \\
+\textbf{Revision}: &
+ is managed by a version control system. \\
+\textbf{Version}: &
+ 1 \\
+\textbf{Copyright}: &
+ This document has been placed in the public domain. You
+may do with it as you wish. You may copy, modify,
+redistribute, reattribute, sell, buy, rent, lease,
+destroy, or improve it, quote it at length, excerpt,
+incorporate, collate, fold, staple, or mutilate it, or do
+anything else to it that your or anyone else’s heart
+desires. \\
+\textbf{field name}: &
+This is a “generic bibliographic field”.
+\\
+\textbf{field name “2”}: &
+Generic bibliographic fields may contain multiple body elements.
+
+Like this.
+\\
+\end{tabularx}
+\end{center}
+
+\begin{DUclass}{dedication}
+\begin{quote}
+\DUtitle[dedication]{Dedication}
+
+For Docutils users \& co-developers.
+\end{quote}
+\end{DUclass}
+
+\begin{DUclass}{abstract}
+\begin{quote}
+\DUtitle[abstract]{Abstract}
+
+This is a test document, containing at least one example of each
+reStructuredText construct.
+\end{quote}
+\end{DUclass}
+
+% This is a comment. Note how any initial comments are moved by
+% transforms to after the document title, subtitle, and docinfo.
+
+% Above is the document title, and below is the subtitle.
+% They are transformed from section titles after parsing.
+
+% bibliographic fields (which also require a transform):
+
+\pagebreak[4] % start ToC on new page
+
+\phantomsection\label{table-of-contents}
+\pdfbookmark[1]{Table of Contents}{table-of-contents}
+\renewcommand{\contentsname}{Table of Contents}
+\tableofcontents
+
+
+\section{1 Structural Elements%
+ \label{structural-elements}%
+}
+
+
+\subsection{1.1 Section Title%
+ \label{section-title}%
+}
+\subsubsection*{Section Subtitle}
+
+Lone subsections are converted to a section subtitle by a transform
+activated with the \texttt{-{}-section-subtitles} command line option or the
+\texttt{sectsubtitle-xform} configuration value.
+
+
+\subsection{1.2 Empty Section%
+ \label{empty-section}%
+}
+
+
+\subsection{1.3 Transitions%
+ \label{transitions}%
+}
+
+Here’s a transition:
+
+%___________________________________________________________________________
+\DUtransition
+
+It divides the section. Transitions may also occur between sections:
+
+%___________________________________________________________________________
+\DUtransition
+
+
+\section{2 Body Elements%
+ \label{body-elements}%
+}
+
+
+\subsection{2.1 Paragraphs%
+ \label{paragraphs}%
+}
+
+A paragraph.
+
+
+\subsubsection{2.1.1 Inline Markup%
+ \label{inline-markup}%
+}
+
+Paragraphs contain text and may contain inline markup: \emph{emphasis},
+\textbf{strong emphasis}, \texttt{inline literals}, standalone hyperlinks
+(\url{http://www.python.org}), external hyperlinks (\href{http://www.python.org/}{Python}\DUfootnotemark{footnote-reference-10}{footnote-6}{5}), internal
+cross-references (\hyperref[example]{example}), external hyperlinks with embedded URIs
+(\href{http://www.python.org}{Python web site}), \href{http://www.python.org/}{anonymous hyperlink
+references}\DUfootnotemark{footnote-reference-16}{footnote-6}{5} (\href{http://docutils.sourceforge.net/}{a second reference}\DUfootnotemark{footnote-reference-17}{footnote-9}{8}), footnote references (manually
+numbered\DUfootnotemark{footnote-reference-1}{footnote-1}{1}, anonymous auto-numbered\DUfootnotemark{footnote-reference-2}{footnote-2}{3}, labeled auto-numbered\DUfootnotemark{footnote-reference-3}{label}{2}, or symbolic\DUfootnotemark{footnote-reference-4}{footnote-3}{*}), citation references (\hyperlink{cit2002}{[CIT2002]}),
+substitution references (\includegraphics{../../../docs/user/rst/images/biohazard.png} \&
+a \emph{trimmed heart} \texttt{(U+2665):}\ding{170}), and %
+\phantomsection\label{inline-hyperlink-targets}inline hyperlink targets
+(see \hyperref[targets]{Targets} below for a reference back to here). Character-level
+inline markup is also possible (although exceedingly ugly!) in \emph{re}\texttt{Structured}\emph{Text}. Problems are indicated by %
+\raisebox{1em}{\hypertarget{problematic-1}{}}\hyperlink{system-message-1}{\textbf{\color{red}|problematic|}} text
+(generated by processing errors; this one is intentional). Here is a
+reference to the \hyperref[doctitle]{doctitle} and the \hyperref[subtitle]{subtitle}.
+
+The default role for interpreted text is \DUroletitlereference{Title Reference}. Here are
+some explicit interpreted text roles: a PEP reference (\href{http://www.python.org/dev/peps/pep-0287}{PEP 287}); an
+RFC reference (\href{http://tools.ietf.org/html/rfc2822.html}{RFC 2822}); an abbreviation (\DUrole{abbreviation}{abb.}), an acronym
+(\DUrole{acronym}{reST}), code (\texttt{\DUrole{code}{print \textquotedbl{}hello world\textquotedbl{}}}); a \textsubscript{subscript};
+a \textsuperscript{superscript} and explicit roles for \DUroletitlereference{Docutils}’
+\emph{standard} \textbf{inline} \texttt{markup}.
+
+% DO NOT RE-WRAP THE FOLLOWING PARAGRAPH!
+
+Let’s test wrapping and whitespace significance in inline literals:
+\texttt{This is an example of -{}-inline-literal -{}-text, -{}-including some-{}-
+strangely-{}-hyphenated-words. ~Adjust-the-width-of-your-browser-window
+to see how the text is wrapped. ~-{}- -{}-{}-{}- -{}-{}-{}-{}-{}-{}-{}- ~Now note ~ ~the
+spacing ~ ~between the ~ ~words of ~ ~this sentence ~ ~(words
+should ~ ~be grouped ~ ~in pairs).}
+
+If the \texttt{-{}-pep-references} option was supplied, there should be a
+live link to PEP 258 here.
+
+
+\subsection{2.2 Bullet Lists%
+ \label{bullet-lists}%
+}
+
+\begin{itemize}
+\item A bullet list
+
+\begin{itemize}
+\item Nested bullet list.
+
+\item Nested item 2.
+\end{itemize}
+
+\item Item 2.
+
+Paragraph 2 of item 2.
+
+\begin{itemize}
+\item Nested bullet list.
+
+\item Nested item 2.
+
+\begin{itemize}
+\item Third level.
+
+\item Item 2.
+\end{itemize}
+
+\item Nested item 3.
+
+\item This nested list should be compacted by the HTML writer.
+%
+\phantomsection\label{target}
+% Even if this item contains a target and a comment.
+\end{itemize}
+\end{itemize}
+
+
+\subsection{2.3 Enumerated Lists%
+ \label{enumerated-lists}%
+}
+
+\begin{enumerate}
+\item Arabic numerals.
+
+\begin{enumerate}
+\renewcommand{\labelenumii}{\alph{enumii})}
+\item lower alpha)
+
+\begin{enumerate}
+\renewcommand{\labelenumiii}{(\roman{enumiii})}
+\item (lower roman)
+
+\begin{enumerate}
+\item upper alpha.
+
+\begin{list}{\Roman{enumv})}{\usecounter{enumv}}
+\item upper roman)
+\end{list}
+\end{enumerate}
+\end{enumerate}
+\end{enumerate}
+
+\item Lists that don’t start at 1:
+
+\begin{enumerate}
+\renewcommand{\labelenumii}{\arabic{enumii}.}
+\setcounter{enumii}{2}
+\item Three
+
+\item Four
+\end{enumerate}
+
+\begin{enumerate}
+\renewcommand{\labelenumii}{\Alph{enumii}.}
+\setcounter{enumii}{2}
+\item C
+
+\item D
+\end{enumerate}
+
+\begin{enumerate}
+\renewcommand{\labelenumii}{\roman{enumii}.}
+\setcounter{enumii}{2}
+\item iii
+
+\item iv
+\end{enumerate}
+\end{enumerate}
+
+
+\subsection{2.4 Definition Lists%
+ \label{definition-lists}%
+}
+
+\begin{description}
+\item[{Term}] \leavevmode
+Definition
+
+\item[{Term}] \leavevmode (\textbf{classifier})
+Definition paragraph 1.
+
+Definition paragraph 2.
+
+\item[{Term}] \leavevmode
+Definition
+
+\item[{Term}] \leavevmode (\textbf{classifier one})(\textbf{classifier two})
+Definition
+
+\end{description}
+
+
+\subsection{2.5 Field Lists%
+ \label{field-lists}%
+}
+
+\begin{DUfieldlist}
+\item[{what:}]
+Field lists map field names to field bodies, like database
+records. They are often part of an extension syntax. They are
+an unambiguous variant of RFC 2822 fields.
+
+\item[{how arg1 arg2:}]
+The field marker is a colon, the field name, and a colon.
+
+The field body may contain one or more body elements, indented
+relative to the field marker.
+
+\item[{credits:}]
+\DUrole{credits}{This paragraph has the \DUroletitlereference{credits} class set. (This is actually not
+about credits but just for ensuring that the class attribute
+doesn’t get stripped away.)}
+\end{DUfieldlist}
+
+
+\subsection{2.6 Option Lists%
+ \label{option-lists}%
+}
+
+For listing command-line options:
+
+\begin{DUoptionlist}
+\item[-a] command-line option “a”
+
+\item[-b file] options can have arguments
+and long descriptions
+
+\item[-{}-long] options can be long also
+
+\item[-{}-input=file] long options can also have
+arguments
+
+\item[-{}-very-long-option] The description can also start on the next line.
+
+The description may contain multiple body elements,
+regardless of where it starts.
+
+\item[-x, -y, -z] Multiple options are an “option group”.
+
+\item[-v, -{}-verbose] Commonly-seen: short \& long options.
+
+\item[-1 file, -{}-one=file, -{}-two file] Multiple options with arguments.
+
+\item[/V] DOS/VMS-style options too
+\end{DUoptionlist}
+
+There must be at least two spaces between the option and the
+description.
+
+
+\subsection{2.7 Literal Blocks%
+ \label{literal-blocks}%
+}
+
+Literal blocks are indicated with a double-colon (“::”) at the end of
+the preceding paragraph (over there \texttt{-{}->}). They can be indented:
+
+\begin{quote}
+\begin{alltt}
+if literal_block:
+ text = 'is left as-is'
+ spaces_and_linebreaks = 'are preserved'
+ markup_processing = None
+\end{alltt}
+\end{quote}
+
+Or they can be quoted without indentation:
+
+\begin{quote}
+\begin{alltt}
+>> Great idea!
+>
+> Why didn't I think of that?
+\end{alltt}
+\end{quote}
+
+
+\subsection{2.8 Line Blocks%
+ \label{line-blocks}%
+}
+
+This section tests line blocks. Line blocks are body elements which
+consist of lines and other line blocks. Nested line blocks cause
+indentation.
+
+\begin{DUlineblock}{0em}
+\item[] This is a line block. It ends with a blank line.
+\item[]
+\begin{DUlineblock}{\DUlineblockindent}
+\item[] New lines begin with a vertical bar (“|”).
+\item[] Line breaks and initial indent are significant, and preserved.
+\item[]
+\begin{DUlineblock}{\DUlineblockindent}
+\item[] Continuation lines are also possible. A long line that is intended
+to wrap should begin with a space in place of the vertical bar.
+\end{DUlineblock}
+\item[] The left edge of a continuation line need not be aligned with
+the left edge of the text above it.
+\end{DUlineblock}
+\end{DUlineblock}
+
+\begin{DUlineblock}{0em}
+\item[] This is a second line block.
+\item[]
+\item[] Blank lines are permitted internally, but they must begin with a “|”.
+\end{DUlineblock}
+
+Another line block, surrounded by paragraphs:
+
+\begin{DUlineblock}{0em}
+\item[] And it’s no good waiting by the window
+\item[] It’s no good waiting for the sun
+\item[] Please believe me, the things you dream of
+\item[] They don’t fall in the lap of no-one
+\end{DUlineblock}
+
+Take it away, Eric the Orchestra Leader!
+
+\begin{quote}
+\begin{DUlineblock}{0em}
+\item[] A one, two, a one two three four
+\item[]
+\item[] Half a bee, philosophically,
+\item[]
+\begin{DUlineblock}{\DUlineblockindent}
+\item[] must, \emph{ipso facto}, half not be.
+\end{DUlineblock}
+\item[] But half the bee has got to be,
+\item[]
+\begin{DUlineblock}{\DUlineblockindent}
+\item[] \emph{vis a vis} its entity. D’you see?
+\item[]
+\end{DUlineblock}
+\item[] But can a bee be said to be
+\item[]
+\begin{DUlineblock}{\DUlineblockindent}
+\item[] or not to be an entire bee,
+\item[]
+\begin{DUlineblock}{\DUlineblockindent}
+\item[] when half the bee is not a bee,
+\item[]
+\begin{DUlineblock}{\DUlineblockindent}
+\item[] due to some ancient injury?
+\item[]
+\end{DUlineblock}
+\end{DUlineblock}
+\end{DUlineblock}
+\item[] Singing…
+\end{DUlineblock}
+\end{quote}
+
+A line block, like the following poem by Christian Morgenstern, can
+also be centre-aligned:
+
+\begin{selectlanguage}{ngerman}
+\begin{DUlineblock}{0em}
+\centering
+\item[] \textbf{Die Trichter}
+\item[]
+\item[] Zwei Trichter wandeln durch die Nacht.
+\item[] Durch ihres Rumpfs verengten Schacht
+\item[] fließt weißes Mondlicht
+\item[] still und heiter
+\item[] auf ihren
+\item[] Waldweg
+\item[] u. s.
+\item[] w.
+\item[]
+\end{DUlineblock}
+\end{selectlanguage}
+
+
+\subsection{2.9 Block Quotes%
+ \label{block-quotes}%
+}
+
+Block quotes consist of indented body elements:
+
+\begin{quote}
+My theory by A. Elk. Brackets Miss, brackets. This theory goes
+as follows and begins now. All brontosauruses are thin at one
+end, much much thicker in the middle and then thin again at the
+far end. That is my theory, it is mine, and belongs to me and I
+own it, and what it is too.
+\nopagebreak
+
+\raggedleft —Anne Elk (Miss)
+\end{quote}
+
+The language of a quote (like any other object) can be specified by
+a class attribute:
+
+%
+
+\begin{selectlanguage}{french}
+\begin{quote}
+ReStructuredText est un langage de balisage léger utilisé
+notamment dans la documentation du langage Python.
+\end{quote}
+\end{selectlanguage}
+
+
+\subsection{2.10 Doctest Blocks%
+ \label{doctest-blocks}%
+}
+
+\begin{quote}
+\begin{alltt}
+>>> print 'Python-specific usage examples; begun with ">>>"'
+Python-specific usage examples; begun with ">>>"
+>>> print '(cut and pasted from interactive Python sessions)'
+(cut and pasted from interactive Python sessions)
+\end{alltt}
+\end{quote}
+
+
+\subsection{2.11 Footnotes%
+ \label{footnotes}%
+}
+%
+\DUfootnotetext{footnote-1}{footnote-reference-1}{1}{%
+A footnote contains body elements, consistently indented by at
+least 3 spaces.
+
+This is the footnote’s second paragraph.
+}
+%
+\DUfootnotetext{label}{footnote-reference-3}{2}{\phantomsection\label{label}%
+Footnotes may be numbered, either manually (as in\DUfootnotemark{footnote-reference-5}{footnote-1}{1}) or
+automatically using a “\#”-prefixed label. This footnote has a
+label so it can be referred to from multiple places, both as a
+footnote reference (\DUfootnotemark{footnote-reference-6}{label}{2}) and as a \hyperref[label]{hyperlink reference}.
+}
+%
+\DUfootnotetext{footnote-2}{footnote-reference-2}{3}{%
+This footnote is numbered automatically and anonymously using a
+label of “\#” only.
+
+This is the second paragraph.
+
+And this is the third paragraph.
+}
+%
+\DUfootnotetext{footnote-3}{footnote-reference-4}{*}{%
+Footnotes may also use symbols, specified with a “*” label.
+Here’s a reference to the next footnote:\DUfootnotemark{footnote-reference-7}{footnote-4}{†}.
+}
+%
+\DUfootnotetext{footnote-4}{footnote-reference-7}{†}{%
+This footnote shows the next symbol in the sequence.
+}
+%
+\DUfootnotetext{footnote-5}{footnote-5}{4}{%
+Here’s an unreferenced footnote, with a reference to a
+nonexistent footnote:%
+\raisebox{1em}{\hypertarget{footnote-reference-8}{}}\hyperlink{system-message-2}{\textbf{\color{red}{[}5{]}\_}}.
+}
+
+
+\subsection{2.12 Citations%
+ \label{citations}%
+}
+\begin{figure}[b]\raisebox{1em}{\hypertarget{cit2002}{}}[CIT2002]
+Citations are text-labeled footnotes. They may be
+rendered separately and differently from footnotes.
+\end{figure}
+
+Here’s a reference to the above, \hyperlink{cit2002}{[CIT2002]}, and a %
+\raisebox{1em}{\hypertarget{citation-reference-3}{}}\hyperlink{system-message-3}{\textbf{\color{red}{[}nonexistent{]}\_}}
+citation.
+
+
+\subsection{2.13 Targets%
+ \label{targets}%
+ \label{another-target}%
+}
+
+\phantomsection\label{example}
+This paragraph is pointed to by the explicit “example” target. A
+reference can be found under \hyperref[inline-markup]{Inline Markup}, above. \hyperref[inline-hyperlink-targets]{Inline
+hyperlink targets} are also possible.
+
+Section headers are implicit targets, referred to by name. See
+\hyperref[targets]{Targets}, which is a subsection of \hyperref[body-elements]{Body Elements}.
+
+Explicit external targets are interpolated into references such as
+“\href{http://www.python.org/}{Python}\DUfootnotemark{footnote-reference-11}{footnote-6}{5}”.
+
+Targets may be indirect and anonymous. Thus \hyperref[targets]{this phrase} may also
+refer to the \hyperref[targets]{Targets} section.
+
+Here’s a %
+\raisebox{1em}{\hypertarget{problematic-2}{}}\hyperlink{system-message-4}{\textbf{\color{red}`hyperlink reference without a target`\_}}, which generates an
+error.
+
+
+\subsubsection{2.13.1 Duplicate Target Names%
+ \label{duplicate-target-names}%
+}
+
+Duplicate names in section headers or other implicit targets will
+generate “info” (level-1) system messages. Duplicate names in
+explicit targets will generate “warning” (level-2) system messages.
+
+
+\subsubsection{2.13.2 Duplicate Target Names%
+ \label{duplicate-target-names-1}%
+}
+
+Since there are two “Duplicate Target Names” section headers, we
+cannot uniquely refer to either of them by name. If we try to (like
+this: %
+\raisebox{1em}{\hypertarget{problematic-3}{}}\hyperlink{system-message-5}{\textbf{\color{red}`Duplicate Target Names`\_}}), an error is generated.
+
+
+\subsection{2.14 Directives%
+ \label{directives}%
+}
+
+\phantomsection\label{contents}
+These are just a sample of the many reStructuredText Directives. For
+others, please see
+\url{http://docutils.sourceforge.net/docs/ref/rst/directives.html}.
+
+
+\subsubsection{2.14.1 Document Parts%
+ \label{document-parts}%
+}
+
+An example of the “contents” directive can be seen above this section
+(a local, untitled table of \hyperref[contents]{contents}) and at the beginning of the
+document (a document-wide \hyperref[table-of-contents]{table of contents}).
+
+
+\subsubsection{2.14.2 Images and Figures%
+ \label{images-and-figures}%
+}
+
+An image directive (also clickable – a hyperlink reference):
+
+\hyperref[directives]{\includegraphics{../../../docs/user/rst/images/title.png}}
+
+Image with multiple IDs:
+
+\includegraphics{../../../docs/user/rst/images/title.png}
+\phantomsection\label{image-target-3}\label{image-target-2}\label{image-target-1}
+
+A centered image:
+
+\noindent\makebox[\linewidth][c]{\includegraphics{../../../docs/user/rst/images/biohazard.png}}
+
+A left-aligned image:
+
+\noindent{\includegraphics{../../../docs/user/rst/images/biohazard.png}\hfill}
+
+This paragraph might flow around the image.
+The specific behavior depends upon the style sheet and
+the browser or rendering software used.
+
+A right-aligned image:
+
+\noindent{\hfill\includegraphics{../../../docs/user/rst/images/biohazard.png}}
+
+This paragraph might flow around the image.
+The specific behavior depends upon the style sheet and
+the browser or rendering software used.
+
+For inline images see \hyperref[substitution-definitions]{Substitution Definitions}.
+
+Image size:
+
+An image 2 em wide:
+
+\includegraphics[width=2em]{../../../docs/user/rst/images/biohazard.png}
+
+An image 2 em wide and 15 pixel high:
+
+\includegraphics[height=15px,width=2em]{../../../docs/user/rst/images/biohazard.png}
+
+An image occupying 50\% of the line width:
+
+\includegraphics[width=0.500\linewidth]{../../../docs/user/rst/images/title.png}
+
+An image 2 cm high:
+
+\includegraphics[height=2cm]{../../../docs/user/rst/images/biohazard.png}
+
+A \emph{figure} is an image with a caption and/or a legend. With page-based output
+media, figures might float to a different position if this helps the page
+layout.
+
+\begin{DUclass}{figclass1}
+\begin{DUclass}{figclass2}
+\begin{figure}
+\noindent\makebox[\linewidth][c]{\includegraphics[width=258bp]{../../../docs/user/rst/images/title.png}}
+\caption{Plaintext markup syntax and parser system.}
+\begin{DUlegend}
+\setlength{\DUtablewidth}{\linewidth}
+\begin{longtable*}[c]{|p{0.156\DUtablewidth}|p{0.563\DUtablewidth}|}
+\hline
+
+re
+ &
+Revised, revisited, based on ‘re’ module.
+ \\
+\hline
+
+Structured
+ &
+Structure-enhanced text, structuredtext.
+ \\
+\hline
+
+Text
+ &
+Well it is, isn’t it?
+ \\
+\hline
+\end{longtable*}
+
+This paragraph is also part of the legend.
+\end{DUlegend}
+\end{figure}
+\end{DUclass}
+\end{DUclass}
+
+A left-aligned figure:
+
+\begin{DUclass}{figclass1}
+\begin{DUclass}{figclass2}
+\begin{figure} % align = "left"
+\noindent\makebox[\linewidth][c]{\includegraphics[width=40px]{../../../docs/user/rst/images/biohazard.png}}
+\caption{This is the caption.}
+\begin{DUlegend}
+This is the legend.
+
+The legend may consist of several paragraphs.
+\end{DUlegend}
+\end{figure}
+\end{DUclass}
+\end{DUclass}
+
+This paragraph might flow around the figure.
+
+The specific behavior depends upon the style sheet and the browser or
+rendering software used.
+
+A centered figure:
+
+\begin{figure}
+\noindent\makebox[\linewidth][c]{\includegraphics[width=40px]{../../../docs/user/rst/images/biohazard.png}}
+\caption{This is the caption.}
+\begin{DUlegend}
+This is the legend.
+
+The legend may consist of several paragraphs.
+\end{DUlegend}
+\end{figure}
+
+This paragraph might flow around the figure.
+
+The specific behavior depends upon the style sheet and the browser or
+rendering software used.
+
+A right-aligned figure:
+
+\begin{figure} % align = "right"
+\noindent\makebox[\linewidth][c]{\includegraphics[width=40px]{../../../docs/user/rst/images/biohazard.png}}
+\caption{This is the caption.}
+\begin{DUlegend}
+This is the legend.
+
+The legend may consist of several paragraphs.
+\end{DUlegend}
+\end{figure}
+
+This paragraph might flow around the figure. The specific behavior depends
+upon the style sheet and the browser or rendering software used.
+
+Tables may be given titles and additional arguments with the \emph{table}
+directive:
+
+\setlength{\DUtablewidth}{\linewidth}
+\begin{longtable}[l]{|p{0.075\DUtablewidth}|p{0.075\DUtablewidth}|}
+\caption{left-aligned table}\\
+\hline
+\textbf{%
+A
+} & \textbf{%
+not A
+} \\
+\hline
+\endfirsthead
+\caption[]{left-aligned table (... continued)}\\
+\hline
+\textbf{%
+A
+} & \textbf{%
+not A
+} \\
+\hline
+\endhead
+\multicolumn{2}{c}{\hfill ... continued on next page} \\
+\endfoot
+\endlastfoot
+
+False
+ &
+True
+ \\
+\hline
+
+True
+ &
+False
+ \\
+\hline
+\end{longtable}
+
+\setlength{\DUtablewidth}{\linewidth}
+\begin{longtable}[c]{|p{0.075\DUtablewidth}|p{0.075\DUtablewidth}|}
+\caption{center-aligned table}\\
+\hline
+\textbf{%
+A
+} & \textbf{%
+not A
+} \\
+\hline
+\endfirsthead
+\caption[]{center-aligned table (... continued)}\\
+\hline
+\textbf{%
+A
+} & \textbf{%
+not A
+} \\
+\hline
+\endhead
+\multicolumn{2}{c}{\hfill ... continued on next page} \\
+\endfoot
+\endlastfoot
+
+False
+ &
+True
+ \\
+\hline
+
+True
+ &
+False
+ \\
+\hline
+\end{longtable}
+
+\setlength{\DUtablewidth}{\linewidth}
+\begin{longtable}[r]{|p{0.075\DUtablewidth}|p{0.075\DUtablewidth}|}
+\caption{right-aligned table}\\
+\hline
+\textbf{%
+A
+} & \textbf{%
+not A
+} \\
+\hline
+\endfirsthead
+\caption[]{right-aligned table (... continued)}\\
+\hline
+\textbf{%
+A
+} & \textbf{%
+not A
+} \\
+\hline
+\endhead
+\multicolumn{2}{c}{\hfill ... continued on next page} \\
+\endfoot
+\endlastfoot
+
+False
+ &
+True
+ \\
+\hline
+
+True
+ &
+False
+ \\
+\hline
+\end{longtable}
+
+With the “widths” argument “auto” (or “class” value “colwidths-auto”),
+column widths are determined by the backend (if supported by the
+writer/backend).
+
+\begin{longtable*}[c]{|l|l|l|}
+\hline
+\textbf{A} & \textbf{B} & \textbf{A or B} \\
+\hline
+\endfirsthead
+\hline
+\textbf{A} & \textbf{B} & \textbf{A or B} \\
+\hline
+\endhead
+\multicolumn{3}{c}{\hfill ... continued on next page} \\
+\endfoot
+\endlastfoot
+False & False & False \\
+\hline
+True & False & True \\
+\hline
+False & True & True \\
+\hline
+True & True & True \\
+\hline
+\end{longtable*}
+\label{target2}\label{target1}
+
+
+\subsubsection{2.14.3 Admonitions%
+ \label{admonitions}%
+}
+
+\DUadmonition[attention]{
+\DUtitle[attention]{Attention!}
+
+Directives at large.
+}
+
+\DUadmonition[caution]{
+\DUtitle[caution]{Caution!}
+
+Don’t take any wooden nickels.
+}
+
+\DUadmonition[danger]{
+\DUtitle[danger]{!DANGER!}
+
+Mad scientist at work!
+}
+
+\DUadmonition[error]{
+\DUtitle[error]{Error}
+
+Does not compute.
+}
+
+\DUadmonition[hint]{
+\DUtitle[hint]{Hint}
+
+It’s bigger than a bread box.
+}
+
+\DUadmonition[important]{
+\DUtitle[important]{Important}
+
+\begin{itemize}
+\item Wash behind your ears.
+
+\item Clean up your room.
+
+\item Call your mother.
+
+\item Back up your data.
+\end{itemize}
+}
+
+\DUadmonition[note]{
+\DUtitle[note]{Note}
+
+This is a note.
+}
+
+\DUadmonition[tip]{
+\DUtitle[tip]{Tip}
+
+15\% if the service is good.
+}
+
+\DUadmonition[warning]{
+\DUtitle[warning]{Warning}
+
+Strong prose may provoke extreme mental exertion.
+Reader discretion is strongly advised.
+}
+
+\DUadmonition[admonition-and-by-the-way]{
+\DUtitle[admonition-and-by-the-way]{And, by the way…}
+
+You can make up your own admonition too.
+}
+
+
+\subsubsection{2.14.4 Topics, Sidebars, and Rubrics%
+ \label{topics-sidebars-and-rubrics}%
+}
+
+\emph{Sidebars} are like miniature, parallel documents.
+
+\DUsidebar{
+\DUtitle[sidebar]{Sidebar Title}
+
+\DUsubtitle{Optional Subtitle}
+
+This is a sidebar. It is for text outside the flow of the main
+text.
+
+\DUrubric{This is a rubric inside a sidebar}
+
+Sidebars often appear beside the main text with a border and a different
+background or font color.
+}
+
+A \emph{topic} is like a block quote with a title, or a self-contained section
+with no subsections.
+
+\begin{DUclass}{topic}
+\begin{quote}
+\DUtitle[topic]{Topic Title}
+
+This is a topic.
+\end{quote}
+\end{DUclass}
+
+A \emph{rubric} is like an informal heading that doesn’t correspond to the
+document’s structure. It is typically highlighted in red (hence the name).
+
+\DUrubric{This is a rubric}
+
+Topics and rubrics can be used at places where a \hyperref[section-title]{section title} is not
+allowed (e.g. inside a directive).
+
+
+\subsubsection{2.14.5 Target Footnotes%
+ \label{target-footnotes}%
+}
+%
+\DUfootnotetext{footnote-6}{footnote-reference-10}{5}{%
+\url{http://www.python.org/}
+}
+%
+\DUfootnotetext{footnote-7}{footnote-reference-13}{6}{%
+\url{http://pygments.org/}
+}
+%
+\DUfootnotetext{footnote-8}{footnote-reference-14}{7}{%
+\url{ftp://ftp.ams.org/ams/doc/amsmath/short-math-guide.pdf}
+}
+%
+\DUfootnotetext{footnote-9}{footnote-reference-17}{8}{%
+\url{http://docutils.sourceforge.net/}
+}
+%
+\DUfootnotetext{footnote-10}{footnote-reference-18}{9}{%
+\url{A:DOS\\path\\}
+}
+
+
+\subsubsection{2.14.6 Replacement Text%
+ \label{replacement-text}%
+}
+
+I recommend you try \href{http://www.python.org/}{Python, \emph{the} best language around}\DUfootnotemark{footnote-reference-12}{footnote-6}{5}.
+
+
+\subsubsection{2.14.7 Compound Paragraph%
+ \label{compound-paragraph}%
+}
+
+The \emph{compound} directive is used to create a “compound paragraph”, which
+is a single logical paragraph containing multiple physical body
+elements. For example:
+
+\begin{DUclass}{compound}
+The ‘rm’ command is very dangerous. If you are logged
+in as root and enter
+\begin{quote}
+\begin{alltt}
+cd /
+rm -rf *
+\end{alltt}
+\end{quote}
+you will erase the entire contents of your file system.
+\end{DUclass}
+
+Test the handling and display of compound paragraphs:
+
+\begin{DUclass}{compound}
+\begin{DUclass}{some-class}
+Compound 2, paragraph 1,
+
+compound 2, paragraph 2,
+\begin{itemize}
+\item list item 1,
+
+\item list item 2,
+\end{itemize}
+compound 2, paragraph 3.
+\end{DUclass}
+\end{DUclass}
+
+\begin{DUclass}{compound}
+Compound 3, only consisting of one paragraph.
+\end{DUclass}
+
+\begin{DUclass}{compound}
+\begin{quote}
+\begin{alltt}
+Compound 4.
+This one starts with a literal block.
+\end{alltt}
+\end{quote}
+Compound 4, paragraph following the literal block.
+\end{DUclass}
+
+Now something \emph{really} perverted – a nested compound block. This is
+just to test that it works at all; the results don’t have to be
+meaningful.
+
+\begin{DUclass}{compound}
+Compound 5, block 1 (a paragraph).
+
+\begin{DUclass}{compound}
+Compound 6 is block 2 in compound 5.
+
+Compound 6, another paragraph.
+\end{DUclass}
+
+Compound 5, block 3 (a paragraph).
+\end{DUclass}
+
+\begin{DUclass}{compound}
+Compound 7, tests the inclusion of various block-level
+elements in one logical paragraph. First a table,
+
+\setlength{\DUtablewidth}{\linewidth}
+\begin{longtable*}[c]{|p{0.249\DUtablewidth}|p{0.249\DUtablewidth}|p{0.249\DUtablewidth}|}
+\hline
+
+Left cell, first
+paragraph.
+
+Left cell, second
+paragraph.
+ &
+Middle cell,
+consisting of
+exactly one
+paragraph.
+ &
+Right cell.
+
+Paragraph 2.
+
+Paragraph 3.
+ \\
+\hline
+\end{longtable*}
+followed by a paragraph. This physical paragraph is
+actually a continuation of the paragraph before the table. It is followed
+by
+\begin{quote}
+a quote and
+\end{quote}
+\begin{enumerate}
+\item an enumerated list,
+\end{enumerate}
+a paragraph,
+\begin{DUoptionlist}
+\item[-{}-an] option list,
+\end{DUoptionlist}
+a paragraph,
+\begin{DUfieldlist}
+\item[{a field:}]
+list,
+\end{DUfieldlist}
+a paragraph,
+\begin{description}
+\item[{a definition}] \leavevmode
+list,
+
+\end{description}
+a paragraph, an image:
+\includegraphics{../../../docs/user/rst/images/biohazard.png}
+a paragraph,
+\begin{DUlineblock}{0em}
+\item[] a line
+\item[] block,
+\end{DUlineblock}
+a paragraph followed by a comment,
+% this is a comment
+a paragraph, a
+
+\DUadmonition[note]{
+\DUtitle[note]{Note}
+
+with content
+}
+and the final paragraph of the compound 7.
+\end{DUclass}
+
+
+\subsubsection{2.14.8 Parsed Literal Blocks%
+ \label{parsed-literal-blocks}%
+}
+
+\begin{quote}
+\ttfamily\raggedright
+This~is~a~parsed~literal~block.\\
+~~~~This~line~is~indented.~~The~next~line~is~blank.\\
+~\\
+Inline~markup~is~supported,~e.g.~\emph{emphasis},~\textbf{strong},~\texttt{literal\\
+text},~\textsubscript{sub-}~and~\textsuperscript{super}scripts,\\
+inline~formulas:~$A = 2 \pi r^2$,\\
+footnotes\DUfootnotemark{footnote-reference-9}{footnote-1}{1},~%
+\phantomsection\label{hyperlink-targets}hyperlink~targets,~and~\href{http://www.python.org/}{references}.
+\end{quote}
+
+
+\subsubsection{2.14.9 Code%
+ \label{code}%
+}
+
+Blocks of source code can be set with the \DUroletitlereference{code} directive. If the code
+language is specified, the content is parsed and tagged by the \href{http://pygments.org/}{Pygments}\DUfootnotemark{footnote-reference-13}{footnote-7}{6}
+syntax highlighter and can be formatted with a style sheet. (Code parsing
+is turned off using the \texttt{syntax-highlight} config setting in the test
+conversions in order to get identical results with/without installed
+Pygments highlighter.)
+
+\begin{DUclass}{code}
+\begin{DUclass}{python}
+\begin{quote}
+\begin{alltt}
+print 'This is Python code.'
+\end{alltt}
+\end{quote}
+\end{DUclass}
+\end{DUclass}
+
+The \texttt{:number-lines:} option (with optional start value) generates line
+numbers:
+
+\begin{DUclass}{code}
+\begin{DUclass}{python}
+\begin{quote}
+\ttfamily\raggedright
+\DUrole{ln}{~8~}\#~print~integers~from~0~to~9:\\
+\DUrole{ln}{~9~}for~i~in~range(10):\\
+\DUrole{ln}{10~}~~~~print~i
+\end{quote}
+\end{DUclass}
+\end{DUclass}
+
+For inline code snippets, there is the \DUroletitlereference{code} role, which can be used
+directly (the code will not be parsed/tagged, as the language is not known)
+or as base for special code roles, e.g. the LaTeX code in the next
+paragraph.
+
+Docutils uses LaTeX syntax for math directives and roles:
+\texttt{\DUrole{code}{\DUrole{tex}{\textbackslash{}alpha = f(x)}}} prints $\alpha = f(x)$.
+
+The \texttt{:code:} option of the \DUroletitlereference{include} directive sets the included content
+as a code block, here the rst file \texttt{header\_footer.txt} with line numbers:
+
+\begin{DUclass}{code}
+\begin{DUclass}{rst}
+\begin{quote}
+\ttfamily\raggedright
+\DUrole{ln}{1~}..~header::~Document~header\\
+\DUrole{ln}{2~}..~footer::~Document~footer
+\end{quote}
+\end{DUclass}
+\end{DUclass}
+
+
+\subsection{2.15 Substitution Definitions%
+ \label{substitution-definitions}%
+}
+
+An inline image (\includegraphics{../../../docs/user/rst/images/biohazard.png}) example:
+
+A Unicode example:
+
+(Substitution definitions are not visible in the HTML source.)
+
+
+\subsection{2.16 Comments%
+ \label{comments}%
+}
+
+Here’s one:
+
+% Comments begin with two dots and a space. Anything may
+% follow, except for the syntax of footnotes, hyperlink
+% targets, directives, or substitution definitions.
+%
+% Double-dashes -- "--" -- must be escaped somehow in HTML output.
+%
+% Comments may contain non-ASCII characters: ä ö ü æ ø å
+
+(View the HTML source to see the comment.)
+
+
+\subsection{2.17 Raw text%
+ \label{raw-text}%
+}
+
+This does not necessarily look nice, because there may be missing white space.
+
+It’s just there to freeze the behavior.
+
+A test.
+
+Second test.
+
+\DUrole{myclass}{Another test with myclass set.}
+
+This is the \DUrole{myrawroleclass}{fourth test} with myrawroleclass set.
+
+Fifth test in LaTeX.\\Line two.
+
+
+\subsection{2.18 Container%
+ \label{container}%
+}
+
+\begin{DUclass}{custom}
+
+paragraph 1
+
+paragraph 2
+\end{DUclass}
+
+% currently not implemented in LaTeX:
+% .. include:: data/header_footer.txt
+
+
+\subsection{2.19 Colspanning tables%
+ \label{colspanning-tables}%
+}
+
+This table has a cell spanning two columns:
+
+\setlength{\DUtablewidth}{\linewidth}
+\begin{longtable*}[c]{|p{0.075\DUtablewidth}|p{0.075\DUtablewidth}|p{0.086\DUtablewidth}|}
+\hline
+\multicolumn{2}{|p{0.15\DUtablewidth}|}{\textbf{%
+Inputs
+}} & \textbf{%
+Output
+} \\
+\hline
+\textbf{%
+A
+} & \textbf{%
+B
+} & \textbf{%
+A or B
+} \\
+\hline
+\endfirsthead
+\hline
+\multicolumn{2}{|p{0.15\DUtablewidth}|}{\textbf{%
+Inputs
+}} & \textbf{%
+Output
+} \\
+\hline
+\textbf{%
+A
+} & \textbf{%
+B
+} & \textbf{%
+A or B
+} \\
+\hline
+\endhead
+\multicolumn{3}{c}{\hfill ... continued on next page} \\
+\endfoot
+\endlastfoot
+
+False
+ &
+False
+ &
+False
+ \\
+\hline
+
+True
+ &
+False
+ &
+True
+ \\
+\hline
+
+False
+ &
+True
+ &
+True
+ \\
+\hline
+
+True
+ &
+True
+ &
+True
+ \\
+\hline
+\end{longtable*}
+
+
+\subsection{2.20 Rowspanning tables%
+ \label{rowspanning-tables}%
+}
+
+Here’s a table with cells spanning several rows:
+
+\setlength{\DUtablewidth}{\linewidth}
+\begin{longtable*}[c]{|p{0.296\DUtablewidth}|p{0.156\DUtablewidth}|p{0.226\DUtablewidth}|}
+\hline
+\textbf{%
+Header row, column 1
+(header rows optional)
+} & \textbf{%
+Header 2
+} & \textbf{%
+Header 3
+} \\
+\hline
+\endfirsthead
+\hline
+\textbf{%
+Header row, column 1
+(header rows optional)
+} & \textbf{%
+Header 2
+} & \textbf{%
+Header 3
+} \\
+\hline
+\endhead
+\multicolumn{3}{c}{\hfill ... continued on next page} \\
+\endfoot
+\endlastfoot
+
+body row 1, column 1
+ &
+column 2
+ &
+column 3
+ \\
+\hline
+
+body row 2
+ & \multirow{2}{0.16\DUtablewidth}{%
+Cells may
+span rows.
+} & \multirow{2}{0.23\DUtablewidth}{%
+Another
+rowspanning
+cell.
+} \\
+\cline{1-1}
+
+body row 3
+ & & \\
+\hline
+\end{longtable*}
+
+
+\subsection{2.21 List Tables%
+ \label{list-tables}%
+}
+
+Here’s a list table exercising all features:
+
+\setlength{\DUtablewidth}{40em}
+\begin{longtable}[c]{|p{0.133\DUtablewidth}|p{0.249\DUtablewidth}|p{0.365\DUtablewidth}|}
+\caption{list table with integral header}\\
+\hline
+\textbf{%
+Treat
+} & \textbf{%
+Quantity
+} & \textbf{%
+Description
+} \\
+\hline
+\endfirsthead
+\caption[]{list table with integral header (... continued)}\\
+\hline
+\textbf{%
+Treat
+} & \textbf{%
+Quantity
+} & \textbf{%
+Description
+} \\
+\hline
+\endhead
+\multicolumn{3}{c}{\hfill ... continued on next page} \\
+\endfoot
+\endlastfoot
+\textbf{%
+Albatross
+} &
+2.99
+ &
+On a stick!
+ \\
+\hline
+\textbf{%
+Crunchy Frog
+} &
+1.49
+ &
+If we took the bones out, it wouldn’t be
+crunchy, now would it?
+ \\
+\hline
+\textbf{%
+Gannet Ripple
+} &
+1.99
+ &
+On a stick!
+ \\
+\hline
+\end{longtable}
+
+\begin{longtable}[c]{|l|l|}
+\caption{center aligned list table}\\
+\hline
+Albatross & 2.99 \\
+\hline
+Crunchy Frog & 1.49 \\
+\hline
+Gannet Ripple & 1.99 \\
+\hline
+\end{longtable}
+
+
+\subsection{2.22 Custom Roles%
+ \label{custom-roles}%
+}
+
+\begin{itemize}
+\item A role based on an existing role.
+
+\texttt{\DUrole{custom}{one}} \texttt{\DUrole{custom}{two}} \texttt{\DUrole{custom}{three}}
+
+\item A new role.
+
+\DUrole{customnew}{one two three}
+
+\item A role with class attribute.
+
+\DUrole{special}{interpreted text}
+
+\item A language-switching role:
+
+Let’s count in German \foreignlanguage{ngerman}{eins zwei drei}.
+
+\item A role with multiple class attributes, styled with raw directives:
+
+\newcommand{\DUrolegreen}[1]{\textcolor{green}{#1}}
+\newcommand{\DUrolesc}[1]{\textsc{#1}}
+
+The following works in most browsers but does not validate
+(\texttt{<style>} is only allowed in the document head):
+
+\begin{quote}
+\begin{alltt}
+.. raw:: html
+
+ <style type="text/css"><!-{}-
+ .green \{color: green;\}
+ .sc \{font-variant: small-caps;\}
+ -{}-></style>
+\end{alltt}
+\end{quote}
+
+\DUrole{green}{\DUrole{sc}{\foreignlanguage{british}{British colourful text in small-caps}}}.
+\end{itemize}
+
+
+\subsection{2.23 Mathematics%
+ \label{mathematics}%
+}
+
+Docutils supports inline math with the prefix or postfix \texttt{:math:}
+role specificator, $n! + \sin(x_n^2)$ and $A_\text{c} =
+\frac{\pi}{4} d^2$, as well as displayed math via the
+\DUroletitlereference{math} directive:
+%
+\begin{equation*}
+f(\epsilon) = \frac{1}{1 + \exp\left(\frac{\varepsilon}{k_\text{B}T}\right)}
+\end{equation*}
+Content may start on the first line of the directive, e.g.
+%
+\begin{equation*}
+N = \frac{\text{number of apples}}{7}
+\end{equation*}
+Equations can be labeled with a reference name using the \texttt{:name:} option.
+See \hyperref[eq-m]{eq:M} and \hyperref[eq-schrodinger]{eq:schrödinger} below.
+
+The determinant of the matrix
+%
+\begin{equation*}
+\mathbf{M} = \left(\begin{matrix}a&b\\c&d\end{matrix}\right)
+\phantomsection
+\label{eq-m}
+\end{equation*}
+is $|\mathbf{M}| = ad - bc$.
+
+More than one display math block can be put in one math directive.
+For example, the following sum and integral with limits:
+%
+\begin{equation*}
+\int_0^1 x^n dx = \frac{1}{n + 1}
+\end{equation*}%
+\begin{equation*}
+\sum_{n=1}^m n = \frac{m(m+1)}{2}
+\end{equation*}
+LaTeX-supported Unicode math symbols can be used in math roles and
+directives:
+
+The Schrödinger equation
+%
+\begin{equation*}
+i\hbar \frac{\partial }{\partial t}\Psi = \hat{H}\Psi ,
+\phantomsection
+\label{eq-schrodinger}
+\end{equation*}
+with the \emph{wave function} $\Psi $, describes how the quantum state of a
+physical system changes in time.
+
+\begin{description}
+\item[{Math-Accents:}] \leavevmode
+\setlength{\DUtablewidth}{\linewidth}
+\begin{longtable*}[c]{p{0.315\DUtablewidth}p{0.315\DUtablewidth}p{0.315\DUtablewidth}}
+
+$\acute{a}$ \texttt{\textbackslash{}acute\{a\}}
+ &
+$\dot{t}$ \texttt{\textbackslash{}dot\{t\}}
+ &
+$\hat{\gamma}$ \texttt{\textbackslash{}hat\{\textbackslash{}gamma\}}
+ \\
+
+$\grave{a}$ \texttt{\textbackslash{}grave\{a\}}
+ &
+$\ddot{t}$ \texttt{\textbackslash{}ddot\{t\}}
+ &
+$\tilde{\alpha}$ \texttt{\textbackslash{}tilde\{\textbackslash{}alpha\}}
+ \\
+
+$\breve{x}$ \texttt{\textbackslash{}breve\{x\}}
+ &
+$\dddot{t}$ \texttt{\textbackslash{}dddot\{t\}}
+ &
+$\vec{\imath}$ \texttt{\textbackslash{}vec\{\textbackslash{}imath\}}
+ \\
+
+$\check{a}$ \texttt{\textbackslash{}check\{a\}}
+ &
+$\bar{a}$ \texttt{\textbackslash{}bar\{a\}}
+ &
+$\vec{R}$ \texttt{\textbackslash{}vec\{R\}}
+ \\
+\end{longtable*}
+
+\end{description}
+
+% \widetilde{xxx}
+% \widehat{xxx}
+
+Modulation Transfer Function:
+%
+\begin{equation*}
+\text{MTF} = \left|\frac{\mathcal{F}\{s(x)\}}
+ {\mathcal{F}\{ s(x)\} |_{\omega _{x}=0}}\right|
+ = \mathrm{abs}\left(\frac
+ {\int _{-\infty }^{\infty }s(x) \mathrm{e}^{\mathrm{i}\omega _{x}x}\mathrm{d}{x}}
+ {\int _{-\infty }^{\infty }s(x)\mathrm{d}{x}}
+ \right).
+\end{equation*}
+Math split over two lines: If a double backslash is detected outside a
+\texttt{\textbackslash{}begin\{...\} \textbackslash{}end\{...\}} pair, the math code is wrapped in an \href{ftp://ftp.ams.org/ams/doc/amsmath/short-math-guide.pdf}{AMSmath}\DUfootnotemark{footnote-reference-14}{footnote-8}{7}
+\texttt{align} environment:
+%
+\begin{align*}
+s_{\mathrm{out}}(x) & = s_{\mathrm{in}}(x') * s_\delta (x-x') \\
+ & = \int s_{\mathrm{in}}(x')s_\delta (x-x')\mathrm{d}x'
+\end{align*}
+Cases (“manually”, with \texttt{matrix} environment):
+%
+\begin{equation*}
+\mathrm{sgn}(x) = \left\{\begin{matrix}
+ -1 & x<0\\
+ 1 & x>0
+ \end{matrix}\right.
+\end{equation*}
+Cases with the \href{ftp://ftp.ams.org/ams/doc/amsmath/short-math-guide.pdf}{AMSmath}\DUfootnotemark{footnote-reference-15}{footnote-8}{7} \texttt{cases} environment (not (yet) supported by
+HTML writers with \texttt{-{}-math-output=MathML}):
+%
+\begin{equation*}
+\mathrm{sgn}(x) = \begin{cases}
+ -1 & x<0\\
+ 1 & x>0
+ \end{cases}
+\end{equation*}
+
+\section{3 Tests for the LaTeX writer%
+ \label{tests-for-the-latex-writer}%
+}
+
+Test syntax elements which may cause trouble for the LaTeX writer but might
+not need to be tested with other writers (e.g. the HTML writer).
+
+
+\subsection{3.1 Custom Roles in LaTeX%
+ \label{custom-roles-in-latex}%
+}
+
+\begin{itemize}
+\item Role names and class arguments are converted to conform to the
+regular expression \texttt{{[}a-z{]}{[}-a-z0-9{]}*} (letters are downcased,
+accents and similar decoration is stripped, non-conforming
+characters are replaced by a hyphen).
+
+Class arguments may contain numbers and hyphens, which need special
+treatment in LaTeX command names.
+
+\DUrole{large}{\DUrole{custom4}{\DUrole{small-caps}{\DUrole{custom-role}{\DUrole{custom-role}{Text with role “custom4”}}}}} (but without styling by \texttt{DUrole*}
+macros).
+
+\item With LaTeX, roles can be styled within the document using the \DUroletitlereference{raw}
+directive.
+
+\newcommand{\DUrolelarge}[1]{{\large #1}}
+\makeatletter
+\@namedef{DUrolesmall-caps}{\textsc}
+\@namedef{DUrolecustom4}{\textbf}
+\makeatother
+
+\DUrole{large}{\DUrole{custom4}{\DUrole{small-caps}{\DUrole{custom-role}{\DUrole{custom-role}{inline text}}}}} in large, bold, small-caps.
+
+\item Custom roles can be based on standard roles:
+
+This is a \emph{\DUrole{custom-emphasis}{customized emphasis text role}}
+
+This is a \texttt{\DUrole{custom-literal}{customized literal text role}}
+
+This is a \textbf{\DUrole{custom-strong}{customized strong text role}}
+
+This is a \textsubscript{\DUrole{custom-subscript}{customized subscript text role}}
+
+This is a \textsuperscript{\DUrole{custom-superscript}{customized superscript text role}}
+
+This is a \DUroletitlereference{\DUrole{custom-title-reference}{customized title-reference text role}}
+\end{itemize}
+
+
+\subsection{3.2 class handling%
+ \label{class-handling}%
+}
+
+This section tests class handling for block level elements by the LaTeX
+writer. See the input file \texttt{classes\_latex.txt} for the raw LaTeX code used
+to style the examples.
+
+An “epigraph” directive is exported as “quote” wrapped in a “DUclass”
+environment. Here, it is styled by a “DUCLASSepigraph” environment
+redefining the “quote” environment as “minipage”:
+
+\newcommand*{\DUCLASSepigraph}{%
+ \renewenvironment{quote}{\vspace{1em}
+ \footnotesize\hfill{}%
+ \begin{minipage}{0.4\columnwidth}}%
+ {\end{minipage}\vskip\baselineskip}}
+
+\begin{DUclass}{epigraph}
+\begin{quote}
+Do not play this piece fast. It is never right to play \emph{Ragtime} fast.
+\nopagebreak
+
+\raggedleft —Scott Joplin
+\end{quote}
+\end{DUclass}
+
+Raw latex is also used to style the following lists: “DUCLASSenumerateitems”
+redefines “itemize” as “enumerate”, “DUCLASSrules” draws horizontal lines
+above and below.
+
+\newcommand*{\DUCLASSenumerateitems}{%
+ \renewenvironment{itemize}{\begin{enumerate}}%
+ {\end{enumerate}}%
+}
+
+\newenvironment{DUCLASSrules}%
+ {\noindent\rule[0.5ex]{1\columnwidth}{1pt}}%
+ {\noindent\rule[0.5ex]{1\columnwidth}{1pt}}
+
+An “enumerated” bullet list:
+
+\begin{DUclass}{enumerateitems}
+\begin{itemize}
+\item item
+
+\item next item
+
+\item third item
+\end{itemize}
+\end{DUclass}
+
+A list with lines above and below:
+
+\begin{DUclass}{rules}
+\begin{itemize}
+\item item
+
+\item next item
+\end{itemize}
+\end{DUclass}
+
+A normal bullet list is kept unchanged by the above redefinitions:
+
+\begin{itemize}
+\item item
+
+\item next item
+
+\item third item
+\end{itemize}
+
+A container wraps several elements in a common “class wrapper”. Here, we use
+it to set 2 paragraphs and a list in small caps:
+
+\newcommand*{\DUCLASSscshape}{\scshape}
+
+\begin{DUclass}{scshape}
+
+paragraph 1
+
+paragraph 2
+
+\begin{itemize}
+\item bullet list
+
+\item still bullet list
+\end{itemize}
+\end{DUclass}
+
+A right-aligned line-block. Alignment handling is built into the latex
+writer for image, table, and line block elements.
+
+\begin{DUlineblock}{0em}
+\raggedleft
+\item[] Max Mustermann
+\item[] Waldstr. 22
+\item[] D 01234 Testdorf
+\item[] Tel.: 0123/456789
+\end{DUlineblock}
+
+
+\subsection{3.3 More Tables%
+ \label{more-tables}%
+}
+
+A table with multi-paragraph multicolumn cells:
+
+\setlength{\DUtablewidth}{\linewidth}
+\begin{longtable*}[c]{|p{0.133\DUtablewidth}|p{0.179\DUtablewidth}|p{0.179\DUtablewidth}|p{0.110\DUtablewidth}|p{0.121\DUtablewidth}|p{0.145\DUtablewidth}|}
+\hline
+
+test
+ &
+\textbf{bold hd}
+ & \multicolumn{3}{p{0.41\DUtablewidth}|}{%
+multicolumn 1
+
+With a second paragraph
+} &
+\emph{emph hd}
+ \\
+\hline
+\multicolumn{2}{|p{0.31\DUtablewidth}|}{%
+multicolumn 2
+
+With a second paragraph
+} &
+cell
+ &
+cell
+ &
+cell
+ &
+cell
+ \\
+\hline
+
+cell
+ & \multicolumn{2}{p{0.36\DUtablewidth}|}{%
+multicolumn 3 (one line,
+but very very very very
+very looooong)
+} &
+cell
+ &
+cell
+ &
+cell
+ \\
+\hline
+
+cell
+ &
+cell
+ &
+cell
+ & \multicolumn{3}{p{0.38\DUtablewidth}|}{%
+Short multicolumn 4
+} \\
+\hline
+\end{longtable*}
+
+Tables with multi-paragraph multirow cells currently fail due to a LaTeX
+limitation (see \url{https://sourceforge.net/p/docutils/bugs/225/}).
+
+A table with multirow header and column-widths set by LaTeX:
+
+\begin{longtable*}[c]{|l|l|}
+\hline
+\multirow{2}{*}{\textbf{XXX}} & \textbf{Variable Summary} \\
+\cline{2-2}
+ & \textbf{Description} \\
+\hline
+\endfirsthead
+\hline
+\multirow{2}{*}{\textbf{XXX}} & \textbf{Variable Summary} \\
+\cline{2-2}
+ & \textbf{Description} \\
+\hline
+\endhead
+\multicolumn{2}{c}{\hfill ... continued on next page} \\
+\endfoot
+\endlastfoot
+\multicolumn{2}{|l|}{multicollumn cell} \\
+\hline
+\end{longtable*}
+
+In a table with column-widths set by LaTeX, each cell has just one line.
+Paragraphs are merged (a warning is given).
+
+\begin{longtable*}[c]{|l|l|}
+\hline
+11 & first paragraph
+second paragraph
+third paragraph \\
+\hline
+21 & 22 \\
+\hline
+\end{longtable*}
+
+% This file is used by the standalone_rst_latex test.
+
+
+\subsection{3.4 Option lists%
+ \label{option-lists-1}%
+}
+
+The LaTeX-2e description environment is used for definition lists.
+The definition is continued on the same line as the term, this should
+not happen if a option-list is at the top of the definition.
+
+If the option list is not at the first element in the definition, it
+is contained in a quote
+
+\begin{quote}
+\begin{DUoptionlist}
+\item[-{}-help] show help
+
+\item[-v] verbose
+\end{DUoptionlist}
+\end{quote}
+
+\begin{description}
+\item[{In a definition list:}] \leavevmode
+\begin{DUoptionlist}
+\item[-{}-help] show help
+
+\item[-v] verbose
+\end{DUoptionlist}
+
+\end{description}
+
+
+\subsection{3.5 Monospaced non-alphanumeric characters%
+ \label{monospaced-non-alphanumeric-characters}%
+}
+
+These are all ASCII characters except a-zA-Z0-9 and space:
+
+\texttt{!!!\textquotedbl{}\textquotedbl{}\textquotedbl{}\#\#\#\$\$\$\%\%\%\&\&\&'{}'{}'((()))***+++,{},{},-{}-{}-...///:::}
+
+\texttt{;;;<{}<{}<===>{}>{}>???@@@{[}{[}{[}\textbackslash{}\textbackslash{}\textbackslash{}{]}{]}{]}\textasciicircum{}\textasciicircum{}\textasciicircum{}\_\_\_`{}`{}`\{\{\{|||\}\}\}\textasciitilde{}\textasciitilde{}\textasciitilde{}}
+
+\texttt{xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx}
+
+The two lines of non-alphanumeric characters should both have the same
+width as the third line.
+
+
+\subsection{3.6 Non-ASCII characters%
+ \label{non-ascii-characters}%
+}
+
+Punctuation and footnote symbols
+
+\setlength{\DUtablewidth}{\linewidth}
+\begin{longtable*}[c]{|p{0.028\DUtablewidth}|p{0.424\DUtablewidth}|}
+\hline
+
+–
+ &
+en-dash
+ \\
+\hline
+
+—
+ &
+em-dash
+ \\
+\hline
+
+‘
+ &
+single turned comma quotation mark
+ \\
+\hline
+
+’
+ &
+single comma quotation mark
+ \\
+\hline
+
+‚
+ &
+low single comma quotation mark
+ \\
+\hline
+
+“
+ &
+double turned comma quotation mark
+ \\
+\hline
+
+”
+ &
+double comma quotation mark
+ \\
+\hline
+
+„
+ &
+low double comma quotation mark
+ \\
+\hline
+
+†
+ &
+dagger
+ \\
+\hline
+
+‡
+ &
+double dagger
+ \\
+\hline
+
+\ding{169}
+ &
+black diamond suit
+ \\
+\hline
+
+\ding{170}
+ &
+black heart suit
+ \\
+\hline
+
+♠
+ &
+black spade suit
+ \\
+\hline
+
+♣
+ &
+black club suit
+ \\
+\hline
+
+…
+ &
+ellipsis
+ \\
+\hline
+
+™
+ &
+trade mark sign
+ \\
+\hline
+
+⇔
+ &
+left-right double arrow
+ \\
+\hline
+\end{longtable*}
+
+The \DUroletitlereference{Latin-1 extended} Unicode block
+
+\setlength{\DUtablewidth}{\linewidth}
+\begin{longtable*}[c]{|p{0.051\DUtablewidth}|p{0.028\DUtablewidth}|p{0.028\DUtablewidth}|p{0.028\DUtablewidth}|p{0.028\DUtablewidth}|p{0.028\DUtablewidth}|p{0.028\DUtablewidth}|p{0.028\DUtablewidth}|p{0.028\DUtablewidth}|p{0.028\DUtablewidth}|p{0.028\DUtablewidth}|}
+\hline
+
+%
+ &
+0
+ &
+1
+ &
+2
+ &
+3
+ &
+4
+ &
+5
+ &
+6
+ &
+7
+ &
+8
+ &
+9
+ \\
+\hline
+
+160
+ & &
+¡
+ &
+¢
+ &
+£
+ & &
+¥
+ &
+¦
+ &
+§
+ &
+¨
+ &
+©
+ \\
+\hline
+
+170
+ &
+ª
+ &
+«
+ &
+¬
+ &
+\-
+ &
+®
+ &
+¯
+ &
+°
+ &
+±
+ &
+²
+ &
+³
+ \\
+\hline
+
+180
+ &
+´
+ &
+µ
+ &
+¶
+ &
+·
+ &
+¸
+ &
+¹
+ &
+º
+ &
+»
+ &
+¼
+ &
+½
+ \\
+\hline
+
+190
+ &
+¾
+ &
+¿
+ &
+À
+ &
+Á
+ &
+Â
+ &
+Ã
+ &
+Ä
+ &
+Å
+ &
+Æ
+ &
+Ç
+ \\
+\hline
+
+200
+ &
+È
+ &
+É
+ &
+Ê
+ &
+Ë
+ &
+Ì
+ &
+Í
+ &
+Î
+ &
+Ï
+ &
+Ð
+ &
+Ñ
+ \\
+\hline
+
+210
+ &
+Ò
+ &
+Ó
+ &
+Ô
+ &
+Õ
+ &
+Ö
+ &
+×
+ &
+Ø
+ &
+Ù
+ &
+Ú
+ &
+Û
+ \\
+\hline
+
+220
+ &
+Ü
+ &
+Ý
+ &
+Þ
+ &
+ß
+ &
+à
+ &
+á
+ &
+â
+ &
+ã
+ &
+ä
+ &
+å
+ \\
+\hline
+
+230
+ &
+æ
+ &
+ç
+ &
+è
+ &
+é
+ &
+ê
+ &
+ë
+ &
+ì
+ &
+í
+ &
+î
+ &
+ï
+ \\
+\hline
+
+240
+ &
+ð
+ &
+ñ
+ &
+ò
+ &
+ó
+ &
+ô
+ &
+õ
+ &
+ö
+ &
+÷
+ &
+ø
+ &
+ù
+ \\
+\hline
+
+250
+ &
+ú
+ &
+û
+ &
+ü
+ &
+ý
+ &
+þ
+ &
+ÿ
+ & & & & \\
+\hline
+\end{longtable*}
+
+\begin{itemize}
+\item The following line should not be wrapped, because it uses
+no-break spaces (\textbackslash{}u00a0):
+
+X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X
+
+\item Line wrapping with/without breakpoints marked by soft hyphens
+(\textbackslash{}u00ad):
+
+pdn\-derd\-mdtd\-ri\-schpdn\-derd\-mdtd\-ri\-schpdn\-derd\-mdtd\-ri\-schpdn\-derd\-mdtd\-ri\-schpdn\-derd\-mdtd\-ri\-sch
+
+pdnderdmdtdrischpdnderdmdtdrischpdnderdmdtdrischpdnderdmdtdrischpdnderdmdtdrisch
+\end{itemize}
+
+
+\subsection{3.7 Encoding special chars%
+ \label{encoding-special-chars}%
+}
+
+The LaTeX Info pages lists under “2.18 Special Characters”
+
+\begin{quote}
+The following characters play a special role in LaTeX and are called
+“special printing characters”, or simply “special characters”.
+
+\begin{quote}
+\# \$ \% \& \textasciitilde{} \_ \textasciicircum{} \textbackslash{} \{ \}
+\end{quote}
+\end{quote}
+
+The special chars verbatim:
+
+\begin{quote}
+\begin{alltt}
+# $ % & ~ _ ^ \textbackslash{} \{ \}
+\end{alltt}
+\end{quote}
+
+However also \emph{square brackets} {[}{]} need special care.
+
+\begin{quote}
+Commands with optional arguments (e.g. \texttt{\textbackslash{}item}) check
+if the token right after the macro name is an opening bracket.
+In that case the contents between that bracket and the following
+closing bracket on the same grouping level are taken as the
+optional argument. What makes this unintuitive is the fact that
+the square brackets aren’t grouping characters themselves, so in
+your last example \texttt{\textbackslash{}item{[}{[}...{]}{]}} the optional argument consists of
+{[}… (without the closing bracket).
+\end{quote}
+
+Compare the items in the following lists:
+
+\begin{itemize}
+\item simple item
+
+\item {[}bracketed{]} item
+\end{itemize}
+
+\begin{description}
+\item[{simple}] \leavevmode
+description term
+
+\item[{{[}bracketed{]}}] \leavevmode
+description term
+
+\end{description}
+
+The OT1 font-encoding has different characters for the less-than,
+greater-than and bar, < | >, except for typewriter font \DUroletitlereference{cmtt}:
+
+\begin{quote}
+\begin{alltt}
+< | >
+\end{alltt}
+\end{quote}
+
+
+\subsection{3.8 Hyperlinks and -targets%
+ \label{hyperlinks-and-targets}%
+}
+
+In LaTeX, we must set an explicit anchor (\texttt{\textbackslash{}phantomsection}) for a
+%
+\phantomsection\label{hypertarget-in-plain-text}hypertarget in plain text or in a figure but not in a longtable or
+caption:
+
+\setlength{\DUtablewidth}{\linewidth}
+\begin{longtable}[c]{|p{0.075\DUtablewidth}|p{0.075\DUtablewidth}|p{0.075\DUtablewidth}|}
+\caption{Table with %
+\label{hypertarget-in-table-title}hypertarget in table title.}\\
+\hline
+
+False
+ &
+True
+ &
+None
+ \\
+\hline
+\end{longtable}
+\label{table-label}
+
+\begin{figure}
+\phantomsection\label{figure-label}
+\noindent\makebox[\linewidth][c]{\includegraphics{../../../docs/user/rst/images/biohazard.png}}
+\caption{Figure with %
+\label{hypertarget-in-figure-caption}hypertarget in figure caption.}
+\begin{DUlegend}
+Legend with %
+\phantomsection\label{hypertarget-in-figure-legend}hypertarget in figure legend.
+\end{DUlegend}
+\end{figure}
+
+\includegraphics{../../../docs/user/rst/images/biohazard.png}
+\phantomsection\label{image-label}
+
+See \hyperref[hypertarget-in-plain-text]{hypertarget in plain text},
+\hyperref[table-label]{table label}, \hyperref[hypertarget-in-table-title]{hypertarget in table title},
+\hyperref[figure-label]{figure label}, \hyperref[hypertarget-in-figure-caption]{hypertarget in figure caption},
+\hyperref[hypertarget-in-figure-legend]{hypertarget in figure legend}, and
+\hyperref[image-label]{image label}.
+
+
+\subsection{3.9 External references%
+ \label{external-references}%
+}
+
+Long URLs should be wrapped in the PDF. This can be achieved with the
+\texttt{\textbackslash{}url} command which is used by the LaTeX writer whenever the content
+(name) of a reference node equals the link URL.
+
+\begin{description}
+\item[{Example:}] \leavevmode
+a long URL that should wrap in the output
+\url{http://docutils.sourceforge.net/docs/user/latex.html\#id79}
+
+\end{description}
+
+If the argument contains any “\%”, “\#”, or “\textasciicircum{}\textasciicircum{}”, or ends with \texttt{\textbackslash{}}, it can’t
+be used in the argument to another command. The argument must not contain
+unbalanced braces.
+
+The characters \textasciicircum{}, \{, \}, and \texttt{\textbackslash{}} are invalid in a “http:” or “ftp:” URL
+and not recognized as part of it:
+
+\begin{DUlineblock}{0em}
+\item[] \url{http://www.example.org}/strange\textasciicircum{}\textasciicircum{}name
+\item[] \url{http://www.example.org}\textbackslash{}using\textbackslash{}DOS\textbackslash{}paths\textbackslash{}
+\item[] \url{http://www.example.org/XML}/strange\{n\}ame
+\end{DUlineblock}
+
+They can, however be used in paths and/or filenames.
+
+Handling by the LaTeX writer:
+
+\begin{itemize}
+\item \texttt{\#}, \texttt{\textbackslash{}} and \texttt{\%} are escaped:
+
+\begin{DUlineblock}{0em}
+\item[] \href{http://www.w3.org/XML/Schema\#dev}{URL with \#}
+\url{http://www.w3.org/XML/Schema\#dev}
+\item[] \href{http://www.w3.org/XML/Schema\%dev}{URL with \%}
+\url{http://example.org/Schema\%dev}
+\item[] \href{A:DOS\\path\\}{file with DOS path}\DUfootnotemark{footnote-reference-18}{footnote-10}{9} \url{A:DOS\\path\\}\DUfootnotemark{footnote-reference-19}{footnote-10}{9}
+\end{DUlineblock}
+
+\DUadmonition[note]{
+\DUtitle[note]{Note}
+
+These URLs are typeset inside a LaTeX command without error.
+
+\begin{DUlineblock}{0em}
+\item[] \url{http://www.w3.org/XML/Schema\#dev}
+\item[] \url{http://example.org/Schema\%dev}
+\item[] \url{A:DOS\\path\\}\DUfootnotemark{footnote-reference-20}{footnote-10}{9}
+\end{DUlineblock}
+}
+\end{itemize}
+
+\begin{itemize}
+\item \texttt{\textasciicircum{}\textasciicircum{}} LaTeX’s special syntax for characters results in “strange” replacements
+(both with \texttt{\textbackslash{}href} and \texttt{\textbackslash{}url}). A warning is given.
+
+\href{../strange^^name}{file with \textasciicircum{}\textasciicircum{}}:
+\url{../strange^^name}
+
+\item Unbalanced braces, \{ or \}, will fail (both with \texttt{\textbackslash{}href} and \texttt{\textbackslash{}url}):
+
+\begin{quote}
+\begin{alltt}
+`file with \{ <../strange\{name>`__
+`<../strange\{name>`__
+\end{alltt}
+\end{quote}
+
+while balanced braces are suported:
+
+\begin{DUlineblock}{0em}
+\item[] \url{../strange{n}ame}
+\item[] \url{../st{r}ange{n}ame}
+\item[] \url{../{st{r}ange{n}ame}}
+\end{DUlineblock}
+\end{itemize}
+
+
+\subsection{3.10 Section titles with \hyperref[inline-markup]{inline markup}%
+ \label{section-titles-with-inline-markup}%
+}
+
+
+\subsubsection{3.10.1 \emph{emphasized}, H\textsubscript{2}O and $x^2$%
+ \label{emphasized-h2o-and-x-2}%
+}
+
+
+\subsubsection{3.10.2 Substitutions work%
+ \label{substitutions-fail}%
+}
+
+
+\subsection{3.11 Deeply nested sections%
+ \label{deeply-nested-sections}%
+}
+
+In LaTeX and HTML,
+
+
+\subsubsection{3.11.1 Level 3%
+ \label{level-3}%
+}
+
+nested sections
+
+
+\paragraph{3.11.1.1 level 4%
+ \label{level-4}%
+}
+
+reach at some level
+
+
+\subparagraph{3.11.1.1.1 level 5%
+ \label{level-5}%
+}
+
+(depending on the document class)
+
+
+\DUtitle[sectionVI]{3.11.1.1.1.1 level 6%
+ \label{level-6}%
+}
+
+an unsupported level.
+
+% unusual combinations (currently separately tested)
+% .. include:: data/latex_cornercases.txt
+
+% Preface for System Messages:
+
+
+\section{4 Error Handling%
+ \label{error-handling}%
+}
+
+Any errors caught during processing will generate system messages.
+
+There should be five messages in the following, auto-generated
+section, “Docutils System Messages”:
+
+% section should be added by Docutils automatically
+
+
+\section[Docutils System Messages]{\color{red}Docutils System Messages%
+}
+
+\DUadmonition[system-message]{
+\DUtitle[system-message]{system-message}
+\raisebox{1em}{\hypertarget{system-message-1}{}}
+
+{\color{red}ERROR/3} in \texttt{functional/input/data/standard.txt}, line~104
+
+\hyperlink{problematic-1}{
+Undefined substitution referenced: \textquotedbl{}problematic\textquotedbl{}.
+}}
+
+\DUadmonition[system-message]{
+\DUtitle[system-message]{system-message}
+\raisebox{1em}{\hypertarget{system-message-2}{}}
+
+{\color{red}ERROR/3} in \texttt{functional/input/data/standard.txt}, line~392
+
+\hyperlink{footnote-reference-8}{
+Unknown target name: \textquotedbl{}5\textquotedbl{}.
+}}
+
+\DUadmonition[system-message]{
+\DUtitle[system-message]{system-message}
+\raisebox{1em}{\hypertarget{system-message-3}{}}
+
+{\color{red}ERROR/3} in \texttt{functional/input/data/standard.txt}, line~401
+
+\hyperlink{citation-reference-3}{
+Unknown target name: \textquotedbl{}nonexistent\textquotedbl{}.
+}}
+
+\DUadmonition[system-message]{
+\DUtitle[system-message]{system-message}
+\raisebox{1em}{\hypertarget{system-message-4}{}}
+
+{\color{red}ERROR/3} in \texttt{functional/input/data/standard.txt}, line~428
+
+\hyperlink{problematic-2}{
+Unknown target name: \textquotedbl{}hyperlink reference without a target\textquotedbl{}.
+}}
+
+\DUadmonition[system-message]{
+\DUtitle[system-message]{system-message}
+\raisebox{1em}{\hypertarget{system-message-5}{}}
+
+{\color{red}ERROR/3} in \texttt{functional/input/data/standard.txt}, line~441
+
+\hyperlink{problematic-3}{
+Duplicate target name, cannot be used as a unique reference: \textquotedbl{}duplicate target names\textquotedbl{}.
+}}
+
+\end{document}
--- /dev/null
+.\" Man page generated from reStructuredText.
+.
+.TH RST2MAN 1 "2006-10-22" "0.1" "text processing"
+.SH NAME
+rst2man \- generate unix manpages from reStructured text
+.
+.nr rst2man-indent-level 0
+.
+.de1 rstReportMargin
+\\$1 \\n[an-margin]
+level \\n[rst2man-indent-level]
+level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
+-
+\\n[rst2man-indent0]
+\\n[rst2man-indent1]
+\\n[rst2man-indent2]
+..
+.de1 INDENT
+.\" .rstReportMargin pre:
+. RS \\$1
+. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin]
+. nr rst2man-indent-level +1
+.\" .rstReportMargin post:
+..
+.de UNINDENT
+. RE
+.\" indent \\n[an-margin]
+.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.nr rst2man-indent-level -1
+.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
+..
+.\" TODO: authors and author with name <email>
+.
+.SH SYNOPSIS
+.INDENT 0.0
+.INDENT 3.5
+rst2man.py inputfile outputfile
+.UNINDENT
+.UNINDENT
+.SH DESCRIPTION
+.sp
+rst2man transforms a reStructured text document into a unix man page.
+.sp
+In theory any valid reStructured text document should be processable,
+in reality this is
+.INDENT 0.0
+.IP \(bu 2
+a goal, that is not met yet
+.IP \(bu 2
+a goal that might never be met, because only few constructs are
+used in man pages \fIand\fP because the common text file does not adhere
+to man page requirements.
+.sp
+For example a unix man page belongs into a numbered section, 1 is
+user commands, 8 contains administrator commands and the headlines
+of all manpages are collected into a database, queryable with the
+programm \fBapropos\fP, therefore the headline should contain a short
+text describing into which group this command belongs.
+.sp
+These informations are collected from title, subtitle and the
+docinfo, see this document as an example.
+.UNINDENT
+.SH OPTIONS
+.INDENT 0.0
+.TP
+.BI \-\-config\fB= <file>
+Read configuration settings from <file>, if it exists.
+.TP
+.B \-\-version\fP,\fB \-V
+Show this program\(aqs version number and exit.
+.TP
+.B \-\-help\fP,\fB \-h
+Show this help message and exit.
+.UNINDENT
+.sp
+And a lot more standard docutils options.
+.SH FILES
+.sp
+None yet.
+.SH SEE ALSO
+.sp
+\fI\%docutils\fP
+\fI\%linux man page howto\fP
+.sp
+and \fBman man\fP also \fBman 7 man\fP
+.SH BUGS
+.INDENT 0.0
+.IP 1. 3
+Format options are included as they are required.
+.IP 2. 3
+bullet lists
+.IP 3. 3
+number lists
+.IP 4. 3
+math: The LaTeX source is shown, e.g. \fBn! + \esin(x_n^2)\fP\&.
+.UNINDENT
+.sp
+Discussion is still open.
+.SH AUTHOR
+grubert@users.sourceforge.net
+.SH COPYRIGHT
+public domain
+.\" Generated by docutils manpage writer.
+.
--- /dev/null
+<document ids="restructuredtext-test-document doctitle" names="restructuredtext\ test\ document doctitle" source="functional/input/standalone_rst_pseudoxml.txt" title="reStructuredText Test Document">
+ <title>
+ reStructuredText Test Document
+ <subtitle ids="examples-of-syntax-constructs subtitle" names="examples\ of\ syntax\ constructs subtitle">
+ Examples of Syntax Constructs
+ <decoration>
+ <header>
+ <paragraph>
+ Document header
+ <footer>
+ <paragraph>
+ Document footer
+ <docinfo>
+ <author>
+ David Goodger
+ <address xml:space="preserve">
+ 123 Example Street
+ Example, EX Canada
+ A1B 2C3
+ <contact>
+ <reference refuri="mailto:goodger@python.org">
+ goodger@python.org
+ <authors>
+ <author>
+ Me
+ <author>
+ Myself
+ <author>
+ I
+ <organization>
+ humankind
+ <date>
+ Now, or yesterday. Or maybe even
+ <emphasis>
+ before
+ yesterday.
+ <status>
+ This is a "work in progress"
+ <revision>
+ is managed by a version control system.
+ <version>
+ 1
+ <copyright>
+ This document has been placed in the public domain. You
+ may do with it as you wish. You may copy, modify,
+ redistribute, reattribute, sell, buy, rent, lease,
+ destroy, or improve it, quote it at length, excerpt,
+ incorporate, collate, fold, staple, or mutilate it, or do
+ anything else to it that your or anyone else's heart
+ desires.
+ <field classes="field-name">
+ <field_name>
+ field name
+ <field_body>
+ <paragraph>
+ This is a "generic bibliographic field".
+ <field classes="field-name-2">
+ <field_name>
+ field name "2"
+ <field_body>
+ <paragraph>
+ Generic bibliographic fields may contain multiple body elements.
+ <paragraph>
+ Like this.
+ <topic classes="dedication">
+ <title>
+ Dedication
+ <paragraph>
+ For Docutils users & co-developers.
+ <topic classes="abstract">
+ <title>
+ Abstract
+ <paragraph>
+ This is a test document, containing at least one example of each
+ reStructuredText construct.
+ <comment xml:space="preserve">
+ This is a comment. Note how any initial comments are moved by
+ transforms to after the document title, subtitle, and docinfo.
+ <target refid="doctitle">
+ <comment xml:space="preserve">
+ Above is the document title, and below is the subtitle.
+ They are transformed from section titles after parsing.
+ <target refid="subtitle">
+ <comment xml:space="preserve">
+ bibliographic fields (which also require a transform):
+ <meta content="reStructuredText, test, parser" name="keywords">
+ <meta content="A test document, containing at least one example of each reStructuredText construct." lang="en" name="description">
+ <raw format="latex" xml:space="preserve">
+ \pagebreak[4] % start ToC on new page
+ <topic classes="contents" ids="table-of-contents" names="table\ of\ contents">
+ <title>
+ Table of Contents
+ <bullet_list classes="auto-toc">
+ <list_item>
+ <paragraph>
+ <reference ids="toc-entry-1" refid="structural-elements">
+ <generated classes="sectnum">
+ 1
+ Structural Elements
+ <bullet_list classes="auto-toc">
+ <list_item>
+ <paragraph>
+ <reference ids="toc-entry-2" refid="section-title">
+ <generated classes="sectnum">
+ 1.1
+ Section Title
+ <list_item>
+ <paragraph>
+ <reference ids="toc-entry-3" refid="empty-section">
+ <generated classes="sectnum">
+ 1.2
+ Empty Section
+ <list_item>
+ <paragraph>
+ <reference ids="toc-entry-4" refid="transitions">
+ <generated classes="sectnum">
+ 1.3
+ Transitions
+ <list_item>
+ <paragraph>
+ <reference ids="toc-entry-5" refid="body-elements">
+ <generated classes="sectnum">
+ 2
+ Body Elements
+ <bullet_list classes="auto-toc">
+ <list_item>
+ <paragraph>
+ <reference ids="toc-entry-6" refid="paragraphs">
+ <generated classes="sectnum">
+ 2.1
+ Paragraphs
+ <bullet_list classes="auto-toc">
+ <list_item>
+ <paragraph>
+ <reference ids="toc-entry-7" refid="inline-markup">
+ <generated classes="sectnum">
+ 2.1.1
+ Inline Markup
+ <list_item>
+ <paragraph>
+ <reference ids="toc-entry-8" refid="bullet-lists">
+ <generated classes="sectnum">
+ 2.2
+ Bullet Lists
+ <list_item>
+ <paragraph>
+ <reference ids="toc-entry-9" refid="enumerated-lists">
+ <generated classes="sectnum">
+ 2.3
+ Enumerated Lists
+ <list_item>
+ <paragraph>
+ <reference ids="toc-entry-10" refid="definition-lists">
+ <generated classes="sectnum">
+ 2.4
+ Definition Lists
+ <list_item>
+ <paragraph>
+ <reference ids="toc-entry-11" refid="field-lists">
+ <generated classes="sectnum">
+ 2.5
+ Field Lists
+ <list_item>
+ <paragraph>
+ <reference ids="toc-entry-12" refid="option-lists">
+ <generated classes="sectnum">
+ 2.6
+ Option Lists
+ <list_item>
+ <paragraph>
+ <reference ids="toc-entry-13" refid="literal-blocks">
+ <generated classes="sectnum">
+ 2.7
+ Literal Blocks
+ <list_item>
+ <paragraph>
+ <reference ids="toc-entry-14" refid="line-blocks">
+ <generated classes="sectnum">
+ 2.8
+ Line Blocks
+ <list_item>
+ <paragraph>
+ <reference ids="toc-entry-15" refid="block-quotes">
+ <generated classes="sectnum">
+ 2.9
+ Block Quotes
+ <list_item>
+ <paragraph>
+ <reference ids="toc-entry-16" refid="doctest-blocks">
+ <generated classes="sectnum">
+ 2.10
+ Doctest Blocks
+ <list_item>
+ <paragraph>
+ <reference ids="toc-entry-17" refid="footnotes">
+ <generated classes="sectnum">
+ 2.11
+ Footnotes
+ <list_item>
+ <paragraph>
+ <reference ids="toc-entry-18" refid="citations">
+ <generated classes="sectnum">
+ 2.12
+ Citations
+ <list_item>
+ <paragraph>
+ <reference ids="toc-entry-19" refid="targets">
+ <generated classes="sectnum">
+ 2.13
+ Targets
+ <bullet_list classes="auto-toc">
+ <list_item>
+ <paragraph>
+ <reference ids="toc-entry-20" refid="duplicate-target-names">
+ <generated classes="sectnum">
+ 2.13.1
+ Duplicate Target Names
+ <list_item>
+ <paragraph>
+ <reference ids="toc-entry-21" refid="duplicate-target-names-1">
+ <generated classes="sectnum">
+ 2.13.2
+ Duplicate Target Names
+ <list_item>
+ <paragraph>
+ <reference ids="toc-entry-22" refid="directives">
+ <generated classes="sectnum">
+ 2.14
+ Directives
+ <bullet_list classes="auto-toc">
+ <list_item>
+ <paragraph>
+ <reference ids="toc-entry-23" refid="document-parts">
+ <generated classes="sectnum">
+ 2.14.1
+ Document Parts
+ <list_item>
+ <paragraph>
+ <reference ids="toc-entry-24" refid="images-and-figures">
+ <generated classes="sectnum">
+ 2.14.2
+ Images and Figures
+ <list_item>
+ <paragraph>
+ <reference ids="toc-entry-25" refid="admonitions">
+ <generated classes="sectnum">
+ 2.14.3
+ Admonitions
+ <list_item>
+ <paragraph>
+ <reference ids="toc-entry-26" refid="topics-sidebars-and-rubrics">
+ <generated classes="sectnum">
+ 2.14.4
+ Topics, Sidebars, and Rubrics
+ <list_item>
+ <paragraph>
+ <reference ids="toc-entry-27" refid="target-footnotes">
+ <generated classes="sectnum">
+ 2.14.5
+ Target Footnotes
+ <list_item>
+ <paragraph>
+ <reference ids="toc-entry-28" refid="replacement-text">
+ <generated classes="sectnum">
+ 2.14.6
+ Replacement Text
+ <list_item>
+ <paragraph>
+ <reference ids="toc-entry-29" refid="compound-paragraph">
+ <generated classes="sectnum">
+ 2.14.7
+ Compound Paragraph
+ <list_item>
+ <paragraph>
+ <reference ids="toc-entry-30" refid="parsed-literal-blocks">
+ <generated classes="sectnum">
+ 2.14.8
+ Parsed Literal Blocks
+ <list_item>
+ <paragraph>
+ <reference ids="toc-entry-31" refid="code">
+ <generated classes="sectnum">
+ 2.14.9
+ Code
+ <list_item>
+ <paragraph>
+ <reference ids="toc-entry-32" refid="substitution-definitions">
+ <generated classes="sectnum">
+ 2.15
+ Substitution Definitions
+ <list_item>
+ <paragraph>
+ <reference ids="toc-entry-33" refid="comments">
+ <generated classes="sectnum">
+ 2.16
+ Comments
+ <list_item>
+ <paragraph>
+ <reference ids="toc-entry-34" refid="raw-text">
+ <generated classes="sectnum">
+ 2.17
+ Raw text
+ <list_item>
+ <paragraph>
+ <reference ids="toc-entry-35" refid="container">
+ <generated classes="sectnum">
+ 2.18
+ Container
+ <list_item>
+ <paragraph>
+ <reference ids="toc-entry-36" refid="colspanning-tables">
+ <generated classes="sectnum">
+ 2.19
+ Colspanning tables
+ <list_item>
+ <paragraph>
+ <reference ids="toc-entry-37" refid="rowspanning-tables">
+ <generated classes="sectnum">
+ 2.20
+ Rowspanning tables
+ <list_item>
+ <paragraph>
+ <reference ids="toc-entry-38" refid="complex-tables">
+ <generated classes="sectnum">
+ 2.21
+ Complex tables
+ <list_item>
+ <paragraph>
+ <reference ids="toc-entry-39" refid="list-tables">
+ <generated classes="sectnum">
+ 2.22
+ List Tables
+ <list_item>
+ <paragraph>
+ <reference ids="toc-entry-40" refid="error-handling">
+ <generated classes="sectnum">
+ 3
+ Error Handling
+ <section ids="structural-elements" names="structural\ elements">
+ <title auto="1" refid="toc-entry-1">
+ <generated classes="sectnum">
+ 1
+ Structural Elements
+ <section ids="section-title" names="section\ title">
+ <title auto="1" refid="toc-entry-2">
+ <generated classes="sectnum">
+ 1.1
+ Section Title
+ <subtitle ids="section-subtitle" names="section\ subtitle">
+ Section Subtitle
+ <paragraph>
+ Lone subsections are converted to a section subtitle by a transform
+ activated with the
+ <literal>
+ --section-subtitles
+ command line option or the
+ <literal>
+ sectsubtitle-xform
+ configuration value.
+ <section ids="empty-section" names="empty\ section">
+ <title auto="1" refid="toc-entry-3">
+ <generated classes="sectnum">
+ 1.2
+ Empty Section
+ <section ids="transitions" names="transitions">
+ <title auto="1" refid="toc-entry-4">
+ <generated classes="sectnum">
+ 1.3
+ Transitions
+ <paragraph>
+ Here's a transition:
+ <transition>
+ <paragraph>
+ It divides the section. Transitions may also occur between sections:
+ <transition>
+ <section ids="body-elements" names="body\ elements">
+ <title auto="1" refid="toc-entry-5">
+ <generated classes="sectnum">
+ 2
+ Body Elements
+ <section ids="paragraphs" names="paragraphs">
+ <title auto="1" refid="toc-entry-6">
+ <generated classes="sectnum">
+ 2.1
+ Paragraphs
+ <paragraph>
+ A paragraph.
+ <section ids="inline-markup" names="inline\ markup">
+ <title auto="1" refid="toc-entry-7">
+ <generated classes="sectnum">
+ 2.1.1
+ Inline Markup
+ <paragraph>
+ Paragraphs contain text and may contain inline markup:
+ <emphasis>
+ emphasis
+ ,
+ <strong>
+ strong emphasis
+ ,
+ <literal>
+ inline literals
+ , standalone hyperlinks
+ (
+ <reference refuri="http://www.python.org">
+ http://www.python.org
+ ), external hyperlinks (
+ <reference name="Python" refuri="http://www.python.org/">
+ Python
+
+ <footnote_reference auto="1" ids="footnote-reference-10" refid="footnote-6">
+ 5
+ ), internal
+ cross-references (
+ <reference name="example" refid="example">
+ example
+ ), external hyperlinks with embedded URIs
+ (
+ <reference name="Python web site" refuri="http://www.python.org">
+ Python web site
+ ),
+ <reference anonymous="1" name="anonymous hyperlink references" refuri="http://www.python.org/">
+ anonymous hyperlink
+ references
+
+ <footnote_reference auto="1" ids="footnote-reference-14" refid="footnote-6">
+ 5
+ (
+ <reference anonymous="1" name="a second reference" refuri="http://docutils.sourceforge.net/">
+ a second reference
+
+ <footnote_reference auto="1" ids="footnote-reference-15" refid="footnote-8">
+ 7
+ ), footnote references (manually
+ numbered
+ <footnote_reference ids="footnote-reference-1" refid="footnote-1">
+ 1
+ , anonymous auto-numbered
+ <footnote_reference auto="1" ids="footnote-reference-2" refid="footnote-2">
+ 3
+ , labeled auto-numbered
+ <footnote_reference auto="1" ids="footnote-reference-3" refid="label">
+ 2
+ , or symbolic
+ <footnote_reference auto="*" ids="footnote-reference-4" refid="footnote-3">
+ *
+ ), citation references (
+ <citation_reference ids="citation-reference-1" refid="cit2002">
+ CIT2002
+ ),
+ substitution references (
+ <image alt="EXAMPLE" uri="../../../docs/user/rst/images/biohazard.png">
+ &
+ a
+ <emphasis>
+ trimmed heart
+
+ <literal>
+ (U+2665):
+ ♥
+ ), and
+ <target ids="inline-hyperlink-targets" names="inline\ hyperlink\ targets">
+ inline hyperlink targets
+
+ (see
+ <reference name="Targets" refid="targets">
+ Targets
+ below for a reference back to here). Character-level
+ inline markup is also possible (although exceedingly ugly!) in
+ <emphasis>
+ re
+ <literal>
+ Structured
+ <emphasis>
+ Text
+ . Problems are indicated by
+ <problematic ids="problematic-1" refid="system-message-1">
+ |problematic|
+ text
+ (generated by processing errors; this one is intentional). Here is a
+ reference to the
+ <reference name="doctitle" refid="doctitle">
+ doctitle
+ and the
+ <reference name="subtitle" refid="subtitle">
+ subtitle
+ .
+ <target anonymous="1" ids="target-1" refuri="http://www.python.org/">
+ <target anonymous="1" ids="target-2" refuri="http://docutils.sourceforge.net/">
+ <paragraph>
+ The default role for interpreted text is
+ <title_reference>
+ Title Reference
+ . Here are
+ some explicit interpreted text roles: a PEP reference (
+ <reference refuri="http://www.python.org/dev/peps/pep-0287">
+ PEP 287
+ ); an
+ RFC reference (
+ <reference refuri="http://tools.ietf.org/html/rfc2822.html">
+ RFC 2822
+ ); an abbreviation (
+ <abbreviation>
+ abb.
+ ), an acronym
+ (
+ <acronym>
+ reST
+ ), code (
+ <literal classes="code">
+ print "hello world"
+ ); a
+ <subscript>
+ subscript
+ ;
+ a
+ <superscript>
+ superscript
+ and explicit roles for
+ <title_reference>
+ Docutils
+ '
+ <emphasis>
+ standard
+
+ <strong>
+ inline
+
+ <literal>
+ markup
+ .
+ <comment xml:space="preserve">
+ DO NOT RE-WRAP THE FOLLOWING PARAGRAPH!
+ <paragraph>
+ Let's test wrapping and whitespace significance in inline literals:
+ <literal>
+ This is an example of --inline-literal --text, --including some--
+ strangely--hyphenated-words. Adjust-the-width-of-your-browser-window
+ to see how the text is wrapped. -- ---- -------- Now note the
+ spacing between the words of this sentence (words
+ should be grouped in pairs).
+ <paragraph>
+ If the
+ <literal>
+ --pep-references
+ option was supplied, there should be a
+ live link to PEP 258 here.
+ <section ids="bullet-lists" names="bullet\ lists">
+ <title auto="1" refid="toc-entry-8">
+ <generated classes="sectnum">
+ 2.2
+ Bullet Lists
+ <bullet_list bullet="-">
+ <list_item>
+ <paragraph>
+ A bullet list
+ <bullet_list bullet="+">
+ <list_item>
+ <paragraph>
+ Nested bullet list.
+ <list_item>
+ <paragraph>
+ Nested item 2.
+ <list_item>
+ <paragraph>
+ Item 2.
+ <paragraph>
+ Paragraph 2 of item 2.
+ <bullet_list bullet="*">
+ <list_item>
+ <paragraph>
+ Nested bullet list.
+ <list_item>
+ <paragraph>
+ Nested item 2.
+ <bullet_list bullet="-">
+ <list_item>
+ <paragraph>
+ Third level.
+ <list_item>
+ <paragraph>
+ Item 2.
+ <list_item>
+ <paragraph>
+ Nested item 3.
+ <list_item>
+ <paragraph>
+ This nested list should be compacted by the HTML writer.
+ <target ids="target" names="target">
+ <comment xml:space="preserve">
+ Even if this item contains a target and a comment.
+ <section ids="enumerated-lists" names="enumerated\ lists">
+ <title auto="1" refid="toc-entry-9">
+ <generated classes="sectnum">
+ 2.3
+ Enumerated Lists
+ <enumerated_list enumtype="arabic" prefix="" suffix=".">
+ <list_item>
+ <paragraph>
+ Arabic numerals.
+ <enumerated_list enumtype="loweralpha" prefix="" suffix=")">
+ <list_item>
+ <paragraph>
+ lower alpha)
+ <enumerated_list enumtype="lowerroman" prefix="(" suffix=")">
+ <list_item>
+ <paragraph>
+ (lower roman)
+ <enumerated_list enumtype="upperalpha" prefix="" suffix=".">
+ <list_item>
+ <paragraph>
+ upper alpha.
+ <enumerated_list enumtype="upperroman" prefix="" suffix=")">
+ <list_item>
+ <paragraph>
+ upper roman)
+ <list_item>
+ <paragraph>
+ Lists that don't start at 1:
+ <enumerated_list enumtype="arabic" prefix="" start="3" suffix=".">
+ <list_item>
+ <paragraph>
+ Three
+ <list_item>
+ <paragraph>
+ Four
+ <system_message level="1" line="8" source="functional/input/data/standard.txt" type="INFO">
+ <paragraph>
+ Enumerated list start value not ordinal-1: "3" (ordinal 3)
+ <enumerated_list enumtype="upperalpha" prefix="" start="3" suffix=".">
+ <list_item>
+ <paragraph>
+ C
+ <list_item>
+ <paragraph>
+ D
+ <system_message level="1" line="8" source="functional/input/data/standard.txt" type="INFO">
+ <paragraph>
+ Enumerated list start value not ordinal-1: "C" (ordinal 3)
+ <enumerated_list enumtype="lowerroman" prefix="" start="3" suffix=".">
+ <list_item>
+ <paragraph>
+ iii
+ <list_item>
+ <paragraph>
+ iv
+ <system_message level="1" line="8" source="functional/input/data/standard.txt" type="INFO">
+ <paragraph>
+ Enumerated list start value not ordinal-1: "iii" (ordinal 3)
+ <section ids="definition-lists" names="definition\ lists">
+ <title auto="1" refid="toc-entry-10">
+ <generated classes="sectnum">
+ 2.4
+ Definition Lists
+ <definition_list>
+ <definition_list_item>
+ <term>
+ Term
+ <definition>
+ <paragraph>
+ Definition
+ <definition_list_item>
+ <term>
+ Term
+ <classifier>
+ classifier
+ <definition>
+ <paragraph>
+ Definition paragraph 1.
+ <paragraph>
+ Definition paragraph 2.
+ <definition_list_item>
+ <term>
+ Term
+ <definition>
+ <paragraph>
+ Definition
+ <definition_list_item>
+ <term>
+ Term
+ <classifier>
+ classifier one
+ <classifier>
+ classifier two
+ <definition>
+ <paragraph>
+ Definition
+ <section ids="field-lists" names="field\ lists">
+ <title auto="1" refid="toc-entry-11">
+ <generated classes="sectnum">
+ 2.5
+ Field Lists
+ <field_list>
+ <field>
+ <field_name>
+ what
+ <field_body>
+ <paragraph>
+ Field lists map field names to field bodies, like database
+ records. They are often part of an extension syntax. They are
+ an unambiguous variant of RFC 2822 fields.
+ <field>
+ <field_name>
+ how arg1 arg2
+ <field_body>
+ <paragraph>
+ The field marker is a colon, the field name, and a colon.
+ <paragraph>
+ The field body may contain one or more body elements, indented
+ relative to the field marker.
+ <field>
+ <field_name>
+ credits
+ <field_body>
+ <paragraph classes="credits">
+ This paragraph has the
+ <title_reference>
+ credits
+ class set. (This is actually not
+ about credits but just for ensuring that the class attribute
+ doesn't get stripped away.)
+ <section ids="option-lists" names="option\ lists">
+ <title auto="1" refid="toc-entry-12">
+ <generated classes="sectnum">
+ 2.6
+ Option Lists
+ <paragraph>
+ For listing command-line options:
+ <option_list>
+ <option_list_item>
+ <option_group>
+ <option>
+ <option_string>
+ -a
+ <description>
+ <paragraph>
+ command-line option "a"
+ <option_list_item>
+ <option_group>
+ <option>
+ <option_string>
+ -b
+ <option_argument delimiter=" ">
+ file
+ <description>
+ <paragraph>
+ options can have arguments
+ and long descriptions
+ <option_list_item>
+ <option_group>
+ <option>
+ <option_string>
+ --long
+ <description>
+ <paragraph>
+ options can be long also
+ <option_list_item>
+ <option_group>
+ <option>
+ <option_string>
+ --input
+ <option_argument delimiter="=">
+ file
+ <description>
+ <paragraph>
+ long options can also have
+ arguments
+ <option_list_item>
+ <option_group>
+ <option>
+ <option_string>
+ --very-long-option
+ <description>
+ <paragraph>
+ The description can also start on the next line.
+ <paragraph>
+ The description may contain multiple body elements,
+ regardless of where it starts.
+ <option_list_item>
+ <option_group>
+ <option>
+ <option_string>
+ -x
+ <option>
+ <option_string>
+ -y
+ <option>
+ <option_string>
+ -z
+ <description>
+ <paragraph>
+ Multiple options are an "option group".
+ <option_list_item>
+ <option_group>
+ <option>
+ <option_string>
+ -v
+ <option>
+ <option_string>
+ --verbose
+ <description>
+ <paragraph>
+ Commonly-seen: short & long options.
+ <option_list_item>
+ <option_group>
+ <option>
+ <option_string>
+ -1
+ <option_argument delimiter=" ">
+ file
+ <option>
+ <option_string>
+ --one
+ <option_argument delimiter="=">
+ file
+ <option>
+ <option_string>
+ --two
+ <option_argument delimiter=" ">
+ file
+ <description>
+ <paragraph>
+ Multiple options with arguments.
+ <option_list_item>
+ <option_group>
+ <option>
+ <option_string>
+ /V
+ <description>
+ <paragraph>
+ DOS/VMS-style options too
+ <paragraph>
+ There must be at least two spaces between the option and the
+ description.
+ <section ids="literal-blocks" names="literal\ blocks">
+ <title auto="1" refid="toc-entry-13">
+ <generated classes="sectnum">
+ 2.7
+ Literal Blocks
+ <paragraph>
+ Literal blocks are indicated with a double-colon ("::") at the end of
+ the preceding paragraph (over there
+ <literal>
+ -->
+ ). They can be indented:
+ <literal_block xml:space="preserve">
+ if literal_block:
+ text = 'is left as-is'
+ spaces_and_linebreaks = 'are preserved'
+ markup_processing = None
+ <paragraph>
+ Or they can be quoted without indentation:
+ <literal_block xml:space="preserve">
+ >> Great idea!
+ >
+ > Why didn't I think of that?
+ <section ids="line-blocks" names="line\ blocks">
+ <title auto="1" refid="toc-entry-14">
+ <generated classes="sectnum">
+ 2.8
+ Line Blocks
+ <paragraph>
+ This section tests line blocks. Line blocks are body elements which
+ consist of lines and other line blocks. Nested line blocks cause
+ indentation.
+ <line_block>
+ <line>
+ This is a line block. It ends with a blank line.
+ <line_block>
+ <line>
+ New lines begin with a vertical bar ("|").
+ <line>
+ Line breaks and initial indent are significant, and preserved.
+ <line_block>
+ <line>
+ Continuation lines are also possible. A long line that is intended
+ to wrap should begin with a space in place of the vertical bar.
+ <line>
+ The left edge of a continuation line need not be aligned with
+ the left edge of the text above it.
+ <line_block>
+ <line>
+ This is a second line block.
+ <line>
+ <line>
+ Blank lines are permitted internally, but they must begin with a "|".
+ <paragraph>
+ Another line block, surrounded by paragraphs:
+ <line_block>
+ <line>
+ And it's no good waiting by the window
+ <line>
+ It's no good waiting for the sun
+ <line>
+ Please believe me, the things you dream of
+ <line>
+ They don't fall in the lap of no-one
+ <paragraph>
+ Take it away, Eric the Orchestra Leader!
+ <block_quote>
+ <line_block>
+ <line>
+ A one, two, a one two three four
+ <line>
+ <line>
+ Half a bee, philosophically,
+ <line_block>
+ <line>
+ must,
+ <emphasis>
+ ipso facto
+ , half not be.
+ <line>
+ But half the bee has got to be,
+ <line_block>
+ <line>
+ <emphasis>
+ vis a vis
+ its entity. D'you see?
+ <line>
+ <line>
+ But can a bee be said to be
+ <line_block>
+ <line>
+ or not to be an entire bee,
+ <line_block>
+ <line>
+ when half the bee is not a bee,
+ <line_block>
+ <line>
+ due to some ancient injury?
+ <line>
+ <line>
+ Singing...
+ <paragraph>
+ A line block, like the following poem by Christian Morgenstern, can
+ also be centre-aligned:
+ <line_block classes="language-de align-center">
+ <line>
+ <strong>
+ Die Trichter
+ <line>
+ <line>
+ Zwei Trichter wandeln durch die Nacht.
+ <line>
+ Durch ihres Rumpfs verengten Schacht
+ <line>
+ fließt weißes Mondlicht
+ <line>
+ still und heiter
+ <line>
+ auf ihren
+ <line>
+ Waldweg
+ <line>
+ u. s.
+ <line>
+ w.
+ <line>
+ <section ids="block-quotes" names="block\ quotes">
+ <title auto="1" refid="toc-entry-15">
+ <generated classes="sectnum">
+ 2.9
+ Block Quotes
+ <paragraph>
+ Block quotes consist of indented body elements:
+ <block_quote>
+ <paragraph>
+ My theory by A. Elk. Brackets Miss, brackets. This theory goes
+ as follows and begins now. All brontosauruses are thin at one
+ end, much much thicker in the middle and then thin again at the
+ far end. That is my theory, it is mine, and belongs to me and I
+ own it, and what it is too.
+ <attribution>
+ Anne Elk (Miss)
+ <paragraph>
+ The language of a quote (like any other object) can be specified by
+ a class attribute:
+ <comment xml:space="preserve">
+ <block_quote classes="language-fr">
+ <paragraph>
+ ReStructuredText est un langage de balisage léger utilisé
+ notamment dans la documentation du langage Python.
+ <section ids="doctest-blocks" names="doctest\ blocks">
+ <title auto="1" refid="toc-entry-16">
+ <generated classes="sectnum">
+ 2.10
+ Doctest Blocks
+ <doctest_block xml:space="preserve">
+ >>> print 'Python-specific usage examples; begun with ">>>"'
+ Python-specific usage examples; begun with ">>>"
+ >>> print '(cut and pasted from interactive Python sessions)'
+ (cut and pasted from interactive Python sessions)
+ <section ids="footnotes" names="footnotes">
+ <title auto="1" refid="toc-entry-17">
+ <generated classes="sectnum">
+ 2.11
+ Footnotes
+ <footnote backrefs="footnote-reference-1 footnote-reference-5 footnote-reference-9" ids="footnote-1" names="1">
+ <label>
+ 1
+ <paragraph>
+ A footnote contains body elements, consistently indented by at
+ least 3 spaces.
+ <paragraph>
+ This is the footnote's second paragraph.
+ <footnote auto="1" backrefs="footnote-reference-3 footnote-reference-6" ids="label" names="label">
+ <label>
+ 2
+ <paragraph>
+ Footnotes may be numbered, either manually (as in
+ <footnote_reference ids="footnote-reference-5" refid="footnote-1">
+ 1
+ ) or
+ automatically using a "#"-prefixed label. This footnote has a
+ label so it can be referred to from multiple places, both as a
+ footnote reference (
+ <footnote_reference auto="1" ids="footnote-reference-6" refid="label">
+ 2
+ ) and as a
+ <reference anonymous="1" name="hyperlink reference" refid="label">
+ hyperlink reference
+ .
+ <target anonymous="1" ids="target-3" refid="label">
+ <footnote auto="1" backrefs="footnote-reference-2" ids="footnote-2" names="3">
+ <label>
+ 3
+ <paragraph>
+ This footnote is numbered automatically and anonymously using a
+ label of "#" only.
+ <paragraph>
+ This is the second paragraph.
+ <paragraph>
+ And this is the third paragraph.
+ <footnote auto="*" backrefs="footnote-reference-4" ids="footnote-3">
+ <label>
+ *
+ <paragraph>
+ Footnotes may also use symbols, specified with a "*" label.
+ Here's a reference to the next footnote:
+ <footnote_reference auto="*" ids="footnote-reference-7" refid="footnote-4">
+ †
+ .
+ <footnote auto="*" backrefs="footnote-reference-7" ids="footnote-4">
+ <label>
+ †
+ <paragraph>
+ This footnote shows the next symbol in the sequence.
+ <footnote ids="footnote-5" names="4">
+ <label>
+ 4
+ <paragraph>
+ Here's an unreferenced footnote, with a reference to a
+ nonexistent footnote:
+ <problematic ids="footnote-reference-8" refid="system-message-2">
+ [5]_
+ .
+ <section ids="citations" names="citations">
+ <title auto="1" refid="toc-entry-18">
+ <generated classes="sectnum">
+ 2.12
+ Citations
+ <citation backrefs="citation-reference-1 citation-reference-2" ids="cit2002" names="cit2002">
+ <label>
+ CIT2002
+ <paragraph>
+ Citations are text-labeled footnotes. They may be
+ rendered separately and differently from footnotes.
+ <paragraph>
+ Here's a reference to the above,
+ <citation_reference ids="citation-reference-2" refid="cit2002">
+ CIT2002
+ , and a
+ <problematic ids="citation-reference-3" refid="system-message-3">
+ [nonexistent]_
+
+ citation.
+ <target refid="another-target">
+ <section ids="targets another-target" names="targets another\ target">
+ <title auto="1" refid="toc-entry-19">
+ <generated classes="sectnum">
+ 2.13
+ Targets
+ <target refid="example">
+ <paragraph ids="example" names="example">
+ This paragraph is pointed to by the explicit "example" target. A
+ reference can be found under
+ <reference name="Inline Markup" refid="inline-markup">
+ Inline Markup
+ , above.
+ <reference name="Inline hyperlink targets" refid="inline-hyperlink-targets">
+ Inline
+ hyperlink targets
+ are also possible.
+ <paragraph>
+ Section headers are implicit targets, referred to by name. See
+ <reference name="Targets" refid="targets">
+ Targets
+ , which is a subsection of
+ <reference name="Body Elements" refid="body-elements">
+ Body Elements
+ .
+ <paragraph>
+ Explicit external targets are interpolated into references such as
+ "
+ <reference name="Python" refuri="http://www.python.org/">
+ Python
+
+ <footnote_reference auto="1" ids="footnote-reference-11" refid="footnote-6">
+ 5
+ ".
+ <target ids="python" names="python" refuri="http://www.python.org/">
+ <paragraph>
+ Targets may be indirect and anonymous. Thus
+ <reference anonymous="1" name="this phrase" refid="targets">
+ this phrase
+ may also
+ refer to the
+ <reference name="Targets" refid="targets">
+ Targets
+ section.
+ <target anonymous="1" ids="target-4" refid="targets">
+ <paragraph>
+ Here's a
+ <problematic ids="problematic-2" refid="system-message-4">
+ `hyperlink reference without a target`_
+ , which generates an
+ error.
+ <section dupnames="duplicate\ target\ names" ids="duplicate-target-names">
+ <title auto="1" refid="toc-entry-20">
+ <generated classes="sectnum">
+ 2.13.1
+ Duplicate Target Names
+ <paragraph>
+ Duplicate names in section headers or other implicit targets will
+ generate "info" (level-1) system messages. Duplicate names in
+ explicit targets will generate "warning" (level-2) system messages.
+ <section dupnames="duplicate\ target\ names" ids="duplicate-target-names-1">
+ <title auto="1" refid="toc-entry-21">
+ <generated classes="sectnum">
+ 2.13.2
+ Duplicate Target Names
+ <system_message backrefs="duplicate-target-names-1" level="1" line="439" source="functional/input/data/standard.txt" type="INFO">
+ <paragraph>
+ Duplicate implicit target name: "duplicate target names".
+ <paragraph>
+ Since there are two "Duplicate Target Names" section headers, we
+ cannot uniquely refer to either of them by name. If we try to (like
+ this:
+ <problematic ids="problematic-3" refid="system-message-5">
+ `Duplicate Target Names`_
+ ), an error is generated.
+ <section ids="directives" names="directives">
+ <title auto="1" refid="toc-entry-22">
+ <generated classes="sectnum">
+ 2.14
+ Directives
+ <topic classes="contents local" ids="contents" names="contents">
+ <bullet_list classes="auto-toc">
+ <list_item>
+ <paragraph>
+ <reference ids="toc-entry-41" refid="document-parts">
+ <generated classes="sectnum">
+ 2.14.1
+ Document Parts
+ <list_item>
+ <paragraph>
+ <reference ids="toc-entry-42" refid="images-and-figures">
+ <generated classes="sectnum">
+ 2.14.2
+ Images and Figures
+ <list_item>
+ <paragraph>
+ <reference ids="toc-entry-43" refid="admonitions">
+ <generated classes="sectnum">
+ 2.14.3
+ Admonitions
+ <list_item>
+ <paragraph>
+ <reference ids="toc-entry-44" refid="topics-sidebars-and-rubrics">
+ <generated classes="sectnum">
+ 2.14.4
+ Topics, Sidebars, and Rubrics
+ <list_item>
+ <paragraph>
+ <reference ids="toc-entry-45" refid="target-footnotes">
+ <generated classes="sectnum">
+ 2.14.5
+ Target Footnotes
+ <list_item>
+ <paragraph>
+ <reference ids="toc-entry-46" refid="replacement-text">
+ <generated classes="sectnum">
+ 2.14.6
+ Replacement Text
+ <list_item>
+ <paragraph>
+ <reference ids="toc-entry-47" refid="compound-paragraph">
+ <generated classes="sectnum">
+ 2.14.7
+ Compound Paragraph
+ <list_item>
+ <paragraph>
+ <reference ids="toc-entry-48" refid="parsed-literal-blocks">
+ <generated classes="sectnum">
+ 2.14.8
+ Parsed Literal Blocks
+ <list_item>
+ <paragraph>
+ <reference ids="toc-entry-49" refid="code">
+ <generated classes="sectnum">
+ 2.14.9
+ Code
+ <paragraph>
+ These are just a sample of the many reStructuredText Directives. For
+ others, please see
+ <reference refuri="http://docutils.sourceforge.net/docs/ref/rst/directives.html">
+ http://docutils.sourceforge.net/docs/ref/rst/directives.html
+ .
+ <section ids="document-parts" names="document\ parts">
+ <title auto="1" refid="toc-entry-41">
+ <generated classes="sectnum">
+ 2.14.1
+ Document Parts
+ <paragraph>
+ An example of the "contents" directive can be seen above this section
+ (a local, untitled table of
+ <reference name="contents" refid="contents">
+ contents
+ ) and at the beginning of the
+ document (a document-wide
+ <reference name="table of contents" refid="table-of-contents">
+ table of contents
+ ).
+ <section ids="images-and-figures" names="images\ and\ figures">
+ <title auto="1" refid="toc-entry-42">
+ <generated classes="sectnum">
+ 2.14.2
+ Images and Figures
+ <paragraph>
+ An image directive (also clickable -- a hyperlink reference):
+ <reference name="directives" refid="directives">
+ <image classes="class1 class2" uri="../../../docs/user/rst/images/title.png">
+ <paragraph>
+ Image with multiple IDs:
+ <target refid="image-target-1">
+ <target refid="image-target-2">
+ <target refid="image-target-3">
+ <image ids="image-target-3 image-target-2 image-target-1" names="image\ target\ 3 image\ target\ 2 image\ target\ 1" uri="../../../docs/user/rst/images/title.png">
+ <paragraph>
+ A centered image:
+ <image align="center" uri="../../../docs/user/rst/images/biohazard.png">
+ <paragraph>
+ A left-aligned image:
+ <image align="left" uri="../../../docs/user/rst/images/biohazard.png">
+ <paragraph>
+ This paragraph might flow around the image.
+ The specific behavior depends upon the style sheet and
+ the browser or rendering software used.
+ <paragraph>
+ A right-aligned image:
+ <image align="right" uri="../../../docs/user/rst/images/biohazard.png">
+ <paragraph>
+ This paragraph might flow around the image.
+ The specific behavior depends upon the style sheet and
+ the browser or rendering software used.
+ <paragraph>
+ For inline images see
+ <reference name="Substitution Definitions" refid="substitution-definitions">
+ Substitution Definitions
+ .
+ <paragraph>
+ Image size:
+ <paragraph>
+ An image 2 em wide:
+ <image uri="../../../docs/user/rst/images/biohazard.png" width="2em">
+ <paragraph>
+ An image 2 em wide and 15 pixel high:
+ <image height="15px" uri="../../../docs/user/rst/images/biohazard.png" width="2em">
+ <paragraph>
+ An image occupying 50% of the line width:
+ <image uri="../../../docs/user/rst/images/title.png" width="50%">
+ <paragraph>
+ An image 2 cm high:
+ <image height="2cm" uri="../../../docs/user/rst/images/biohazard.png">
+ <paragraph>
+ A
+ <emphasis>
+ figure
+ is an image with a caption and/or a legend. With page-based output
+ media, figures might float to a different position if this helps the page
+ layout.
+ <figure classes="figclass1 figclass2">
+ <image alt="reStructuredText, the markup syntax" classes="class1 class2" uri="../../../docs/user/rst/images/title.png" width="258">
+ <caption>
+ Plaintext markup syntax and parser system.
+ <legend>
+ <table>
+ <tgroup cols="2">
+ <colspec colwidth="12">
+ <colspec colwidth="47">
+ <tbody>
+ <row>
+ <entry>
+ <paragraph>
+ re
+ <entry>
+ <paragraph>
+ Revised, revisited, based on 're' module.
+ <row>
+ <entry>
+ <paragraph>
+ Structured
+ <entry>
+ <paragraph>
+ Structure-enhanced text, structuredtext.
+ <row>
+ <entry>
+ <paragraph>
+ Text
+ <entry>
+ <paragraph>
+ Well it is, isn't it?
+ <paragraph>
+ This paragraph is also part of the legend.
+ <paragraph>
+ A left-aligned figure:
+ <figure align="left" classes="figclass1 figclass2" width="70%">
+ <image alt="reStructuredText, the markup syntax" classes="class1 class2" uri="../../../docs/user/rst/images/biohazard.png" width="40px">
+ <caption>
+ This is the caption.
+ <legend>
+ <paragraph>
+ This is the legend.
+ <paragraph>
+ The legend may consist of several paragraphs.
+ <paragraph>
+ This paragraph might flow around the figure.
+ <paragraph>
+ The specific behavior depends upon the style sheet and the browser or
+ rendering software used.
+ <paragraph>
+ A centered figure:
+ <figure align="center">
+ <image uri="../../../docs/user/rst/images/biohazard.png" width="40px">
+ <caption>
+ This is the caption.
+ <legend>
+ <paragraph>
+ This is the legend.
+ <paragraph>
+ The legend may consist of several paragraphs.
+ <paragraph>
+ This paragraph might flow around the figure.
+ <paragraph>
+ The specific behavior depends upon the style sheet and the browser or
+ rendering software used.
+ <paragraph>
+ A right-aligned figure:
+ <figure align="right">
+ <image uri="../../../docs/user/rst/images/biohazard.png" width="40px">
+ <caption>
+ This is the caption.
+ <legend>
+ <paragraph>
+ This is the legend.
+ <paragraph>
+ The legend may consist of several paragraphs.
+ <paragraph>
+ This paragraph might flow around the figure. The specific behavior depends
+ upon the style sheet and the browser or rendering software used.
+ <paragraph>
+ Tables may be given titles and additional arguments with the
+ <emphasis>
+ table
+
+ directive:
+ <table align="left">
+ <title>
+ left-aligned table
+ <tgroup cols="2">
+ <colspec colwidth="5">
+ <colspec colwidth="5">
+ <thead>
+ <row>
+ <entry>
+ <paragraph>
+ A
+ <entry>
+ <paragraph>
+ not A
+ <tbody>
+ <row>
+ <entry>
+ <paragraph>
+ False
+ <entry>
+ <paragraph>
+ True
+ <row>
+ <entry>
+ <paragraph>
+ True
+ <entry>
+ <paragraph>
+ False
+ <table align="center">
+ <title>
+ center-aligned table
+ <tgroup cols="2">
+ <colspec colwidth="5">
+ <colspec colwidth="5">
+ <thead>
+ <row>
+ <entry>
+ <paragraph>
+ A
+ <entry>
+ <paragraph>
+ not A
+ <tbody>
+ <row>
+ <entry>
+ <paragraph>
+ False
+ <entry>
+ <paragraph>
+ True
+ <row>
+ <entry>
+ <paragraph>
+ True
+ <entry>
+ <paragraph>
+ False
+ <table align="right">
+ <title>
+ right-aligned table
+ <tgroup cols="2">
+ <colspec colwidth="5">
+ <colspec colwidth="5">
+ <thead>
+ <row>
+ <entry>
+ <paragraph>
+ A
+ <entry>
+ <paragraph>
+ not A
+ <tbody>
+ <row>
+ <entry>
+ <paragraph>
+ False
+ <entry>
+ <paragraph>
+ True
+ <row>
+ <entry>
+ <paragraph>
+ True
+ <entry>
+ <paragraph>
+ False
+ <paragraph>
+ With the "widths" argument "auto" (or "class" value "colwidths-auto"),
+ column widths are determined by the backend (if supported by the
+ writer/backend).
+ <target refid="target1">
+ <target refid="target2">
+ <table classes="colwidths-auto" ids="target2 target1" names="target2 target1">
+ <tgroup cols="3">
+ <colspec colwidth="7">
+ <colspec colwidth="7">
+ <colspec colwidth="10">
+ <thead>
+ <row>
+ <entry>
+ <paragraph>
+ A
+ <entry>
+ <paragraph>
+ B
+ <entry>
+ <paragraph>
+ A or B
+ <tbody>
+ <row>
+ <entry>
+ <paragraph>
+ False
+ <entry>
+ <paragraph>
+ False
+ <entry>
+ <paragraph>
+ False
+ <row>
+ <entry>
+ <paragraph>
+ True
+ <entry>
+ <paragraph>
+ False
+ <entry>
+ <paragraph>
+ True
+ <row>
+ <entry>
+ <paragraph>
+ False
+ <entry>
+ <paragraph>
+ True
+ <entry>
+ <paragraph>
+ True
+ <row>
+ <entry>
+ <paragraph>
+ True
+ <entry>
+ <paragraph>
+ True
+ <entry>
+ <paragraph>
+ True
+ <section ids="admonitions" names="admonitions">
+ <title auto="1" refid="toc-entry-43">
+ <generated classes="sectnum">
+ 2.14.3
+ Admonitions
+ <attention>
+ <paragraph>
+ Directives at large.
+ <caution>
+ <paragraph>
+ Don't take any wooden nickels.
+ <danger>
+ <paragraph>
+ Mad scientist at work!
+ <error>
+ <paragraph>
+ Does not compute.
+ <hint>
+ <paragraph>
+ It's bigger than a bread box.
+ <important>
+ <bullet_list bullet="-">
+ <list_item>
+ <paragraph>
+ Wash behind your ears.
+ <list_item>
+ <paragraph>
+ Clean up your room.
+ <list_item>
+ <paragraph>
+ Call your mother.
+ <list_item>
+ <paragraph>
+ Back up your data.
+ <note>
+ <paragraph>
+ This is a note.
+ <tip>
+ <paragraph>
+ 15% if the service is good.
+ <warning>
+ <paragraph>
+ Strong prose may provoke extreme mental exertion.
+ Reader discretion is strongly advised.
+ <admonition classes="admonition-and-by-the-way">
+ <title>
+ And, by the way...
+ <paragraph>
+ You can make up your own admonition too.
+ <target ids="docutils" names="docutils" refuri="http://docutils.sourceforge.net/">
+ <section ids="topics-sidebars-and-rubrics" names="topics,\ sidebars,\ and\ rubrics">
+ <title auto="1" refid="toc-entry-44">
+ <generated classes="sectnum">
+ 2.14.4
+ Topics, Sidebars, and Rubrics
+ <paragraph>
+ <emphasis>
+ Sidebars
+ are like miniature, parallel documents.
+ <sidebar>
+ <title>
+ Sidebar Title
+ <subtitle>
+ Optional Subtitle
+ <paragraph>
+ This is a sidebar. It is for text outside the flow of the main
+ text.
+ <rubric>
+ This is a rubric inside a sidebar
+ <paragraph>
+ Sidebars often appear beside the main text with a border and a different
+ background or font color.
+ <paragraph>
+ A
+ <emphasis>
+ topic
+ is like a block quote with a title, or a self-contained section
+ with no subsections.
+ <topic>
+ <title>
+ Topic Title
+ <paragraph>
+ This is a topic.
+ <paragraph>
+ A
+ <emphasis>
+ rubric
+ is like an informal heading that doesn't correspond to the
+ document's structure. It is typically highlighted in red (hence the name).
+ <rubric>
+ This is a rubric
+ <paragraph>
+ Topics and rubrics can be used at places where a
+ <reference name="section title" refid="section-title">
+ section title
+ is not
+ allowed (e.g. inside a directive).
+ <section ids="target-footnotes" names="target\ footnotes">
+ <title auto="1" refid="toc-entry-45">
+ <generated classes="sectnum">
+ 2.14.5
+ Target Footnotes
+ <footnote auto="1" backrefs="footnote-reference-10 footnote-reference-11 footnote-reference-12 footnote-reference-14" ids="footnote-6" names="TARGET_NOTE:\ footnote-6">
+ <label>
+ 5
+ <paragraph>
+ <reference refuri="http://www.python.org/">
+ http://www.python.org/
+ <footnote auto="1" backrefs="footnote-reference-13" ids="footnote-7" names="TARGET_NOTE:\ footnote-7">
+ <label>
+ 6
+ <paragraph>
+ <reference refuri="http://pygments.org/">
+ http://pygments.org/
+ <footnote auto="1" backrefs="footnote-reference-15" ids="footnote-8" names="TARGET_NOTE:\ footnote-8">
+ <label>
+ 7
+ <paragraph>
+ <reference refuri="http://docutils.sourceforge.net/">
+ http://docutils.sourceforge.net/
+ <section ids="replacement-text" names="replacement\ text">
+ <title auto="1" refid="toc-entry-46">
+ <generated classes="sectnum">
+ 2.14.6
+ Replacement Text
+ <paragraph>
+ I recommend you try
+ <reference refuri="http://www.python.org/">
+ Python,
+ <emphasis>
+ the
+ best language around
+
+ <footnote_reference auto="1" ids="footnote-reference-12" refid="footnote-6">
+ 5
+ .
+ <substitution_definition names="Python">
+ Python,
+ <emphasis>
+ the
+ best language around
+ <section ids="compound-paragraph" names="compound\ paragraph">
+ <title auto="1" refid="toc-entry-47">
+ <generated classes="sectnum">
+ 2.14.7
+ Compound Paragraph
+ <paragraph>
+ The
+ <emphasis>
+ compound
+ directive is used to create a "compound paragraph", which
+ is a single logical paragraph containing multiple physical body
+ elements. For example:
+ <compound>
+ <paragraph>
+ The 'rm' command is very dangerous. If you are logged
+ in as root and enter
+ <literal_block xml:space="preserve">
+ cd /
+ rm -rf *
+ <paragraph>
+ you will erase the entire contents of your file system.
+ <paragraph>
+ Test the handling and display of compound paragraphs:
+ <compound classes="some-class">
+ <paragraph>
+ Compound 2, paragraph 1,
+ <paragraph>
+ compound 2, paragraph 2,
+ <bullet_list bullet="*">
+ <list_item>
+ <paragraph>
+ list item 1,
+ <list_item>
+ <paragraph>
+ list item 2,
+ <paragraph>
+ compound 2, paragraph 3.
+ <compound>
+ <paragraph>
+ Compound 3, only consisting of one paragraph.
+ <compound>
+ <literal_block xml:space="preserve">
+ Compound 4.
+ This one starts with a literal block.
+ <paragraph>
+ Compound 4, paragraph following the literal block.
+ <paragraph>
+ Now something
+ <emphasis>
+ really
+ perverted -- a nested compound block. This is
+ just to test that it works at all; the results don't have to be
+ meaningful.
+ <compound>
+ <paragraph>
+ Compound 5, block 1 (a paragraph).
+ <compound>
+ <paragraph>
+ Compound 6 is block 2 in compound 5.
+ <paragraph>
+ Compound 6, another paragraph.
+ <paragraph>
+ Compound 5, block 3 (a paragraph).
+ <compound>
+ <paragraph>
+ Compound 7, tests the inclusion of various block-level
+ elements in one logical paragraph. First a table,
+ <table>
+ <tgroup cols="3">
+ <colspec colwidth="20">
+ <colspec colwidth="20">
+ <colspec colwidth="20">
+ <tbody>
+ <row>
+ <entry>
+ <paragraph>
+ Left cell, first
+ paragraph.
+ <paragraph>
+ Left cell, second
+ paragraph.
+ <entry>
+ <paragraph>
+ Middle cell,
+ consisting of
+ exactly one
+ paragraph.
+ <entry>
+ <paragraph>
+ Right cell.
+ <paragraph>
+ Paragraph 2.
+ <paragraph>
+ Paragraph 3.
+ <paragraph>
+ followed by a paragraph. This physical paragraph is
+ actually a continuation of the paragraph before the table. It is followed
+ by
+ <block_quote>
+ <paragraph>
+ a quote and
+ <enumerated_list enumtype="arabic" prefix="" suffix=".">
+ <list_item>
+ <paragraph>
+ an enumerated list,
+ <paragraph>
+ a paragraph,
+ <option_list>
+ <option_list_item>
+ <option_group>
+ <option>
+ <option_string>
+ --an
+ <description>
+ <paragraph>
+ option list,
+ <paragraph>
+ a paragraph,
+ <field_list>
+ <field>
+ <field_name>
+ a field
+ <field_body>
+ <paragraph>
+ list,
+ <paragraph>
+ a paragraph,
+ <definition_list>
+ <definition_list_item>
+ <term>
+ a definition
+ <definition>
+ <paragraph>
+ list,
+ <paragraph>
+ a paragraph, an image:
+ <image uri="../../../docs/user/rst/images/biohazard.png">
+ <paragraph>
+ a paragraph,
+ <line_block>
+ <line>
+ a line
+ <line>
+ block,
+ <paragraph>
+ a paragraph followed by a comment,
+ <comment xml:space="preserve">
+ this is a comment
+ <paragraph>
+ a paragraph, a
+ <note>
+ <paragraph>
+ with content
+ <paragraph>
+ and the final paragraph of the compound 7.
+ <section ids="parsed-literal-blocks" names="parsed\ literal\ blocks">
+ <title auto="1" refid="toc-entry-48">
+ <generated classes="sectnum">
+ 2.14.8
+ Parsed Literal Blocks
+ <literal_block xml:space="preserve">
+ This is a parsed literal block.
+ This line is indented. The next line is blank.
+
+ Inline markup is supported, e.g.
+ <emphasis>
+ emphasis
+ ,
+ <strong>
+ strong
+ ,
+ <literal>
+ literal
+ text
+ ,
+ <subscript>
+ sub-
+ and
+ <superscript>
+ super
+ scripts,
+ inline formulas:
+ <math>
+ A = 2 \pi r^2
+ ,
+ footnotes
+ <footnote_reference ids="footnote-reference-9" refid="footnote-1">
+ 1
+ ,
+ <target ids="hyperlink-targets" names="hyperlink\ targets">
+ hyperlink targets
+ , and
+ <reference name="references" refuri="http://www.python.org/">
+ references
+ <target ids="references" names="references" refuri="http://www.python.org/">
+ .
+ <section ids="code" names="code">
+ <title auto="1" refid="toc-entry-49">
+ <generated classes="sectnum">
+ 2.14.9
+ Code
+ <paragraph>
+ Blocks of source code can be set with the
+ <title_reference>
+ code
+ directive. If the code
+ language is specified, the content is parsed and tagged by the
+ <reference name="Pygments" refuri="http://pygments.org/">
+ Pygments
+
+ <footnote_reference auto="1" ids="footnote-reference-13" refid="footnote-7">
+ 6
+
+ syntax highlighter and can be formatted with a style sheet. (Code parsing
+ is turned off using the
+ <literal>
+ syntax-highlight
+ config setting in the test
+ conversions in order to get identical results with/without installed
+ Pygments highlighter.)
+ <literal_block classes="code python" xml:space="preserve">
+ print 'This is Python code.'
+ <paragraph>
+ The
+ <literal>
+ :number-lines:
+ option (with optional start value) generates line
+ numbers:
+ <literal_block classes="code python" xml:space="preserve">
+ <inline classes="ln">
+ 8
+ # print integers from 0 to 9:
+ <inline classes="ln">
+ 9
+ for i in range(10):
+ <inline classes="ln">
+ 10
+ print i
+ <paragraph>
+ For inline code snippets, there is the
+ <title_reference>
+ code
+ role, which can be used
+ directly (the code will not be parsed/tagged, as the language is not known)
+ or as base for special code roles, e.g. the LaTeX code in the next
+ paragraph.
+ <paragraph>
+ Docutils uses LaTeX syntax for math directives and roles:
+ <literal classes="code tex">
+ \alpha = f(x)
+ prints
+ <math>
+ \alpha = f(x)
+ .
+ <paragraph>
+ The
+ <literal>
+ :code:
+ option of the
+ <title_reference>
+ include
+ directive sets the included content
+ as a code block, here the rst file
+ <literal>
+ header_footer.txt
+ with line numbers:
+ <literal_block classes="code rst" source="functional/input/data/header_footer.txt" xml:space="preserve">
+ <inline classes="ln">
+ 1
+ .. header:: Document header
+ <inline classes="ln">
+ 2
+ .. footer:: Document footer
+ <target ids="pygments" names="pygments" refuri="http://pygments.org/">
+ <section ids="substitution-definitions" names="substitution\ definitions">
+ <title auto="1" refid="toc-entry-32">
+ <generated classes="sectnum">
+ 2.15
+ Substitution Definitions
+ <paragraph>
+ An inline image (
+ <image alt="EXAMPLE" uri="../../../docs/user/rst/images/biohazard.png">
+ ) example:
+ <substitution_definition names="EXAMPLE">
+ <image alt="EXAMPLE" uri="../../../docs/user/rst/images/biohazard.png">
+ <paragraph>
+ A Unicode example:
+ <substitution_definition ltrim="1" names="heart" rtrim="1">
+ ♥
+ <paragraph>
+ (Substitution definitions are not visible in the HTML source.)
+ <section ids="comments" names="comments">
+ <title auto="1" refid="toc-entry-33">
+ <generated classes="sectnum">
+ 2.16
+ Comments
+ <paragraph>
+ Here's one:
+ <comment xml:space="preserve">
+ Comments begin with two dots and a space. Anything may
+ follow, except for the syntax of footnotes, hyperlink
+ targets, directives, or substitution definitions.
+
+ Double-dashes -- "--" -- must be escaped somehow in HTML output.
+
+ Comments may contain non-ASCII characters: ä ö ü æ ø å
+ <paragraph>
+ (View the HTML source to see the comment.)
+ <section ids="raw-text" names="raw\ text">
+ <title auto="1" refid="toc-entry-34">
+ <generated classes="sectnum">
+ 2.17
+ Raw text
+ <paragraph>
+ This does not necessarily look nice, because there may be missing white space.
+ <paragraph>
+ It's just there to freeze the behavior.
+ <raw format="html latex" xml:space="preserve">
+ A test.
+ <raw format="html latex" xml:space="preserve">
+ Second test.
+ <raw classes="myclass" format="html latex" xml:space="preserve">
+ Another test with myclass set.
+ <paragraph>
+ This is the
+ <raw classes="myrawroleclass" format="html latex" xml:space="preserve">
+ fourth test
+ with myrawroleclass set.
+ <raw format="html" xml:space="preserve">
+ Fifth test in HTML.<br />Line two.
+ <raw format="latex" xml:space="preserve">
+ Fifth test in LaTeX.\\Line two.
+ <section ids="container" names="container">
+ <title auto="1" refid="toc-entry-35">
+ <generated classes="sectnum">
+ 2.18
+ Container
+ <container classes="custom">
+ <paragraph>
+ paragraph 1
+ <paragraph>
+ paragraph 2
+ <section ids="colspanning-tables" names="colspanning\ tables">
+ <title auto="1" refid="toc-entry-36">
+ <generated classes="sectnum">
+ 2.19
+ Colspanning tables
+ <paragraph>
+ This table has a cell spanning two columns:
+ <table>
+ <tgroup cols="3">
+ <colspec colwidth="5">
+ <colspec colwidth="5">
+ <colspec colwidth="6">
+ <thead>
+ <row>
+ <entry morecols="1">
+ <paragraph>
+ Inputs
+ <entry>
+ <paragraph>
+ Output
+ <row>
+ <entry>
+ <paragraph>
+ A
+ <entry>
+ <paragraph>
+ B
+ <entry>
+ <paragraph>
+ A or B
+ <tbody>
+ <row>
+ <entry>
+ <paragraph>
+ False
+ <entry>
+ <paragraph>
+ False
+ <entry>
+ <paragraph>
+ False
+ <row>
+ <entry>
+ <paragraph>
+ True
+ <entry>
+ <paragraph>
+ False
+ <entry>
+ <paragraph>
+ True
+ <row>
+ <entry>
+ <paragraph>
+ False
+ <entry>
+ <paragraph>
+ True
+ <entry>
+ <paragraph>
+ True
+ <row>
+ <entry>
+ <paragraph>
+ True
+ <entry>
+ <paragraph>
+ True
+ <entry>
+ <paragraph>
+ True
+ <section ids="rowspanning-tables" names="rowspanning\ tables">
+ <title auto="1" refid="toc-entry-37">
+ <generated classes="sectnum">
+ 2.20
+ Rowspanning tables
+ <paragraph>
+ Here's a table with cells spanning several rows:
+ <table>
+ <tgroup cols="3">
+ <colspec colwidth="24">
+ <colspec colwidth="12">
+ <colspec colwidth="18">
+ <thead>
+ <row>
+ <entry>
+ <paragraph>
+ Header row, column 1
+ (header rows optional)
+ <entry>
+ <paragraph>
+ Header 2
+ <entry>
+ <paragraph>
+ Header 3
+ <tbody>
+ <row>
+ <entry>
+ <paragraph>
+ body row 1, column 1
+ <entry>
+ <paragraph>
+ column 2
+ <entry>
+ <paragraph>
+ column 3
+ <row>
+ <entry>
+ <paragraph>
+ body row 2
+ <entry morerows="1">
+ <paragraph>
+ Cells may
+ span rows.
+ <entry morerows="1">
+ <paragraph>
+ Another
+ rowspanning
+ cell.
+ <row>
+ <entry>
+ <paragraph>
+ body row 3
+ <section ids="complex-tables" names="complex\ tables">
+ <title auto="1" refid="toc-entry-38">
+ <generated classes="sectnum">
+ 2.21
+ Complex tables
+ <paragraph>
+ Here's a complex table, which should test all features.
+ <table>
+ <tgroup cols="4">
+ <colspec colwidth="24">
+ <colspec colwidth="12">
+ <colspec colwidth="10">
+ <colspec colwidth="10">
+ <thead>
+ <row>
+ <entry>
+ <paragraph>
+ Header row, column 1
+ (header rows optional)
+ <entry>
+ <paragraph>
+ Header 2
+ <entry>
+ <paragraph>
+ Header 3
+ <entry>
+ <paragraph>
+ Header 4
+ <tbody>
+ <row>
+ <entry>
+ <paragraph>
+ body row 1, column 1
+ <entry>
+ <paragraph>
+ column 2
+ <entry>
+ <paragraph>
+ column 3
+ <entry>
+ <paragraph>
+ column 4
+ <row>
+ <entry>
+ <paragraph>
+ body row 2
+ <entry morecols="2">
+ <paragraph>
+ Cells may span columns.
+ <row>
+ <entry>
+ <paragraph>
+ body row 3
+ <entry morerows="1">
+ <paragraph>
+ Cells may
+ span rows.
+ <paragraph>
+ Paragraph.
+ <entry morecols="1" morerows="1">
+ <bullet_list bullet="-">
+ <list_item>
+ <paragraph>
+ Table cells
+ <list_item>
+ <paragraph>
+ contain
+ <list_item>
+ <paragraph>
+ body elements.
+ <row>
+ <entry>
+ <paragraph>
+ body row 4
+ <row>
+ <entry>
+ <paragraph>
+ body row 5
+ <entry morecols="1">
+ <paragraph>
+ Cells may also be
+ empty:
+ <literal>
+ -->
+ <entry>
+ <section ids="list-tables" names="list\ tables">
+ <title auto="1" refid="toc-entry-39">
+ <generated classes="sectnum">
+ 2.22
+ List Tables
+ <paragraph>
+ Here's a list table exercising all features:
+ <table classes="colwidths-given test" width="40em">
+ <title>
+ list table with integral header
+ <tgroup cols="3">
+ <colspec colwidth="10" stub="1">
+ <colspec colwidth="20">
+ <colspec colwidth="30">
+ <thead>
+ <row>
+ <entry>
+ <paragraph>
+ Treat
+ <entry>
+ <paragraph>
+ Quantity
+ <entry>
+ <paragraph>
+ Description
+ <tbody>
+ <row>
+ <entry>
+ <paragraph>
+ Albatross
+ <entry>
+ <paragraph>
+ 2.99
+ <entry>
+ <paragraph>
+ On a stick!
+ <row>
+ <entry>
+ <paragraph>
+ Crunchy Frog
+ <entry>
+ <paragraph>
+ 1.49
+ <entry>
+ <paragraph>
+ If we took the bones out, it wouldn't be
+ crunchy, now would it?
+ <row>
+ <entry>
+ <paragraph>
+ Gannet Ripple
+ <entry>
+ <paragraph>
+ 1.99
+ <entry>
+ <paragraph>
+ On a stick!
+ <table align="center" classes="colwidths-auto">
+ <title>
+ center aligned list table
+ <tgroup cols="2">
+ <colspec colwidth="50">
+ <colspec colwidth="50">
+ <tbody>
+ <row>
+ <entry>
+ <paragraph>
+ Albatross
+ <entry>
+ <paragraph>
+ 2.99
+ <row>
+ <entry>
+ <paragraph>
+ Crunchy Frog
+ <entry>
+ <paragraph>
+ 1.49
+ <row>
+ <entry>
+ <paragraph>
+ Gannet Ripple
+ <entry>
+ <paragraph>
+ 1.99
+ <section ids="error-handling" names="error\ handling">
+ <title auto="1" refid="toc-entry-40">
+ <generated classes="sectnum">
+ 3
+ Error Handling
+ <paragraph>
+ Any errors caught during processing will generate system messages.
+ <paragraph>
+ There should be five messages in the following, auto-generated
+ section, "Docutils System Messages":
+ <comment xml:space="preserve">
+ section should be added by Docutils automatically
+ <section classes="system-messages">
+ <title>
+ Docutils System Messages
+ <system_message backrefs="problematic-1" ids="system-message-1" level="3" line="104" source="functional/input/data/standard.txt" type="ERROR">
+ <paragraph>
+ Undefined substitution referenced: "problematic".
+ <system_message backrefs="footnote-reference-8" ids="system-message-2" level="3" line="392" source="functional/input/data/standard.txt" type="ERROR">
+ <paragraph>
+ Unknown target name: "5".
+ <system_message backrefs="citation-reference-3" ids="system-message-3" level="3" line="401" source="functional/input/data/standard.txt" type="ERROR">
+ <paragraph>
+ Unknown target name: "nonexistent".
+ <system_message backrefs="problematic-2" ids="system-message-4" level="3" line="428" source="functional/input/data/standard.txt" type="ERROR">
+ <paragraph>
+ Unknown target name: "hyperlink reference without a target".
+ <system_message backrefs="problematic-3" ids="system-message-5" level="3" line="441" source="functional/input/data/standard.txt" type="ERROR">
+ <paragraph>
+ Duplicate target name, cannot be used as a unique reference: "duplicate target names".
+ <system_message level="1" line="164" source="functional/input/data/standard.txt" type="INFO">
+ <paragraph>
+ Hyperlink target "target" is not referenced.
+ <system_message level="1" line="406" source="functional/input/data/standard.txt" type="INFO">
+ <paragraph>
+ Hyperlink target "another-target" is not referenced.
+ <system_message level="1" line="474" source="functional/input/data/standard.txt" type="INFO">
+ <paragraph>
+ Hyperlink target "image-target-1" is not referenced.
+ <system_message level="1" line="475" source="functional/input/data/standard.txt" type="INFO">
+ <paragraph>
+ Hyperlink target "image-target-2" is not referenced.
+ <system_message level="1" line="476" source="functional/input/data/standard.txt" type="INFO">
+ <paragraph>
+ Hyperlink target "image-target-3" is not referenced.
+ <system_message level="1" line="640" source="functional/input/data/standard.txt" type="INFO">
+ <paragraph>
+ Hyperlink target "target1" is not referenced.
+ <system_message level="1" line="641" source="functional/input/data/standard.txt" type="INFO">
+ <paragraph>
+ Hyperlink target "target2" is not referenced.
+ <system_message level="1" line="686" source="functional/input/data/standard.txt" type="INFO">
+ <paragraph>
+ Hyperlink target "docutils" is not referenced.
+ <system_message level="1" line="852" source="functional/input/data/standard.txt" type="INFO">
+ <paragraph>
+ Hyperlink target "hyperlink targets" is not referenced.
--- /dev/null
+<?xml version="1.0" encoding="utf-8" ?>
+<!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">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<meta name="generator" content="Docutils 0.16: http://docutils.sourceforge.net/" />
+<meta name="version" content="S5 1.1" />
+<title>Slide Shows</title>
+<meta name="author" content="David Goodger" />
+<meta name="date" content="2005-11-28" />
+<link rel="stylesheet" href="../input/data/html4css1.css" type="text/css" />
+<!-- configuration parameters -->
+<meta name="defaultView" content="slideshow" />
+<meta name="controlVis" content="hidden" />
+<!-- style sheet links -->
+<script src="ui/small-black/slides.js" type="text/javascript"></script>
+<link rel="stylesheet" href="ui/small-black/slides.css"
+ type="text/css" media="projection" id="slideProj" />
+<link rel="stylesheet" href="ui/small-black/outline.css"
+ type="text/css" media="screen" id="outlineStyle" />
+<link rel="stylesheet" href="ui/small-black/print.css"
+ type="text/css" media="print" id="slidePrint" />
+<link rel="stylesheet" href="ui/small-black/opera.css"
+ type="text/css" media="projection" id="operaFix" />
+
+<style type="text/css">
+#currentSlide {display: none;}
+</style>
+</head>
+<body>
+<div class="layout">
+<div id="controls"></div>
+<div id="currentSlide"></div>
+<div id="header">
+
+</div>
+<div id="footer">
+<h1>Slide Shows</h1>
+<h2>Location • Date</h2>
+</div>
+</div>
+<div class="presentation">
+<div class="slide" id="slide0">
+<h1 class="title">Slide Shows</h1>
+<table class="docinfo" frame="void" rules="none">
+<col class="docinfo-name" />
+<col class="docinfo-content" />
+<tbody valign="top">
+<tr><th class="docinfo-name">Author:</th>
+<td>David Goodger</td></tr>
+<tr><th class="docinfo-name">Date:</th>
+<td>2005-11-28</td></tr>
+</tbody>
+</table>
+<!-- Definitions of interpreted text roles (classes) for S5/HTML data. -->
+<!-- This data file has been placed in the public domain. -->
+<!-- Colours
+======= -->
+<!-- Text Sizes
+========== -->
+<!-- Display in Slides (Presentation Mode) Only
+========================================== -->
+<!-- Display in Outline Mode Only
+============================ -->
+<!-- Display in Print Only
+===================== -->
+<!-- Display in Handout Mode Only
+============================ -->
+<!-- Incremental Display
+=================== -->
+<div class="contents handout topic" id="contents">
+<p class="topic-title">Contents</p>
+<ul class="simple">
+<li><a class="reference internal" href="#introduction" id="toc-entry-1">Introduction</a></li>
+<li><a class="reference internal" href="#features-1" id="toc-entry-2">Features (1)</a></li>
+<li><a class="reference internal" href="#features-2" id="toc-entry-3">Features (2)</a></li>
+<li><a class="reference internal" href="#checklist" id="toc-entry-4">Checklist</a></li>
+</ul>
+</div>
+<p class="handout">This is a test. This is only a test. If this were a real slide
+show, there would be a projector handy.</p>
+<p>Let's test the S5/HTML writer!</p>
+<ul class="small simple">
+<li>Use the arrow keys to navigate.</li>
+<li>Click the "Ø" button to switch between presentation &
+handout/outline modes.</li>
+</ul>
+<div class="handout docutils container">
+In presentation mode, mouse over to the lower right-hand corner to
+display the controls.</div>
+
+</div>
+<div class="slide" id="introduction">
+<h1>Introduction</h1>
+<ul class="compact simple">
+<li>reStructuredText<p class="handout">Uses normal reStructuredText as input.</p>
+</li>
+<li>One section per slide<p class="handout">Each first-level section is converted into a single slide.</p>
+</li>
+<li>(X)HTML output<p class="handout">Presentations can be viewed using any modern graphical web browser.
+The browser must support CSS, JavaScript, and XHTML. S5 even works
+with IE!</p>
+</li>
+<li>Themes<p class="handout">A variety of themes are available.</p>
+</li>
+<li><tt class="docutils literal">rst2s5.py</tt><p class="handout">The front-end tool to generate S5 slide shows.</p>
+</li>
+</ul>
+</div>
+<div class="slide" id="features-1">
+<h1>Features (1)</h1>
+<p class="left">A flush-left paragraph</p>
+<p class="center">A centered paragraph</p>
+<p class="right">A flush-right paragraph</p>
+<p>Some colours: <span class="black">black</span> [black], <span class="gray">gray</span>, <span class="silver">silver</span>,
+<span class="white">white</span> [white], <span class="maroon">maroon</span>, <span class="red">red</span>,
+<span class="magenta">magenta</span>, <span class="fuchsia">fuchsia</span>, <span class="pink">pink</span>,
+<span class="orange">orange</span>, <span class="yellow">yellow</span>, <span class="lime">lime</span>, <span class="green">green</span>,
+<span class="olive">olive</span>, <span class="teal">teal</span>, <span class="cyan">cyan</span>, <span class="aqua">aqua</span>,
+<span class="blue">blue</span>, <span class="navy">navy</span>, <span class="purple">purple</span></p>
+</div>
+<div class="slide" id="features-2">
+<h1>Features (2)</h1>
+<p><span class="incremental">Some</span> <span class="incremental">incremental</span> <span class="incremental">text.</span></p>
+<ul class="incremental open">
+<li><p class="first"><span class="tiny">tiny</span> (class & role name: "tiny", e.g. "<tt class="docutils literal"><span class="pre">:tiny:`text`</span></tt>")</p>
+</li>
+<li><p class="first"><span class="small">small</span> ("small")</p>
+</li>
+<li><p class="first">normal (unstyled)</p>
+</li>
+<li><p class="first"><span class="big">big</span> ("big")</p>
+</li>
+<li><p class="first"><span class="huge">huge</span> ("huge")</p>
+</li>
+</ul>
+</div>
+<div class="slide" id="checklist">
+<h1>Checklist</h1>
+<ul class="simple">
+<li>The document title should be duplicated on each slide in the footer
+(except for the first slide, <tt class="docutils literal">slide0</tt>, where the entire footer is
+disabled).</li>
+<li>The footer also contains a second line, "Location • Date"</li>
+<li>There's no table of contents on the first slide, although it does
+appear in the handout/outline.</li>
+<li>Handout material is not displayed in presentation mode.</li>
+<li>The theme directories should be created, and the theme files copied
+over.</li>
+</ul>
+</div>
+</div>
+</body>
+</html>
--- /dev/null
+<?xml version="1.0" encoding="utf-8" ?>
+<!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">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<meta name="generator" content="Docutils 0.16: http://docutils.sourceforge.net/" />
+<meta name="version" content="S5 1.1" />
+<title>Slide Shows</title>
+<meta name="author" content="David Goodger" />
+<meta name="date" content="2005-11-28" />
+<link rel="stylesheet" href="../input/data/html4css1.css" type="text/css" />
+<!-- configuration parameters -->
+<meta name="defaultView" content="slideshow" />
+<meta name="controlVis" content="hidden" />
+<!-- style sheet links -->
+<script src="ui/default/slides.js" type="text/javascript"></script>
+<link rel="stylesheet" href="ui/default/slides.css"
+ type="text/css" media="projection" id="slideProj" />
+<link rel="stylesheet" href="ui/default/outline.css"
+ type="text/css" media="screen" id="outlineStyle" />
+<link rel="stylesheet" href="ui/default/print.css"
+ type="text/css" media="print" id="slidePrint" />
+<link rel="stylesheet" href="ui/default/opera.css"
+ type="text/css" media="projection" id="operaFix" />
+</head>
+<body>
+<div class="layout">
+<div id="controls"></div>
+<div id="currentSlide"></div>
+<div id="header">
+
+</div>
+<div id="footer">
+<h1>Slide Shows</h1>
+<h2>Location • Date</h2>
+</div>
+</div>
+<div class="presentation">
+<div class="slide" id="slide0">
+<h1 class="title">Slide Shows</h1>
+<table class="docinfo" frame="void" rules="none">
+<col class="docinfo-name" />
+<col class="docinfo-content" />
+<tbody valign="top">
+<tr><th class="docinfo-name">Author:</th>
+<td>David Goodger</td></tr>
+<tr><th class="docinfo-name">Date:</th>
+<td>2005-11-28</td></tr>
+</tbody>
+</table>
+<!-- Definitions of interpreted text roles (classes) for S5/HTML data. -->
+<!-- This data file has been placed in the public domain. -->
+<!-- Colours
+======= -->
+<!-- Text Sizes
+========== -->
+<!-- Display in Slides (Presentation Mode) Only
+========================================== -->
+<!-- Display in Outline Mode Only
+============================ -->
+<!-- Display in Print Only
+===================== -->
+<!-- Display in Handout Mode Only
+============================ -->
+<!-- Incremental Display
+=================== -->
+<div class="contents handout topic" id="contents">
+<p class="topic-title">Contents</p>
+<ul class="simple">
+<li><a class="reference internal" href="#introduction" id="toc-entry-1">Introduction</a></li>
+<li><a class="reference internal" href="#features-1" id="toc-entry-2">Features (1)</a></li>
+<li><a class="reference internal" href="#features-2" id="toc-entry-3">Features (2)</a></li>
+<li><a class="reference internal" href="#checklist" id="toc-entry-4">Checklist</a></li>
+</ul>
+</div>
+<p class="handout">This is a test. This is only a test. If this were a real slide
+show, there would be a projector handy.</p>
+<p>Let's test the S5/HTML writer!</p>
+<ul class="small simple">
+<li>Use the arrow keys to navigate.</li>
+<li>Click the "Ø" button to switch between presentation &
+handout/outline modes.</li>
+</ul>
+<div class="handout docutils container">
+In presentation mode, mouse over to the lower right-hand corner to
+display the controls.</div>
+
+</div>
+<div class="slide" id="introduction">
+<h1>Introduction</h1>
+<ul class="compact simple">
+<li>reStructuredText<p class="handout">Uses normal reStructuredText as input.</p>
+</li>
+<li>One section per slide<p class="handout">Each first-level section is converted into a single slide.</p>
+</li>
+<li>(X)HTML output<p class="handout">Presentations can be viewed using any modern graphical web browser.
+The browser must support CSS, JavaScript, and XHTML. S5 even works
+with IE!</p>
+</li>
+<li>Themes<p class="handout">A variety of themes are available.</p>
+</li>
+<li><tt class="docutils literal">rst2s5.py</tt><p class="handout">The front-end tool to generate S5 slide shows.</p>
+</li>
+</ul>
+</div>
+<div class="slide" id="features-1">
+<h1>Features (1)</h1>
+<p class="left">A flush-left paragraph</p>
+<p class="center">A centered paragraph</p>
+<p class="right">A flush-right paragraph</p>
+<p>Some colours: <span class="black">black</span> [black], <span class="gray">gray</span>, <span class="silver">silver</span>,
+<span class="white">white</span> [white], <span class="maroon">maroon</span>, <span class="red">red</span>,
+<span class="magenta">magenta</span>, <span class="fuchsia">fuchsia</span>, <span class="pink">pink</span>,
+<span class="orange">orange</span>, <span class="yellow">yellow</span>, <span class="lime">lime</span>, <span class="green">green</span>,
+<span class="olive">olive</span>, <span class="teal">teal</span>, <span class="cyan">cyan</span>, <span class="aqua">aqua</span>,
+<span class="blue">blue</span>, <span class="navy">navy</span>, <span class="purple">purple</span></p>
+</div>
+<div class="slide" id="features-2">
+<h1>Features (2)</h1>
+<p><span class="incremental">Some</span> <span class="incremental">incremental</span> <span class="incremental">text.</span></p>
+<ul class="incremental open">
+<li><p class="first"><span class="tiny">tiny</span> (class & role name: "tiny", e.g. "<tt class="docutils literal"><span class="pre">:tiny:`text`</span></tt>")</p>
+</li>
+<li><p class="first"><span class="small">small</span> ("small")</p>
+</li>
+<li><p class="first">normal (unstyled)</p>
+</li>
+<li><p class="first"><span class="big">big</span> ("big")</p>
+</li>
+<li><p class="first"><span class="huge">huge</span> ("huge")</p>
+</li>
+</ul>
+</div>
+<div class="slide" id="checklist">
+<h1>Checklist</h1>
+<ul class="simple">
+<li>The document title should be duplicated on each slide in the footer
+(except for the first slide, <tt class="docutils literal">slide0</tt>, where the entire footer is
+disabled).</li>
+<li>The footer also contains a second line, "Location • Date"</li>
+<li>There's no table of contents on the first slide, although it does
+appear in the handout/outline.</li>
+<li>Handout material is not displayed in presentation mode.</li>
+<li>The theme directories should be created, and the theme files copied
+over.</li>
+</ul>
+</div>
+</div>
+</body>
+</html>
--- /dev/null
+\documentclass[a4paper]{article}
+% generated by Docutils <http://docutils.sourceforge.net/>
+% 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
+\usepackage{ifthen}
+\usepackage{alltt}
+\usepackage{amsmath}
+\usepackage{polyglossia}
+\setdefaultlanguage{english}
+\setotherlanguages{english,french,german}
+\usepackage{color}
+\usepackage{float} % float configuration
+\floatplacement{figure}{H} % place figures here definitely
+\usepackage{graphicx}
+\usepackage{multirow}
+\setcounter{secnumdepth}{0}
+\usepackage{longtable,ltcaption,array}
+\setlength{\extrarowheight}{2pt}
+\newlength{\DUtablewidth} % internal use in tables
+\usepackage{tabularx}
+
+%%% Custom LaTeX 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}
+
+%%% User specified packages and stylesheets
+
+%%% Fallback definitions for Docutils-specific commands
+
+% 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]%
+ {\def\DocutilsClassFunctionName{DUCLASS#1}% arg cannot be used in end-part of environment.
+ \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}}{}
+}
+
+% abstract title
+\providecommand*{\DUtitleabstract}[1]{\centerline{\textbf{#1}}}
+
+% admonition (specially marked topic)
+\providecommand{\DUadmonition}[2][class-arg]{%
+ % try \DUadmonition#1{#2}:
+ \ifcsname DUadmonition#1\endcsname%
+ \csname DUadmonition#1\endcsname{#2}%
+ \else
+ \begin{center}
+ \fbox{\parbox{0.9\linewidth}{#2}}
+ \end{center}
+ \fi
+}
+
+% dedication topic
+\providecommand*{\DUCLASSdedication}{%
+ \renewenvironment{quote}{\begin{center}}{\end{center}}%
+}
+
+% docinfo (width of docinfo table)
+\DUprovidelength{\DUdocinfowidth}{0.9\linewidth}
+
+% subtitle (in document title)
+\providecommand*{\DUdocumentsubtitle}[1]{{\large #1}}
+\newcounter{enumv}
+
+% error admonition title
+\providecommand*{\DUtitleerror}[1]{\DUtitle{\color{red}#1}}
+
+% fieldlist environment
+\ifthenelse{\isundefined{\DUfieldlist}}{
+ \newenvironment{DUfieldlist}%
+ {\quote\description}
+ {\enddescription\endquote}
+}{}
+% numeric or symbol footnotes with hyperlinks
+\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 markup (custom roles)
+% \DUrole{#1}{#2} tries \DUrole#1{#2}
+\providecommand*{\DUrole}[2]{%
+ \ifcsname DUrole#1\endcsname%
+ \csname DUrole#1\endcsname{#2}%
+ \else
+ % backwards compatibility: try \docutilsrole#1{#2}
+ \ifcsname docutilsrole#1\endcsname%
+ \PackageWarningNoLine{docutils}{Command prefix "docutilsrole" is
+ deprecated, \MessageBreak use `\protect\DUrole #1`}
+ \csname docutilsrole#1\endcsname{#2}%
+ \else%
+ #2%
+ \fi%
+ \fi%
+}
+
+% legend environment
+\ifthenelse{\isundefined{\DUlegend}}{
+ \newenvironment{DUlegend}{\small}{}
+}{}
+
+% lineblock 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 environment
+\providecommand*{\DUoptionlistlabel}[1]{\bf #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}
+}{}
+
+\DUprovidelength{\pdfpxdimen}{1bp}
+
+
+% 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}
+}
+
+% subtitle (for sidebar)
+\providecommand*{\DUsubtitle}[1]{\par\emph{#1}\smallskip}
+
+% text mode subscript
+\ifx\textsubscript\undefined
+ \usepackage{fixltx2e} % since 2015 loaded by default
+\fi
+
+% title for topics, admonitions, unsupported section levels, and sidebar
+\providecommand*{\DUtitle}[2][class-arg]{%
+ % call \DUtitle#1{#2} if it exists:
+ \ifcsname DUtitle#1\endcsname%
+ \csname DUtitle#1\endcsname{#2}%
+ \else
+ \smallskip\noindent\textbf{#2}\smallskip%
+ \fi
+}
+
+% titlereference role
+\providecommand*{\DUroletitlereference}[1]{\textsl{#1}}
+
+% transition (break, fancybreak, anonymous section)
+\providecommand*{\DUtransition}{%
+ \hspace*{\fill}\hrulefill\hspace*{\fill}
+ \vskip 0.5\baselineskip
+}
+% hyperlinks:
+\ifthenelse{\isundefined{\hypersetup}}{
+ \usepackage[colorlinks=true,linkcolor=blue,urlcolor=blue]{hyperref}
+ \usepackage{bookmark}
+ \urlstyle{same} % normal text font (alternatives: tt, rm, sf)
+}{}
+\hypersetup{
+ pdftitle={reStructuredText Test Document},
+ pdfauthor={David Goodger;Me;Myself;I}
+}
+
+\title{reStructuredText Test Document%
+ \label{restructuredtext-test-document}%
+ \label{doctitle}%
+ \\%
+ \DUdocumentsubtitle{Examples of Syntax Constructs}%
+ \label{examples-of-syntax-constructs}%
+ \label{subtitle}}
+\author{}
+\date{}
+
+%%% Body
+\begin{document}
+\maketitle
+
+% Docinfo
+\begin{center}
+\begin{tabularx}{\DUdocinfowidth}{lX}
+\textbf{Author}: &
+ David Goodger \\
+\textbf{Address}: &
+ {\raggedright
+123 Example Street\\
+Example, EX Canada\\
+A1B 2C3 } \\
+\textbf{Contact}: &
+ \href{mailto:goodger@python.org}{goodger@python.org} \\
+\textbf{Author}: &
+ Me \\
+\textbf{Author}: &
+ Myself \\
+\textbf{Author}: &
+ I \\
+\textbf{Organization}: &
+ humankind \\
+\textbf{Date}: &
+ Now, or yesterday. Or maybe even \emph{before} yesterday. \\
+\textbf{Status}: &
+ This is a “work in progress” \\
+\textbf{Revision}: &
+ is managed by a version control system. \\
+\textbf{Version}: &
+ 1 \\
+\textbf{Copyright}: &
+ This document has been placed in the public domain. You
+may do with it as you wish. You may copy, modify,
+redistribute, reattribute, sell, buy, rent, lease,
+destroy, or improve it, quote it at length, excerpt,
+incorporate, collate, fold, staple, or mutilate it, or do
+anything else to it that your or anyone else’s heart
+desires. \\
+\textbf{field name}: &
+This is a “generic bibliographic field”.
+\\
+\textbf{field name “2”}: &
+Generic bibliographic fields may contain multiple body elements.
+
+Like this.
+\\
+\end{tabularx}
+\end{center}
+
+\begin{DUclass}{dedication}
+\begin{quote}
+\DUtitle[dedication]{Dedication}
+
+For Docutils users \& co-developers.
+\end{quote}
+\end{DUclass}
+
+\begin{DUclass}{abstract}
+\begin{quote}
+\DUtitle[abstract]{Abstract}
+
+This is a test document, containing at least one example of each
+reStructuredText construct.
+\end{quote}
+\end{DUclass}
+
+% This is a comment. Note how any initial comments are moved by
+% transforms to after the document title, subtitle, and docinfo.
+
+% Above is the document title, and below is the subtitle.
+% They are transformed from section titles after parsing.
+
+% bibliographic fields (which also require a transform):
+
+\pagebreak[4] % start ToC on new page
+
+\phantomsection\label{table-of-contents}
+\pdfbookmark[1]{Table of Contents}{table-of-contents}
+\renewcommand{\contentsname}{Table of Contents}
+\tableofcontents
+
+
+\section{1 Structural Elements%
+ \label{structural-elements}%
+}
+
+
+\subsection{1.1 Section Title%
+ \label{section-title}%
+}
+\subsubsection*{Section Subtitle}
+
+Lone subsections are converted to a section subtitle by a transform
+activated with the \texttt{--section-subtitles} command line option or the
+\texttt{sectsubtitle-xform} configuration value.
+
+
+\subsection{1.2 Empty Section%
+ \label{empty-section}%
+}
+
+
+\subsection{1.3 Transitions%
+ \label{transitions}%
+}
+
+Here’s a transition:
+
+%___________________________________________________________________________
+\DUtransition
+
+It divides the section. Transitions may also occur between sections:
+
+%___________________________________________________________________________
+\DUtransition
+
+
+\section{2 Body Elements%
+ \label{body-elements}%
+}
+
+
+\subsection{2.1 Paragraphs%
+ \label{paragraphs}%
+}
+
+A paragraph.
+
+
+\subsubsection{2.1.1 Inline Markup%
+ \label{inline-markup}%
+}
+
+Paragraphs contain text and may contain inline markup: \emph{emphasis},
+\textbf{strong emphasis}, \texttt{inline literals}, standalone hyperlinks
+(\url{http://www.python.org}), external hyperlinks (\href{http://www.python.org/}{Python}\DUfootnotemark{footnote-reference-10}{footnote-6}{5}), internal
+cross-references (\hyperref[example]{example}), external hyperlinks with embedded URIs
+(\href{http://www.python.org}{Python web site}), \href{http://www.python.org/}{anonymous hyperlink
+references}\DUfootnotemark{footnote-reference-17}{footnote-6}{5} (\href{http://docutils.sourceforge.net/}{a second reference}\DUfootnotemark{footnote-reference-18}{footnote-10}{9}), footnote references (manually
+numbered\DUfootnotemark{footnote-reference-1}{footnote-1}{1}, anonymous auto-numbered\DUfootnotemark{footnote-reference-2}{footnote-2}{3}, labeled auto-numbered\DUfootnotemark{footnote-reference-3}{label}{2}, or symbolic\DUfootnotemark{footnote-reference-4}{footnote-3}{*}), citation references (\hyperlink{cit2002}{[CIT2002]}),
+substitution references (\includegraphics{../../../docs/user/rst/images/biohazard.png} \&
+a \emph{trimmed heart} \texttt{(U+2665):}♥), and %
+\phantomsection\label{inline-hyperlink-targets}inline hyperlink targets
+(see \hyperref[targets]{Targets} below for a reference back to here). Character-level
+inline markup is also possible (although exceedingly ugly!) in \emph{re}\texttt{Structured}\emph{Text}. Problems are indicated by %
+\raisebox{1em}{\hypertarget{problematic-1}{}}\hyperlink{system-message-1}{\textbf{\color{red}|problematic|}} text
+(generated by processing errors; this one is intentional). Here is a
+reference to the \hyperref[doctitle]{doctitle} and the \hyperref[subtitle]{subtitle}.
+
+The default role for interpreted text is \DUroletitlereference{Title Reference}. Here are
+some explicit interpreted text roles: a PEP reference (\href{http://www.python.org/dev/peps/pep-0287}{PEP 287}); an
+RFC reference (\href{http://tools.ietf.org/html/rfc2822.html}{RFC 2822}); an abbreviation (\DUrole{abbreviation}{abb.}), an acronym
+(\DUrole{acronym}{reST}), code (\texttt{\DUrole{code}{print \textquotedbl{}hello world\textquotedbl{}}}); a \textsubscript{subscript};
+a \textsuperscript{superscript} and explicit roles for \DUroletitlereference{Docutils}’
+\emph{standard} \textbf{inline} \texttt{markup}.
+
+% DO NOT RE-WRAP THE FOLLOWING PARAGRAPH!
+
+Let’s test wrapping and whitespace significance in inline literals:
+\texttt{This is an example of --inline-literal --text, --including some--
+strangely--hyphenated-words. ~Adjust-the-width-of-your-browser-window
+to see how the text is wrapped. ~-- ---- -------- ~Now note ~ ~the
+spacing ~ ~between the ~ ~words of ~ ~this sentence ~ ~(words
+should ~ ~be grouped ~ ~in pairs).}
+
+If the \texttt{--pep-references} option was supplied, there should be a
+live link to PEP 258 here.
+
+
+\subsection{2.2 Bullet Lists%
+ \label{bullet-lists}%
+}
+
+\begin{itemize}
+\item A bullet list
+
+\begin{itemize}
+\item Nested bullet list.
+
+\item Nested item 2.
+\end{itemize}
+
+\item Item 2.
+
+Paragraph 2 of item 2.
+
+\begin{itemize}
+\item Nested bullet list.
+
+\item Nested item 2.
+
+\begin{itemize}
+\item Third level.
+
+\item Item 2.
+\end{itemize}
+
+\item Nested item 3.
+
+\item This nested list should be compacted by the HTML writer.
+%
+\phantomsection\label{target}
+% Even if this item contains a target and a comment.
+\end{itemize}
+\end{itemize}
+
+
+\subsection{2.3 Enumerated Lists%
+ \label{enumerated-lists}%
+}
+
+\begin{enumerate}
+\item Arabic numerals.
+
+\begin{enumerate}
+\renewcommand{\labelenumii}{\alph{enumii})}
+\item lower alpha)
+
+\begin{enumerate}
+\renewcommand{\labelenumiii}{(\roman{enumiii})}
+\item (lower roman)
+
+\begin{enumerate}
+\item upper alpha.
+
+\begin{list}{\Roman{enumv})}{\usecounter{enumv}}
+\item upper roman)
+\end{list}
+\end{enumerate}
+\end{enumerate}
+\end{enumerate}
+
+\item Lists that don’t start at 1:
+
+\begin{enumerate}
+\renewcommand{\labelenumii}{\arabic{enumii}.}
+\setcounter{enumii}{2}
+\item Three
+
+\item Four
+\end{enumerate}
+
+\begin{enumerate}
+\renewcommand{\labelenumii}{\Alph{enumii}.}
+\setcounter{enumii}{2}
+\item C
+
+\item D
+\end{enumerate}
+
+\begin{enumerate}
+\renewcommand{\labelenumii}{\roman{enumii}.}
+\setcounter{enumii}{2}
+\item iii
+
+\item iv
+\end{enumerate}
+\end{enumerate}
+
+
+\subsection{2.4 Definition Lists%
+ \label{definition-lists}%
+}
+
+\begin{description}
+\item[{Term}] \leavevmode
+Definition
+
+\item[{Term}] \leavevmode (\textbf{classifier})
+Definition paragraph 1.
+
+Definition paragraph 2.
+
+\item[{Term}] \leavevmode
+Definition
+
+\item[{Term}] \leavevmode (\textbf{classifier one})(\textbf{classifier two})
+Definition
+
+\end{description}
+
+
+\subsection{2.5 Field Lists%
+ \label{field-lists}%
+}
+
+\begin{DUfieldlist}
+\item[{what:}]
+Field lists map field names to field bodies, like database
+records. They are often part of an extension syntax. They are
+an unambiguous variant of RFC 2822 fields.
+
+\item[{how arg1 arg2:}]
+The field marker is a colon, the field name, and a colon.
+
+The field body may contain one or more body elements, indented
+relative to the field marker.
+
+\item[{credits:}]
+\DUrole{credits}{This paragraph has the \DUroletitlereference{credits} class set. (This is actually not
+about credits but just for ensuring that the class attribute
+doesn’t get stripped away.)}
+\end{DUfieldlist}
+
+
+\subsection{2.6 Option Lists%
+ \label{option-lists}%
+}
+
+For listing command-line options:
+
+\begin{DUoptionlist}
+\item[-a] command-line option “a”
+
+\item[-b file] options can have arguments
+and long descriptions
+
+\item[--long] options can be long also
+
+\item[--input=file] long options can also have
+arguments
+
+\item[--very-long-option] The description can also start on the next line.
+
+The description may contain multiple body elements,
+regardless of where it starts.
+
+\item[-x, -y, -z] Multiple options are an “option group”.
+
+\item[-v, --verbose] Commonly-seen: short \& long options.
+
+\item[-1 file, --one=file, --two file] Multiple options with arguments.
+
+\item[/V] DOS/VMS-style options too
+\end{DUoptionlist}
+
+There must be at least two spaces between the option and the
+description.
+
+
+\subsection{2.7 Literal Blocks%
+ \label{literal-blocks}%
+}
+
+Literal blocks are indicated with a double-colon (“::”) at the end of
+the preceding paragraph (over there \texttt{-->}). They can be indented:
+
+\begin{quote}
+\begin{alltt}
+if literal_block:
+ text = 'is left as-is'
+ spaces_and_linebreaks = 'are preserved'
+ markup_processing = None
+\end{alltt}
+\end{quote}
+
+Or they can be quoted without indentation:
+
+\begin{quote}
+\begin{alltt}
+>> Great idea!
+>
+> Why didn't I think of that?
+\end{alltt}
+\end{quote}
+
+
+\subsection{2.8 Line Blocks%
+ \label{line-blocks}%
+}
+
+This section tests line blocks. Line blocks are body elements which
+consist of lines and other line blocks. Nested line blocks cause
+indentation.
+
+\begin{DUlineblock}{0em}
+\item[] This is a line block. It ends with a blank line.
+\item[]
+\begin{DUlineblock}{\DUlineblockindent}
+\item[] New lines begin with a vertical bar (“|”).
+\item[] Line breaks and initial indent are significant, and preserved.
+\item[]
+\begin{DUlineblock}{\DUlineblockindent}
+\item[] Continuation lines are also possible. A long line that is intended
+to wrap should begin with a space in place of the vertical bar.
+\end{DUlineblock}
+\item[] The left edge of a continuation line need not be aligned with
+the left edge of the text above it.
+\end{DUlineblock}
+\end{DUlineblock}
+
+\begin{DUlineblock}{0em}
+\item[] This is a second line block.
+\item[]
+\item[] Blank lines are permitted internally, but they must begin with a “|”.
+\end{DUlineblock}
+
+Another line block, surrounded by paragraphs:
+
+\begin{DUlineblock}{0em}
+\item[] And it’s no good waiting by the window
+\item[] It’s no good waiting for the sun
+\item[] Please believe me, the things you dream of
+\item[] They don’t fall in the lap of no-one
+\end{DUlineblock}
+
+Take it away, Eric the Orchestra Leader!
+
+\begin{quote}
+\begin{DUlineblock}{0em}
+\item[] A one, two, a one two three four
+\item[]
+\item[] Half a bee, philosophically,
+\item[]
+\begin{DUlineblock}{\DUlineblockindent}
+\item[] must, \emph{ipso facto}, half not be.
+\end{DUlineblock}
+\item[] But half the bee has got to be,
+\item[]
+\begin{DUlineblock}{\DUlineblockindent}
+\item[] \emph{vis a vis} its entity. D’you see?
+\item[]
+\end{DUlineblock}
+\item[] But can a bee be said to be
+\item[]
+\begin{DUlineblock}{\DUlineblockindent}
+\item[] or not to be an entire bee,
+\item[]
+\begin{DUlineblock}{\DUlineblockindent}
+\item[] when half the bee is not a bee,
+\item[]
+\begin{DUlineblock}{\DUlineblockindent}
+\item[] due to some ancient injury?
+\item[]
+\end{DUlineblock}
+\end{DUlineblock}
+\end{DUlineblock}
+\item[] Singing…
+\end{DUlineblock}
+\end{quote}
+
+A line block, like the following poem by Christian Morgenstern, can
+also be centre-aligned:
+
+\begin{selectlanguage}{german}
+\begin{DUlineblock}{0em}
+\centering
+\item[] \textbf{Die Trichter}
+\item[]
+\item[] Zwei Trichter wandeln durch die Nacht.
+\item[] Durch ihres Rumpfs verengten Schacht
+\item[] fließt weißes Mondlicht
+\item[] still und heiter
+\item[] auf ihren
+\item[] Waldweg
+\item[] u. s.
+\item[] w.
+\item[]
+\end{DUlineblock}
+\end{selectlanguage}
+
+
+\subsection{2.9 Block Quotes%
+ \label{block-quotes}%
+}
+
+Block quotes consist of indented body elements:
+
+\begin{quote}
+My theory by A. Elk. Brackets Miss, brackets. This theory goes
+as follows and begins now. All brontosauruses are thin at one
+end, much much thicker in the middle and then thin again at the
+far end. That is my theory, it is mine, and belongs to me and I
+own it, and what it is too.
+\nopagebreak
+
+\raggedleft —Anne Elk (Miss)
+\end{quote}
+
+The language of a quote (like any other object) can be specified by
+a class attribute:
+
+%
+
+\begin{selectlanguage}{french}
+\begin{quote}
+ReStructuredText est un langage de balisage léger utilisé
+notamment dans la documentation du langage Python.
+\end{quote}
+\end{selectlanguage}
+
+
+\subsection{2.10 Doctest Blocks%
+ \label{doctest-blocks}%
+}
+
+\begin{quote}
+\begin{alltt}
+>>> print 'Python-specific usage examples; begun with ">>>"'
+Python-specific usage examples; begun with ">>>"
+>>> print '(cut and pasted from interactive Python sessions)'
+(cut and pasted from interactive Python sessions)
+\end{alltt}
+\end{quote}
+
+
+\subsection{2.11 Footnotes%
+ \label{footnotes}%
+}
+%
+\DUfootnotetext{footnote-1}{footnote-reference-1}{1}{%
+A footnote contains body elements, consistently indented by at
+least 3 spaces.
+
+This is the footnote’s second paragraph.
+}
+%
+\DUfootnotetext{label}{footnote-reference-3}{2}{\phantomsection\label{label}%
+Footnotes may be numbered, either manually (as in\DUfootnotemark{footnote-reference-5}{footnote-1}{1}) or
+automatically using a “\#”-prefixed label. This footnote has a
+label so it can be referred to from multiple places, both as a
+footnote reference (\DUfootnotemark{footnote-reference-6}{label}{2}) and as a \hyperref[label]{hyperlink reference}.
+}
+%
+\DUfootnotetext{footnote-2}{footnote-reference-2}{3}{%
+This footnote is numbered automatically and anonymously using a
+label of “\#” only.
+
+This is the second paragraph.
+
+And this is the third paragraph.
+}
+%
+\DUfootnotetext{footnote-3}{footnote-reference-4}{*}{%
+Footnotes may also use symbols, specified with a “*” label.
+Here’s a reference to the next footnote:\DUfootnotemark{footnote-reference-7}{footnote-4}{†}.
+}
+%
+\DUfootnotetext{footnote-4}{footnote-reference-7}{†}{%
+This footnote shows the next symbol in the sequence.
+}
+%
+\DUfootnotetext{footnote-5}{footnote-5}{4}{%
+Here’s an unreferenced footnote, with a reference to a
+nonexistent footnote:%
+\raisebox{1em}{\hypertarget{footnote-reference-8}{}}\hyperlink{system-message-2}{\textbf{\color{red}{[}5{]}\_}}.
+}
+
+
+\subsection{2.12 Citations%
+ \label{citations}%
+}
+\begin{figure}[b]\raisebox{1em}{\hypertarget{cit2002}{}}[CIT2002]
+Citations are text-labeled footnotes. They may be
+rendered separately and differently from footnotes.
+\end{figure}
+
+Here’s a reference to the above, \hyperlink{cit2002}{[CIT2002]}, and a %
+\raisebox{1em}{\hypertarget{citation-reference-3}{}}\hyperlink{system-message-3}{\textbf{\color{red}{[}nonexistent{]}\_}}
+citation.
+
+
+\subsection{2.13 Targets%
+ \label{targets}%
+ \label{another-target}%
+}
+
+\phantomsection\label{example}
+This paragraph is pointed to by the explicit “example” target. A
+reference can be found under \hyperref[inline-markup]{Inline Markup}, above. \hyperref[inline-hyperlink-targets]{Inline
+hyperlink targets} are also possible.
+
+Section headers are implicit targets, referred to by name. See
+\hyperref[targets]{Targets}, which is a subsection of \hyperref[body-elements]{Body Elements}.
+
+Explicit external targets are interpolated into references such as
+“\href{http://www.python.org/}{Python}\DUfootnotemark{footnote-reference-11}{footnote-6}{5}”.
+
+Targets may be indirect and anonymous. Thus \hyperref[targets]{this phrase} may also
+refer to the \hyperref[targets]{Targets} section.
+
+Here’s a %
+\raisebox{1em}{\hypertarget{problematic-2}{}}\hyperlink{system-message-4}{\textbf{\color{red}`hyperlink reference without a target`\_}}, which generates an
+error.
+
+
+\subsubsection{2.13.1 Duplicate Target Names%
+ \label{duplicate-target-names}%
+}
+
+Duplicate names in section headers or other implicit targets will
+generate “info” (level-1) system messages. Duplicate names in
+explicit targets will generate “warning” (level-2) system messages.
+
+
+\subsubsection{2.13.2 Duplicate Target Names%
+ \label{duplicate-target-names-1}%
+}
+
+Since there are two “Duplicate Target Names” section headers, we
+cannot uniquely refer to either of them by name. If we try to (like
+this: %
+\raisebox{1em}{\hypertarget{problematic-3}{}}\hyperlink{system-message-5}{\textbf{\color{red}`Duplicate Target Names`\_}}), an error is generated.
+
+
+\subsection{2.14 Directives%
+ \label{directives}%
+}
+
+\phantomsection\label{contents}
+These are just a sample of the many reStructuredText Directives. For
+others, please see
+\url{http://docutils.sourceforge.net/docs/ref/rst/directives.html}.
+
+
+\subsubsection{2.14.1 Document Parts%
+ \label{document-parts}%
+}
+
+An example of the “contents” directive can be seen above this section
+(a local, untitled table of \hyperref[contents]{contents}) and at the beginning of the
+document (a document-wide \hyperref[table-of-contents]{table of contents}).
+
+
+\subsubsection{2.14.2 Images and Figures%
+ \label{images-and-figures}%
+}
+
+An image directive (also clickable – a hyperlink reference):
+
+\hyperref[directives]{\includegraphics{../../../docs/user/rst/images/title.png}}
+
+Image with multiple IDs:
+
+\includegraphics{../../../docs/user/rst/images/title.png}
+\phantomsection\label{image-target-3}\label{image-target-2}\label{image-target-1}
+
+A centered image:
+
+\noindent\makebox[\linewidth][c]{\includegraphics{../../../docs/user/rst/images/biohazard.png}}
+
+A left-aligned image:
+
+\noindent{\includegraphics{../../../docs/user/rst/images/biohazard.png}\hfill}
+
+This paragraph might flow around the image.
+The specific behavior depends upon the style sheet and
+the browser or rendering software used.
+
+A right-aligned image:
+
+\noindent{\hfill\includegraphics{../../../docs/user/rst/images/biohazard.png}}
+
+This paragraph might flow around the image.
+The specific behavior depends upon the style sheet and
+the browser or rendering software used.
+
+For inline images see \hyperref[substitution-definitions]{Substitution Definitions}.
+
+Image size:
+
+An image 2 em wide:
+
+\includegraphics[width=2em]{../../../docs/user/rst/images/biohazard.png}
+
+An image 2 em wide and 15 pixel high:
+
+\includegraphics[height=15\pdfpxdimen,width=2em]{../../../docs/user/rst/images/biohazard.png}
+
+An image occupying 50\% of the line width:
+
+\includegraphics[width=0.500\linewidth]{../../../docs/user/rst/images/title.png}
+
+An image 2 cm high:
+
+\includegraphics[height=2cm]{../../../docs/user/rst/images/biohazard.png}
+
+A \emph{figure} is an image with a caption and/or a legend. With page-based output
+media, figures might float to a different position if this helps the page
+layout.
+
+\begin{DUclass}{figclass1}
+\begin{DUclass}{figclass2}
+\begin{figure}
+\noindent\makebox[\linewidth][c]{\includegraphics[width=258bp]{../../../docs/user/rst/images/title.png}}
+\caption{Plaintext markup syntax and parser system.}
+\begin{DUlegend}
+\setlength{\DUtablewidth}{\linewidth}
+\begin{longtable*}[c]{|p{0.156\DUtablewidth}|p{0.563\DUtablewidth}|}
+\hline
+
+re
+ &
+Revised, revisited, based on ‘re’ module.
+ \\
+\hline
+
+Structured
+ &
+Structure-enhanced text, structuredtext.
+ \\
+\hline
+
+Text
+ &
+Well it is, isn’t it?
+ \\
+\hline
+\end{longtable*}
+
+This paragraph is also part of the legend.
+\end{DUlegend}
+\end{figure}
+\end{DUclass}
+\end{DUclass}
+
+A left-aligned figure:
+
+\begin{DUclass}{figclass1}
+\begin{DUclass}{figclass2}
+\begin{figure} % align = "left"
+\noindent\makebox[\linewidth][c]{\includegraphics[width=40\pdfpxdimen]{../../../docs/user/rst/images/biohazard.png}}
+\caption{This is the caption.}
+\begin{DUlegend}
+This is the legend.
+
+The legend may consist of several paragraphs.
+\end{DUlegend}
+\end{figure}
+\end{DUclass}
+\end{DUclass}
+
+This paragraph might flow around the figure.
+
+The specific behavior depends upon the style sheet and the browser or
+rendering software used.
+
+A centered figure:
+
+\begin{figure}
+\noindent\makebox[\linewidth][c]{\includegraphics[width=40\pdfpxdimen]{../../../docs/user/rst/images/biohazard.png}}
+\caption{This is the caption.}
+\begin{DUlegend}
+This is the legend.
+
+The legend may consist of several paragraphs.
+\end{DUlegend}
+\end{figure}
+
+This paragraph might flow around the figure.
+
+The specific behavior depends upon the style sheet and the browser or
+rendering software used.
+
+A right-aligned figure:
+
+\begin{figure} % align = "right"
+\noindent\makebox[\linewidth][c]{\includegraphics[width=40\pdfpxdimen]{../../../docs/user/rst/images/biohazard.png}}
+\caption{This is the caption.}
+\begin{DUlegend}
+This is the legend.
+
+The legend may consist of several paragraphs.
+\end{DUlegend}
+\end{figure}
+
+This paragraph might flow around the figure. The specific behavior depends
+upon the style sheet and the browser or rendering software used.
+
+Tables may be given titles and additional arguments with the \emph{table}
+directive:
+
+\setlength{\DUtablewidth}{\linewidth}
+\begin{longtable}[l]{|p{0.075\DUtablewidth}|p{0.075\DUtablewidth}|}
+\caption{left-aligned table}\\
+\hline
+\textbf{%
+A
+} & \textbf{%
+not A
+} \\
+\hline
+\endfirsthead
+\caption[]{left-aligned table (... continued)}\\
+\hline
+\textbf{%
+A
+} & \textbf{%
+not A
+} \\
+\hline
+\endhead
+\multicolumn{2}{c}{\hfill ... continued on next page} \\
+\endfoot
+\endlastfoot
+
+False
+ &
+True
+ \\
+\hline
+
+True
+ &
+False
+ \\
+\hline
+\end{longtable}
+
+\setlength{\DUtablewidth}{\linewidth}
+\begin{longtable}[c]{|p{0.075\DUtablewidth}|p{0.075\DUtablewidth}|}
+\caption{center-aligned table}\\
+\hline
+\textbf{%
+A
+} & \textbf{%
+not A
+} \\
+\hline
+\endfirsthead
+\caption[]{center-aligned table (... continued)}\\
+\hline
+\textbf{%
+A
+} & \textbf{%
+not A
+} \\
+\hline
+\endhead
+\multicolumn{2}{c}{\hfill ... continued on next page} \\
+\endfoot
+\endlastfoot
+
+False
+ &
+True
+ \\
+\hline
+
+True
+ &
+False
+ \\
+\hline
+\end{longtable}
+
+\setlength{\DUtablewidth}{\linewidth}
+\begin{longtable}[r]{|p{0.075\DUtablewidth}|p{0.075\DUtablewidth}|}
+\caption{right-aligned table}\\
+\hline
+\textbf{%
+A
+} & \textbf{%
+not A
+} \\
+\hline
+\endfirsthead
+\caption[]{right-aligned table (... continued)}\\
+\hline
+\textbf{%
+A
+} & \textbf{%
+not A
+} \\
+\hline
+\endhead
+\multicolumn{2}{c}{\hfill ... continued on next page} \\
+\endfoot
+\endlastfoot
+
+False
+ &
+True
+ \\
+\hline
+
+True
+ &
+False
+ \\
+\hline
+\end{longtable}
+
+With the “widths” argument “auto” (or “class” value “colwidths-auto”),
+column widths are determined by the backend (if supported by the
+writer/backend).
+
+\begin{longtable*}[c]{|l|l|l|}
+\hline
+\textbf{A} & \textbf{B} & \textbf{A or B} \\
+\hline
+\endfirsthead
+\hline
+\textbf{A} & \textbf{B} & \textbf{A or B} \\
+\hline
+\endhead
+\multicolumn{3}{c}{\hfill ... continued on next page} \\
+\endfoot
+\endlastfoot
+False & False & False \\
+\hline
+True & False & True \\
+\hline
+False & True & True \\
+\hline
+True & True & True \\
+\hline
+\end{longtable*}
+\label{target2}\label{target1}
+
+
+\subsubsection{2.14.3 Admonitions%
+ \label{admonitions}%
+}
+
+\DUadmonition[attention]{
+\DUtitle[attention]{Attention!}
+
+Directives at large.
+}
+
+\DUadmonition[caution]{
+\DUtitle[caution]{Caution!}
+
+Don’t take any wooden nickels.
+}
+
+\DUadmonition[danger]{
+\DUtitle[danger]{!DANGER!}
+
+Mad scientist at work!
+}
+
+\DUadmonition[error]{
+\DUtitle[error]{Error}
+
+Does not compute.
+}
+
+\DUadmonition[hint]{
+\DUtitle[hint]{Hint}
+
+It’s bigger than a bread box.
+}
+
+\DUadmonition[important]{
+\DUtitle[important]{Important}
+
+\begin{itemize}
+\item Wash behind your ears.
+
+\item Clean up your room.
+
+\item Call your mother.
+
+\item Back up your data.
+\end{itemize}
+}
+
+\DUadmonition[note]{
+\DUtitle[note]{Note}
+
+This is a note.
+}
+
+\DUadmonition[tip]{
+\DUtitle[tip]{Tip}
+
+15\% if the service is good.
+}
+
+\DUadmonition[warning]{
+\DUtitle[warning]{Warning}
+
+Strong prose may provoke extreme mental exertion.
+Reader discretion is strongly advised.
+}
+
+\DUadmonition[admonition-and-by-the-way]{
+\DUtitle[admonition-and-by-the-way]{And, by the way…}
+
+You can make up your own admonition too.
+}
+
+
+\subsubsection{2.14.4 Topics, Sidebars, and Rubrics%
+ \label{topics-sidebars-and-rubrics}%
+}
+
+\emph{Sidebars} are like miniature, parallel documents.
+
+\DUsidebar{
+\DUtitle[sidebar]{Sidebar Title}
+
+\DUsubtitle{Optional Subtitle}
+
+This is a sidebar. It is for text outside the flow of the main
+text.
+
+\DUrubric{This is a rubric inside a sidebar}
+
+Sidebars often appear beside the main text with a border and a different
+background or font color.
+}
+
+A \emph{topic} is like a block quote with a title, or a self-contained section
+with no subsections.
+
+\begin{DUclass}{topic}
+\begin{quote}
+\DUtitle[topic]{Topic Title}
+
+This is a topic.
+\end{quote}
+\end{DUclass}
+
+A \emph{rubric} is like an informal heading that doesn’t correspond to the
+document’s structure. It is typically highlighted in red (hence the name).
+
+\DUrubric{This is a rubric}
+
+Topics and rubrics can be used at places where a \hyperref[section-title]{section title} is not
+allowed (e.g. inside a directive).
+
+
+\subsubsection{2.14.5 Target Footnotes%
+ \label{target-footnotes}%
+}
+%
+\DUfootnotetext{footnote-6}{footnote-reference-10}{5}{%
+\url{http://www.python.org/}
+}
+%
+\DUfootnotetext{footnote-7}{footnote-reference-13}{6}{%
+\url{http://pygments.org/}
+}
+%
+\DUfootnotetext{footnote-8}{footnote-reference-14}{7}{%
+\url{ftp://ftp.ams.org/ams/doc/amsmath/short-math-guide.pdf}
+}
+%
+\DUfootnotetext{footnote-9}{footnote-reference-16}{8}{%
+\url{http://ctan.org/pkg/polyglossia}
+}
+%
+\DUfootnotetext{footnote-10}{footnote-reference-18}{9}{%
+\url{http://docutils.sourceforge.net/}
+}
+%
+\DUfootnotetext{footnote-11}{footnote-reference-19}{10}{%
+\url{A:DOS\\path\\}
+}
+
+
+\subsubsection{2.14.6 Replacement Text%
+ \label{replacement-text}%
+}
+
+I recommend you try \href{http://www.python.org/}{Python, \emph{the} best language around}\DUfootnotemark{footnote-reference-12}{footnote-6}{5}.
+
+
+\subsubsection{2.14.7 Compound Paragraph%
+ \label{compound-paragraph}%
+}
+
+The \emph{compound} directive is used to create a “compound paragraph”, which
+is a single logical paragraph containing multiple physical body
+elements. For example:
+
+\begin{DUclass}{compound}
+The ‘rm’ command is very dangerous. If you are logged
+in as root and enter
+\begin{quote}
+\begin{alltt}
+cd /
+rm -rf *
+\end{alltt}
+\end{quote}
+you will erase the entire contents of your file system.
+\end{DUclass}
+
+Test the handling and display of compound paragraphs:
+
+\begin{DUclass}{compound}
+\begin{DUclass}{some-class}
+Compound 2, paragraph 1,
+
+compound 2, paragraph 2,
+\begin{itemize}
+\item list item 1,
+
+\item list item 2,
+\end{itemize}
+compound 2, paragraph 3.
+\end{DUclass}
+\end{DUclass}
+
+\begin{DUclass}{compound}
+Compound 3, only consisting of one paragraph.
+\end{DUclass}
+
+\begin{DUclass}{compound}
+\begin{quote}
+\begin{alltt}
+Compound 4.
+This one starts with a literal block.
+\end{alltt}
+\end{quote}
+Compound 4, paragraph following the literal block.
+\end{DUclass}
+
+Now something \emph{really} perverted – a nested compound block. This is
+just to test that it works at all; the results don’t have to be
+meaningful.
+
+\begin{DUclass}{compound}
+Compound 5, block 1 (a paragraph).
+
+\begin{DUclass}{compound}
+Compound 6 is block 2 in compound 5.
+
+Compound 6, another paragraph.
+\end{DUclass}
+
+Compound 5, block 3 (a paragraph).
+\end{DUclass}
+
+\begin{DUclass}{compound}
+Compound 7, tests the inclusion of various block-level
+elements in one logical paragraph. First a table,
+
+\setlength{\DUtablewidth}{\linewidth}
+\begin{longtable*}[c]{|p{0.249\DUtablewidth}|p{0.249\DUtablewidth}|p{0.249\DUtablewidth}|}
+\hline
+
+Left cell, first
+paragraph.
+
+Left cell, second
+paragraph.
+ &
+Middle cell,
+consisting of
+exactly one
+paragraph.
+ &
+Right cell.
+
+Paragraph 2.
+
+Paragraph 3.
+ \\
+\hline
+\end{longtable*}
+followed by a paragraph. This physical paragraph is
+actually a continuation of the paragraph before the table. It is followed
+by
+\begin{quote}
+a quote and
+\end{quote}
+\begin{enumerate}
+\item an enumerated list,
+\end{enumerate}
+a paragraph,
+\begin{DUoptionlist}
+\item[--an] option list,
+\end{DUoptionlist}
+a paragraph,
+\begin{DUfieldlist}
+\item[{a field:}]
+list,
+\end{DUfieldlist}
+a paragraph,
+\begin{description}
+\item[{a definition}] \leavevmode
+list,
+
+\end{description}
+a paragraph, an image:
+\includegraphics{../../../docs/user/rst/images/biohazard.png}
+a paragraph,
+\begin{DUlineblock}{0em}
+\item[] a line
+\item[] block,
+\end{DUlineblock}
+a paragraph followed by a comment,
+% this is a comment
+a paragraph, a
+
+\DUadmonition[note]{
+\DUtitle[note]{Note}
+
+with content
+}
+and the final paragraph of the compound 7.
+\end{DUclass}
+
+
+\subsubsection{2.14.8 Parsed Literal Blocks%
+ \label{parsed-literal-blocks}%
+}
+
+\begin{quote}
+\ttfamily\raggedright
+This~is~a~parsed~literal~block.\\
+~~~~This~line~is~indented.~~The~next~line~is~blank.\\
+~\\
+Inline~markup~is~supported,~e.g.~\emph{emphasis},~\textbf{strong},~\texttt{literal\\
+text},~\textsubscript{sub-}~and~\textsuperscript{super}scripts,\\
+inline~formulas:~$A = 2 \pi r^2$,\\
+footnotes\DUfootnotemark{footnote-reference-9}{footnote-1}{1},~%
+\phantomsection\label{hyperlink-targets}hyperlink~targets,~and~\href{http://www.python.org/}{references}.
+\end{quote}
+
+
+\subsubsection{2.14.9 Code%
+ \label{code}%
+}
+
+Blocks of source code can be set with the \DUroletitlereference{code} directive. If the code
+language is specified, the content is parsed and tagged by the \href{http://pygments.org/}{Pygments}\DUfootnotemark{footnote-reference-13}{footnote-7}{6}
+syntax highlighter and can be formatted with a style sheet. (Code parsing
+is turned off using the \texttt{syntax-highlight} config setting in the test
+conversions in order to get identical results with/without installed
+Pygments highlighter.)
+
+\begin{DUclass}{code}
+\begin{DUclass}{python}
+\begin{quote}
+\begin{alltt}
+print 'This is Python code.'
+\end{alltt}
+\end{quote}
+\end{DUclass}
+\end{DUclass}
+
+The \texttt{:number-lines:} option (with optional start value) generates line
+numbers:
+
+\begin{DUclass}{code}
+\begin{DUclass}{python}
+\begin{quote}
+\ttfamily\raggedright
+\DUrole{ln}{~8~}\#~print~integers~from~0~to~9:\\
+\DUrole{ln}{~9~}for~i~in~range(10):\\
+\DUrole{ln}{10~}~~~~print~i
+\end{quote}
+\end{DUclass}
+\end{DUclass}
+
+For inline code snippets, there is the \DUroletitlereference{code} role, which can be used
+directly (the code will not be parsed/tagged, as the language is not known)
+or as base for special code roles, e.g. the LaTeX code in the next
+paragraph.
+
+Docutils uses LaTeX syntax for math directives and roles:
+\texttt{\DUrole{code}{\DUrole{tex}{\textbackslash{}alpha = f(x)}}} prints $\alpha = f(x)$.
+
+The \texttt{:code:} option of the \DUroletitlereference{include} directive sets the included content
+as a code block, here the rst file \texttt{header\_footer.txt} with line numbers:
+
+\begin{DUclass}{code}
+\begin{DUclass}{rst}
+\begin{quote}
+\ttfamily\raggedright
+\DUrole{ln}{1~}..~header::~Document~header\\
+\DUrole{ln}{2~}..~footer::~Document~footer
+\end{quote}
+\end{DUclass}
+\end{DUclass}
+
+
+\subsection{2.15 Substitution Definitions%
+ \label{substitution-definitions}%
+}
+
+An inline image (\includegraphics{../../../docs/user/rst/images/biohazard.png}) example:
+
+A Unicode example:
+
+(Substitution definitions are not visible in the HTML source.)
+
+
+\subsection{2.16 Comments%
+ \label{comments}%
+}
+
+Here’s one:
+
+% Comments begin with two dots and a space. Anything may
+% follow, except for the syntax of footnotes, hyperlink
+% targets, directives, or substitution definitions.
+%
+% Double-dashes -- "--" -- must be escaped somehow in HTML output.
+%
+% Comments may contain non-ASCII characters: ä ö ü æ ø å
+
+(View the HTML source to see the comment.)
+
+
+\subsection{2.17 Raw text%
+ \label{raw-text}%
+}
+
+This does not necessarily look nice, because there may be missing white space.
+
+It’s just there to freeze the behavior.
+
+A test.
+
+Second test.
+
+\DUrole{myclass}{Another test with myclass set.}
+
+This is the \DUrole{myrawroleclass}{fourth test} with myrawroleclass set.
+
+Fifth test in LaTeX.\\Line two.
+
+
+\subsection{2.18 Container%
+ \label{container}%
+}
+
+\begin{DUclass}{custom}
+
+paragraph 1
+
+paragraph 2
+\end{DUclass}
+
+% currently not implemented in LaTeX:
+% .. include:: data/header_footer.txt
+
+
+\subsection{2.19 Colspanning tables%
+ \label{colspanning-tables}%
+}
+
+This table has a cell spanning two columns:
+
+\setlength{\DUtablewidth}{\linewidth}
+\begin{longtable*}[c]{|p{0.075\DUtablewidth}|p{0.075\DUtablewidth}|p{0.086\DUtablewidth}|}
+\hline
+\multicolumn{2}{|p{0.15\DUtablewidth}|}{\textbf{%
+Inputs
+}} & \textbf{%
+Output
+} \\
+\hline
+\textbf{%
+A
+} & \textbf{%
+B
+} & \textbf{%
+A or B
+} \\
+\hline
+\endfirsthead
+\hline
+\multicolumn{2}{|p{0.15\DUtablewidth}|}{\textbf{%
+Inputs
+}} & \textbf{%
+Output
+} \\
+\hline
+\textbf{%
+A
+} & \textbf{%
+B
+} & \textbf{%
+A or B
+} \\
+\hline
+\endhead
+\multicolumn{3}{c}{\hfill ... continued on next page} \\
+\endfoot
+\endlastfoot
+
+False
+ &
+False
+ &
+False
+ \\
+\hline
+
+True
+ &
+False
+ &
+True
+ \\
+\hline
+
+False
+ &
+True
+ &
+True
+ \\
+\hline
+
+True
+ &
+True
+ &
+True
+ \\
+\hline
+\end{longtable*}
+
+
+\subsection{2.20 Rowspanning tables%
+ \label{rowspanning-tables}%
+}
+
+Here’s a table with cells spanning several rows:
+
+\setlength{\DUtablewidth}{\linewidth}
+\begin{longtable*}[c]{|p{0.296\DUtablewidth}|p{0.156\DUtablewidth}|p{0.226\DUtablewidth}|}
+\hline
+\textbf{%
+Header row, column 1
+(header rows optional)
+} & \textbf{%
+Header 2
+} & \textbf{%
+Header 3
+} \\
+\hline
+\endfirsthead
+\hline
+\textbf{%
+Header row, column 1
+(header rows optional)
+} & \textbf{%
+Header 2
+} & \textbf{%
+Header 3
+} \\
+\hline
+\endhead
+\multicolumn{3}{c}{\hfill ... continued on next page} \\
+\endfoot
+\endlastfoot
+
+body row 1, column 1
+ &
+column 2
+ &
+column 3
+ \\
+\hline
+
+body row 2
+ & \multirow{2}{0.16\DUtablewidth}{%
+Cells may
+span rows.
+} & \multirow{2}{0.23\DUtablewidth}{%
+Another
+rowspanning
+cell.
+} \\
+\cline{1-1}
+
+body row 3
+ & & \\
+\hline
+\end{longtable*}
+
+
+\subsection{2.21 List Tables%
+ \label{list-tables}%
+}
+
+Here’s a list table exercising all features:
+
+\setlength{\DUtablewidth}{40em}
+\begin{longtable}[c]{|p{0.133\DUtablewidth}|p{0.249\DUtablewidth}|p{0.365\DUtablewidth}|}
+\caption{list table with integral header}\\
+\hline
+\textbf{%
+Treat
+} & \textbf{%
+Quantity
+} & \textbf{%
+Description
+} \\
+\hline
+\endfirsthead
+\caption[]{list table with integral header (... continued)}\\
+\hline
+\textbf{%
+Treat
+} & \textbf{%
+Quantity
+} & \textbf{%
+Description
+} \\
+\hline
+\endhead
+\multicolumn{3}{c}{\hfill ... continued on next page} \\
+\endfoot
+\endlastfoot
+\textbf{%
+Albatross
+} &
+2.99
+ &
+On a stick!
+ \\
+\hline
+\textbf{%
+Crunchy Frog
+} &
+1.49
+ &
+If we took the bones out, it wouldn’t be
+crunchy, now would it?
+ \\
+\hline
+\textbf{%
+Gannet Ripple
+} &
+1.99
+ &
+On a stick!
+ \\
+\hline
+\end{longtable}
+
+\begin{longtable}[c]{|l|l|}
+\caption{center aligned list table}\\
+\hline
+Albatross & 2.99 \\
+\hline
+Crunchy Frog & 1.49 \\
+\hline
+Gannet Ripple & 1.99 \\
+\hline
+\end{longtable}
+
+
+\subsection{2.22 Custom Roles%
+ \label{custom-roles}%
+}
+
+\begin{itemize}
+\item A role based on an existing role.
+
+\texttt{\DUrole{custom}{one}} \texttt{\DUrole{custom}{two}} \texttt{\DUrole{custom}{three}}
+
+\item A new role.
+
+\DUrole{customnew}{one two three}
+
+\item A role with class attribute.
+
+\DUrole{special}{interpreted text}
+
+\item A language-switching role:
+
+Let’s count in German \foreignlanguage{german}{eins zwei drei}.
+
+\item A role with multiple class attributes, styled with raw directives:
+
+\newcommand{\DUrolegreen}[1]{\textcolor{green}{#1}}
+\newcommand{\DUrolesc}[1]{\textsc{#1}}
+
+The following works in most browsers but does not validate
+(\texttt{<style>} is only allowed in the document head):
+
+\begin{quote}
+\begin{alltt}
+.. raw:: html
+
+ <style type="text/css"><!--
+ .green \{color: green;\}
+ .sc \{font-variant: small-caps;\}
+ --></style>
+\end{alltt}
+\end{quote}
+
+\DUrole{green}{\DUrole{sc}{\foreignlanguage{english}{British colourful text in small-caps}}}.
+\end{itemize}
+
+
+\subsection{2.23 Mathematics%
+ \label{mathematics}%
+}
+
+Docutils supports inline math with the prefix or postfix \texttt{:math:}
+role specificator, $n! + \sin(x_n^2)$ and $A_\text{c} =
+\frac{\pi}{4} d^2$, as well as displayed math via the
+\DUroletitlereference{math} directive:
+%
+\begin{equation*}
+f(\epsilon) = \frac{1}{1 + \exp\left(\frac{\varepsilon}{k_\text{B}T}\right)}
+\end{equation*}
+Content may start on the first line of the directive, e.g.
+%
+\begin{equation*}
+N = \frac{\text{number of apples}}{7}
+\end{equation*}
+Equations can be labeled with a reference name using the \texttt{:name:} option.
+See \hyperref[eq-m]{eq:M} and \hyperref[eq-schrodinger]{eq:schrödinger} below.
+
+The determinant of the matrix
+%
+\begin{equation*}
+\mathbf{M} = \left(\begin{matrix}a&b\\c&d\end{matrix}\right)
+\phantomsection
+\label{eq-m}
+\end{equation*}
+is $|\mathbf{M}| = ad - bc$.
+
+More than one display math block can be put in one math directive.
+For example, the following sum and integral with limits:
+%
+\begin{equation*}
+\int_0^1 x^n dx = \frac{1}{n + 1}
+\end{equation*}%
+\begin{equation*}
+\sum_{n=1}^m n = \frac{m(m+1)}{2}
+\end{equation*}
+LaTeX-supported Unicode math symbols can be used in math roles and
+directives:
+
+The Schrödinger equation
+%
+\begin{equation*}
+i\hbar \frac{\partial }{\partial t}\Psi = \hat{H}\Psi ,
+\phantomsection
+\label{eq-schrodinger}
+\end{equation*}
+with the \emph{wave function} $\Psi $, describes how the quantum state of a
+physical system changes in time.
+
+\begin{description}
+\item[{Math-Accents:}] \leavevmode
+\setlength{\DUtablewidth}{\linewidth}
+\begin{longtable*}[c]{p{0.315\DUtablewidth}p{0.315\DUtablewidth}p{0.315\DUtablewidth}}
+
+$\acute{a}$ \texttt{\textbackslash{}acute\{a\}}
+ &
+$\dot{t}$ \texttt{\textbackslash{}dot\{t\}}
+ &
+$\hat{\gamma}$ \texttt{\textbackslash{}hat\{\textbackslash{}gamma\}}
+ \\
+
+$\grave{a}$ \texttt{\textbackslash{}grave\{a\}}
+ &
+$\ddot{t}$ \texttt{\textbackslash{}ddot\{t\}}
+ &
+$\tilde{\alpha}$ \texttt{\textbackslash{}tilde\{\textbackslash{}alpha\}}
+ \\
+
+$\breve{x}$ \texttt{\textbackslash{}breve\{x\}}
+ &
+$\dddot{t}$ \texttt{\textbackslash{}dddot\{t\}}
+ &
+$\vec{\imath}$ \texttt{\textbackslash{}vec\{\textbackslash{}imath\}}
+ \\
+
+$\check{a}$ \texttt{\textbackslash{}check\{a\}}
+ &
+$\bar{a}$ \texttt{\textbackslash{}bar\{a\}}
+ &
+$\vec{R}$ \texttt{\textbackslash{}vec\{R\}}
+ \\
+\end{longtable*}
+
+\end{description}
+
+% \widetilde{xxx}
+% \widehat{xxx}
+
+Modulation Transfer Function:
+%
+\begin{equation*}
+\text{MTF} = \left|\frac{\mathcal{F}\{s(x)\}}
+ {\mathcal{F}\{ s(x)\} |_{\omega _{x}=0}}\right|
+ = \mathrm{abs}\left(\frac
+ {\int _{-\infty }^{\infty }s(x) \mathrm{e}^{\mathrm{i}\omega _{x}x}\mathrm{d}{x}}
+ {\int _{-\infty }^{\infty }s(x)\mathrm{d}{x}}
+ \right).
+\end{equation*}
+Math split over two lines: If a double backslash is detected outside a
+\texttt{\textbackslash{}begin\{...\} \textbackslash{}end\{...\}} pair, the math code is wrapped in an \href{ftp://ftp.ams.org/ams/doc/amsmath/short-math-guide.pdf}{AMSmath}\DUfootnotemark{footnote-reference-14}{footnote-8}{7}
+\texttt{align} environment:
+%
+\begin{align*}
+s_{\mathrm{out}}(x) & = s_{\mathrm{in}}(x') * s_\delta (x-x') \\
+ & = \int s_{\mathrm{in}}(x')s_\delta (x-x')\mathrm{d}x'
+\end{align*}
+Cases (“manually”, with \texttt{matrix} environment):
+%
+\begin{equation*}
+\mathrm{sgn}(x) = \left\{\begin{matrix}
+ -1 & x<0\\
+ 1 & x>0
+ \end{matrix}\right.
+\end{equation*}
+Cases with the \href{ftp://ftp.ams.org/ams/doc/amsmath/short-math-guide.pdf}{AMSmath}\DUfootnotemark{footnote-reference-15}{footnote-8}{7} \texttt{cases} environment (not (yet) supported by
+HTML writers with \texttt{--math-output=MathML}):
+%
+\begin{equation*}
+\mathrm{sgn}(x) = \begin{cases}
+ -1 & x<0\\
+ 1 & x>0
+ \end{cases}
+\end{equation*}
+
+\section{3 Tests for the LaTeX writer%
+ \label{tests-for-the-latex-writer}%
+}
+
+Test syntax elements which may cause trouble for the LaTeX writer but might
+not need to be tested with other writers (e.g. the HTML writer).
+
+
+\subsection{3.1 Custom Roles in LaTeX%
+ \label{custom-roles-in-latex}%
+}
+
+\begin{itemize}
+\item Role names and class arguments are converted to conform to the
+regular expression \texttt{{[}a-z{]}{[}-a-z0-9{]}*} (letters are downcased,
+accents and similar decoration is stripped, non-conforming
+characters are replaced by a hyphen).
+
+Class arguments may contain numbers and hyphens, which need special
+treatment in LaTeX command names.
+
+\DUrole{large}{\DUrole{custom4}{\DUrole{small-caps}{\DUrole{custom-role}{\DUrole{custom-role}{Text with role “custom4”}}}}} (but without styling by \texttt{DUrole*}
+macros).
+
+\item With LaTeX, roles can be styled within the document using the \DUroletitlereference{raw}
+directive.
+
+\newcommand{\DUrolelarge}[1]{{\large #1}}
+\makeatletter
+\@namedef{DUrolesmall-caps}{\textsc}
+\@namedef{DUrolecustom4}{\textbf}
+\makeatother
+
+\DUrole{large}{\DUrole{custom4}{\DUrole{small-caps}{\DUrole{custom-role}{\DUrole{custom-role}{inline text}}}}} in large, bold, small-caps.
+
+\item Custom roles can be based on standard roles:
+
+This is a \emph{\DUrole{custom-emphasis}{customized emphasis text role}}
+
+This is a \texttt{\DUrole{custom-literal}{customized literal text role}}
+
+This is a \textbf{\DUrole{custom-strong}{customized strong text role}}
+
+This is a \textsubscript{\DUrole{custom-subscript}{customized subscript text role}}
+
+This is a \textsuperscript{\DUrole{custom-superscript}{customized superscript text role}}
+
+This is a \DUroletitlereference{\DUrole{custom-title-reference}{customized title-reference text role}}
+\end{itemize}
+
+
+\subsection{3.2 class handling%
+ \label{class-handling}%
+}
+
+This section tests class handling for block level elements by the LaTeX
+writer. See the input file \texttt{classes\_latex.txt} for the raw LaTeX code used
+to style the examples.
+
+An “epigraph” directive is exported as “quote” wrapped in a “DUclass”
+environment. Here, it is styled by a “DUCLASSepigraph” environment
+redefining the “quote” environment as “minipage”:
+
+\newcommand*{\DUCLASSepigraph}{%
+ \renewenvironment{quote}{\vspace{1em}
+ \footnotesize\hfill{}%
+ \begin{minipage}{0.4\columnwidth}}%
+ {\end{minipage}\vskip\baselineskip}}
+
+\begin{DUclass}{epigraph}
+\begin{quote}
+Do not play this piece fast. It is never right to play \emph{Ragtime} fast.
+\nopagebreak
+
+\raggedleft —Scott Joplin
+\end{quote}
+\end{DUclass}
+
+Raw latex is also used to style the following lists: “DUCLASSenumerateitems”
+redefines “itemize” as “enumerate”, “DUCLASSrules” draws horizontal lines
+above and below.
+
+\newcommand*{\DUCLASSenumerateitems}{%
+ \renewenvironment{itemize}{\begin{enumerate}}%
+ {\end{enumerate}}%
+}
+
+\newenvironment{DUCLASSrules}%
+ {\noindent\rule[0.5ex]{1\columnwidth}{1pt}}%
+ {\noindent\rule[0.5ex]{1\columnwidth}{1pt}}
+
+An “enumerated” bullet list:
+
+\begin{DUclass}{enumerateitems}
+\begin{itemize}
+\item item
+
+\item next item
+
+\item third item
+\end{itemize}
+\end{DUclass}
+
+A list with lines above and below:
+
+\begin{DUclass}{rules}
+\begin{itemize}
+\item item
+
+\item next item
+\end{itemize}
+\end{DUclass}
+
+A normal bullet list is kept unchanged by the above redefinitions:
+
+\begin{itemize}
+\item item
+
+\item next item
+
+\item third item
+\end{itemize}
+
+A container wraps several elements in a common “class wrapper”. Here, we use
+it to set 2 paragraphs and a list in small caps:
+
+\newcommand*{\DUCLASSscshape}{\scshape}
+
+\begin{DUclass}{scshape}
+
+paragraph 1
+
+paragraph 2
+
+\begin{itemize}
+\item bullet list
+
+\item still bullet list
+\end{itemize}
+\end{DUclass}
+
+A right-aligned line-block. Alignment handling is built into the latex
+writer for image, table, and line block elements.
+
+\begin{DUlineblock}{0em}
+\raggedleft
+\item[] Max Mustermann
+\item[] Waldstr. 22
+\item[] D 01234 Testdorf
+\item[] Tel.: 0123/456789
+\end{DUlineblock}
+
+
+\subsection{3.3 More Tables%
+ \label{more-tables}%
+}
+
+A table with multi-paragraph multicolumn cells:
+
+\setlength{\DUtablewidth}{\linewidth}
+\begin{longtable*}[c]{|p{0.133\DUtablewidth}|p{0.179\DUtablewidth}|p{0.179\DUtablewidth}|p{0.110\DUtablewidth}|p{0.121\DUtablewidth}|p{0.145\DUtablewidth}|}
+\hline
+
+test
+ &
+\textbf{bold hd}
+ & \multicolumn{3}{p{0.41\DUtablewidth}|}{%
+multicolumn 1
+
+With a second paragraph
+} &
+\emph{emph hd}
+ \\
+\hline
+\multicolumn{2}{|p{0.31\DUtablewidth}|}{%
+multicolumn 2
+
+With a second paragraph
+} &
+cell
+ &
+cell
+ &
+cell
+ &
+cell
+ \\
+\hline
+
+cell
+ & \multicolumn{2}{p{0.36\DUtablewidth}|}{%
+multicolumn 3 (one line,
+but very very very very
+very looooong)
+} &
+cell
+ &
+cell
+ &
+cell
+ \\
+\hline
+
+cell
+ &
+cell
+ &
+cell
+ & \multicolumn{3}{p{0.38\DUtablewidth}|}{%
+Short multicolumn 4
+} \\
+\hline
+\end{longtable*}
+
+Tables with multi-paragraph multirow cells currently fail due to a LaTeX
+limitation (see \url{https://sourceforge.net/p/docutils/bugs/225/}).
+
+A table with multirow header and column-widths set by LaTeX:
+
+\begin{longtable*}[c]{|l|l|}
+\hline
+\multirow{2}{*}{\textbf{XXX}} & \textbf{Variable Summary} \\
+\cline{2-2}
+ & \textbf{Description} \\
+\hline
+\endfirsthead
+\hline
+\multirow{2}{*}{\textbf{XXX}} & \textbf{Variable Summary} \\
+\cline{2-2}
+ & \textbf{Description} \\
+\hline
+\endhead
+\multicolumn{2}{c}{\hfill ... continued on next page} \\
+\endfoot
+\endlastfoot
+\multicolumn{2}{|l|}{multicollumn cell} \\
+\hline
+\end{longtable*}
+
+In a table with column-widths set by LaTeX, each cell has just one line.
+Paragraphs are merged (a warning is given).
+
+\begin{longtable*}[c]{|l|l|}
+\hline
+11 & first paragraph
+second paragraph
+third paragraph \\
+\hline
+21 & 22 \\
+\hline
+\end{longtable*}
+
+% This file is used by the standalone_rst_latex test.
+
+
+\subsection{3.4 Option lists%
+ \label{option-lists-1}%
+}
+
+The LaTeX-2e description environment is used for definition lists.
+The definition is continued on the same line as the term, this should
+not happen if a option-list is at the top of the definition.
+
+If the option list is not at the first element in the definition, it
+is contained in a quote
+
+\begin{quote}
+\begin{DUoptionlist}
+\item[--help] show help
+
+\item[-v] verbose
+\end{DUoptionlist}
+\end{quote}
+
+\begin{description}
+\item[{In a definition list:}] \leavevmode
+\begin{DUoptionlist}
+\item[--help] show help
+
+\item[-v] verbose
+\end{DUoptionlist}
+
+\end{description}
+
+
+\subsection{3.5 Monospaced non-alphanumeric characters%
+ \label{monospaced-non-alphanumeric-characters}%
+}
+
+These are all ASCII characters except a-zA-Z0-9 and space:
+
+\texttt{!!!\textquotedbl{}\textquotedbl{}\textquotedbl{}\#\#\#\$\$\$\%\%\%\&\&\&'''((()))***+++,,,---...///:::}
+
+\texttt{;;;<<<===>>>???@@@{[}{[}{[}\textbackslash{}\textbackslash{}\textbackslash{}{]}{]}{]}\textasciicircum{}\textasciicircum{}\textasciicircum{}\_\_\_```\{\{\{|||\}\}\}\textasciitilde{}\textasciitilde{}\textasciitilde{}}
+
+\texttt{xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx}
+
+The two lines of non-alphanumeric characters should both have the same
+width as the third line.
+
+
+\subsection{3.6 Non-ASCII characters%
+ \label{non-ascii-characters}%
+}
+
+Punctuation and footnote symbols
+
+\setlength{\DUtablewidth}{\linewidth}
+\begin{longtable*}[c]{|p{0.028\DUtablewidth}|p{0.424\DUtablewidth}|}
+\hline
+
+–
+ &
+en-dash
+ \\
+\hline
+
+—
+ &
+em-dash
+ \\
+\hline
+
+‘
+ &
+single turned comma quotation mark
+ \\
+\hline
+
+’
+ &
+single comma quotation mark
+ \\
+\hline
+
+‚
+ &
+low single comma quotation mark
+ \\
+\hline
+
+“
+ &
+double turned comma quotation mark
+ \\
+\hline
+
+”
+ &
+double comma quotation mark
+ \\
+\hline
+
+„
+ &
+low double comma quotation mark
+ \\
+\hline
+
+†
+ &
+dagger
+ \\
+\hline
+
+‡
+ &
+double dagger
+ \\
+\hline
+
+♦
+ &
+black diamond suit
+ \\
+\hline
+
+♥
+ &
+black heart suit
+ \\
+\hline
+
+♠
+ &
+black spade suit
+ \\
+\hline
+
+♣
+ &
+black club suit
+ \\
+\hline
+
+…
+ &
+ellipsis
+ \\
+\hline
+
+™
+ &
+trade mark sign
+ \\
+\hline
+
+⇔
+ &
+left-right double arrow
+ \\
+\hline
+\end{longtable*}
+
+The \DUroletitlereference{Latin-1 extended} Unicode block
+
+\setlength{\DUtablewidth}{\linewidth}
+\begin{longtable*}[c]{|p{0.051\DUtablewidth}|p{0.028\DUtablewidth}|p{0.028\DUtablewidth}|p{0.028\DUtablewidth}|p{0.028\DUtablewidth}|p{0.028\DUtablewidth}|p{0.028\DUtablewidth}|p{0.028\DUtablewidth}|p{0.028\DUtablewidth}|p{0.028\DUtablewidth}|p{0.028\DUtablewidth}|}
+\hline
+
+%
+ &
+0
+ &
+1
+ &
+2
+ &
+3
+ &
+4
+ &
+5
+ &
+6
+ &
+7
+ &
+8
+ &
+9
+ \\
+\hline
+
+160
+ & &
+¡
+ &
+¢
+ &
+£
+ & &
+¥
+ &
+¦
+ &
+§
+ &
+¨
+ &
+©
+ \\
+\hline
+
+170
+ &
+ª
+ &
+«
+ &
+¬
+ &
+\-
+ &
+®
+ &
+¯
+ &
+°
+ &
+±
+ &
+²
+ &
+³
+ \\
+\hline
+
+180
+ &
+´
+ &
+µ
+ &
+¶
+ &
+·
+ &
+¸
+ &
+¹
+ &
+º
+ &
+»
+ &
+¼
+ &
+½
+ \\
+\hline
+
+190
+ &
+¾
+ &
+¿
+ &
+À
+ &
+Á
+ &
+Â
+ &
+Ã
+ &
+Ä
+ &
+Å
+ &
+Æ
+ &
+Ç
+ \\
+\hline
+
+200
+ &
+È
+ &
+É
+ &
+Ê
+ &
+Ë
+ &
+Ì
+ &
+Í
+ &
+Î
+ &
+Ï
+ &
+Ð
+ &
+Ñ
+ \\
+\hline
+
+210
+ &
+Ò
+ &
+Ó
+ &
+Ô
+ &
+Õ
+ &
+Ö
+ &
+×
+ &
+Ø
+ &
+Ù
+ &
+Ú
+ &
+Û
+ \\
+\hline
+
+220
+ &
+Ü
+ &
+Ý
+ &
+Þ
+ &
+ß
+ &
+à
+ &
+á
+ &
+â
+ &
+ã
+ &
+ä
+ &
+å
+ \\
+\hline
+
+230
+ &
+æ
+ &
+ç
+ &
+è
+ &
+é
+ &
+ê
+ &
+ë
+ &
+ì
+ &
+í
+ &
+î
+ &
+ï
+ \\
+\hline
+
+240
+ &
+ð
+ &
+ñ
+ &
+ò
+ &
+ó
+ &
+ô
+ &
+õ
+ &
+ö
+ &
+÷
+ &
+ø
+ &
+ù
+ \\
+\hline
+
+250
+ &
+ú
+ &
+û
+ &
+ü
+ &
+ý
+ &
+þ
+ &
+ÿ
+ & & & & \\
+\hline
+\end{longtable*}
+
+\begin{itemize}
+\item The following line should not be wrapped, because it uses
+no-break spaces (\textbackslash{}u00a0):
+
+X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X
+
+\item Line wrapping with/without breakpoints marked by soft hyphens
+(\textbackslash{}u00ad):
+
+pdn\-derd\-mdtd\-ri\-schpdn\-derd\-mdtd\-ri\-schpdn\-derd\-mdtd\-ri\-schpdn\-derd\-mdtd\-ri\-schpdn\-derd\-mdtd\-ri\-sch
+
+pdnderdmdtdrischpdnderdmdtdrischpdnderdmdtdrischpdnderdmdtdrischpdnderdmdtdrisch
+\end{itemize}
+
+
+\subsection{3.7 Encoding special chars%
+ \label{encoding-special-chars}%
+}
+
+The LaTeX Info pages lists under “2.18 Special Characters”
+
+\begin{quote}
+The following characters play a special role in LaTeX and are called
+“special printing characters”, or simply “special characters”.
+
+\begin{quote}
+\# \$ \% \& \textasciitilde{} \_ \textasciicircum{} \textbackslash{} \{ \}
+\end{quote}
+\end{quote}
+
+The special chars verbatim:
+
+\begin{quote}
+\begin{alltt}
+# $ % & ~ _ ^ \textbackslash{} \{ \}
+\end{alltt}
+\end{quote}
+
+However also \emph{square brackets} {[}{]} need special care.
+
+\begin{quote}
+Commands with optional arguments (e.g. \texttt{\textbackslash{}item}) check
+if the token right after the macro name is an opening bracket.
+In that case the contents between that bracket and the following
+closing bracket on the same grouping level are taken as the
+optional argument. What makes this unintuitive is the fact that
+the square brackets aren’t grouping characters themselves, so in
+your last example \texttt{\textbackslash{}item{[}{[}...{]}{]}} the optional argument consists of
+{[}… (without the closing bracket).
+\end{quote}
+
+Compare the items in the following lists:
+
+\begin{itemize}
+\item simple item
+
+\item {[}bracketed{]} item
+\end{itemize}
+
+\begin{description}
+\item[{simple}] \leavevmode
+description term
+
+\item[{{[}bracketed{]}}] \leavevmode
+description term
+
+\end{description}
+
+The OT1 font-encoding has different characters for the less-than,
+greater-than and bar, < | >, except for typewriter font \DUroletitlereference{cmtt}:
+
+\begin{quote}
+\begin{alltt}
+< | >
+\end{alltt}
+\end{quote}
+
+
+\subsection{3.8 Hyperlinks and -targets%
+ \label{hyperlinks-and-targets}%
+}
+
+In LaTeX, we must set an explicit anchor (\texttt{\textbackslash{}phantomsection}) for a
+%
+\phantomsection\label{hypertarget-in-plain-text}hypertarget in plain text or in a figure but not in a longtable or
+caption:
+
+\setlength{\DUtablewidth}{\linewidth}
+\begin{longtable}[c]{|p{0.075\DUtablewidth}|p{0.075\DUtablewidth}|p{0.075\DUtablewidth}|}
+\caption{Table with %
+\label{hypertarget-in-table-title}hypertarget in table title.}\\
+\hline
+
+False
+ &
+True
+ &
+None
+ \\
+\hline
+\end{longtable}
+\label{table-label}
+
+\begin{figure}
+\phantomsection\label{figure-label}
+\noindent\makebox[\linewidth][c]{\includegraphics{../../../docs/user/rst/images/biohazard.png}}
+\caption{Figure with %
+\label{hypertarget-in-figure-caption}hypertarget in figure caption.}
+\begin{DUlegend}
+Legend with %
+\phantomsection\label{hypertarget-in-figure-legend}hypertarget in figure legend.
+\end{DUlegend}
+\end{figure}
+
+\includegraphics{../../../docs/user/rst/images/biohazard.png}
+\phantomsection\label{image-label}
+
+See \hyperref[hypertarget-in-plain-text]{hypertarget in plain text},
+\hyperref[table-label]{table label}, \hyperref[hypertarget-in-table-title]{hypertarget in table title},
+\hyperref[figure-label]{figure label}, \hyperref[hypertarget-in-figure-caption]{hypertarget in figure caption},
+\hyperref[hypertarget-in-figure-legend]{hypertarget in figure legend}, and
+\hyperref[image-label]{image label}.
+
+
+\subsection{3.9 External references%
+ \label{external-references}%
+}
+
+Long URLs should be wrapped in the PDF. This can be achieved with the
+\texttt{\textbackslash{}url} command which is used by the LaTeX writer whenever the content
+(name) of a reference node equals the link URL.
+
+\begin{description}
+\item[{Example:}] \leavevmode
+a long URL that should wrap in the output
+\url{http://docutils.sourceforge.net/docs/user/latex.html\#id79}
+
+\end{description}
+
+If the argument contains any “\%”, “\#”, or “\textasciicircum{}\textasciicircum{}”, or ends with \texttt{\textbackslash{}}, it can’t
+be used in the argument to another command. The argument must not contain
+unbalanced braces.
+
+The characters \textasciicircum{}, \{, \}, and \texttt{\textbackslash{}} are invalid in a “http:” or “ftp:” URL
+and not recognized as part of it:
+
+\begin{DUlineblock}{0em}
+\item[] \url{http://www.example.org}/strange\textasciicircum{}\textasciicircum{}name
+\item[] \url{http://www.example.org}\textbackslash{}using\textbackslash{}DOS\textbackslash{}paths\textbackslash{}
+\item[] \url{http://www.example.org/XML}/strange\{n\}ame
+\end{DUlineblock}
+
+They can, however be used in paths and/or filenames.
+
+Handling by the LaTeX writer:
+
+\begin{itemize}
+\item \texttt{\#}, \texttt{\textbackslash{}} and \texttt{\%} are escaped:
+
+\begin{DUlineblock}{0em}
+\item[] \href{http://www.w3.org/XML/Schema\#dev}{URL with \#}
+\url{http://www.w3.org/XML/Schema\#dev}
+\item[] \href{http://www.w3.org/XML/Schema\%dev}{URL with \%}
+\url{http://example.org/Schema\%dev}
+\item[] \href{A:DOS\\path\\}{file with DOS path}\DUfootnotemark{footnote-reference-19}{footnote-11}{10} \url{A:DOS\\path\\}\DUfootnotemark{footnote-reference-20}{footnote-11}{10}
+\end{DUlineblock}
+
+\DUadmonition[note]{
+\DUtitle[note]{Note}
+
+These URLs are typeset inside a LaTeX command without error.
+
+\begin{DUlineblock}{0em}
+\item[] \url{http://www.w3.org/XML/Schema\#dev}
+\item[] \url{http://example.org/Schema\%dev}
+\item[] \url{A:DOS\\path\\}\DUfootnotemark{footnote-reference-21}{footnote-11}{10}
+\end{DUlineblock}
+}
+\end{itemize}
+
+\begin{itemize}
+\item \texttt{\textasciicircum{}\textasciicircum{}} LaTeX’s special syntax for characters results in “strange” replacements
+(both with \texttt{\textbackslash{}href} and \texttt{\textbackslash{}url}). A warning is given.
+
+\href{../strange^^name}{file with \textasciicircum{}\textasciicircum{}}:
+\url{../strange^^name}
+
+\item Unbalanced braces, \{ or \}, will fail (both with \texttt{\textbackslash{}href} and \texttt{\textbackslash{}url}):
+
+\begin{quote}
+\begin{alltt}
+`file with \{ <../strange\{name>`__
+`<../strange\{name>`__
+\end{alltt}
+\end{quote}
+
+while balanced braces are suported:
+
+\begin{DUlineblock}{0em}
+\item[] \url{../strange{n}ame}
+\item[] \url{../st{r}ange{n}ame}
+\item[] \url{../{st{r}ange{n}ame}}
+\end{DUlineblock}
+\end{itemize}
+
+
+\subsection{3.10 Section titles with \hyperref[inline-markup]{inline markup}%
+ \label{section-titles-with-inline-markup}%
+}
+
+
+\subsubsection{3.10.1 \emph{emphasized}, H\textsubscript{2}O and $x^2$%
+ \label{emphasized-h2o-and-x-2}%
+}
+
+
+\subsubsection{3.10.2 Substitutions work%
+ \label{substitutions-fail}%
+}
+
+
+\subsection{3.11 Deeply nested sections%
+ \label{deeply-nested-sections}%
+}
+
+In LaTeX and HTML,
+
+
+\subsubsection{3.11.1 Level 3%
+ \label{level-3}%
+}
+
+nested sections
+
+
+\paragraph{3.11.1.1 level 4%
+ \label{level-4}%
+}
+
+reach at some level
+
+
+\subparagraph{3.11.1.1.1 level 5%
+ \label{level-5}%
+}
+
+(depending on the document class)
+
+
+\DUtitle[sectionVI]{3.11.1.1.1.1 level 6%
+ \label{level-6}%
+}
+
+an unsupported level.
+
+
+\section{4 Tests for the XeTeX writer%
+ \label{tests-for-the-xetex-writer}%
+}
+
+With XeTeX, you can typeset text in any language/script supported by
+Unicode and the selected font, e.g. Azərbaycanca, Bân-lâm-gú, Башҡорт
+Беларуская, Български, Català, Чӑвашла, Česky, Ελληνικά, Español,
+Français, Føroyskt, Хальмг, Íslenska, עברית , Қазақша, Kurdî,
+Latviešu, Lietuvių, Македонски, Монгол, Nāhuatl, Português, Română,
+Русский, Slovenščina, Српски, Türkçe, Українська, Tiếng Việt, Volapük,
+Võro, ייִדיש , Žemaitėška.
+Currently, there is extended support for 28 languages in the
+\href{http://ctan.org/pkg/polyglossia}{polyglossia}\DUfootnotemark{footnote-reference-16}{footnote-9}{8} package.
+
+% System Messages:
+
+
+\section{5 Error Handling%
+ \label{error-handling}%
+}
+
+Any errors caught during processing will generate system messages.
+
+There should be five messages in the following, auto-generated
+section, “Docutils System Messages”:
+
+% section should be added by Docutils automatically
+
+
+\section[Docutils System Messages]{\color{red}Docutils System Messages%
+}
+
+\DUadmonition[system-message]{
+\DUtitle[system-message]{system-message}
+\raisebox{1em}{\hypertarget{system-message-1}{}}
+
+{\color{red}ERROR/3} in \texttt{functional/input/data/standard.txt}, line~104
+
+\hyperlink{problematic-1}{
+Undefined substitution referenced: \textquotedbl{}problematic\textquotedbl{}.
+}}
+
+\DUadmonition[system-message]{
+\DUtitle[system-message]{system-message}
+\raisebox{1em}{\hypertarget{system-message-2}{}}
+
+{\color{red}ERROR/3} in \texttt{functional/input/data/standard.txt}, line~392
+
+\hyperlink{footnote-reference-8}{
+Unknown target name: \textquotedbl{}5\textquotedbl{}.
+}}
+
+\DUadmonition[system-message]{
+\DUtitle[system-message]{system-message}
+\raisebox{1em}{\hypertarget{system-message-3}{}}
+
+{\color{red}ERROR/3} in \texttt{functional/input/data/standard.txt}, line~401
+
+\hyperlink{citation-reference-3}{
+Unknown target name: \textquotedbl{}nonexistent\textquotedbl{}.
+}}
+
+\DUadmonition[system-message]{
+\DUtitle[system-message]{system-message}
+\raisebox{1em}{\hypertarget{system-message-4}{}}
+
+{\color{red}ERROR/3} in \texttt{functional/input/data/standard.txt}, line~428
+
+\hyperlink{problematic-2}{
+Unknown target name: \textquotedbl{}hyperlink reference without a target\textquotedbl{}.
+}}
+
+\DUadmonition[system-message]{
+\DUtitle[system-message]{system-message}
+\raisebox{1em}{\hypertarget{system-message-5}{}}
+
+{\color{red}ERROR/3} in \texttt{functional/input/data/standard.txt}, line~441
+
+\hyperlink{problematic-3}{
+Duplicate target name, cannot be used as a unique reference: \textquotedbl{}duplicate target names\textquotedbl{}.
+}}
+
+\end{document}
--- /dev/null
+/* 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;}
+*/
--- /dev/null
+<public:component>
+<public:attach event="onpropertychange" onevent="doFix()" />
+
+<script>
+
+// IE5.5+ PNG Alpha Fix v1.0 by Angus Turnbull http://www.twinhelix.com
+// Free usage permitted as long as this notice remains intact.
+
+// This must be a path to a blank image. That's all the configuration you need here.
+var blankImg = 'ui/default/blank.gif';
+
+var f = 'DXImageTransform.Microsoft.AlphaImageLoader';
+
+function filt(s, m) {
+ if (filters[f]) {
+ filters[f].enabled = s ? true : false;
+ if (s) with (filters[f]) { src = s; sizingMethod = m }
+ } else if (s) style.filter = 'progid:'+f+'(src="'+s+'",sizingMethod="'+m+'")';
+}
+
+function doFix() {
+ if ((parseFloat(navigator.userAgent.match(/MSIE (\S+)/)[1]) < 5.5) ||
+ (event && !/(background|src)/.test(event.propertyName))) return;
+
+ if (tagName == 'IMG') {
+ if ((/\.png$/i).test(src)) {
+ filt(src, 'image'); // was 'scale'
+ src = blankImg;
+ } else if (src.indexOf(blankImg) < 0) filt();
+ } else if (style.backgroundImage) {
+ if (style.backgroundImage.match(/^url[("']+(.*\.png)[)"']+$/i)) {
+ var s = RegExp.$1;
+ style.backgroundImage = '';
+ filt(s, 'crop');
+ } else filt();
+ }
+}
+
+doFix();
+
+</script>
+</public:component>
\ No newline at end of file
--- /dev/null
+/* 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;}
--- /dev/null
+/* 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;}
--- /dev/null
+/* 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;}
+*/
--- /dev/null
+/* 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;}
--- /dev/null
+/* 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;}
--- /dev/null
+/* 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);
--- /dev/null
+// S5 v1.1 slides.js -- released into the Public Domain
+// Modified for Docutils (http://docutils.sf.net) 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();">Ø<\/a>' +
+ '<a accesskey="z" id="prev" href="javascript:go(-1);">«<\/a>' +
+ '<a accesskey="x" id="next" href="javascript:go(1);">»<\/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);}
--- /dev/null
+/* 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;}
+*/
--- /dev/null
+<public:component>
+<public:attach event="onpropertychange" onevent="doFix()" />
+
+<script>
+
+// IE5.5+ PNG Alpha Fix v1.0 by Angus Turnbull http://www.twinhelix.com
+// Free usage permitted as long as this notice remains intact.
+
+// This must be a path to a blank image. That's all the configuration you need here.
+var blankImg = 'ui/small-black/blank.gif';
+
+var f = 'DXImageTransform.Microsoft.AlphaImageLoader';
+
+function filt(s, m) {
+ if (filters[f]) {
+ filters[f].enabled = s ? true : false;
+ if (s) with (filters[f]) { src = s; sizingMethod = m }
+ } else if (s) style.filter = 'progid:'+f+'(src="'+s+'",sizingMethod="'+m+'")';
+}
+
+function doFix() {
+ if ((parseFloat(navigator.userAgent.match(/MSIE (\S+)/)[1]) < 5.5) ||
+ (event && !/(background|src)/.test(event.propertyName))) return;
+
+ if (tagName == 'IMG') {
+ if ((/\.png$/i).test(src)) {
+ filt(src, 'image'); // was 'scale'
+ src = blankImg;
+ } else if (src.indexOf(blankImg) < 0) filt();
+ } else if (style.backgroundImage) {
+ if (style.backgroundImage.match(/^url[("']+(.*\.png)[)"']+$/i)) {
+ var s = RegExp.$1;
+ style.backgroundImage = '';
+ filt(s, 'crop');
+ } else filt();
+ }
+}
+
+doFix();
+
+</script>
+</public:component>
\ No newline at end of file
--- /dev/null
+/* 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;}
--- /dev/null
+/* 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;}
--- /dev/null
+/* 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;}
+*/
--- /dev/null
+/* 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;}
--- /dev/null
+/* 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;}
--- /dev/null
+/* 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);
--- /dev/null
+// S5 v1.1 slides.js -- released into the Public Domain
+// Modified for Docutils (http://docutils.sf.net) 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();">Ø<\/a>' +
+ '<a accesskey="z" id="prev" href="javascript:go(-1);">«<\/a>' +
+ '<a accesskey="x" id="next" href="javascript:go(1);">»<\/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/small-black/iepngfix.htc)');
+ document.styleSheets[0].addRule('div', 'behavior: url(ui/small-black/iepngfix.htc)');
+ document.styleSheets[0].addRule('.slide', 'behavior: url(ui/small-black/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);}
--- /dev/null
+\documentclass[a4paper,russian]{article}
+% generated by Docutils <http://docutils.sourceforge.net/>
+% 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
+\usepackage{ifthen}
+\usepackage{polyglossia}
+\setdefaultlanguage{russian}
+\setotherlanguages{english}
+\setcounter{secnumdepth}{0}
+
+%%% Custom LaTeX 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}
+
+%%% User specified packages and stylesheets
+
+%%% Fallback definitions for Docutils-specific commands
+
+% titlereference role
+\providecommand*{\DUroletitlereference}[1]{\textsl{#1}}
+% hyperlinks:
+\ifthenelse{\isundefined{\hypersetup}}{
+ \usepackage[colorlinks=true,linkcolor=blue,urlcolor=blue,unicode=false]{hyperref}
+ \usepackage{bookmark}
+ \urlstyle{same} % normal text font (alternatives: tt, rm, sf)
+}{}
+
+
+%%% Body
+\begin{document}
+
+
+\section{Заголовок%
+ \label{section-1}%
+}
+
+первый пример: «Здравствуй, мир!»
+
+
+\section{Title%
+ \label{title}%
+}
+
+\foreignlanguage{english}{first example: “Hello world”.}
+
+
+\section{Notes%
+ \label{notes}%
+}
+
+\foreignlanguage{english}{This example tests rendering of Latin and Cyrillic characters by the LaTeX
+and XeTeX writers. Check the compiled PDF for garbage characters in text and
+bookmarks.}
+
+\foreignlanguage{english}{To work around a problem with Cyrillic in PDF-bookmarks in \DUroletitlereference{hyperref}
+versions older than v6.79g 2009/11/20, the test caller \texttt{latex\_cyrillic.py}
+sets \texttt{hyperref\_options} to \texttt{'unicode=true'} while \texttt{xetex\_cyrillic.py}
+sets it to \texttt{'unicode=false'}. The recommended option for current
+(2011-08-24) hyperref versions is \texttt{'pdfencoding=auto'}.}
+
+\end{document}
--- /dev/null
+* This is an ordinary simple bullet list.
+* It should be made compact (<p> & </p> tags omitted).
+
+**********
+
+* This is a bullet list that is not simple.
+
+ There are multiple paragraphs in some items.
+
+* It should not be made compact.
+
+* Even though some items may have only one paragraph.
+
+**********
+
+.. class:: open
+
+* This is a simple bullet list, but class="open" is set.
+* It should not be made compact.
+
+**********
+
+.. class:: compact
+
+* This is a bullet list that is not simple.
+
+ There are multiple paragraphs in some items.
+
+* However, the class="compact" setting will cause
+ all first paragraph's <p> & </p> tags to be omitted.
+
+* Items with multiple paragraphs will not appear changed.
+
+* Items may have one paragraph, or multiple.
+
+ Items with multiple paragraphs will still be followed
+ by vertical whitespace because of the later paragraphs.
+
+* The effect is interesting.
--- /dev/null
+Заголовок
+---------
+
+первый пример: "Здравствуй, мир!"
+
+Title
+-----
+
+.. class:: language-en
+
+first example: "Hello world".
+
+Notes
+-----
+
+.. class:: language-en
+
+This example tests rendering of Latin and Cyrillic characters by the LaTeX
+and XeTeX writers. Check the compiled PDF for garbage characters in text and
+bookmarks.
+
+.. class:: language-en
+
+To work around a problem with Cyrillic in PDF-bookmarks in `hyperref`
+versions older than v6.79g 2009/11/20, the test caller ``latex_cyrillic.py``
+sets ``hyperref_options`` to ``'unicode=true'`` while ``xetex_cyrillic.py``
+sets it to ``'unicode=false'``. The recommended option for current
+(2011-08-24) hyperref versions is ``'pdfencoding=auto'``.
+
+
+
+
--- /dev/null
+Potentially dangerous features (security holes):
+
+.. include:: /etc/passwd
+.. raw:: html
+ :file: /etc/passwd
+.. raw:: html
+ :url: file:///etc/passwd
+.. raw:: html
+
+ <script>
+ that does something really nasty
+ </script>
+.. csv-table:: :file: /etc/passwd
+.. csv-table:: :url: file:///etc/passwd
+.. figure:: picture.png
+ :figwidth: image
--- /dev/null
+class handling
+--------------
+
+This section tests class handling for block level elements by the LaTeX
+writer. See the input file ``classes_latex.txt`` for the raw LaTeX code used
+to style the examples.
+
+An "epigraph" directive is exported as "quote" wrapped in a "DUclass"
+environment. Here, it is styled by a "DUCLASSepigraph" environment
+redefining the "quote" environment as "minipage":
+
+.. raw:: latex
+
+ \newcommand*{\DUCLASSepigraph}{%
+ \renewenvironment{quote}{\vspace{1em}
+ \footnotesize\hfill{}%
+ \begin{minipage}{0.4\columnwidth}}%
+ {\end{minipage}\vskip\baselineskip}}
+
+.. epigraph::
+
+ Do not play this piece fast. It is never right to play *Ragtime* fast.
+
+ -- Scott Joplin
+
+Raw latex is also used to style the following lists: "DUCLASSenumerateitems"
+redefines "itemize" as "enumerate", "DUCLASSrules" draws horizontal lines
+above and below.
+
+.. raw:: latex
+
+ \newcommand*{\DUCLASSenumerateitems}{%
+ \renewenvironment{itemize}{\begin{enumerate}}%
+ {\end{enumerate}}%
+ }
+
+ \newenvironment{DUCLASSrules}%
+ {\noindent\rule[0.5ex]{1\columnwidth}{1pt}}%
+ {\noindent\rule[0.5ex]{1\columnwidth}{1pt}}
+
+An "enumerated" bullet list:
+
+.. class:: enumerateItems
+
+* item
+* next item
+* third item
+
+A list with lines above and below:
+
+.. class:: rules
+
+* item
+* next item
+
+A normal bullet list is kept unchanged by the above redefinitions:
+
+* item
+* next item
+* third item
+
+A container wraps several elements in a common "class wrapper". Here, we use
+it to set 2 paragraphs and a list in small caps:
+
+.. raw:: latex
+
+ \newcommand*{\DUCLASSscshape}{\scshape}
+
+.. container:: scshape
+
+ paragraph 1
+
+ paragraph 2
+
+ * bullet list
+ * still bullet list
+
+
+A right-aligned line-block. Alignment handling is built into the latex
+writer for image, table, and line block elements.
+
+.. class:: align-right
+
+| Max Mustermann
+| Waldstr. 22
+| D 01234 Testdorf
+| Tel.: 0123/456789
--- /dev/null
+Custom Roles
+------------
+
+* A role based on an existing role.
+
+ .. role:: custom(literal)
+
+ :custom:`one` :custom:`two` :custom:`three`
+
+* A new role.
+
+ .. role:: customnew
+
+ :customnew:`one two three`
+
+* A role with class attribute.
+
+ .. role:: customclass
+ :class: special
+
+ :customclass:`interpreted text`
+
+* A language-switching role:
+
+ .. role:: language-de
+
+ Let's count in German :language-de:`eins zwei drei`.
+
+* A role with multiple class attributes, styled with raw directives:
+
+ .. role:: customx
+ :class: green sc language-en-GB
+
+ .. raw:: latex
+
+ \newcommand{\DUrolegreen}[1]{\textcolor{green}{#1}}
+ \newcommand{\DUrolesc}[1]{\textsc{#1}}
+
+ The following works in most browsers but does not validate
+ (``<style>`` is only allowed in the document head)::
+
+ .. raw:: html
+
+ <style type="text/css"><!--
+ .green {color: green;}
+ .sc {font-variant: small-caps;}
+ --></style>
+
+ :customx:`British colourful text in small-caps`.
--- /dev/null
+Custom Roles in LaTeX
+---------------------
+
+* Role names and class arguments are converted to conform to the
+ regular expression ``[a-z][-a-z0-9]*`` (letters are downcased,
+ accents and similar decoration is stripped, non-conforming
+ characters are replaced by a hyphen).
+
+ Class arguments may contain numbers and hyphens, which need special
+ treatment in LaTeX command names.
+
+ .. role:: custom4
+ :class: large custom4 small_caps custom.role custom\role
+
+ :custom4:`Text with role "custom4"` (but without styling by ``DUrole*``
+ macros).
+
+* With LaTeX, roles can be styled within the document using the `raw`
+ directive.
+
+ .. raw:: latex
+
+ \newcommand{\DUrolelarge}[1]{{\large #1}}
+ \makeatletter
+ \@namedef{DUrolesmall-caps}{\textsc}
+ \@namedef{DUrolecustom4}{\textbf}
+ \makeatother
+
+ :custom4:`inline text` in large, bold, small-caps.
+
+* Custom roles can be based on standard roles:
+
+ .. role:: custom-emphasis(emphasis)
+
+ This is a :custom-emphasis:`customized emphasis text role`
+
+ .. role:: custom-literal(literal)
+
+ This is a :custom-literal:`customized literal text role`
+
+ .. role:: custom-strong(strong)
+
+ This is a :custom-strong:`customized strong text role`
+
+ .. role:: custom-subscript(subscript)
+
+ This is a :custom-subscript:`customized subscript text role`
+
+ .. role:: custom-superscript(superscript)
+
+ This is a :custom-superscript:`customized superscript text role`
+
+ .. role:: custom-title-reference(title-reference)
+
+ This is a :custom-title-reference:`customized title-reference text role`
--- /dev/null
+Error Handling
+==============
+
+Any errors caught during processing will generate system messages.
+
+There should be five messages in the following, auto-generated
+section, "Docutils System Messages":
+
+.. section should be added by Docutils automatically
--- /dev/null
+.. header:: Document header
+.. footer:: Document footer
--- /dev/null
+/*
+:Author: David Goodger (goodger@python.org)
+:Id: $Id: html4css1.css 7952 2016-07-26 18:15:59Z milde $
+:Copyright: This stylesheet has been placed in the public domain.
+
+Default cascading style sheet for the HTML output of Docutils.
+
+See http://docutils.sf.net/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: grey; } /* 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 {
+ 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 }
--- /dev/null
+Hyperlinks and -targets
+-----------------------
+
+In LaTeX, we must set an explicit anchor (``\phantomsection``) for a
+_`hypertarget in plain text` or in a figure but not in a longtable or
+caption:
+
+.. _`table label`:
+
+.. table:: Table with _`hypertarget in table title`.
+
+ ===== ===== =====
+ False True None
+ ===== ===== =====
+
+.. _`figure label`:
+
+.. figure:: ../../../docs/user/rst/images/biohazard.png
+
+ Figure with _`hypertarget in figure caption`.
+
+ Legend with _`hypertarget in figure legend`.
+
+.. _`image label`:
+
+.. image:: ../../../docs/user/rst/images/biohazard.png
+
+See `hypertarget in plain text`_,
+`table label`_, `hypertarget in table title`_,
+`figure label`_, `hypertarget in figure caption`_,
+`hypertarget in figure legend`_, and
+`image label`_.
--- /dev/null
+Problematic Cases for the LaTeX Writer
+======================================
+
+These tests contain unusual combinations of syntax elements which may cause
+trouble for the LaTeX writer but do not need to be tested with other writers
+(e.g. the HTML writer).
+
+The file `latex-problematic.txt` contains the cases with non unsatisfying
+results. It is only used to control the visual appearance of the output, not
+by any automated test
+
+Sidebars
+--------
+
+This paragraph precedes the sidebar. This is some text. This is some
+text. This is some text. This is some text. This is some text.
+This is some text. This is some text. This is some text.
+
+.. sidebar:: Sidebar Title
+
+ These are the sidebar contents. These are the sidebar contents.
+
+ These are the sidebar contents. These are the sidebar contents.
+
+ These are the sidebar contents. These are the sidebar contents.
+ These are the sidebar contents. These are the sidebar contents.
+
+This paragraph follows the sidebar. This is some text. This is some
+text. This is some text.
+
+This is some text. This is some text. This is some text. This is
+some text. This is some text. This is some text. This is some text.
+
+
+Next Section
+------------
+
+This section comes after the sidebar, and this text should float
+around the sidebar as well. This is some text. This is some text.
+This is some text. This is some text. This is some text. This is
+some text. This is some text. This is some text. This is some text.
+This is some text. This is some text. This is some text. This is
+some text. This is some text.
+
+This is some text. This is some text. This is some text. This is
+some text. This is some text. This is some text. This is some text.
+This is some text. This is some text. This is some text.
+
+Nested Elements
+---------------
+
+:Field list: | Line
+ | Block
+:Field 2: * Bullet
+ * list
+:Another (longer) field: * Bullet
+ * list
+:Yet another long field:
+ * .. comment
+
+ Bullet
+
+ .. comment
+
+ * .. comment
+
+ list
+
+ .. comment
+
+:Field: * This
+
+ is
+
+ a
+
+ * bullet
+
+ list
+
+:Field: * | This is
+ | a bullet
+ * | list with
+ | line blocks
+:Last field: Last field.
+
+Too deeply nested lists fail. TODO: generate an error or provide a workaround.
+
+.. * * * * * * * * Deeply nested list.
+
+.. 1. 2. 3. 4. 5. 6. 7. 8. Deeply nested list.
+
++-----------------+
+| | Line block |
+| |
+| * Bullet list |
+| |
+| :: |
+| |
+| Literal |
+| block |
++-----------------+
+| :Field 1: |
+| Text. |
+| :Field 2: |
+| More text. |
++-----------------+
+| +-------+-----+ |
+| | A |* foo| |
+| | nested| | |
+| | table.|* bar| |
+| +-------+-----+ |
++-----------------+
+| This is a |
+| paragraph. |
+| |
+| +-------+-----+ |
+| | A |* foo| |
+| | nested| | |
+| | table.|* bar| |
+| +-------+-----+ |
+| |
+| Another longer |
+| paragraph. |
++-----------------+
+| * A list. |
+| * A list. |
+| |
+| +-------+-----+ |
+| | A |* foo| |
+| | nested| | |
+| | table.|* bar| |
+| +-------+-----+ |
+| |
+| * Another list. |
+| * Another list. |
++-----------------+
+| Foo |
+| |
+| Bar |
++-----------------+
+| * Foo |
+| |
+| * Bar |
++-----------------+
+| * This is a |
+| paragraph. |
+| |
+| This is a |
+| paragraph. |
+| |
+| * This is a |
+| paragraph. |
+| |
+| This is a |
+| paragraph. |
++-----------------+
+
+Vertical alignment of inline images
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+.. |top| image:: ../../../../docs/user/rst/images/biohazard.png
+ :align: top
+ :width: 3em
+
+.. |middle| image:: ../../../../docs/user/rst/images/biohazard.png
+ :align: middle
+ :width: 2em
+
+.. |bottom| image:: ../../../../docs/user/rst/images/biohazard.png
+ :align: bottom
+ :width: 2.5em
+
+A paragraph with top |top|, middle |middle|, and bottom |bottom|
+aligned images.
+
+A paragraph with top |top| aligned image.
+
+A paragraph with middle |middle| aligned image.
+
+A paragraph with bottom |bottom| aligned image.
+
+
--- /dev/null
+Encoding special chars
+----------------------
+
+The LaTeX Info pages lists under "2.18 Special Characters"
+
+ The following characters play a special role in LaTeX and are called
+ "special printing characters", or simply "special characters".
+
+ # $ % & ~ _ ^ \\ { }
+
+The special chars verbatim::
+
+ # $ % & ~ _ ^ \ { }
+
+However also *square brackets* [] need special care.
+
+ Commands with optional arguments (e.g. ``\item``) check
+ if the token right after the macro name is an opening bracket.
+ In that case the contents between that bracket and the following
+ closing bracket on the same grouping level are taken as the
+ optional argument. What makes this unintuitive is the fact that
+ the square brackets aren't grouping characters themselves, so in
+ your last example ``\item[[...]]`` the optional argument consists of
+ [... (without the closing bracket).
+
+Compare the items in the following lists:
+
+* simple item
+* [bracketed] item
+
+simple
+ description term
+
+[bracketed]
+ description term
+
+The OT1 font-encoding has different characters for the less-than,
+greater-than and bar, < | >, except for typewriter font `cmtt`::
+
+ < | >
+
--- /dev/null
+List Tables
+-----------
+
+Here's a list table exercising all features:
+
+.. list-table:: list table with integral header
+ :class: test
+ :width: 40em
+ :widths: 10 20 30
+ :header-rows: 1
+ :stub-columns: 1
+
+ * - Treat
+ - Quantity
+ - Description
+ * - Albatross
+ - 2.99
+ - On a stick!
+ * - Crunchy Frog
+ - 1.49
+ - If we took the bones out, it wouldn't be
+ crunchy, now would it?
+ * - Gannet Ripple
+ - 1.99
+ - On a stick!
+
+.. list-table:: center aligned list table
+ :align: center
+ :widths: auto
+
+ * - Albatross
+ - 2.99
+ * - Crunchy Frog
+ - 1.49
+ * - Gannet Ripple
+ - 1.99
--- /dev/null
+/*
+* math2html: convert LaTeX equations to HTML output.
+*
+* Copyright (C) 2009,2010 Alex Fernández
+*
+* 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/
+*/
+/* --end--
+* CSS file for LaTeX formulas.
+*/
+
+/* Formulas */
+.formula {
+ text-align: center;
+ font-family: "Droid Serif", "DejaVu Serif", "STIX", serif;
+ margin: 1.2em 0;
+}
+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;
+}
+.formula i {
+ letter-spacing: 0.1ex;
+}
+
+/* Alignment */
+.align-left, .align-l {
+ text-align: left;
+}
+.align-right, .align-r {
+ text-align: right;
+}
+.align-center, .align-c {
+ text-align: center;
+}
+
+/* Structures */
+span.overline, span.bar {
+ text-decoration: overline;
+}
+.fraction, .fullfraction {
+ display: inline-block;
+ vertical-align: middle;
+ text-align: center;
+}
+.fraction .fraction {
+ font-size: 80%;
+ line-height: 100%;
+}
+span.numerator {
+ display: block;
+}
+span.denominator {
+ display: block;
+ padding: 0ex;
+ border-top: thin solid;
+}
+sup.numerator, sup.unit {
+ font-size: 70%;
+ vertical-align: 80%;
+}
+sub.denominator, sub.unit {
+ font-size: 70%;
+ vertical-align: -20%;
+}
+span.sqrt {
+ display: inline-block;
+ vertical-align: middle;
+ padding: 0.1ex;
+}
+sup.root {
+ font-size: 70%;
+ position: relative;
+ left: 1.4ex;
+}
+span.radical {
+ display: inline-block;
+ padding: 0ex;
+ font-size: 150%;
+ vertical-align: top;
+}
+span.root {
+ display: inline-block;
+ border-top: thin solid;
+ padding: 0ex;
+ vertical-align: middle;
+}
+span.symbol {
+ line-height: 125%;
+ font-size: 125%;
+}
+span.bigsymbol {
+ line-height: 150%;
+ font-size: 150%;
+}
+span.largesymbol {
+ font-size: 175%;
+}
+span.hugesymbol {
+ font-size: 200%;
+}
+span.scripts {
+ display: inline-table;
+ vertical-align: middle;
+}
+.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.symbolover {
+ display: inline-block;
+ text-align: center;
+ position: relative;
+ float: right;
+ right: 100%;
+ bottom: 0.5em;
+ width: 0px;
+}
+span.withsymbol {
+ display: inline-block;
+}
+span.symbolunder {
+ display: inline-block;
+ text-align: center;
+ position: relative;
+ float: right;
+ right: 80%;
+ top: 0.3em;
+ width: 0px;
+}
+
+/* Environments */
+span.array, span.bracketcases, span.binomial, span.environment {
+ display: inline-table;
+ text-align: center;
+ border-collapse: collapse;
+ margin: 0em;
+ vertical-align: middle;
+}
+span.arrayrow, span.binomrow {
+ display: table-row;
+ padding: 0ex;
+ border: 0ex;
+}
+span.arraycell, span.bracket, span.case, span.binomcell, span.environmentcell {
+ display: table-cell;
+ padding: 0ex 0.2ex;
+ line-height: 99%;
+ border: 0ex;
+}
+/*
+* CSS file for LaTeX formulas, extra stuff:
+* binomials, vertical braces, stackrel, fonts and colors.
+*/
+
+/* 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 */
+span.mathsf, span.textsf {
+ font-style: normal;
+ font-family: sans-serif;
+}
+span.mathrm, span.textrm {
+ font-style: normal;
+ font-family: serif;
+}
+span.text, span.textnormal {
+ font-style: normal;
+}
+span.textipa {
+ color: #008080;
+}
+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;
+}
+
+/* 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;
+}
+
--- /dev/null
+Mathematics
+-----------
+
+Docutils supports inline math with the prefix or postfix ``:math:``
+role specificator, :math:`n! + \sin(x_n^2)` and `A_\text{c} =
+\frac{\pi}{4} d^2`:math:, as well as displayed math via the
+`math` directive:
+
+.. math::
+
+ f(\epsilon) = \frac{1}{1 + \exp\left(\frac{\varepsilon}{k_\text{B}T}\right)}
+
+Content may start on the first line of the directive, e.g.
+
+.. math:: N = \frac{\text{number of apples}}{7}
+
+Equations can be labeled with a reference name using the ``:name:`` option.
+See `eq:M`_ and `eq:schrödinger`_ below.
+
+The determinant of the matrix
+
+.. math:: :name: eq:M
+
+ \mathbf{M} = \left(\begin{matrix}a&b\\c&d\end{matrix}\right)
+
+is :math:`|\mathbf{M}| = ad - bc`.
+
+More than one display math block can be put in one math directive.
+For example, the following sum and integral with limits:
+
+.. math::
+
+ \int_0^1 x^n dx = \frac{1}{n + 1}
+
+ \sum_{n=1}^m n = \frac{m(m+1)}{2}
+
+LaTeX-supported Unicode math symbols can be used in math roles and
+directives:
+
+The Schrödinger equation
+
+.. math:: :name: eq:schrödinger
+
+ i\hbar \frac{∂}{∂t}Ψ = \hat{H}Ψ,
+
+with the *wave function* :math:`Ψ`, describes how the quantum state of a
+physical system changes in time.
+
+Math-Accents:
+ .. list-table::
+ :class: borderless
+ :widths: 26 26 26
+
+ * - :math:`\acute{a}` ``\acute{a}``
+ - :math:`\dot{t}` ``\dot{t}``
+ - :math:`\hat{\gamma}` ``\hat{\gamma}``
+
+ * - :math:`\grave{a}` ``\grave{a}``
+ - :math:`\ddot{t}` ``\ddot{t}``
+ - :math:`\tilde{\alpha}` ``\tilde{\alpha}``
+
+ * - :math:`\breve{x}` ``\breve{x}``
+ - :math:`\dddot{t}` ``\dddot{t}``
+ - :math:`\vec{\imath}` ``\vec{\imath}``
+
+ * - :math:`\check{a}` ``\check{a}``
+ - :math:`\bar{a}` ``\bar{a}``
+ - :math:`\vec{R}` ``\vec{R}``
+
+..
+ \widetilde{xxx}
+ \widehat{xxx}
+
+Modulation Transfer Function:
+
+.. math::
+
+ \text{MTF} = \left|\frac{\mathcal{F}\{s(x)\}}
+ {\mathcal{F}\{ s(x)\} |_{ω_{x}=0}}\right|
+ = \mathrm{abs}\left(\frac
+ {∫_{-∞}^{∞}s(x) \mathrm{e}^{\mathrm{i}ω_{x}x}\mathrm{d}{x}}
+ {∫_{-∞}^{∞}s(x)\mathrm{d}{x}}
+ \right).
+
+Math split over two lines: If a double backslash is detected outside a
+``\begin{...} \end{...}`` pair, the math code is wrapped in an AMSmath_
+``align`` environment:
+
+.. math::
+
+ s_{\mathrm{out}}(x) & = s_{\mathrm{in}}(x') * s_δ(x-x') \\
+ & = ∫ s_{\mathrm{in}}(x')s_δ(x-x')\mathrm{d}x'
+
+Cases ("manually", with ``matrix`` environment):
+
+.. math::
+
+ \mathrm{sgn}(x) = \left\{\begin{matrix}
+ -1 & x<0\\
+ 1 & x>0
+ \end{matrix}\right.
+
+Cases with the AMSmath_ ``cases`` environment (not (yet) supported by
+HTML writers with ``--math-output=MathML``):
+
+.. math::
+
+ \mathrm{sgn}(x) = \begin{cases}
+ -1 & x<0\\
+ 1 & x>0
+ \end{cases}
+
+.. _AMSmath: ftp://ftp.ams.org/ams/doc/amsmath/short-math-guide.pdf
--- /dev/null
+/* Minimal style sheet for the HTML output of Docutils. */
+/* */
+/* :Author: Günter Milde, based on html4css1.css by David Goodger */
+/* :Id: $Id: minimal.css 8397 2019-09-20 11:09:34Z 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 */
+
+/* This CSS2.1_ stylesheet defines rules for Docutils elements without */
+/* HTML equivalent. It is required to make the document semantic visible. */
+/* */
+/* .. _CSS2.1: http://www.w3.org/TR/CSS2 */
+/* .. _validates: http://jigsaw.w3.org/css-validator/validator$link */
+
+/* alignment of text and inline objects inside block objects*/
+.align-left { text-align: left; }
+.align-right { text-align: right; }
+.align-center { clear: both; text-align: center; }
+.align-top { vertical-align: top; }
+.align-middle { vertical-align: middle; }
+.align-bottom { vertical-align: bottom; }
+
+/* titles */
+h1.title, p.subtitle {
+ text-align: center;
+}
+p.topic-title,
+p.sidebar-title,
+p.rubric,
+p.admonition-title,
+p.system-message-title {
+ font-weight: bold;
+}
+h1 + p.subtitle,
+h1 + p.section-subtitle {
+ font-size: 1.6em;
+}
+h2 + p.section-subtitle { font-size: 1.28em; }
+p.subtitle,
+p.section-subtitle,
+p.sidebar-subtitle {
+ font-weight: bold;
+ margin-top: -0.5em;
+}
+p.sidebar-title,
+p.rubric {
+ font-size: larger;
+}
+p.rubric { color: maroon; }
+a.toc-backref {
+ color: black;
+ text-decoration: none; }
+
+/* Warnings, Errors */
+div.caution p.admonition-title,
+div.attention p.admonition-title,
+div.danger p.admonition-title,
+div.error p.admonition-title,
+div.warning p.admonition-title,
+div.system-messages h1,
+div.error,
+span.problematic,
+p.system-message-title {
+ color: red;
+}
+
+/* inline literals */
+span.docutils.literal {
+ font-family: monospace;
+ white-space: pre-wrap;
+}
+/* do not wraph at hyphens and similar: */
+.literal > span.pre { white-space: nowrap; }
+
+/* Lists */
+
+/* compact and simple lists: no margin between items */
+.simple li, .compact li,
+.simple ul, .compact ul,
+.simple ol, .compact ol,
+.simple > li p, .compact > li p,
+dl.simple > dd, dl.compact > dd {
+ margin-top: 0;
+ margin-bottom: 0;
+}
+
+/* Table of Contents */
+div.topic.contents { margin: 0.5em 0; }
+div.topic.contents ul {
+ list-style-type: none;
+ padding-left: 1.5em;
+}
+
+/* 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 }
+
+dt span.classifier { font-style: italic }
+dt span.classifier:before {
+ font-style: normal;
+ margin: 0.5em;
+ content: ":";
+}
+
+/* Field Lists and drivatives */
+/* bold field name, content starts on the same line */
+dl.field-list > dt,
+dl.option-list > dt,
+dl.docinfo > dt,
+dl.footnote > dt,
+dl.citation > dt {
+ font-weight: bold;
+ clear: left;
+ float: left;
+ margin: 0;
+ padding: 0;
+ padding-right: 0.5em;
+}
+/* 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 */
+}
+/* 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;
+}
+/* field names followed by a colon */
+dl.field-list > dt:after,
+dl.docinfo > dt:after {
+ content: ":";
+}
+
+/* Bibliographic Fields (docinfo) */
+pre.address { font: inherit; }
+dd.authors > p { margin: 0; }
+
+/* Option Lists */
+dl.option-list { margin-left: 1.5em; }
+dl.option-list > dt { font-weight: normal; }
+span.option { white-space: nowrap; }
+
+/* Footnotes and Citations */
+dl.footnote.superscript > dd {margin-left: 1em; }
+dl.footnote.brackets > dd {margin-left: 2em; }
+dl > dt.label { font-weight: normal; }
+a.footnote-reference.brackets:before,
+dt.label > span.brackets:before { content: "["; }
+a.footnote-reference.brackets:after,
+dt.label > span.brackets:after { content: "]"; }
+a.footnote-reference.superscript,
+dl.footnote.superscript > dt.label {
+ vertical-align: super;
+ font-size: smaller;
+}
+dt.label > span.fn-backref { margin-left: 0.2em; }
+dt.label > span.fn-backref > a { font-style: italic; }
+
+/* Line Blocks */
+div.line-block { display: block; }
+div.line-block div.line-block {
+ margin-top: 0;
+ margin-bottom: 0;
+ margin-left: 40px;
+}
+
+/* Figures, Images, and Tables */
+.figure.align-left,
+figure.align-left,
+img.align-left,
+object.align-left,
+table.align-left {
+ margin-right: auto;
+}
+.figure.align-center,
+figure.align-center,
+img.align-center,
+object.align-center,
+table.align-center {
+ margin-left: auto;
+ margin-right: auto;
+}
+.figure.align-right,
+figure.align-right,
+img.align-right,
+object.align-right,
+table.align-right {
+ margin-left: auto;
+}
+.figure.align-center, .figure.align-right,
+figure.align-center, figure.align-right,
+img.align-center, img.align-right,
+object.align-center, object.align-right {
+ display: block;
+}
+/* reset inner alignment in figures and tables */
+.figure.align-left, .figure.align-right,
+figure.align-left, figure.align-right,
+table.align-left, table.align-center, table.align-right {
+ text-align: inherit;
+}
+
+/* Admonitions and System Messages */
+div.admonition,
+div.system-message,
+div.sidebar,
+aside.sidebar {
+ margin: 1em 1.5em;
+ border: medium outset;
+ padding-top: 0.5em;
+ padding-bottom: 0.5em;
+ padding-right: 1em;
+ padding-left: 1em;
+}
+
+/* Sidebar */
+div.sidebar,
+aside.sidebar {
+ width: 30%;
+ max-width: 26em;
+ float: right;
+ clear: right;
+}
+
+/* Text Blocks */
+blockquote,
+div.topic,
+pre.literal-block,
+pre.doctest-block,
+pre.math,
+pre.code {
+ margin-left: 1.5em;
+ margin-right: 1.5em;
+}
+pre.code .ln { color: gray; } /* line numbers */
+
+/* Tables */
+table { border-collapse: collapse; }
+td, th {
+ border-style: solid;
+ border-color: silver;
+ padding: 0 1ex;
+ border-width: thin;
+}
+td > p:first-child, th > p:first-child { margin-top: 0; }
+td > p, th > p { margin-bottom: 0; }
+
+table > caption {
+ text-align: left;
+ margin-bottom: 0.25em
+}
+
+table.borderless td, table.borderless th {
+ border: 0;
+ padding: 0;
+ padding-right: 0.5em /* separate table cells */
+}
+
+/* Document Header and Footer */
+/* div.header, */
+/* header { border-bottom: 1px solid black; } */
+/* div.footer, */
+/* footer { border-top: 1px solid black; } */
+
+/* new HTML5 block elements: set display for older browsers */
+header, section, footer, aside, nav, main, article, figure {
+ display: block;
+}
--- /dev/null
+Monospaced non-alphanumeric characters
+--------------------------------------
+
+These are all ASCII characters except a-zA-Z0-9 and space:
+
+``!!!"""###$$$%%%&&&'''((()))***+++,,,---...///:::``
+
+``;;;<<<===>>>???@@@[[[\\\]]]^^^___```{{{|||}}}~~~``
+
+``xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx``
+
+The two lines of non-alphanumeric characters should both have the same
+width as the third line.
--- /dev/null
+.. This file is used by the standalone_rst_latex test.
+
+Option lists
+------------
+
+The LaTeX-2e description environment is used for definition lists.
+The definition is continued on the same line as the term, this should
+not happen if a option-list is at the top of the definition.
+
+If the option list is not at the first element in the definition, it
+is contained in a quote
+
+ --help show help
+ -v verbose
+
+In a definition list:
+ --help show help
+ -v verbose
--- /dev/null
+/* 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 8397 2019-09-20 11:09:34Z 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: http://www.w3.org/TR/CSS3 */
+
+
+/* Document Structure */
+/* ****************** */
+
+/* "page layout" */
+body {
+ margin: 0;
+ background-color: #dbdbdb;
+}
+div.document,
+main {
+ line-height:1.3;
+ counter-reset: table;
+ /* counter-reset: figure; */
+ /* avoid long lines --> better reading */
+ /* OTOH: lines should not be too short because of missing hyphenation, */
+ max-width: 50em;
+ padding: 1px 2%; /* 1px on top avoids grey bar above title (mozilla) */
+ margin: auto;
+ background-color: white;
+}
+
+/* Sections */
+
+/* Transitions */
+
+hr.docutils {
+ width: 80%;
+ margin-top: 1em;
+ margin-bottom: 1em;
+ clear: both;
+}
+
+/* Paragraphs */
+/* ========== */
+
+/* vertical space (parskip) */
+p, ol, ul, dl,
+div.line-block,
+div.topic,
+table {
+ margin-top: 0.5em;
+ margin-bottom: 0.5em;
+}
+p:first-child { margin-top: 0; }
+/* (:last-child is new in CSS 3) */
+p:last-child { margin-bottom: 0; }
+
+h1, h2, h3, h4, h5, h6,
+dl > dd {
+ margin-bottom: 0.5em;
+}
+
+/* Lists */
+/* ===== */
+
+/* Definition Lists */
+
+/* lists nested in definition lists */
+/* (:only-child is new in CSS 3) */
+dd > ul:only-child, dd > ol:only-child { padding-left: 1em; }
+
+/* Description Lists */
+/* styled like in most dictionaries, encyclopedias etc. */
+dl.description > dt {
+ font-weight: bold;
+ clear: left;
+ float: left;
+ margin: 0;
+ padding: 0;
+ padding-right: 0.5em;
+}
+
+/* Field Lists */
+
+/* example for custom field-name width */
+dl.field-list.narrow > dd {
+ margin-left: 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 special definition list dl.docinfo */
+/* but dedication and abstract are placed into "topic" 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;
+}
+
+/* Citations */
+dl.citation dt.label {
+ font-weight: bold;
+}
+span.fn-backref {
+ font-weight: normal;
+}
+
+/* Text Blocks */
+/* =========== */
+
+/* Literal Blocks */
+
+pre.literal-block,
+pre.doctest-block,
+pre.math,
+pre.code {
+ font-family: monospace;
+}
+
+/* Block Quotes */
+
+blockquote > table,
+div.topic > table {
+ margin-top: 0;
+ margin-bottom: 0;
+}
+blockquote p.attribution,
+div.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 */
+dl.footnote {
+ padding-left: 1ex;
+ border-left: solid;
+ border-left-width: thin;
+}
+
+/* Directives */
+/* ---------- */
+
+/* Body Elements */
+/* ~~~~~~~~~~~~~ */
+
+/* Images and Figures */
+
+/* let content flow to the side of aligned images and figures */
+.figure.align-left,
+figure.align-left,
+img.align-left,
+object.align-left {
+ display: block;
+ clear: left;
+ float: left;
+ margin-right: 1em;
+}
+.figure.align-right,
+figure.align-right,
+img.align-right,
+object.align-right {
+ display: block;
+ clear: right;
+ float: right;
+ margin-left: 1em;
+}
+/* Stop floating sidebars, images and figures at section level 1,2,3 */
+h1, h2, h3 { clear: both; }
+
+/* Sidebar */
+
+/* Move right. In a layout with fixed margins, */
+/* it can be moved into the margin. */
+div.sidebar,
+aside.sidebar {
+ width: 30%;
+ max-width: 26em;
+ margin-left: 1em;
+ margin-right: -2%;
+ background-color: #ffffee;
+}
+
+/* Code */
+
+pre.code { padding: 0.7ex }
+pre.code, code { background-color: #eeeeee }
+pre.code .ln { color: gray; } /* line numbers */
+/* basic highlighting: for a complete scheme, see */
+/* http://docutils.sourceforge.net/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}
+
+/* Math */
+/* styled separately (see math.css for math-output=HTML) */
+
+/* Epigraph */
+/* Highlights */
+/* Pull-Quote */
+/* Compound Paragraph */
+/* Container */
+
+/* can be styled in a custom stylesheet */
+
+/* Document Header and Footer */
+
+footer, header,
+div.footer, div.header {
+ font-size: smaller;
+ clear: both;
+ padding: 0.5em 2%;
+ background-color: #ebebee;
+ border: none;
+}
+
+/* Inline Markup */
+/* ============= */
+
+/* Emphasis */
+/* em */
+/* Strong Emphasis */
+/* strong */
+/* Interpreted Text */
+/* span.interpreted */
+/* Title Reference */
+/* cite */
+
+/* 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.footnote-reference */
+/* Citation References */
+/* a.citation-reference */
--- /dev/null
+Section titles with `inline markup`_
+------------------------------------
+
+*emphasized*, H\ :sub:`2`\ O and :math:`x^2`
+````````````````````````````````````````````
+Substitutions |fail|
+````````````````````
+.. |fail| replace:: work
+
+Deeply nested sections
+----------------------
+In LaTeX and HTML,
+
+Level 3
+```````
+nested sections
+
+level 4
+^^^^^^^
+reach at some level
+
+level 5
+:::::::
+(depending on the document class)
+
+level 6
++++++++
+an unsupported level.
--- /dev/null
+.. This is a comment. Note how any initial comments are moved by
+ transforms to after the document title, subtitle, and docinfo.
+
+.. _doctitle:
+
+================================
+ reStructuredText Test Document
+================================
+
+.. Above is the document title, and below is the subtitle.
+ They are transformed from section titles after parsing.
+
+.. _subtitle:
+
+--------------------------------
+ Examples of Syntax Constructs
+--------------------------------
+
+.. bibliographic fields (which also require a transform):
+
+:Author: David Goodger
+:Address: 123 Example Street
+ Example, EX Canada
+ A1B 2C3
+:Contact: goodger@python.org
+:Authors: Me; Myself; I
+:organization: humankind
+:date: Now, or yesterday. Or maybe even *before* yesterday.
+:status: This is a "work in progress"
+:revision: is managed by a version control system.
+:version: 1
+:copyright: This document has been placed in the public domain. You
+ may do with it as you wish. You may copy, modify,
+ redistribute, reattribute, sell, buy, rent, lease,
+ destroy, or improve it, quote it at length, excerpt,
+ incorporate, collate, fold, staple, or mutilate it, or do
+ anything else to it that your or anyone else's heart
+ desires.
+:field name: This is a "generic bibliographic field".
+:field name "2":
+ Generic bibliographic fields may contain multiple body elements.
+
+ Like this.
+
+:Dedication:
+
+ For Docutils users & co-developers.
+
+:abstract:
+
+ This is a test document, containing at least one example of each
+ reStructuredText construct.
+
+.. meta::
+ :keywords: reStructuredText, test, parser
+ :description lang=en: A test document, containing at least one
+ example of each reStructuredText construct.
+
+.. raw:: latex
+
+ \pagebreak[4] % start ToC on new page
+
+.. contents:: Table of Contents
+.. section-numbering::
+
+
+Structural Elements
+===================
+
+Section Title
+-------------
+Section Subtitle
+````````````````
+
+Lone subsections are converted to a section subtitle by a transform
+activated with the ``--section-subtitles`` command line option or the
+``sectsubtitle-xform`` configuration value.
+
+Empty Section
+-------------
+
+Transitions
+-----------
+
+Here's a transition:
+
+---------
+
+It divides the section. Transitions may also occur between sections:
+
+---------
+
+Body Elements
+=============
+
+Paragraphs
+----------
+
+A paragraph.
+
+Inline Markup
+`````````````
+
+Paragraphs contain text and may contain inline markup: *emphasis*,
+**strong emphasis**, ``inline literals``, standalone hyperlinks
+(http://www.python.org), external hyperlinks (Python_), internal
+cross-references (example_), external hyperlinks with embedded URIs
+(`Python web site <http://www.python.org>`__), `anonymous hyperlink
+references`__ (`a second reference`__), footnote references (manually
+numbered [1]_, anonymous auto-numbered [#]_, labeled auto-numbered
+[#label]_, or symbolic [*]_), citation references ([CIT2002]_),
+substitution references (|example| &
+a *trimmed heart* ``(U+2665):`` |heart|), and _`inline hyperlink targets`
+(see Targets_ below for a reference back to here). Character-level
+inline markup is also possible (although exceedingly ugly!) in *re*\
+``Structured``\ *Text*. Problems are indicated by |problematic| text
+(generated by processing errors; this one is intentional). Here is a
+reference to the doctitle_ and the subtitle_.
+
+__ http://www.python.org/
+__ http://docutils.sourceforge.net/
+
+The default role for interpreted text is `Title Reference`. Here are
+some explicit interpreted text roles: a PEP reference (:PEP:`287`); an
+RFC reference (:RFC:`2822`); an abbreviation (:ab:`abb.`), an acronym
+(:ac:`reST`), code (:code:`print "hello world"`); a :sub:`subscript`;
+a :sup:`superscript` and explicit roles for :title:`Docutils`'
+:emphasis:`standard` :strong:`inline` :literal:`markup`.
+
+.. DO NOT RE-WRAP THE FOLLOWING PARAGRAPH!
+
+Let's test wrapping and whitespace significance in inline literals:
+``This is an example of --inline-literal --text, --including some--
+strangely--hyphenated-words. Adjust-the-width-of-your-browser-window
+to see how the text is wrapped. -- ---- -------- Now note the
+spacing between the words of this sentence (words
+should be grouped in pairs).``
+
+If the ``--pep-references`` option was supplied, there should be a
+live link to PEP 258 here.
+
+Bullet Lists
+------------
+
+- A bullet list
+
+ + Nested bullet list.
+ + Nested item 2.
+
+- Item 2.
+
+ Paragraph 2 of item 2.
+
+ * Nested bullet list.
+ * Nested item 2.
+
+ - Third level.
+ - Item 2.
+
+ * Nested item 3.
+
+ * This nested list should be compacted by the HTML writer.
+
+ .. _target:
+
+ .. Even if this item contains a target and a comment.
+
+Enumerated Lists
+----------------
+
+1. Arabic numerals.
+
+ a) lower alpha)
+
+ (i) (lower roman)
+
+ A. upper alpha.
+
+ I) upper roman)
+
+2. Lists that don't start at 1:
+
+ 3. Three
+
+ 4. Four
+
+ C. C
+
+ D. D
+
+ iii. iii
+
+ iv. iv
+
+Definition Lists
+----------------
+
+Term
+ Definition
+Term : classifier
+ Definition paragraph 1.
+
+ Definition paragraph 2.
+Term
+ Definition
+Term : classifier one : classifier two
+ Definition
+
+Field Lists
+-----------
+
+:what: Field lists map field names to field bodies, like database
+ records. They are often part of an extension syntax. They are
+ an unambiguous variant of RFC 2822 fields.
+
+:how arg1 arg2:
+
+ The field marker is a colon, the field name, and a colon.
+
+ The field body may contain one or more body elements, indented
+ relative to the field marker.
+
+:credits:
+
+ .. class:: credits
+
+ This paragraph has the `credits` class set. (This is actually not
+ about credits but just for ensuring that the class attribute
+ doesn't get stripped away.)
+
+Option Lists
+------------
+
+For listing command-line options:
+
+-a command-line option "a"
+-b file options can have arguments
+ and long descriptions
+--long options can be long also
+--input=file long options can also have
+ arguments
+
+--very-long-option
+ The description can also start on the next line.
+
+ The description may contain multiple body elements,
+ regardless of where it starts.
+
+-x, -y, -z Multiple options are an "option group".
+-v, --verbose Commonly-seen: short & long options.
+-1 file, --one=file, --two file
+ Multiple options with arguments.
+/V DOS/VMS-style options too
+
+There must be at least two spaces between the option and the
+description.
+
+Literal Blocks
+--------------
+
+Literal blocks are indicated with a double-colon ("::") at the end of
+the preceding paragraph (over there ``-->``). They can be indented::
+
+ if literal_block:
+ text = 'is left as-is'
+ spaces_and_linebreaks = 'are preserved'
+ markup_processing = None
+
+Or they can be quoted without indentation::
+
+>> Great idea!
+>
+> Why didn't I think of that?
+
+Line Blocks
+-----------
+
+This section tests line blocks. Line blocks are body elements which
+consist of lines and other line blocks. Nested line blocks cause
+indentation.
+
+| This is a line block. It ends with a blank line.
+| New lines begin with a vertical bar ("|").
+| Line breaks and initial indent are significant, and preserved.
+| Continuation lines are also possible. A long line that is intended
+ to wrap should begin with a space in place of the vertical bar.
+| The left edge of a continuation line need not be aligned with
+ the left edge of the text above it.
+
+| This is a second line block.
+|
+| Blank lines are permitted internally, but they must begin with a "|".
+
+Another line block, surrounded by paragraphs:
+
+| And it's no good waiting by the window
+| It's no good waiting for the sun
+| Please believe me, the things you dream of
+| They don't fall in the lap of no-one
+
+Take it away, Eric the Orchestra Leader!
+
+ | A one, two, a one two three four
+ |
+ | Half a bee, philosophically,
+ | must, *ipso facto*, half not be.
+ | But half the bee has got to be,
+ | *vis a vis* its entity. D'you see?
+ |
+ | But can a bee be said to be
+ | or not to be an entire bee,
+ | when half the bee is not a bee,
+ | due to some ancient injury?
+ |
+ | Singing...
+
+A line block, like the following poem by Christian Morgenstern, can
+also be centre-aligned:
+
+.. class:: language-de align-center
+
+| **Die Trichter**
+|
+| Zwei Trichter wandeln durch die Nacht.
+| Durch ihres Rumpfs verengten Schacht
+| fließt weißes Mondlicht
+| still und heiter
+| auf ihren
+| Waldweg
+| u. s.
+| w.
+|
+
+Block Quotes
+------------
+
+Block quotes consist of indented body elements:
+
+ My theory by A. Elk. Brackets Miss, brackets. This theory goes
+ as follows and begins now. All brontosauruses are thin at one
+ end, much much thicker in the middle and then thin again at the
+ far end. That is my theory, it is mine, and belongs to me and I
+ own it, and what it is too.
+
+ -- Anne Elk (Miss)
+
+The language of a quote (like any other object) can be specified by
+a class attribute:
+
+.. class:: language-fr
+
+..
+
+ ReStructuredText est un langage de balisage léger utilisé
+ notamment dans la documentation du langage Python.
+
+Doctest Blocks
+--------------
+
+>>> print 'Python-specific usage examples; begun with ">>>"'
+Python-specific usage examples; begun with ">>>"
+>>> print '(cut and pasted from interactive Python sessions)'
+(cut and pasted from interactive Python sessions)
+
+Footnotes
+---------
+
+.. [1] A footnote contains body elements, consistently indented by at
+ least 3 spaces.
+
+ This is the footnote's second paragraph.
+
+.. [#label] Footnotes may be numbered, either manually (as in [1]_) or
+ automatically using a "#"-prefixed label. This footnote has a
+ label so it can be referred to from multiple places, both as a
+ footnote reference ([#label]_) and as a `hyperlink reference`__.
+
+ __ label_
+
+.. [#] This footnote is numbered automatically and anonymously using a
+ label of "#" only.
+
+ This is the second paragraph.
+
+ And this is the third paragraph.
+
+.. [*] Footnotes may also use symbols, specified with a "*" label.
+ Here's a reference to the next footnote: [*]_.
+
+.. [*] This footnote shows the next symbol in the sequence.
+
+.. [4] Here's an unreferenced footnote, with a reference to a
+ nonexistent footnote: [5]_.
+
+Citations
+---------
+
+.. [CIT2002] Citations are text-labeled footnotes. They may be
+ rendered separately and differently from footnotes.
+
+Here's a reference to the above, [CIT2002]_, and a [nonexistent]_
+citation.
+
+.. _Another Target:
+
+Targets
+-------
+
+.. _example:
+
+This paragraph is pointed to by the explicit "example" target. A
+reference can be found under `Inline Markup`_, above. `Inline
+hyperlink targets`_ are also possible.
+
+Section headers are implicit targets, referred to by name. See
+Targets_, which is a subsection of `Body Elements`_.
+
+Explicit external targets are interpolated into references such as
+"Python_".
+
+.. _Python: http://www.python.org/
+
+Targets may be indirect and anonymous. Thus `this phrase`__ may also
+refer to the Targets_ section.
+
+__ Targets_
+
+Here's a `hyperlink reference without a target`_, which generates an
+error.
+
+Duplicate Target Names
+``````````````````````
+
+Duplicate names in section headers or other implicit targets will
+generate "info" (level-1) system messages. Duplicate names in
+explicit targets will generate "warning" (level-2) system messages.
+
+Duplicate Target Names
+``````````````````````
+
+Since there are two "Duplicate Target Names" section headers, we
+cannot uniquely refer to either of them by name. If we try to (like
+this: `Duplicate Target Names`_), an error is generated.
+
+Directives
+----------
+
+.. contents:: :local:
+
+These are just a sample of the many reStructuredText Directives. For
+others, please see
+http://docutils.sourceforge.net/docs/ref/rst/directives.html.
+
+Document Parts
+``````````````
+
+An example of the "contents" directive can be seen above this section
+(a local, untitled table of contents_) and at the beginning of the
+document (a document-wide `table of contents`_).
+
+Images and Figures
+``````````````````
+
+An image directive (also clickable -- a hyperlink reference):
+
+.. image:: ../../../docs/user/rst/images/title.png
+ :class: class1 class2
+ :target: directives_
+
+Image with multiple IDs:
+
+.. _image target 1:
+.. _image target 2:
+.. _image target 3:
+.. image:: ../../../docs/user/rst/images/title.png
+
+A centered image:
+
+.. image:: ../../../docs/user/rst/images/biohazard.png
+ :align: center
+
+A left-aligned image:
+
+.. image:: ../../../docs/user/rst/images/biohazard.png
+ :align: left
+
+This paragraph might flow around the image.
+The specific behavior depends upon the style sheet and
+the browser or rendering software used.
+
+A right-aligned image:
+
+.. image:: ../../../docs/user/rst/images/biohazard.png
+ :align: right
+
+This paragraph might flow around the image.
+The specific behavior depends upon the style sheet and
+the browser or rendering software used.
+
+For inline images see `Substitution Definitions`_.
+
+Image size:
+
+An image 2 em wide:
+
+.. image:: ../../../docs/user/rst/images/biohazard.png
+ :width: 2 em
+
+An image 2 em wide and 15 pixel high:
+
+.. image:: ../../../docs/user/rst/images/biohazard.png
+ :width: 2em
+ :height: 15 px
+
+An image occupying 50% of the line width:
+
+.. image:: ../../../docs/user/rst/images/title.png
+ :width: 50%
+
+An image 2 cm high:
+
+.. image:: ../../../docs/user/rst/images/biohazard.png
+ :height: 2 cm
+
+A *figure* is an image with a caption and/or a legend. With page-based output
+media, figures might float to a different position if this helps the page
+layout.
+
+.. figure:: ../../../docs/user/rst/images/title.png
+ :figclass: figclass1 figclass2
+ :class: class1 class2
+ :alt: reStructuredText, the markup syntax
+ :width: 258
+
+ Plaintext markup syntax and parser system.
+
+ +------------+-----------------------------------------------+
+ | re | Revised, revisited, based on 're' module. |
+ +------------+-----------------------------------------------+
+ | Structured | Structure-enhanced text, structuredtext. |
+ +------------+-----------------------------------------------+
+ | Text | Well it is, isn't it? |
+ +------------+-----------------------------------------------+
+
+ This paragraph is also part of the legend.
+
+A left-aligned figure:
+
+.. figure:: ../../../docs/user/rst/images/biohazard.png
+ :figclass: figclass1 figclass2
+ :class: class1 class2
+ :alt: reStructuredText, the markup syntax
+ :align: left
+ :width: 40 px
+ :figwidth: 70 %
+
+ This is the caption.
+
+ This is the legend.
+
+ The legend may consist of several paragraphs.
+
+This paragraph might flow around the figure.
+
+The specific behavior depends upon the style sheet and the browser or
+rendering software used.
+
+A centered figure:
+
+.. figure:: ../../../docs/user/rst/images/biohazard.png
+ :align: center
+ :width: 40 px
+
+ This is the caption.
+
+ This is the legend.
+
+ The legend may consist of several paragraphs.
+
+This paragraph might flow around the figure.
+
+The specific behavior depends upon the style sheet and the browser or
+rendering software used.
+
+A right-aligned figure:
+
+.. figure:: ../../../docs/user/rst/images/biohazard.png
+ :align: right
+ :width: 40 px
+
+ This is the caption.
+
+ This is the legend.
+
+ The legend may consist of several paragraphs.
+
+This paragraph might flow around the figure. The specific behavior depends
+upon the style sheet and the browser or rendering software used.
+
+
+Tables may be given titles and additional arguments with the *table*
+directive:
+
+.. Table:: left-aligned table
+ :align: left
+
+ ===== =====
+ A not A
+ ===== =====
+ False True
+ True False
+ ===== =====
+
+.. Table:: center-aligned table
+ :align: center
+
+ ===== =====
+ A not A
+ ===== =====
+ False True
+ True False
+ ===== =====
+
+.. Table:: right-aligned table
+ :align: right
+
+ ===== =====
+ A not A
+ ===== =====
+ False True
+ True False
+ ===== =====
+
+With the "widths" argument "auto" (or "class" value "colwidths-auto"),
+column widths are determined by the backend (if supported by the
+writer/backend).
+
+.. _target1:
+.. _target2:
+
+.. table::
+ :widths: auto
+
+ ======= ======= ==========
+ A B A or B
+ ======= ======= ==========
+ False False False
+ True False True
+ False True True
+ True True True
+ ======= ======= ==========
+
+
+Admonitions
+```````````
+
+.. Attention:: Directives at large.
+
+.. Caution::
+
+ Don't take any wooden nickels.
+
+.. DANGER:: Mad scientist at work!
+
+.. Error:: Does not compute.
+
+.. Hint:: It's bigger than a bread box.
+
+.. Important::
+ - Wash behind your ears.
+ - Clean up your room.
+ - Call your mother.
+ - Back up your data.
+
+.. Note:: This is a note.
+
+.. Tip:: 15% if the service is good.
+
+.. WARNING:: Strong prose may provoke extreme mental exertion.
+ Reader discretion is strongly advised.
+
+.. admonition:: And, by the way...
+
+ You can make up your own admonition too.
+
+ .. _Docutils: http://docutils.sourceforge.net/
+
+Topics, Sidebars, and Rubrics
+`````````````````````````````
+
+*Sidebars* are like miniature, parallel documents.
+
+.. sidebar:: Sidebar Title
+ :subtitle: Optional Subtitle
+
+ This is a sidebar. It is for text outside the flow of the main
+ text.
+
+ .. rubric:: This is a rubric inside a sidebar
+
+ Sidebars often appear beside the main text with a border and a different
+ background or font color.
+
+A *topic* is like a block quote with a title, or a self-contained section
+with no subsections.
+
+.. topic:: Topic Title
+
+ This is a topic.
+
+A *rubric* is like an informal heading that doesn't correspond to the
+document's structure. It is typically highlighted in red (hence the name).
+
+.. rubric:: This is a rubric
+
+Topics and rubrics can be used at places where a `section title`_ is not
+allowed (e.g. inside a directive).
+
+Target Footnotes
+````````````````
+
+.. target-notes::
+
+
+Replacement Text
+````````````````
+
+I recommend you try |Python|_.
+
+.. |Python| replace:: Python, *the* best language around
+
+Compound Paragraph
+``````````````````
+
+The *compound* directive is used to create a "compound paragraph", which
+is a single logical paragraph containing multiple physical body
+elements. For example:
+
+.. compound::
+
+ The 'rm' command is very dangerous. If you are logged
+ in as root and enter ::
+
+ cd /
+ rm -rf *
+
+ you will erase the entire contents of your file system.
+
+Test the handling and display of compound paragraphs:
+
+.. compound::
+ :class: some-class
+
+ Compound 2, paragraph 1,
+
+ compound 2, paragraph 2,
+
+ * list item 1,
+ * list item 2,
+
+ compound 2, paragraph 3.
+
+.. compound::
+
+ Compound 3, only consisting of one paragraph.
+
+.. compound::
+
+ ::
+
+ Compound 4.
+ This one starts with a literal block.
+
+ Compound 4, paragraph following the literal block.
+
+Now something *really* perverted -- a nested compound block. This is
+just to test that it works at all; the results don't have to be
+meaningful.
+
+.. compound::
+
+ Compound 5, block 1 (a paragraph).
+
+ .. compound::
+
+ Compound 6 is block 2 in compound 5.
+
+ Compound 6, another paragraph.
+
+ Compound 5, block 3 (a paragraph).
+
+.. compound::
+
+ Compound 7, tests the inclusion of various block-level
+ elements in one logical paragraph. First a table,
+
+ +--------------------+--------------------+--------------------+
+ | Left cell, first | Middle cell, | Right cell. |
+ | paragraph. | consisting of | |
+ | | exactly one | Paragraph 2. |
+ | Left cell, second | paragraph. | |
+ | paragraph. | | Paragraph 3. |
+ +--------------------+--------------------+--------------------+
+
+ followed by a paragraph. This physical paragraph is
+ actually a continuation of the paragraph before the table. It is followed
+ by
+
+ a quote and
+
+ #. an enumerated list,
+
+ a paragraph,
+
+ --an option list,
+
+ a paragraph,
+
+ :a field: list,
+
+ a paragraph,
+
+ a definition
+ list,
+
+ a paragraph, an image:
+
+ .. image:: ../../../docs/user/rst/images/biohazard.png
+
+ a paragraph,
+
+ | a line
+ | block,
+
+ a paragraph followed by a comment,
+
+ .. this is a comment
+
+ a paragraph, a
+
+ .. note:: with content
+
+ and the final paragraph of the compound 7.
+
+Parsed Literal Blocks
+`````````````````````
+
+.. parsed-literal::
+
+ This is a parsed literal block.
+ This line is indented. The next line is blank.
+
+ Inline markup is supported, e.g. *emphasis*, **strong**, ``literal
+ text``, :sub:`sub-` and :sup:`super`\ scripts,
+ inline formulas: :math:`A = 2 \pi r^2`,
+ footnotes [1]_, _`hyperlink targets`, and `references
+ <http://www.python.org/>`_.
+
+Code
+````
+
+Blocks of source code can be set with the `code` directive. If the code
+language is specified, the content is parsed and tagged by the Pygments_
+syntax highlighter and can be formatted with a style sheet. (Code parsing
+is turned off using the ``syntax-highlight`` config setting in the test
+conversions in order to get identical results with/without installed
+Pygments highlighter.)
+
+.. code:: python
+
+ print 'This is Python code.'
+
+The ``:number-lines:`` option (with optional start value) generates line
+numbers:
+
+.. code:: python
+ :number-lines: 8
+
+ # print integers from 0 to 9:
+ for i in range(10):
+ print i
+
+For inline code snippets, there is the `code` role, which can be used
+directly (the code will not be parsed/tagged, as the language is not known)
+or as base for special code roles, e.g. the LaTeX code in the next
+paragraph.
+
+.. role:: tex(code)
+ :language: tex
+
+Docutils uses LaTeX syntax for math directives and roles:
+:tex:`\alpha = f(x)` prints :math:`\alpha = f(x)`.
+
+The ``:code:`` option of the `include` directive sets the included content
+as a code block, here the rst file ``header_footer.txt`` with line numbers:
+
+.. include:: header_footer.txt
+ :code: rst
+ :number-lines:
+
+.. _Pygments: http://pygments.org/
+
+Substitution Definitions
+------------------------
+
+An inline image (|example|) example:
+
+.. |EXAMPLE| image:: ../../../docs/user/rst/images/biohazard.png
+
+A Unicode example:
+
+.. |heart| unicode:: 0x2665
+ :trim:
+
+(Substitution definitions are not visible in the HTML source.)
+
+Comments
+--------
+
+Here's one:
+
+.. Comments begin with two dots and a space. Anything may
+ follow, except for the syntax of footnotes, hyperlink
+ targets, directives, or substitution definitions.
+
+ Double-dashes -- "--" -- must be escaped somehow in HTML output.
+
+ Comments may contain non-ASCII characters: ä ö ü æ ø å
+
+(View the HTML source to see the comment.)
+
+Raw text
+--------
+
+This does not necessarily look nice, because there may be missing white space.
+
+It's just there to freeze the behavior.
+
+.. raw:: html latex
+
+ A test.
+
+.. raw:: html latex
+
+ Second test.
+
+.. class:: myclass
+
+.. raw:: html latex
+
+ Another test with myclass set.
+
+.. role:: raw-role(raw)
+ :format: html latex
+ :class: myrawroleclass
+
+This is the :raw-role:`fourth test` with myrawroleclass set.
+
+.. raw:: html
+
+ Fifth test in HTML.<br />Line two.
+
+.. raw:: latex
+
+ Fifth test in LaTeX.\\Line two.
+
+Container
+---------
+
+.. container:: custom
+
+ paragraph 1
+
+ paragraph 2
--- /dev/null
+SVG Images
+----------
+
+.. image:: ../../../docs/user/rst/images/biohazard.svg
+ :width: 48 px
+ :height: 48 px
+ :align: left
+
+Scalable vector graphics (SVG) images are the only standards-compliable way
+to include vector graphics in HTML documents. However, they are not
+supported by all backends/output formats. (E.g., LaTeX supports the
+PDF or Postscript formats for vector graphics instead.)
+
+Rendering behaviour varies, depending on
+
+a) The SVG image itself, e.g. fixed-size vs. scaling::
+
+ width="280" viewBox="0 0 280 27"
+ height="27" width="100%"
+ height="100%"
+
+b) The method used to put the image in the document.
+
+ For HTML, there are several alternatives including:
+
+ * using the HTML ``<img>`` tag (not for interactive/animated SVG),
+ * using the HTML ``<object>`` tag,
+ * including within SVG using the SVG ``<image>`` tag,
+ * embedd the SVG code within HTML (inlining).
+
+ The `html4css1` writer uses ``<object>`` tags, the `html5`
+ writer uses ``<img>`` tags.
+
+ .. cf. http://edutechwiki.unige.ch/en/Using_SVG_with_HTML5_tutorial
+
+c) The viewing agent.
+
+ All up-to-date HTML browsers support SVG, however not all do this fully
+ and in the same manner. Many older versions, especially IE < 9, have
+ deficiencies or require plug-ins (i.e. don't support the ``<img>`` tag).
+
+If the image is wrapped in ``<object>`` or ``<svg>`` tags, it depends on the
+``viewBox`` declaration inside the images root ``<svg>`` element whether an
+SVG image is scaled or clipped/padded. Images wrapped in ``<img>`` are
+always scaled.
+
+* .. image:: ../../../docs/user/rst/images/title-scaling.svg
+ :width: 50%
+ :align: right
+
+ A scaling image (scales with the browser window), occupying 50% of the line
+ width. The ``viewBox`` setting in the image file enables auto-scaling also in
+ ``<object>`` tags and embedded SVG (if width and hight are set to 100% in the
+ SVG <image> tag).
+
+
+* .. image:: ../../../docs/user/rst/images/title.svg
+ :width: 50%
+ :height: 15 px
+ :align: right
+
+ A fixed-size image in a box 50% wide and 15 pixles high. This image is
+ scaled, if wrapped in an ``<img>`` tag but clipped in an ``<object>`` tag
+ or within SVG.
+
+* .. image:: ../../../docs/user/rst/images/title-scaling.svg
+ :width: 50 %
+ :height: 1.5 em
+ :align: right
+
+ A right aligned, scaling image 50% wide and 1.5 em high. (This SVG image
+ keeps the aspect ratio.)
+
+* An inline image |inline-svg| scaled to a height of 0.8 em.
+
+ .. |inline-svg| image:: ../../../docs/user/rst/images/biohazard-scaling.svg
+ :height: 0.8 em
+
+* .. image:: ../../../docs/user/rst/images/biohazard-scaling.svg
+ :height: 1 em
+ :align: right
+
+ A scaling image 1 em high, right aligned:
+
+* A scaling image 5 mm x 5 mm, centered, with hyperlink reference:
+
+ .. image:: ../../../docs/user/rst/images/biohazard-scaling.svg
+ :target: `SVG Images`_
+ :width: 5 mm
+ :height: 5 mm
+ :align: center
+
+* .. image:: ../../../docs/user/rst/images/biohazard.svg
+ :width: 4 cm
+ :height: 2 em
+ :align: right
+
+ A fixed-size image in a 4 cm x 2 em box.
+
+Older versions of `webkit` based browsers (chromium, safari, midori,
+konqueror) support the ``<img>`` tag but don't display contained bitmap
+images in this case.
+
+* .. image:: ../../../docs/user/rst/images/biohazard-bitmap.svg
+ :width: 3em
+ :align: right
+
+ A small, fixed-size SVG image with embedded bitmap, The ``:width:`` is
+ set to 3 em in the rST source. Does not scale if wrapped in ``<object>``
+ tags.
+
+
+* .. image:: ../../../docs/user/rst/images/biohazard-bitmap-scaling.svg
+ :width: 3em
+ :align: right
+
+ A scaling SVG image with embedded bitmap, 3 em wide.
+
+SVG images can also be put in figures:
+
+ .. figure:: ../../../docs/user/rst/images/title.svg
+ :alt: reStructuredText, the markup syntax
+ :width: 290 px
+ :height: 28 px
+ :align: center
+
+ **Figure:** SVG image in a figure.
--- /dev/null
+SWF Images
+----------
+
+Shockwave Flash is an image/movie format that most modern web browsers
+support via a plugin. It is sometimes blocked due to privacy/security
+concerns.
+
+Images with extension ``.swf`` are placed inside <object> elements.
+For complete control over display options use raw HTML.
+
+.. image:: ../../../docs/user/rst/images/biohazard.swf
+ :alt: [biohazard.swf]
+ :width: 4 cm
+ :height: 2 em
+ :align: left
+
+An SWF image in a 4 cm x 2 em box, left aligned.
+
+.. |inline-swf| image:: ../../../docs/user/rst/images/biohazard.swf
+ :width: 0.8 em
+ :height: 0.8 em
+
+An inline SWF image |inline-swf| scaled to 0.8 em x 0.8 em.
--- /dev/null
+Colspanning tables
+------------------
+
+This table has a cell spanning two columns:
+
+===== ===== ======
+ Inputs Output
+------------ ------
+ A B A or B
+===== ===== ======
+False False False
+True False True
+False True True
+True True True
+===== ===== ======
--- /dev/null
+Complex tables
+--------------
+
+Here's a complex table, which should test all features.
+
++------------------------+------------+----------+----------+
+| Header row, column 1 | Header 2 | Header 3 | Header 4 |
+| (header rows optional) | | | |
++========================+============+==========+==========+
+| body row 1, column 1 | column 2 | column 3 | column 4 |
++------------------------+------------+----------+----------+
+| body row 2 | Cells may span columns. |
++------------------------+------------+---------------------+
+| body row 3 | Cells may | - Table cells |
++------------------------+ span rows. | - contain |
+| body row 4 | | - body elements. |
+| | Paragraph. | |
++------------------------+------------+----------+----------+
+| body row 5 | Cells may also be | |
+| | empty: ``-->`` | |
++------------------------+-----------------------+----------+
--- /dev/null
+Rowspanning tables
+------------------
+
+Here's a table with cells spanning several rows:
+
++------------------------+------------+------------------+
+| Header row, column 1 | Header 2 | Header 3 |
+| (header rows optional) | | |
++========================+============+==================+
+| body row 1, column 1 | column 2 | column 3 |
++------------------------+------------+------------------+
+| body row 2 | Cells may | Another |
++------------------------+ span rows. | rowspanning |
+| body row 3 | | cell. |
++------------------------+------------+------------------+
--- /dev/null
+More Tables
+-----------
+
+A table with multi-paragraph multicolumn cells:
+
++----------+--------------+---------------------------------+-----------+
+| test | **bold hd** | multicolumn 1 | *emph hd* |
+| | | | |
+| | | With a second paragraph | |
++----------+--------------+--------------+--------+---------+-----------+
+| multicolumn 2 | cell | cell | cell | cell |
+| | | | | |
+| With a second paragraph | | | | |
++----------+--------------+--------------+--------+---------+-----------+
+| cell | multicolumn 3 (one line, | cell | cell | cell |
+| | but very very very very | | | |
+| | very looooong) | | | |
++----------+--------------+--------------+--------+---------+-----------+
+| cell | cell | cell | Short multicolumn 4 |
++----------+--------------+--------------+------------------------------+
+
+Tables with multi-paragraph multirow cells currently fail due to a LaTeX
+limitation (see https://sourceforge.net/p/docutils/bugs/225/).
+
+A table with multirow header and column-widths set by LaTeX:
+
+.. table::
+ :widths: auto
+
+ +------------+-------------------+
+ | XXX | Variable Summary |
+ | +-------------------+
+ | | Description |
+ +============+===================+
+ | multicollumn cell |
+ +--------------------------------+
+
+In a table with column-widths set by LaTeX, each cell has just one line.
+Paragraphs are merged (a warning is given).
+
+.. table::
+ :widths: auto
+
+ +------------+-------------------+
+ | 11 | first paragraph |
+ | | |
+ | | second paragraph |
+ | | |
+ | | third paragraph |
+ +------------+-------------------+
+ | 21 | 22 |
+ +------------+-------------------+
--- /dev/null
+Non-ASCII characters
+--------------------
+
+Punctuation and footnote symbols
+
+= ===================================
+– en-dash
+— em-dash
+‘ single turned comma quotation mark
+’ single comma quotation mark
+‚ low single comma quotation mark
+“ double turned comma quotation mark
+” double comma quotation mark
+„ low double comma quotation mark
+† dagger
+‡ double dagger
+♦ black diamond suit
+♥ black heart suit
+♠ black spade suit
+♣ black club suit
+… ellipsis
+™ trade mark sign
+⇔ left-right double arrow
+= ===================================
+
+
+The `Latin-1 extended` Unicode block
+
+=== = = = = = = = = = =
+ .. 0 1 2 3 4 5 6 7 8 9
+--- - - - - - - - - - -
+160 ¡ ¢ £ ¥ ¦ § ¨ ©
+170 ª « ¬ ® ¯ ° ± ² ³
+180 ´ µ ¶ · ¸ ¹ º » ¼ ½
+190 ¾ ¿ À Á Â Ã Ä Å Æ Ç
+200 È É Ê Ë Ì Í Î Ï Ð Ñ
+210 Ò Ó Ô Õ Ö × Ø Ù Ú Û
+220 Ü Ý Þ ß à á â ã ä å
+230 æ ç è é ê ë ì í î ï
+240 ð ñ ò ó ô õ ö ÷ ø ù
+250 ú û ü ý þ ÿ
+=== = = = = = = = = = =
+
+* The following line should not be wrapped, because it uses
+ no-break spaces (\\u00a0):
+
+ X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X
+
+* Line wrapping with/without breakpoints marked by soft hyphens
+ (\\u00ad):
+
+ pdnderdmdtdrischpdnderdmdtdrischpdnderdmdtdrischpdnderdmdtdrischpdnderdmdtdrisch
+
+ pdnderdmdtdrischpdnderdmdtdrischpdnderdmdtdrischpdnderdmdtdrischpdnderdmdtdrisch
--- /dev/null
+External references
+-------------------
+
+Long URLs should be wrapped in the PDF. This can be achieved with the
+``\url`` command which is used by the LaTeX writer whenever the content
+(name) of a reference node equals the link URL.
+
+Example:
+ a long URL that should wrap in the output
+ http://docutils.sourceforge.net/docs/user/latex.html#id79
+
+
+If the argument contains any "%", "#", or "^^", or ends with ``\``, it can't
+be used in the argument to another command. The argument must not contain
+unbalanced braces.
+
+The characters ^, {, }, and ``\`` are invalid in a "http:" or "ftp:" URL
+and not recognized as part of it:
+
+| http://www.example.org/strange^^name
+| http://www.example.org\\using\\DOS\\paths\\
+| http://www.example.org/XML/strange{n}ame
+
+They can, however be used in paths and/or filenames.
+
+Handling by the LaTeX writer:
+
+* ``#``, ``\`` and ``%`` are escaped:
+
+ | `URL with # <http://www.w3.org/XML/Schema#dev>`__
+ http://www.w3.org/XML/Schema#dev
+ | `URL with % <http://www.w3.org/XML/Schema%dev>`__
+ http://example.org/Schema%dev
+ | `file with DOS path`__ `A:DOS\\path\\`__
+
+ .. note:: These URLs are typeset inside a LaTeX command without error.
+
+ | http://www.w3.org/XML/Schema#dev
+ | http://example.org/Schema%dev
+ | `A:DOS\\path\\`__
+
+__
+__
+__ A:DOS\\path\\
+
+
+* ``^^`` LaTeX's special syntax for characters results in "strange" replacements
+ (both with ``\href`` and ``\url``). A warning is given.
+
+ `file with ^^ <../strange^^name>`__:
+ `<../strange^^name>`__
+
+* Unbalanced braces, { or }, will fail (both with ``\href`` and ``\url``)::
+
+ `file with { <../strange{name>`__
+ `<../strange{name>`__
+
+ while balanced braces are suported:
+
+ | `<../strange{n}ame>`__
+ | `<../st{r}ange{n}ame>`__
+ | `<../{st{r}ange{n}ame}>`__
--- /dev/null
+:short: This field's name is short.
+:medium-length: This field's name is medium-length.
+:long field name: This field's name is long.
+:very very long field name:
+ This field's name is quite long.
--- /dev/null
+Test footnote and citation rendering
+************************************
+
+Paragraphs may contain footnote references (manually numbered
+[1]_, anonymous auto-numbered [#]_, labeled auto-numbered [#label]_, or
+symbolic [*]_) or citation references ([CIT2002]_, [DU2015]_).
+
+.. include:: data/standard.txt
+ :start-after: Footnotes
+ ---------
+ :end-before: Here's a reference to the above, [CIT2002]_,
+
+.. [DU2015] `Example document`, Hometown: 2015.
+
+Here's a reference to the above, [CIT2002]_.
+
+.. [5] this footnote is missing in the standard example document.
--- /dev/null
+Text-level semantics
+--------------------
+
+`HTML 5 tags for representation of text-level semantics`__ and their
+reStructuredText equivalents.
+
+__ https://html.spec.whatwg.org/#text-level-semantics
+
+.. class:: narrow
+
+:a:
+ Hyperlinks
+
+ Visit my `drinks <example.org:drinks.html>`_ page.
+
+:em:
+ Stress emphasis
+
+ I must say I *adore* lemonade. I's :emphasis:`sooo` sweet.
+
+:strong:
+ Importance
+
+ **Warning**: This tea is :strong:`very hot`.
+
+:small:
+ Side comments
+
+ .. role:: small
+
+ These grapes are made into wine.
+ :small:`Alcohol is addictive.`
+
+:s:
+ Inaccurate text
+
+ .. role:: strikeout
+ :class: s
+
+ Price: :strikeout:`£4.50` £2.00!
+
+:cite:
+ Titles of works
+
+ The case `Hugo v. Danielle` is relevant here.
+ I recommend reading :title:`Harry Potter`.
+
+:q:
+ Quotations
+
+ .. role:: quotation
+ :class: q
+
+ The judge said :quotation:`You can drink water from the fish tank`
+ but advised against it.
+
+:dfn:
+ Defining instance
+
+ .. role:: dfn
+
+ The term :dfn:`organic food` refers to food produced without synthetic
+ chemicals.
+
+:abbr:
+ Abbreviations [#attribute-optional]_
+
+ Organic food in Ireland is certified by the :acronym:`IOFGA` [*]_
+
+ In rST there are separate roles for `abbreviations` :abbreviation:`rsp.`
+ `acronymes`. In HTML, the <acronym> tag is obsolete and authors are
+ advised to use <abbr> instead. The HTML5 writer uses <abbr> for Docutil's
+ <abbreviation> element.
+
+ .. [*] Irish Organic Farmers and Growers Association
+
+:ruby, rt, rp: Ruby annotations
+
+ Require inline nesting, currently not supported in rST.
+
+ <ruby> OJ <rp>(</rp><rt>Orange Juice</rt><rp>)</rp></ruby>
+
+:data:
+ Machine-readable equivalent [#attribute-required]_
+
+ Available starting today! <data value="UPC:022014640201">North Coast
+ Organic Apple Cider</data>
+
+
+:time:
+ Machine-readable equivalent of date- or time-related data [#attribute-required]_
+
+ Available starting on <time datetime="2011-11-18">November 18th</time>!
+
+:code:
+ Computer code
+
+ The :code:`fruitdb` program can be used for tracking fruit production.
+
+:var:
+ Variables
+
+ .. role:: var
+
+ If there are :var:`n` fruit in the bowl, at least :var:`n`\ ÷2 will be
+ ripe.
+
+:samp:
+ Computer output
+
+ .. role:: samp(literal)
+
+ The computer said :samp:`Unknown error -3`.
+
+:kbd:
+ User input
+
+ .. role:: kbd
+
+ Hit :kbd:`F1` to continue.
+
+:sub:
+ Subscripts
+
+ Water is H\ :sub:`2`\O.
+
+:sup:
+ Superscripts
+
+ The Hydrogen in heavy water is usually :sup:`2`\H.
+
+:i:
+ Alternative voice
+
+ .. role:: alternative-voice
+ :class: i, language-la
+
+ Lemonade consists primarily of :alternative-voice:`Citrus limon`.
+
+:b:
+ Keywords
+
+ .. role:: b
+
+ Take a :b:`lemon` and squeeze it with a :b:`juicer`.
+
+:u:
+ Annotations
+
+ .. role:: spelling
+ :class: u, spelling
+
+ The mixture of apple juice and :spelling:`eldeflower` juice is very
+ pleasant.
+
+:mark:
+ Highlight
+
+ .. role:: mark
+
+ Elderflower cordial, with one :mark:`part` cordial to ten
+ :mark:`part`\ s water, stands a\ :mark:`part` from the rest.
+
+:bdi:
+ Text directionality isolation [#attribute-optional]_
+
+ .. role:: bdi
+
+ The recommended restaurant is :bdi:`My Juice Café (At The Beach)`.
+
+ The `dir` global attribute defaults to "auto" (not "inherit") on this
+ element.
+
+:bdo:
+ Text directionality formatting [#attribute-required]_
+
+ The proposal is to write English, but in reverse order. "Juice" would
+ become "<bdo dir=rtl>Juice</bdo>">
+
+ Authors must specify the dir attribute on this element.
+
+:span:
+ Other
+
+ .. role:: language-fr
+
+ In French we call it :language-fr:`sirop de sureau`.
+
+:br:
+ Line break
+
+ For complete paragraphs, use a line-block:
+
+ | Simply Orange Juice Company
+ | Apopka, FL 32703
+ | U.S.A.
+
+ rST does not natively support an exceptional hard line break in a floating
+ paragraph. You may use a HTML-only substitution.
+
+ .. |br| raw:: html
+
+ <br />
+
+ I want to break this line after the colon: |br| but allow other
+ linebreaks in this paragraph according to the width of the containing
+ block.
+
+:wbr:
+ Line breaking opportunity
+
+ Not supported by rST. You may use a ZWSP character (u200B), literal or via
+ a substitution.
+
+ .. |wbr| unicode:: 0x200B
+
+ www.simply\ |wbr|\orange\ |wbr|\juice.com
+
+Indicating Edits
+----------------
+
+`HTML tags for representation of edits to the document`__ and their
+reStructuredText equivalents.
+
+__ https://html.spec.whatwg.org/multipage/edits.html
+
+:ins:
+ Additions [#attribute-optional]_
+
+ .. role:: ins
+
+ This text has "always" been here. :ins:`This text has been inserted.`
+
+ .. container:: ins
+
+ This paragraph has been inserted.
+
+
+:del:
+ Removed content [#attribute-optional]_
+
+ .. role:: del
+
+ :del:`This text has been deleted`, here is the rest of the paragraph.
+
+ .. container:: del
+
+ This paragraph has been deleted.
+
+
+.. [#attribute-optional] Would gain from support for attributes/arguments
+ to inline roles. See TODO_
+
+.. [#attribute-required] Requires support for attributes to inline
+ roles to make sense.
+
+
+.. _TODO: http://docutils.sourceforge.net/docs/dev/todo.html#interpreted-text
--- /dev/null
+The babel_ package introduces the concept of "shorthands": additional
+characters that introduce a latex macro. Most common is the active double
+quote ("). Problematic is the tilde character (~) which is regularely used
+for no-break spaces but redefined by some language definition files:
+
+English: 'an' "active"-quote, ^circumflex, and no-break spaces
+
+.. class:: language-eu
+
+Basque: 'an' "active"-quote, ^circumflex, and no-break spaces
+
+.. class:: language-eo
+
+Esperanto: 'an' "active"-quote, ^circumflex, and no-break spaces
+
+.. class:: language-et
+
+Estonian: 'an' "active"-quote, ^circumflex, and no-break spaces
+
+.. class:: language-gl
+
+Galician: 'an' "active"-quote, ^circumflex, and no-break spaces
+
+.. class:: language-de
+
+German: 'an' "active"-quote, ^circumflex, and no-break spaces
+
+Spanish: option clash with Galician!
+
+..
+ .. class:: language-es
+
+ Spanish: 'an' "active"-quote, ^circumflex, and no-break spaces
+
+
+.. _babel: http://www.ctan.org/packages/babel
--- /dev/null
+Some Tests for the LaTeX Writer
+===============================
+
+These tests contain unusual combinations of syntax elements which may cause
+trouble for the LaTeX writer but do not need to be tested with other writers.
+
+Block Quotes
+------------
+
+ This block quote comes directly after the section heading and is
+ followed by a paragraph.
+
+ This is the second paragraph of the block quote and it contains
+ some more text filling up some space which would otherwise be
+ empty.
+
+ -- Attribution
+
+This is a paragraph.
+
+ This block quote does not have an attribution.
+
+This is another paragraph.
+
+ Another block quote at the end of the section.
+
+
+More Block Quotes
+-----------------
+
+ Block quote followed by a transition.
+
+----------
+
+ Another block quote.
+
+
+Images
+------
+
+Image with 20% width:
+
+.. image:: ../../../docs/user/rst/images/title.png
+ :width: 20%
+
+Image with 100% width:
+
+.. image:: ../../../docs/user/rst/images/title.png
+ :width: 100%
+
+
+Rowspanning tables
+------------------
+
+Several rowspanning cells in a table.
+
+Problem:
+
+In LaTeX, "overwritten" cells need to be defined as empty cells.
+
+Docutils (similarily to HTML) uses is the "Exchange Table Model" (also known
+as CALS tables, see docs/ref/soextblx.dtd) which defines only the remaining
+cells in a row "affected" by multirow cells.
+
+Therefore, visit_entry() is only called for the remaining cells and the
+LaTeX writer needs bookkeeping to write out the required number of extra
+'&'s.
+
++-----+----------+----------+------+
+| 11 | 12 | 13 | 14 |
++-----+----------+----------+------+
+| 21 | 2/3 2 | | 24 |
++-----+ | +------+
+| 31 | | 2…4 3 | 34 |
++-----+----------+ +------+
+| 41 | 42 | | 14 |
++-----+----------+----------+------+
+
++-------+-------+----+
+| 11 | 12 | 13 |
++-------+-------+----+
+| 2/3 1 | | 23 |
+| | +----+
+| | 2/3 2 | 33 |
++-------+-------+----+
+
++-------+----+
+| 11 | 12 |
++-------+----+
+| 2/3 1 | 22 |
+| +----+
+| | 32 |
++-------+----+
+
++----+--------+----+
+| 11 | 12 | 13 |
++----+--------+----+
+| 21 | 2/3 2 | 23 |
++----+ +----+
+| 31 | | 33 |
++----+--------+----+
+
++----+--------+
+| 11 | 12 |
++----+--------+
+| 21 | 2/3 1 |
++----+ |
+| 31 | |
++----+--------+
+
+
++----+--------+
+| 11 | 1/2 1 |
++----+ |
+| 21 | |
++----+--------+
+| 31 | 32 |
++----+--------+
+
++----+------------+--------+
+| 11 | 1/2 2 | |
++----+ | 1/2 3 |
+| 21 | | |
++----+------------+--------+
+
++-------+----+--------+
+| | 12 | 1/2 3 |
+| 1/2 3 +----+ |
+| | 22 | |
++-------+----+--------+
+
++-------+----+
+| | 12 |
+| 1/2 3 +----+
+| | 22 |
++-------+----+
+| 31 | 32 |
++-------+----+
--- /dev/null
+:Author: Foo Fred
+:Organization: Food Foomatics & Friends
+:Contact: foo@food.example.info
+:Address: Fox St 13
+ Foowood
+:Author: Bar Barney
+:Organization: Bar-BQ Bar
+:Contact: 1-800-BARBQBAR
+:Address: Barbara St 16
+ South Barwell
--- /dev/null
+In LaTeX, literal blocks can be customized with the "literal-block-env"
+setting. This test file exists to check if the LaTeX writer output compiles
+and looks as expected.
+
+Start with a plain literal block::
+
+ $\sin^2(x)$ and $\cos^2(x)$ equals one:
+
+ \[
+ \sin^2(x) + \cos^2(x) = 1 % for all x
+ \]
+
+A latex "code-block" (set with "literal-block-env", if syntax
+highlight is "none"):
+
+.. code:: latex
+
+ $\sin^2(x)$ and $\cos^2(x)$ equals one:
+
+ \[
+ \sin^2(x) + \cos^2(x) = 1 % for all x
+ \]
+
+A literal block in a table:
+
+==== =========== ====
+test :: test
+
+ \sin^2 x
+==== =========== ====
+
+A literal block in a table with auto-width columns:
+
+.. table::
+ :widths: auto
+
+ ==== =========== ====
+ test :: test
+
+ \sin^2 x
+ ==== =========== ====
+
+.. note:: A literal block in an admonition::
+
+ \sin^2 x
+
+.. role:: custom
+.. role:: custom-role
+
+Parsed literal block with inline markup and leading whitespace:
+
+.. parsed-literal::
+
+ *emphasis*, **strong emphasis**, ``inline literals``,
+ standalone hyperlinks (http://www.python.org),
+ internal_ and external_ hyperlinks,
+ _`internal` hyperlink targets,
+ images via substitution references (|example|),
+ footnote references [*]_,
+ citation references ([CIT2002]_), and more.
+
+ Here are some explicit interpreted text roles:
+ a PEP reference (:PEP:`287`),
+ an RFC reference (:RFC:`2822`),
+ an abbreviation (:ab:`abb.`), an acronym (:ac:`reST`),
+ code (:code:`print "hello world"`),
+ maths :math:`\sin^2(x)`,
+ :sub:`subscript` and :sup:`superscript`,
+ :custom:`custom` :custom-role:`roles`, and explicit roles for
+ :title:`Docutils`' :emphasis:`standard` :strong:`inline` :literal:`markup`.
+
+.. [*] This footnote is referenced in a `parsed literal` block.
+
+ It contains a literal block::
+
+ \sin^2 x
+
+.. [CIT2002] Sample Citation, 2017.
+
+.. _external: http://www.python.org/
+
+.. |EXAMPLE| image:: ../../../docs/user/rst/images/biohazard.png
--- /dev/null
+Test the interaction of transforms.references.Substitutions and
+transforms.references.ExternalLinks.
+
+|rest| is cool!
+
+.. |rest| replace:: reStructuredText_
+
+.. _reStructuredText: http://docutils.sourceforge.net/rst.html
+
+There is a preferred alternative:
+
+|rst|_ is cool!
+
+.. |rst| replace:: reStructuredText
+.. _rst: http://docutils.sourceforge.net/rst.html
+
+This only works for the case where the entire substitution is a
+reference, not when the reference is embedded as part of the
+substitution:
+
+|urst| is uncool!
+
+.. |urst| replace:: unstructured reStructuredText_
--- /dev/null
+=====
+Test
+=====
+
+Basic # 1
+==========
+
+A *simple* test.
+
--- /dev/null
+Definition Lists
+----------------
+
+Term
+ Definition
+Term : classifier
+ Definition paragraph 1.
+
+ Definition paragraph 2.
+Term
+ Definition
+
+
--- /dev/null
+=================
+Table of contents
+=================
+
+.. contents::
+
+In short
+========
+
+Regression to test table of contents construction
+
+End
+===
+
+this
--- /dev/null
+============================
+Custom Headers and Footers
+============================
+
+Test for custom headers and footers and for page numbers, date,
+time, etc.
+
+
+
--- /dev/null
+=========
+Footnotes
+=========
+
+manually numbered [1]_ and referenced twice [1]_ .
+
+.. [1] A footnote contains body elements, consistently indented by at
+ least 3 spaces.
+
--- /dev/null
+=================
+Header and Footer
+=================
+
+.. header:: head in the clouds
+
+.. footer:: feets getting wet
+
+... only *boldness* can deliver from fear. And if the risk is not taken, the
+meaning of life is somehow violated, and the whole future is condemned to
+hopeless staleness.
+
+ -- (Carl Jung, Symbols of Transformation)
--- /dev/null
+literal block ::
+
+ ~~~ ><> ~~ <>< ~~~
+
--- /dev/null
+.. role:: action
+ :class: action parenthetical direction
+
+Hello... `(beat)`:action: ...there!
--- /dev/null
+.. role:: action
+
+Hello... `(beat)`:action: ...there!
--- /dev/null
+========
+Test raw
+========
+
+Some cheese.
+
+.. raw:: odt
+
+ <text:p>what now ?</text:p>
+
+None in shop.
--- /dev/null
+================================================================================
+Grid test
+================================================================================
+
+Test 1
+=======
+
++------------------------+------------+----------+----------+
+| Header row, column 1 | Header 2 | Header 3 | Header 4 |
+| (header rows optional) | | | |
++========================+============+==========+==========+
+| body row 1, column 1 | column 2 | column 3 | column 4 |
++------------------------+------------+----------+----------+
+| body row 2 | Cells may span columns. |
++------------------------+------------+---------------------+
+| body row 3 | Cells may | - Table cells |
++------------------------+ span rows. + - contain +
+| body row 4 | aaa | - body elements. |
++------------------------+------------+---------------------+
+
+Test 2
+=======
+
++------------------------+------------+----------+----------+
+| Header row, column 1 | Header 2 | Header 3 | Header 4 |
+| (header rows optional) | | | |
++========================+============+==========+==========+
+| body row 1, column 1 | column 2 | column 3 | column 4 |
++ +------------+----------+----------+
+| body row 2 | column 2 | column 3 | column 4 |
++------------------------+ +----------+----------+
+| body row 3 | may span | - Table cells |
++------------------------+------------+ - contain +
+| body row 4 | column 2 | - body elements. |
++------------------------+------------+---------------------+
+
+
+Test 3
+=======
+
++------------------------+------------+----------+----------+
+| Header row, column 1 | Header 2 | Header 3 | Header 4 |
+| (header rows optional) | | | |
++========================+============+==========+==========+
+| body row 1, column 1 | column 2 | column 3 | column 4 |
++ +------------+----------+ +
+| body row 2 | column 2 | column 3 | may span |
++------------------------+------------+ +----------+
+| body row 3 | column 2 | may span | column 4 |
++------------------------+ +----------+----------+
+| body row 4 | may span | column 3 | column 4 |
++------------------------+------------+----------+----------+
+
+
+Test 4
+=======
+
++------------------------+------------+----------+----------+
+| Header row, column 1 | Header 2 | Header 3 | Header 4 |
+| (header rows optional) | | | |
++========================+============+==========+==========+
+| body row 1, column 1 | column 2 | column 3 | column 4 |
++ +------------+----------+ +
+| body row 2 | column 2 and column 3 | may span |
++------------------------+ +----------+
+| body row 3 | may span | column 4 |
++ +------------+----------+----------+
+| may span | may span | column 3 | column 4 |
++------------------------+------------+----------+----------+
+
+Test 4a
+=======
+
++------------------------+------------+----------+----------+
+| Header row, column 1 | Header 2 | Header 3 | Header 4 |
+| (header rows optional) | | | |
++========================+============+==========+==========+
+| body row 1, column 1 | column 2 | column 3 | column 4 |
++ +------------+----------+ +
+| body row 2 | column 2 and column 3 | may span |
++------------------------+ +----------+
+| body row 3 | may span | column 4 |
++ +------------+----------+----------+
+| may span | may span | column 3 | column 4 |
++------------------------+------------+----------+----------+
+| body row 4 | column 2 | column 3 | column 4 |
++------------------------+------------+----------+----------+
+
+
+
+
+
+
+
+
+Test 5
+=======
+
++------------------------+------------+----------+----------+
+| Header row, column 1 | Header 2 | Header 3 | Header 4 |
+| (header rows optional) | | | |
++========================+============+==========+==========+
+| body row 1, column 1 | column 2 | column 3 | column 4 |
++------------------------+------------+----------+----------+
+| body row 2 | Cells may span columns. |
++------------------------+------------+---------------------+
+| body row 3 | Cells may | - Table cells |
++------------------------+ span rows. | - contain |
+| body row 4 | | - body elements. |
++------------------------+------------+---------------------+
+
+
+Test 6
+=======
+
+Some care must be taken with grid tables to avoid undesired
+interactions with cell text in rare cases. For example, the
+following table contains a cell in row 2 spanning from column 2 to
+column 4:
+
++--------------+----------+-----------+-----------+
+| row 1, col 1 | column 2 | column 3 | column 4 |
++--------------+----------+-----------+-----------+
+| row 2 | |
++--------------+----------+-----------+-----------+
+| row 3 | | | |
++--------------+----------+-----------+-----------+
+
+Test 7
+=======
+
+If a vertical bar is used in the text of that cell, it could have
+unintended effects if accidentally aligned with column boundaries:
+
++--------------+----------+-----------+-----------+
+| row 1, col 1 | column 2 | column 3 | column 4 |
++--------------+----------+-----------+-----------+
+| row 2 | Use the command ``ls \| more``. |
++--------------+----------+-----------+-----------+
+| row 3 | | | |
++--------------+----------+-----------+-----------+
+
+Test 8
+=======
+
+Several solutions are possible. All that is needed is to break the
+continuity of the cell outline rectangle. One possibility is to
+shift the text by adding an extra space before:
+
+
++--------------+----------+-----------+-----------+
+| row 1, col 1 | column 2 | column 3 | column 4 |
++--------------+----------+-----------+-----------+
+| row 2 | Use the command ``ls | more``. |
++--------------+----------+-----------+-----------+
+| row 3 | | | |
++--------------+----------+-----------+-----------+
+
+Test 9
+=======
+
+Another possibility is to add an extra line to row 2:
+
++--------------+----------+-----------+-----------+
+| row 1, col 1 | column 2 | column 3 | column 4 |
++--------------+----------+-----------+-----------+
+| row 2 | Use the command ``ls | more``. |
+| | |
++--------------+----------+-----------+-----------+
+| row 3 | | | |
++--------------+----------+-----------+-----------+
--- /dev/null
+.. role:: action
+ :class: action
+
+Hello... `(beat)`:action: ...there!
--- /dev/null
+PEP: 100
+Title: Test PEP
+Version: 42
+Last-Modified: A long time ago.
+Author: John Doe <john@example.org>
+Discussions-To: <devnull@example.org>
+Status: Draft
+Type: Standards Track
+Content-Type: text/x-rst
+Created: 01-Jun-2001
+Post-History: 13-Jun-2001
+
+
+Abstract
+========
+
+This is just a test [#]_. See the `PEP repository`_ for the real
+thing.
+
+.. _PEP repository: http://www.python.org/peps/
+
+
+Copyright
+=========
+
+This document has been placed in the public domain.
+
+
+References and Footnotes
+========================
+
+.. [#] PEP editors: peps@python.org
--- /dev/null
+simple input
--- /dev/null
+.. include:: data/standard.txt
+.. include:: data/header_footer.txt
+.. include:: data/table_colspan.txt
+.. include:: data/table_rowspan.txt
+.. include:: data/table_complex.txt
+.. include:: data/list_table.txt
+.. include:: data/errors.txt
--- /dev/null
+.. include:: data/standard.txt
+.. include:: data/header_footer.txt
+.. include:: data/table_colspan.txt
+.. include:: data/table_rowspan.txt
+.. include:: data/table_complex.txt
+.. include:: data/list_table.txt
+.. include:: data/custom_roles.txt
+.. include:: data/svg_images.txt
+.. include:: data/swf_images.txt
+.. include:: data/errors.txt
+
+.. footer:: |valid-xhtml10| |valid-CSS2|
+
+.. |valid-xhtml10| image:: http://www.w3.org/Icons/valid-xhtml10
+ :height: 31
+ :width: 88
+ :alt: Valid XHTML 1.0!
+ :target: http://validator.w3.org/check?uri=referer
+
+.. |valid-CSS2| image:: http://jigsaw.w3.org/css-validator/images/vcss
+ :height: 31
+ :width: 88
+ :alt: Valid CSS 2.1!
+ :target: http://jigsaw.w3.org/css-validator/check/referer
--- /dev/null
+.. include:: data/standard.txt
+.. include:: data/header_footer.txt
+.. include:: data/table_colspan.txt
+.. include:: data/table_rowspan.txt
+.. include:: data/table_complex.txt
+.. include:: data/list_table.txt
+.. include:: data/custom_roles.txt
+
+HTML specific
+=============
+
+.. include:: data/svg_images.txt
+.. include:: data/swf_images.txt
+.. include:: html5-text-level-tags.txt
+
+Changes to the html4css1 writer
+===============================
+
+* Use only meta keywords recognized by HTML 5.
+
+* Set table column widths with <style="width: ...">, not "width" argument.
+
+* Horizontal alignment of table heads with CSS.
+
+* Field lists as styled definition lists.
+
+* Do not drop paragraph objects, use CSS rules to prevent unwanted vertical
+ space.
+
+* Put subtitles in <p> elements.
+
+Field list handling
+-------------------
+
+The following list demonstrates the problems with the html4css1
+approach: the `field-name-limit` setting is given in "number of
+characters" but the field name uses a proportional font.
+
+:The field name: is typeset on the same line, unless it is "long".
+
+:this field name: is considered "long" in the html table rendering by
+ the html4css1 writer with the default setting of
+ ``--field-name-limit=14``.
+
+:iiiiiiiiiiiiiii: a field name that is considered "long" by html4css1
+ with the default setting of `field-name-limit: 14`.
+
+:MMMMMMMMMMMMMM: a field name that is actually longer than the
+ previous one but regarded "short" by html4css1.
+
+With ``html_plain``, a `field list` is typeset as CSS-styled `definition
+list`. The default layout is similar to the look with `html4css1`:
+
+.. class:: open
+
+:A long field name: sticks into the field body.
+
+ The field body is pushed to the next line (you can suppress
+ this behaviour with the `run-in`_ class argument).
+
+:Customization: of the field name width is possible with CSS instead
+ of the `field-name-limit` configuration setting, for
+ example::
+
+ dl.field-list > dd { margin-left: 6em; }
+
+:Empty:
+
+:fields: must not lead to misalignment of the following content.
+
+Styling with class arguments
+----------------------------
+
+The ``plain.css`` style sheet comes with some pre-defined style variants
+that can be choosen via a class argument.
+
+Description lists
+`````````````````
+
+Definition lists with the "description" class argument:
+
+.. class:: description
+
+description lists
+ Definition lists that are styled like in most dictionaries,
+ encyclopedias etc. (as well as the LaTeX `description` environment).
+label
+ The term to be described. Put in boldface.
+content
+ Starts on the same line and has a hanging indent.
+
+Field list variants
+```````````````````
+
+For field lists, the "compact/open", "narrow" and "run-in" styles are defined
+in the style sheet ``plain.css``.
+
+*compact*
+ .. class:: compact
+
+ :Feature: No additional space between list items.
+
+ :Option: The ``--compact-field-lists`` command line option (and the
+ corresponding configuration setting) set the `compact`
+ class argument on all "simple" field lists, if not
+ overridden with `open`.
+
+ :Use: For lists with short field body.
+
+*open*
+ .. class:: open
+
+ :Feature: Additional space between list items also in "simple" lists.
+ (Overrides the ``--compact-field-lists`` command line
+ option and the corresponding configuration setting)
+
+ :Use: For "simple" lists that should keep the space between list items.
+
+*narrow*
+ .. class:: narrow
+
+ :Feature: Less indented field body.
+ :Use: For lists with short field names.
+ :A long field name:
+ sticks into the field body and the field body starts on a
+ new line (if not combined with `run-in`_).
+
+.. _`run-in`:
+
+*run-in*
+ .. class:: run-in
+
+ :Feature: Field body starts on the same line also after long field
+ names.
+
+ :A long field name: sticks into the field body which continues on
+ the same line.
+
+ :The next field name: and field body should align. Long text in the field
+ body is wrapped and aligns with other fields.
+
+Table variants
+``````````````
+
+The following styles can be applied to individual tables via a class
+argument or as document wide setting with the table-style_ configuration
+setting (or command line argument).
+
+* Numbered tables can be achieved with the "numbered" class option:
+
+ .. table:: truth values
+ :class: numbered
+
+ ======= ======= ==========
+ A B A or B
+ ======= ======= ==========
+ False False False
+ True False True
+ False True True
+ True True True
+ ======= ======= ==========
+
+ Currently, referencing to the table by number is not supported. This is a
+ common request and already on the `TODO list`.
+
+* A table with "booktabs" class value, is rendered similar to the style
+ from the booktabs_ LaTeX package.
+
+ .. _table-style:
+ http://docutils.sourceforge.net/docs/user/config.html#table-style
+ .. _booktabs:
+ http://tug.ctan.org/tex-archive/macros/latex/contrib/booktabs/booktabs.pdf
+
+"Booktabs" style table, numbered, centre-aligned, with auto-sized columns:
+
+ .. table:: I/O values
+ :class: booktabs numbered
+ :align: center
+ :widths: auto
+
+ ======= ======= ==========
+ Input Output
+ --------------- ----------
+ A B A or B
+ ======= ======= ==========
+ False False False
+ True False True
+ False True True
+ True True True
+ ======= ======= ==========
+
+.. include:: data/errors.txt
+
+.. footer:: |HTML 5| |validator| |valid-CSS2|
+
+.. |HTML 5| image:: http://www.w3.org/html/logo/badge/html5-badge-h-css3-semantics.png
+ :height: 31
+ :width: 88
+ :alt: Conforms to HTML 5
+ :target: http://www.w3.org/TR/html5/
+
+.. |validator| image:: https://www.w3.org/Icons/ValidatorSuite/vs-blue-190.png
+ :height: 31
+ :width: 88
+ :alt: Check validity!
+ :target: http://validator.w3.org/check?uri=referer
+
+.. |valid-CSS2| image:: http://jigsaw.w3.org/css-validator/images/vcss
+ :height: 31
+ :width: 88
+ :alt: Valid CSS 2.1!
+ :target: http://jigsaw.w3.org/css-validator/check/referer
--- /dev/null
+.. include:: data/standard.txt
+.. currently not implemented in LaTeX:
+ .. include:: data/header_footer.txt
+.. include:: data/table_colspan.txt
+.. include:: data/table_rowspan.txt
+.. include:: data/list_table.txt
+.. include:: data/custom_roles.txt
+.. include:: data/math.txt
+
+Tests for the LaTeX writer
+==========================
+
+Test syntax elements which may cause trouble for the LaTeX writer but might
+not need to be tested with other writers (e.g. the HTML writer).
+
+.. include:: data/custom_roles_latex.txt
+.. include:: data/classes_latex.txt
+.. include:: data/tables_latex.txt
+.. include:: data/option_lists.txt
+.. include:: data/nonalphanumeric.txt
+.. include:: data/unicode.txt
+.. include:: data/latex_encoding.txt
+.. include:: data/hyperlinking.txt
+.. include:: data/urls.txt
+.. include:: data/section_titles.txt
+.. unusual combinations (currently separately tested)
+ .. include:: data/latex_cornercases.txt
+
+.. Preface for System Messages:
+.. include:: data/errors.txt
--- /dev/null
+=========
+ rst2man
+=========
+
+---------------------------------------------
+generate unix manpages from reStructured text
+---------------------------------------------
+
+:Author: grubert@users.sourceforge.net
+:Date: 2006-10-22
+:Copyright: public domain
+:Version: 0.1
+:Manual section: 1
+:Manual group: text processing
+
+.. TODO: authors and author with name <email>
+
+SYNOPSIS
+========
+
+ rst2man.py inputfile outputfile
+
+DESCRIPTION
+===========
+
+rst2man transforms a reStructured text document into a unix man page.
+
+In theory any valid reStructured text document should be processable,
+in reality this is
+
+* a goal, that is not met yet
+* a goal that might never be met, because only few constructs are
+ used in man pages *and* because the common text file does not adhere
+ to man page requirements.
+
+ For example a unix man page belongs into a numbered section, 1 is
+ user commands, 8 contains administrator commands and the headlines
+ of all manpages are collected into a database, queryable with the
+ programm ``apropos``, therefore the headline should contain a short
+ text describing into which group this command belongs.
+
+ These informations are collected from title, subtitle and the
+ docinfo, see this document as an example.
+
+OPTIONS
+=======
+
+--config=<file> Read configuration settings from <file>, if it exists.
+--version, -V Show this program's version number and exit.
+--help, -h Show this help message and exit.
+
+And a lot more standard docutils options.
+
+FILES
+=====
+
+None yet.
+
+SEE ALSO
+========
+
+`docutils <http://docutils.sourceforge.net>`__
+`linux man page howto <http://tldp.org/HOWTO/Man-Page/>`__
+
+and ``man man`` also ``man 7 man``
+
+BUGS
+====
+
+1. Format options are included as they are required.
+2. bullet lists
+3. number lists
+4. math: The LaTeX source is shown, e.g. :math:`n! + \sin(x_n^2)`.
+
+
+Discussion is still open.
+
+
--- /dev/null
+.. include:: data/standard.txt
+.. include:: data/header_footer.txt
+.. include:: data/table_colspan.txt
+.. include:: data/table_rowspan.txt
+.. include:: data/table_complex.txt
+.. include:: data/list_table.txt
+.. include:: data/errors.txt
--- /dev/null
+.. include:: <s5defs.txt>
+
+=============
+ Slide Shows
+=============
+
+:Author: David Goodger
+:Date: 2005-11-28
+
+.. contents::
+ :class: handout
+
+.. class:: handout
+
+ This is a test. This is only a test. If this were a real slide
+ show, there would be a projector handy.
+
+Let's test the S5/HTML writer!
+
+.. class:: small
+
+* Use the arrow keys to navigate.
+
+* Click the "|mode|" button to switch between presentation &
+ handout/outline modes.
+
+.. container:: handout
+
+ In presentation mode, mouse over to the lower right-hand corner to
+ display the controls.
+
+.. |bullet| unicode:: U+02022
+.. |mode| unicode:: U+00D8 .. capital o with stroke
+.. footer:: Location |bullet| Date
+
+
+Introduction
+============
+
+.. class:: compact
+
+* reStructuredText
+
+ .. class:: handout
+
+ Uses normal reStructuredText as input.
+
+* One section per slide
+
+ .. class:: handout
+
+ Each first-level section is converted into a single slide.
+
+* (X)HTML output
+
+ .. class:: handout
+
+ Presentations can be viewed using any modern graphical web browser.
+ The browser must support CSS, JavaScript, and XHTML. S5 even works
+ with IE!
+
+* Themes
+
+ .. class:: handout
+
+ A variety of themes are available.
+
+* ``rst2s5.py``
+
+ .. class:: handout
+
+ The front-end tool to generate S5 slide shows.
+
+
+Features (1)
+============
+
+.. class:: left
+
+A flush-left paragraph
+
+.. class:: center
+
+A centered paragraph
+
+.. class:: right
+
+A flush-right paragraph
+
+Some colours: :black:`black` [black], :gray:`gray`, :silver:`silver`,
+:white:`white` [white], :maroon:`maroon`, :red:`red`,
+:magenta:`magenta`, :fuchsia:`fuchsia`, :pink:`pink`,
+:orange:`orange`, :yellow:`yellow`, :lime:`lime`, :green:`green`,
+:olive:`olive`, :teal:`teal`, :cyan:`cyan`, :aqua:`aqua`,
+:blue:`blue`, :navy:`navy`, :purple:`purple`
+
+Features (2)
+============
+
+`Some` `incremental` `text.`
+
+.. class:: incremental open
+
+ * :tiny:`tiny` (class & role name: "tiny", e.g. "``:tiny:`text```")
+ * :small:`small` ("small")
+ * normal (unstyled)
+ * :big:`big` ("big")
+ * :huge:`huge` ("huge")
+
+
+Checklist
+=========
+
+* The document title should be duplicated on each slide in the footer
+ (except for the first slide, ``slide0``, where the entire footer is
+ disabled).
+
+* The footer also contains a second line, "Location |bullet| Date"
+
+* There's no table of contents on the first slide, although it does
+ appear in the handout/outline.
+
+* Handout material is not displayed in presentation mode.
+
+* The theme directories should be created, and the theme files copied
+ over.
--- /dev/null
+.. include:: data/standard.txt
+.. currently not implemented in LaTeX:
+ .. include:: data/header_footer.txt
+.. include:: data/table_colspan.txt
+.. include:: data/table_rowspan.txt
+.. include:: data/list_table.txt
+.. include:: data/custom_roles.txt
+.. include:: data/math.txt
+
+Tests for the LaTeX writer
+==========================
+
+Test syntax elements which may cause trouble for the LaTeX writer but might
+not need to be tested with other writers (e.g. the HTML writer).
+
+.. include:: data/custom_roles_latex.txt
+.. include:: data/classes_latex.txt
+.. include:: data/tables_latex.txt
+.. include:: data/option_lists.txt
+.. include:: data/nonalphanumeric.txt
+.. include:: data/unicode.txt
+.. include:: data/latex_encoding.txt
+.. include:: data/hyperlinking.txt
+.. include:: data/urls.txt
+.. include:: data/section_titles.txt
+
+Tests for the XeTeX writer
+==========================
+
+With XeTeX, you can typeset text in any language/script supported by
+Unicode and the selected font, e.g. Azərbaycanca, Bân-lâm-gú, Башҡорт
+Беларуская, Български, Català, Чӑвашла, Česky, Ελληνικά, Español,
+Français, Føroyskt, Хальмг, Íslenska, עברית , Қазақша, Kurdî,
+Latviešu, Lietuvių, Македонски, Монгол, Nāhuatl, Português, Română,
+Русский, Slovenščina, Српски, Türkçe, Українська, Tiếng Việt, Volapük,
+Võro, ייִדיש , Žemaitėška.
+Currently, there is extended support for 28 languages in the
+polyglossia_ package.
+
+.. _polyglossia: http://ctan.org/pkg/polyglossia
+
+.. System Messages:
+.. include:: data/errors.txt
--- /dev/null
+This is the directory where the actual output is stored.
+
+This README.txt is just a placeholder to make CVS create the directory.
--- /dev/null
+<?xml version="1.0" encoding="utf-8" ?>
+<!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">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<meta name="generator" content="Docutils 0.16: http://docutils.sourceforge.net/" />
+<title>compact_lists.txt</title>
+<link rel="stylesheet" href="../input/data/html4css1.css" type="text/css" />
+</head>
+<body>
+<div class="document">
+
+
+<ul class="simple">
+<li>This is an ordinary simple bullet list.</li>
+<li>It should be made compact (<p> & </p> tags omitted).</li>
+</ul>
+<hr class="docutils" />
+<ul>
+<li><p class="first">This is a bullet list that is not simple.</p>
+<p>There are multiple paragraphs in some items.</p>
+</li>
+<li><p class="first">It should not be made compact.</p>
+</li>
+<li><p class="first">Even though some items may have only one paragraph.</p>
+</li>
+</ul>
+<hr class="docutils" />
+<ul class="open">
+<li><p class="first">This is a simple bullet list, but class="open" is set.</p>
+</li>
+<li><p class="first">It should not be made compact.</p>
+</li>
+</ul>
+<hr class="docutils" />
+<ul class="compact simple">
+<li>This is a bullet list that is not simple.<p>There are multiple paragraphs in some items.</p>
+</li>
+<li>However, the class="compact" setting will cause
+all first paragraph's <p> & </p> tags to be omitted.</li>
+<li>Items with multiple paragraphs will not appear changed.</li>
+<li>Items may have one paragraph, or multiple.<p>Items with multiple paragraphs will still be followed
+by vertical whitespace because of the later paragraphs.</p>
+</li>
+<li>The effect is interesting.</li>
+</ul>
+</div>
+</body>
+</html>
--- /dev/null
+\documentclass[a4paper,russian]{article}
+% generated by Docutils <http://docutils.sourceforge.net/>
+\usepackage{cmap} % fix search and cut-and-paste in Acrobat
+\usepackage{ifthen}
+\usepackage[T1,T2A]{fontenc}
+\usepackage[utf8]{inputenc}
+\usepackage[english,russian]{babel}
+\setcounter{secnumdepth}{0}
+
+%%% Custom LaTeX preamble
+% PDF Standard Fonts
+\usepackage{mathptmx} % Times
+\usepackage[scaled=.90]{helvet}
+\usepackage{courier}
+
+%%% User specified packages and stylesheets
+\usepackage{cmlgc}
+
+%%% Fallback definitions for Docutils-specific commands
+
+% titlereference role
+\providecommand*{\DUroletitlereference}[1]{\textsl{#1}}
+
+% hyperlinks:
+\ifthenelse{\isundefined{\hypersetup}}{
+ \usepackage[colorlinks=true,linkcolor=blue,urlcolor=blue,unicode=true]{hyperref}
+ \usepackage{bookmark}
+ \urlstyle{same} % normal text font (alternatives: tt, rm, sf)
+}{}
+
+%%% Body
+\begin{document}
+
+
+\section{Заголовок%
+ \label{section-1}%
+}
+
+первый пример: «Здравствуй, мир!»
+
+
+\section{Title%
+ \label{title}%
+}
+
+\foreignlanguage{english}{first example: “Hello world”.}
+
+
+\section{Notes%
+ \label{notes}%
+}
+
+\foreignlanguage{english}{This example tests rendering of Latin and Cyrillic characters by the LaTeX
+and XeTeX writers. Check the compiled PDF for garbage characters in text and
+bookmarks.}
+
+\foreignlanguage{english}{To work around a problem with Cyrillic in PDF-bookmarks in \DUroletitlereference{hyperref}
+versions older than v6.79g 2009/11/20, the test caller \texttt{latex\_cyrillic.py}
+sets \texttt{hyperref\_options} to \texttt{'unicode=true'} while \texttt{xetex\_cyrillic.py}
+sets it to \texttt{'unicode=false'}. The recommended option for current
+(2011-08-24) hyperref versions is \texttt{'pdfencoding=auto'}.}
+
+\end{document}
--- /dev/null
+<?xml version="1.0" encoding="utf-8" ?>
+<!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">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<meta name="generator" content="Docutils 0.16: http://docutils.sourceforge.net/" />
+<title>dangerous.txt</title>
+<link rel="stylesheet" href="../input/data/html4css1.css" type="text/css" />
+</head>
+<body>
+<div class="document">
+
+
+<p>Potentially dangerous features (security holes):</p>
+<div class="system-message">
+<p class="system-message-title">System Message: WARNING/2 (<tt class="docutils">functional/input/dangerous.txt</tt>, line 3)</p>
+<p>"include" directive disabled.</p>
+<pre class="literal-block">
+.. include:: /etc/passwd
+</pre>
+</div>
+<div class="system-message">
+<p class="system-message-title">System Message: WARNING/2 (<tt class="docutils">functional/input/dangerous.txt</tt>, line 4)</p>
+<p>"raw" directive disabled.</p>
+<pre class="literal-block">
+.. raw:: html
+ :file: /etc/passwd
+</pre>
+</div>
+<div class="system-message">
+<p class="system-message-title">System Message: WARNING/2 (<tt class="docutils">functional/input/dangerous.txt</tt>, line 6)</p>
+<p>"raw" directive disabled.</p>
+<pre class="literal-block">
+.. raw:: html
+ :url: file:///etc/passwd
+</pre>
+</div>
+<div class="system-message">
+<p class="system-message-title">System Message: WARNING/2 (<tt class="docutils">functional/input/dangerous.txt</tt>, line 8)</p>
+<p>"raw" directive disabled.</p>
+<pre class="literal-block">
+.. raw:: html
+
+ <script>
+ that does something really nasty
+ </script>
+</pre>
+</div>
+<div class="system-message">
+<p class="system-message-title">System Message: WARNING/2 (<tt class="docutils">functional/input/dangerous.txt</tt>, line 13)</p>
+<p>File and URL access deactivated; ignoring "csv-table" directive.</p>
+<pre class="literal-block">
+.. csv-table:: :file: /etc/passwd
+</pre>
+</div>
+<div class="system-message">
+<p class="system-message-title">System Message: WARNING/2 (<tt class="docutils">functional/input/dangerous.txt</tt>, line 14)</p>
+<p>File and URL access deactivated; ignoring "csv-table" directive.</p>
+<pre class="literal-block">
+.. csv-table:: :url: file:///etc/passwd
+</pre>
+</div>
+<div class="figure">
+<img alt="picture.png" src="picture.png" />
+</div>
+</div>
+</body>
+</html>
--- /dev/null
+<?xml version="1.0" encoding="utf-8" ?>
+<!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">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<meta name="generator" content="Docutils 0.16: http://docutils.sourceforge.net/" />
+<title>field_list.txt</title>
+<link rel="stylesheet" href="../input/data/html4css1.css" type="text/css" />
+</head>
+<body>
+<div class="document">
+
+
+<table class="docutils field-list" frame="void" rules="none">
+<col class="field-name" />
+<col class="field-body" />
+<tbody valign="top">
+<tr class="field"><th class="field-name">short:</th><td class="field-body">This field's name is short.</td>
+</tr>
+<tr class="field"><th class="field-name">medium-length:</th><td class="field-body">This field's name is medium-length.</td>
+</tr>
+<tr class="field"><th class="field-name">long field name:</th><td class="field-body">This field's name is long.</td>
+</tr>
+<tr class="field"><th class="field-name">very very long field name:</th><td class="field-body">This field's name is quite long.</td>
+</tr>
+</tbody>
+</table>
+</div>
+</body>
+</html>
--- /dev/null
+<!DOCTYPE html>
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+<meta charset="utf-8"/>
+<meta name="generator" content="Docutils 0.16: http://docutils.sourceforge.net/" />
+<title>Test footnote and citation rendering</title>
+<link rel="stylesheet" href="../input/data/minimal.css" type="text/css" />
+<link rel="stylesheet" href="../input/data/plain.css" type="text/css" />
+</head>
+<body>
+<div class="document" id="test-footnote-and-citation-rendering">
+<h1 class="title">Test footnote and citation rendering</h1>
+
+<p>Paragraphs may contain footnote references (manually numbered<a class="footnote-reference superscript" href="#footnote-1" id="footnote-reference-1">1</a>, anonymous auto-numbered<a class="footnote-reference superscript" href="#footnote-2" id="footnote-reference-2">3</a>, labeled auto-numbered<a class="footnote-reference superscript" href="#label" id="footnote-reference-3">2</a>, or
+symbolic<a class="footnote-reference superscript" href="#footnote-3" id="footnote-reference-4">*</a>) or citation references (<a class="citation-reference" href="#cit2002" id="citation-reference-1">[CIT2002]</a>, <a class="citation-reference" href="#du2015" id="citation-reference-2">[DU2015]</a>).</p>
+<dl class="footnote superscript">
+<dt class="label" id="footnote-1"><span class="superscript">1</span><span class="fn-backref">(<a href="#footnote-reference-1">1</a>,<a href="#footnote-reference-5">2</a>)</span></dt>
+<dd><p>A footnote contains body elements, consistently indented by at
+least 3 spaces.</p>
+<p>This is the footnote's second paragraph.</p>
+</dd>
+<dt class="label" id="label"><span class="superscript">2</span><span class="fn-backref">(<a href="#footnote-reference-3">1</a>,<a href="#footnote-reference-6">2</a>)</span></dt>
+<dd><p>Footnotes may be numbered, either manually (as in<a class="footnote-reference superscript" href="#footnote-1" id="footnote-reference-5">1</a>) or
+automatically using a "#"-prefixed label. This footnote has a
+label so it can be referred to from multiple places, both as a
+footnote reference (<a class="footnote-reference superscript" href="#label" id="footnote-reference-6">2</a>) and as a <a class="reference internal" href="#label">hyperlink reference</a>.</p>
+</dd>
+<dt class="label" id="footnote-2"><span class="superscript"><a class="fn-backref" href="#footnote-reference-2">3</a></span></dt>
+<dd><p>This footnote is numbered automatically and anonymously using a
+label of "#" only.</p>
+<p>This is the second paragraph.</p>
+<p>And this is the third paragraph.</p>
+</dd>
+<dt class="label" id="footnote-3"><span class="superscript"><a class="fn-backref" href="#footnote-reference-4">*</a></span></dt>
+<dd><p>Footnotes may also use symbols, specified with a "*" label.
+Here's a reference to the next footnote:<a class="footnote-reference superscript" href="#footnote-4" id="footnote-reference-7">†</a>.</p>
+</dd>
+<dt class="label" id="footnote-4"><span class="superscript"><a class="fn-backref" href="#footnote-reference-7">†</a></span></dt>
+<dd><p>This footnote shows the next symbol in the sequence.</p>
+</dd>
+<dt class="label" id="footnote-5"><span class="superscript">4</span></dt>
+<dd><p>Here's an unreferenced footnote, with a reference to a
+nonexistent footnote:<a class="footnote-reference superscript" href="#footnote-6" id="footnote-reference-8">5</a>.</p>
+</dd>
+</dl>
+<div class="section" id="citations">
+<h1>Citations</h1>
+<dl class="citation">
+<dt class="label" id="cit2002"><span class="brackets">CIT2002</span><span class="fn-backref">(<a href="#citation-reference-1">1</a>,<a href="#citation-reference-3">2</a>)</span></dt>
+<dd><p>Citations are text-labeled footnotes. They may be
+rendered separately and differently from footnotes.</p>
+</dd>
+<dt class="label" id="du2015"><span class="brackets"><a class="fn-backref" href="#citation-reference-2">DU2015</a></span></dt>
+<dd><p><cite>Example document</cite>, Hometown: 2015.</p>
+</dd>
+</dl>
+<p>Here's a reference to the above, <a class="citation-reference" href="#cit2002" id="citation-reference-3">[CIT2002]</a>.</p>
+<dl class="footnote superscript">
+<dt class="label" id="footnote-6"><span class="superscript"><a class="fn-backref" href="#footnote-reference-8">5</a></span></dt>
+<dd><p>this footnote is missing in the standard example document.</p>
+</dd>
+</dl>
+</div>
+</div>
+</body>
+</html>
--- /dev/null
+\documentclass[a4paper]{article}
+% generated by Docutils <http://docutils.sourceforge.net/>
+\usepackage{cmap} % fix search and cut-and-paste in Acrobat
+\usepackage{ifthen}
+\usepackage[T1]{fontenc}
+\usepackage[utf8]{inputenc}
+\usepackage[basque,esperanto,estonian,galician,ngerman,english]{babel}
+\AtBeginDocument{\shorthandoff{.<>}}
+\deactivatetilden % restore ~ in Galician
+\makeatletter
+ \addto\extrasestonian{\bbl@deactivate{~}}
+\makeatother
+\makeatletter
+ \addto\extrasbasque{\bbl@deactivate{~}}
+\makeatother
+
+%%% Custom LaTeX preamble
+% PDF Standard Fonts
+\usepackage{mathptmx} % Times
+\usepackage[scaled=.90]{helvet}
+\usepackage{courier}
+
+%%% User specified packages and stylesheets
+
+%%% Fallback definitions for Docutils-specific commands
+
+% hyperlinks:
+\ifthenelse{\isundefined{\hypersetup}}{
+ \usepackage[colorlinks=true,linkcolor=blue,urlcolor=blue]{hyperref}
+ \usepackage{bookmark}
+ \urlstyle{same} % normal text font (alternatives: tt, rm, sf)
+}{}
+
+%%% Body
+\begin{document}
+
+The \href{http://www.ctan.org/packages/babel}{babel} package introduces the concept of \textquotedbl{}shorthands\textquotedbl{}: additional
+characters that introduce a latex macro. Most common is the active double
+quote (\textquotedbl{}). Problematic is the tilde character (\textasciitilde{}) which is regularely used
+for no-break spaces but redefined by some language definition files:
+
+English: 'an' \textquotedbl{}active\textquotedbl{}-quote, \textasciicircum{}circumflex, and no-break spaces
+
+\foreignlanguage{basque}{Basque: 'an' \textquotedbl{}active\textquotedbl{}-quote, \textasciicircum{}circumflex, and no-break spaces}
+
+\foreignlanguage{esperanto}{Esperanto: 'an' \textquotedbl{}active\textquotedbl{}-quote, \textasciicircum{}circumflex, and no-break spaces}
+
+\foreignlanguage{estonian}{Estonian: 'an' \textquotedbl{}active\textquotedbl{}-quote, \textasciicircum{}circumflex, and no-break spaces}
+
+\foreignlanguage{galician}{Galician: 'an' \textquotedbl{}active\textquotedbl{}-quote, \textasciicircum{}circumflex, and no-break spaces}
+
+\foreignlanguage{ngerman}{German: 'an' \textquotedbl{}active\textquotedbl{}-quote, \textasciicircum{}circumflex, and no-break spaces}
+
+Spanish: option clash with Galician!
+
+% .. class:: language-es
+%
+% Spanish: 'an' "active"-quote, ^circumflex, and no-break spaces
+
+\end{document}
--- /dev/null
+\documentclass[a4paper]{article}
+% generated by Docutils <http://docutils.sourceforge.net/>
+\usepackage{cmap} % fix search and cut-and-paste in Acrobat
+\usepackage{ifthen}
+\usepackage[T1]{fontenc}
+\usepackage[utf8]{inputenc}
+\usepackage{graphicx}
+\usepackage{multirow}
+\setcounter{secnumdepth}{0}
+\usepackage{longtable,ltcaption,array}
+\setlength{\extrarowheight}{2pt}
+\newlength{\DUtablewidth} % internal use in tables
+
+%%% Custom LaTeX preamble
+% PDF Standard Fonts
+\usepackage{mathptmx} % Times
+\usepackage[scaled=.90]{helvet}
+\usepackage{courier}
+
+%%% User specified packages and stylesheets
+
+%%% Fallback definitions for Docutils-specific commands
+
+% transition (break, fancybreak, anonymous section)
+\providecommand*{\DUtransition}{%
+ \hspace*{\fill}\hrulefill\hspace*{\fill}
+ \vskip 0.5\baselineskip
+}
+
+% hyperlinks:
+\ifthenelse{\isundefined{\hypersetup}}{
+ \usepackage[colorlinks=true,linkcolor=blue,urlcolor=blue]{hyperref}
+ \usepackage{bookmark}
+ \urlstyle{same} % normal text font (alternatives: tt, rm, sf)
+}{}
+\hypersetup{
+ pdftitle={Some Tests for the LaTeX Writer},
+}
+
+%%% Body
+\begin{document}
+\title{Some Tests for the LaTeX Writer%
+ \label{some-tests-for-the-latex-writer}}
+\author{}
+\date{}
+\maketitle
+
+These tests contain unusual combinations of syntax elements which may cause
+trouble for the LaTeX writer but do not need to be tested with other writers.
+
+
+\section{Block Quotes%
+ \label{block-quotes}%
+}
+
+\begin{quote}
+This block quote comes directly after the section heading and is
+followed by a paragraph.
+
+This is the second paragraph of the block quote and it contains
+some more text filling up some space which would otherwise be
+empty.
+\nopagebreak
+
+\raggedleft —Attribution
+\end{quote}
+
+This is a paragraph.
+
+\begin{quote}
+This block quote does not have an attribution.
+\end{quote}
+
+This is another paragraph.
+
+\begin{quote}
+Another block quote at the end of the section.
+\end{quote}
+
+
+\section{More Block Quotes%
+ \label{more-block-quotes}%
+}
+
+\begin{quote}
+Block quote followed by a transition.
+\end{quote}
+
+%___________________________________________________________________________
+\DUtransition
+
+\begin{quote}
+Another block quote.
+\end{quote}
+
+
+\section{Images%
+ \label{images}%
+}
+
+Image with 20\% width:
+
+\includegraphics[width=0.200\linewidth]{../../../docs/user/rst/images/title.png}
+
+Image with 100\% width:
+
+\includegraphics[width=1.000\linewidth]{../../../docs/user/rst/images/title.png}
+
+
+\section{Rowspanning tables%
+ \label{rowspanning-tables}%
+}
+
+Several rowspanning cells in a table.
+
+Problem:
+
+In LaTeX, \textquotedbl{}overwritten\textquotedbl{} cells need to be defined as empty cells.
+
+Docutils (similarily to HTML) uses is the \textquotedbl{}Exchange Table Model\textquotedbl{} (also known
+as CALS tables, see docs/ref/soextblx.dtd) which defines only the remaining
+cells in a row \textquotedbl{}affected\textquotedbl{} by multirow cells.
+
+Therefore, visit\_entry() is only called for the remaining cells and the
+LaTeX writer needs bookkeeping to write out the required number of extra
+'\&'s.
+
+\setlength{\DUtablewidth}{\linewidth}
+\begin{longtable*}[c]{|p{0.075\DUtablewidth}|p{0.133\DUtablewidth}|p{0.133\DUtablewidth}|p{0.086\DUtablewidth}|}
+\hline
+
+11
+ &
+12
+ &
+13
+ &
+14
+ \\
+\hline
+
+21
+ & \multirow{2}{0.13\DUtablewidth}{%
+2/3 2
+} & \multirow{3}{0.13\DUtablewidth}{%
+2…4 3
+} &
+24
+ \\
+\cline{1-1}
+\cline{4-4}
+
+31
+ & & &
+34
+ \\
+\cline{1-1}
+\cline{2-2}
+\cline{4-4}
+
+41
+ &
+42
+ & &
+14
+ \\
+\hline
+\end{longtable*}
+
+\setlength{\DUtablewidth}{\linewidth}
+\begin{longtable*}[c]{|p{0.098\DUtablewidth}|p{0.098\DUtablewidth}|p{0.063\DUtablewidth}|}
+\hline
+
+11
+ &
+12
+ &
+13
+ \\
+\hline
+\multirow{2}{0.10\DUtablewidth}{%
+2/3 1
+} & \multirow{2}{0.10\DUtablewidth}{%
+2/3 2
+} &
+23
+ \\
+\cline{3-3}
+ & &
+33
+ \\
+\hline
+\end{longtable*}
+
+\setlength{\DUtablewidth}{\linewidth}
+\begin{longtable*}[c]{|p{0.098\DUtablewidth}|p{0.063\DUtablewidth}|}
+\hline
+
+11
+ &
+12
+ \\
+\hline
+\multirow{2}{0.10\DUtablewidth}{%
+2/3 1
+} &
+22
+ \\
+\cline{2-2}
+ &
+32
+ \\
+\hline
+\end{longtable*}
+
+\setlength{\DUtablewidth}{\linewidth}
+\begin{longtable*}[c]{|p{0.063\DUtablewidth}|p{0.110\DUtablewidth}|p{0.063\DUtablewidth}|}
+\hline
+
+11
+ &
+12
+ &
+13
+ \\
+\hline
+
+21
+ & \multirow{2}{0.11\DUtablewidth}{%
+2/3 2
+} &
+23
+ \\
+\cline{1-1}
+\cline{3-3}
+
+31
+ & &
+33
+ \\
+\hline
+\end{longtable*}
+
+\setlength{\DUtablewidth}{\linewidth}
+\begin{longtable*}[c]{|p{0.063\DUtablewidth}|p{0.110\DUtablewidth}|}
+\hline
+
+11
+ &
+12
+ \\
+\hline
+
+21
+ & \multirow{2}{0.11\DUtablewidth}{%
+2/3 1
+} \\
+\cline{1-1}
+
+31
+ & \\
+\hline
+\end{longtable*}
+
+\setlength{\DUtablewidth}{\linewidth}
+\begin{longtable*}[c]{|p{0.063\DUtablewidth}|p{0.110\DUtablewidth}|}
+\hline
+
+11
+ & \multirow{2}{0.11\DUtablewidth}{%
+1/2 1
+} \\
+\cline{1-1}
+
+21
+ & \\
+\hline
+
+31
+ &
+32
+ \\
+\hline
+\end{longtable*}
+
+\setlength{\DUtablewidth}{\linewidth}
+\begin{longtable*}[c]{|p{0.063\DUtablewidth}|p{0.156\DUtablewidth}|p{0.110\DUtablewidth}|}
+\hline
+
+11
+ & \multirow{2}{0.16\DUtablewidth}{%
+1/2 2
+} & \multirow{2}{0.11\DUtablewidth}{%
+1/2 3
+} \\
+\cline{1-1}
+
+21
+ & & \\
+\hline
+\end{longtable*}
+
+\setlength{\DUtablewidth}{\linewidth}
+\begin{longtable*}[c]{|p{0.098\DUtablewidth}|p{0.063\DUtablewidth}|p{0.110\DUtablewidth}|}
+\hline
+\multirow{2}{0.10\DUtablewidth}{%
+1/2 3
+} &
+12
+ & \multirow{2}{0.11\DUtablewidth}{%
+1/2 3
+} \\
+\cline{2-2}
+ &
+22
+ & \\
+\hline
+\end{longtable*}
+
+\setlength{\DUtablewidth}{\linewidth}
+\begin{longtable*}[c]{|p{0.098\DUtablewidth}|p{0.063\DUtablewidth}|}
+\hline
+\multirow{2}{0.10\DUtablewidth}{%
+1/2 3
+} &
+12
+ \\
+\cline{2-2}
+ &
+22
+ \\
+\hline
+
+31
+ &
+32
+ \\
+\hline
+\end{longtable*}
+
+\end{document}
--- /dev/null
+\documentclass[a4paper]{article}
+% generated by Docutils <http://docutils.sourceforge.net/>
+\usepackage{cmap} % fix search and cut-and-paste in Acrobat
+\usepackage{ifthen}
+\usepackage[T1]{fontenc}
+\usepackage[utf8]{inputenc}
+
+%%% Custom LaTeX preamble
+% PDF Standard Fonts
+\usepackage{mathptmx} % Times
+\usepackage[scaled=.90]{helvet}
+\usepackage{courier}
+
+%%% User specified packages and stylesheets
+
+%%% Fallback definitions for Docutils-specific commands
+
+% hyperlinks:
+\ifthenelse{\isundefined{\hypersetup}}{
+ \usepackage[colorlinks=true,linkcolor=blue,urlcolor=blue]{hyperref}
+ \usepackage{bookmark}
+ \urlstyle{same} % normal text font (alternatives: tt, rm, sf)
+}{}
+\hypersetup{
+ pdfauthor={Foo Fred;Bar Barney}
+}
+
+%%% Body
+\begin{document}
+\title{}
+\author{Foo Fred\\
+Food Foomatics \& Friends\\
+foo@food.example.info\\
+Fox St 13\\
+Foowood \and
+Bar Barney\\
+Bar-BQ Bar\\
+1-800-BARBQBAR\\
+Barbara St 16\\
+South Barwell}
+\date{}
+\maketitle
+
+\end{document}
--- /dev/null
+\documentclass[a4paper]{article}
+% generated by Docutils <http://docutils.sourceforge.net/>
+\usepackage{cmap} % fix search and cut-and-paste in Acrobat
+\usepackage{ifthen}
+\usepackage[T1]{fontenc}
+\usepackage[utf8]{inputenc}
+\usepackage{alltt}
+\usepackage{amsmath}
+\usepackage{graphicx}
+\usepackage{longtable,ltcaption,array}
+\setlength{\extrarowheight}{2pt}
+\newlength{\DUtablewidth} % internal use in tables
+
+%%% Custom LaTeX preamble
+% PDF Standard Fonts
+\usepackage{mathptmx} % Times
+\usepackage[scaled=.90]{helvet}
+\usepackage{courier}
+
+%%% User specified packages and stylesheets
+
+%%% Fallback definitions for Docutils-specific commands
+
+% 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]%
+ {\def\DocutilsClassFunctionName{DUCLASS#1}% arg cannot be used in end-part of environment.
+ \csname \DocutilsClassFunctionName \endcsname}%
+ {\csname end\DocutilsClassFunctionName \endcsname}%
+\fi
+
+% admonition (specially marked topic)
+\providecommand{\DUadmonition}[2][class-arg]{%
+ % try \DUadmonition#1{#2}:
+ \ifcsname DUadmonition#1\endcsname%
+ \csname DUadmonition#1\endcsname{#2}%
+ \else
+ \begin{center}
+ \fbox{\parbox{0.9\linewidth}{#2}}
+ \end{center}
+ \fi
+}
+% numeric or symbol footnotes with hyperlinks
+\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 markup (custom roles)
+% \DUrole{#1}{#2} tries \DUrole#1{#2}
+\providecommand*{\DUrole}[2]{%
+ \ifcsname DUrole#1\endcsname%
+ \csname DUrole#1\endcsname{#2}%
+ \else
+ % backwards compatibility: try \docutilsrole#1{#2}
+ \ifcsname docutilsrole#1\endcsname%
+ \PackageWarningNoLine{docutils}{Command prefix "docutilsrole" is
+ deprecated, \MessageBreak use `\protect\DUrole #1`}
+ \csname docutilsrole#1\endcsname{#2}%
+ \else%
+ #2%
+ \fi%
+ \fi%
+}
+
+% text mode subscript
+\ifx\textsubscript\undefined
+ \usepackage{fixltx2e} % since 2015 loaded by default
+\fi
+
+% title for topics, admonitions, unsupported section levels, and sidebar
+\providecommand*{\DUtitle}[2][class-arg]{%
+ % call \DUtitle#1{#2} if it exists:
+ \ifcsname DUtitle#1\endcsname%
+ \csname DUtitle#1\endcsname{#2}%
+ \else
+ \smallskip\noindent\textbf{#2}\smallskip%
+ \fi
+}
+
+% titlereference role
+\providecommand*{\DUroletitlereference}[1]{\textsl{#1}}
+
+% character width in monospaced font
+\newlength{\ttemwidth}
+\settowidth{\ttemwidth}{\ttfamily M}
+
+% hyperlinks:
+\ifthenelse{\isundefined{\hypersetup}}{
+ \usepackage[colorlinks=true,linkcolor=blue,urlcolor=blue]{hyperref}
+ \usepackage{bookmark}
+ \urlstyle{same} % normal text font (alternatives: tt, rm, sf)
+}{}
+
+%%% Body
+\begin{document}
+
+In LaTeX, literal blocks can be customized with the \textquotedbl{}literal-block-env\textquotedbl{}
+setting. This test file exists to check if the LaTeX writer output compiles
+and looks as expected.
+
+Start with a plain literal block:
+
+\begin{quote}
+\begin{alltt}
+$\textbackslash{}sin^2(x)$ and $\textbackslash{}cos^2(x)$ equals one:
+
+\textbackslash{}[
+ \textbackslash{}sin^2(x) + \textbackslash{}cos^2(x) = 1 % for all x
+\textbackslash{}]
+\end{alltt}
+\end{quote}
+
+A latex \textquotedbl{}code-block\textquotedbl{} (set with \textquotedbl{}literal-block-env\textquotedbl{}, if syntax
+highlight is \textquotedbl{}none\textquotedbl{}):
+
+\begin{DUclass}{code}
+\begin{DUclass}{latex}
+\begin{quote}
+\begin{alltt}
+$\textbackslash{}sin^2(x)$ and $\textbackslash{}cos^2(x)$ equals one:
+
+\textbackslash{}[
+ \textbackslash{}sin^2(x) + \textbackslash{}cos^2(x) = 1 % for all x
+\textbackslash{}]
+\end{alltt}
+\end{quote}
+\end{DUclass}
+\end{DUclass}
+
+A literal block in a table:
+
+\setlength{\DUtablewidth}{\linewidth}
+\begin{longtable*}[c]{|p{0.063\DUtablewidth}|p{0.145\DUtablewidth}|p{0.063\DUtablewidth}|}
+\hline
+
+test
+ &
+\begin{minipage}{8\ttemwidth}
+\begin{alltt}
+\textbackslash{}sin^2 x
+\end{alltt}
+\end{minipage}
+ &
+test
+ \\
+\hline
+\end{longtable*}
+
+A literal block in a table with auto-width columns:
+
+\begin{longtable*}[c]{|l|l|l|}
+\hline
+test &
+\ttfamily\raggedright
+\textbackslash{}sin\textasciicircum{}2~x
+ & test \\
+\hline
+\end{longtable*}
+
+\DUadmonition[note]{
+\DUtitle[note]{Note}
+
+A literal block in an admonition:
+
+\begin{quote}
+\ttfamily\raggedright
+\textbackslash{}sin\textasciicircum{}2~x
+\end{quote}
+}
+
+Parsed literal block with inline markup and leading whitespace:
+
+\begin{quote}
+\ttfamily\raggedright
+~~~\emph{emphasis},~\textbf{strong~emphasis},~\texttt{inline~literals},\\
+standalone~hyperlinks~(\url{http://www.python.org}),\\
+\hyperref[internal]{internal}~and~\href{http://www.python.org/}{external}~hyperlinks,\\
+%
+\phantomsection\label{internal}internal~hyperlink~targets,\\
+images~via~substitution~references~(\includegraphics{../../../docs/user/rst/images/biohazard.png}),\\
+footnote~references\DUfootnotemark{footnote-reference-1}{footnote-1}{*},\\
+citation~references~(\hyperlink{cit2002}{[CIT2002]}),~and~more.\\
+~\\
+~~~Here~are~some~explicit~interpreted~text~roles:\\
+a~PEP~reference~(\href{http://www.python.org/dev/peps/pep-0287}{PEP~287}),\\
+an~RFC~reference~(\href{http://tools.ietf.org/html/rfc2822.html}{RFC~2822}),\\
+an~abbreviation~(\DUrole{abbreviation}{abb.}),~an~acronym~(\DUrole{acronym}{reST}),\\
+code~(\texttt{\DUrole{code}{print~\textquotedbl{}hello~world\textquotedbl{}}}),\\
+maths~$\sin^2(x)$,\\
+\textsubscript{subscript}~and~\textsuperscript{superscript},\\
+\DUrole{custom}{custom}~\DUrole{custom-role}{roles},~and~explicit~roles~for\\
+\DUroletitlereference{Docutils}'~\emph{standard}~\textbf{inline}~\texttt{markup}.
+\end{quote}
+%
+\DUfootnotetext{footnote-1}{footnote-reference-1}{*}{%
+This footnote is referenced in a \DUroletitlereference{parsed literal} block.
+
+It contains a literal block:
+
+\begin{quote}
+\ttfamily\raggedright
+\textbackslash{}sin\textasciicircum{}2~x
+\end{quote}
+}
+\begin{figure}[b]\raisebox{1em}{\hypertarget{cit2002}{}}[CIT2002]
+Sample Citation, 2017.
+\end{figure}
+
+\end{document}
--- /dev/null
+\documentclass[a4paper]{article}
+% generated by Docutils <http://docutils.sourceforge.net/>
+\usepackage{cmap} % fix search and cut-and-paste in Acrobat
+\usepackage{ifthen}
+\usepackage[T1]{fontenc}
+\usepackage[utf8]{inputenc}
+\usepackage{amsmath}
+\usepackage{graphicx}
+\usepackage{fancyvrb}
+\usepackage{longtable,ltcaption,array}
+\setlength{\extrarowheight}{2pt}
+\newlength{\DUtablewidth} % internal use in tables
+
+%%% Custom LaTeX preamble
+% PDF Standard Fonts
+\usepackage{mathptmx} % Times
+\usepackage[scaled=.90]{helvet}
+\usepackage{courier}
+
+%%% User specified packages and stylesheets
+
+%%% Fallback definitions for Docutils-specific commands
+
+% 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]%
+ {\def\DocutilsClassFunctionName{DUCLASS#1}% arg cannot be used in end-part of environment.
+ \csname \DocutilsClassFunctionName \endcsname}%
+ {\csname end\DocutilsClassFunctionName \endcsname}%
+\fi
+
+% admonition (specially marked topic)
+\providecommand{\DUadmonition}[2][class-arg]{%
+ % try \DUadmonition#1{#2}:
+ \ifcsname DUadmonition#1\endcsname%
+ \csname DUadmonition#1\endcsname{#2}%
+ \else
+ \begin{center}
+ \fbox{\parbox{0.9\linewidth}{#2}}
+ \end{center}
+ \fi
+}
+% numeric or symbol footnotes with hyperlinks
+\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 markup (custom roles)
+% \DUrole{#1}{#2} tries \DUrole#1{#2}
+\providecommand*{\DUrole}[2]{%
+ \ifcsname DUrole#1\endcsname%
+ \csname DUrole#1\endcsname{#2}%
+ \else
+ % backwards compatibility: try \docutilsrole#1{#2}
+ \ifcsname docutilsrole#1\endcsname%
+ \PackageWarningNoLine{docutils}{Command prefix "docutilsrole" is
+ deprecated, \MessageBreak use `\protect\DUrole #1`}
+ \csname docutilsrole#1\endcsname{#2}%
+ \else%
+ #2%
+ \fi%
+ \fi%
+}
+
+% text mode subscript
+\ifx\textsubscript\undefined
+ \usepackage{fixltx2e} % since 2015 loaded by default
+\fi
+
+% title for topics, admonitions, unsupported section levels, and sidebar
+\providecommand*{\DUtitle}[2][class-arg]{%
+ % call \DUtitle#1{#2} if it exists:
+ \ifcsname DUtitle#1\endcsname%
+ \csname DUtitle#1\endcsname{#2}%
+ \else
+ \smallskip\noindent\textbf{#2}\smallskip%
+ \fi
+}
+
+% titlereference role
+\providecommand*{\DUroletitlereference}[1]{\textsl{#1}}
+
+% character width in monospaced font
+\newlength{\ttemwidth}
+\settowidth{\ttemwidth}{\ttfamily M}
+
+% hyperlinks:
+\ifthenelse{\isundefined{\hypersetup}}{
+ \usepackage[colorlinks=true,linkcolor=blue,urlcolor=blue]{hyperref}
+ \usepackage{bookmark}
+ \urlstyle{same} % normal text font (alternatives: tt, rm, sf)
+}{}
+
+%%% Body
+\begin{document}
+
+In LaTeX, literal blocks can be customized with the \textquotedbl{}literal-block-env\textquotedbl{}
+setting. This test file exists to check if the LaTeX writer output compiles
+and looks as expected.
+
+Start with a plain literal block:
+
+\begin{quote}
+\begin{Verbatim}
+$\sin^2(x)$ and $\cos^2(x)$ equals one:
+
+\[
+ \sin^2(x) + \cos^2(x) = 1 % for all x
+\]
+\end{Verbatim}
+\end{quote}
+
+A latex \textquotedbl{}code-block\textquotedbl{} (set with \textquotedbl{}literal-block-env\textquotedbl{}, if syntax
+highlight is \textquotedbl{}none\textquotedbl{}):
+
+\begin{DUclass}{code}
+\begin{DUclass}{latex}
+\begin{quote}
+\begin{Verbatim}
+$\sin^2(x)$ and $\cos^2(x)$ equals one:
+
+\[
+ \sin^2(x) + \cos^2(x) = 1 % for all x
+\]
+\end{Verbatim}
+\end{quote}
+\end{DUclass}
+\end{DUclass}
+
+A literal block in a table:
+
+\setlength{\DUtablewidth}{\linewidth}
+\begin{longtable*}[c]{|p{0.063\DUtablewidth}|p{0.145\DUtablewidth}|p{0.063\DUtablewidth}|}
+\hline
+
+test
+ &
+\begin{minipage}{8\ttemwidth}
+\begin{Verbatim}
+\sin^2 x
+\end{Verbatim}
+\end{minipage}
+ &
+test
+ \\
+\hline
+\end{longtable*}
+
+A literal block in a table with auto-width columns:
+
+\begin{longtable*}[c]{|l|l|l|}
+\hline
+test &
+\ttfamily\raggedright
+\textbackslash{}sin\textasciicircum{}2~x
+ & test \\
+\hline
+\end{longtable*}
+
+\DUadmonition[note]{
+\DUtitle[note]{Note}
+
+A literal block in an admonition:
+
+\begin{quote}
+\ttfamily\raggedright
+\textbackslash{}sin\textasciicircum{}2~x
+\end{quote}
+}
+
+Parsed literal block with inline markup and leading whitespace:
+
+\begin{quote}
+\ttfamily\raggedright
+~~~\emph{emphasis},~\textbf{strong~emphasis},~\texttt{inline~literals},\\
+standalone~hyperlinks~(\url{http://www.python.org}),\\
+\hyperref[internal]{internal}~and~\href{http://www.python.org/}{external}~hyperlinks,\\
+%
+\phantomsection\label{internal}internal~hyperlink~targets,\\
+images~via~substitution~references~(\includegraphics{../../../docs/user/rst/images/biohazard.png}),\\
+footnote~references\DUfootnotemark{footnote-reference-1}{footnote-1}{*},\\
+citation~references~(\hyperlink{cit2002}{[CIT2002]}),~and~more.\\
+~\\
+~~~Here~are~some~explicit~interpreted~text~roles:\\
+a~PEP~reference~(\href{http://www.python.org/dev/peps/pep-0287}{PEP~287}),\\
+an~RFC~reference~(\href{http://tools.ietf.org/html/rfc2822.html}{RFC~2822}),\\
+an~abbreviation~(\DUrole{abbreviation}{abb.}),~an~acronym~(\DUrole{acronym}{reST}),\\
+code~(\texttt{\DUrole{code}{print~\textquotedbl{}hello~world\textquotedbl{}}}),\\
+maths~$\sin^2(x)$,\\
+\textsubscript{subscript}~and~\textsuperscript{superscript},\\
+\DUrole{custom}{custom}~\DUrole{custom-role}{roles},~and~explicit~roles~for\\
+\DUroletitlereference{Docutils}'~\emph{standard}~\textbf{inline}~\texttt{markup}.
+\end{quote}
+%
+\DUfootnotetext{footnote-1}{footnote-reference-1}{*}{%
+This footnote is referenced in a \DUroletitlereference{parsed literal} block.
+
+It contains a literal block:
+
+\begin{quote}
+\ttfamily\raggedright
+\textbackslash{}sin\textasciicircum{}2~x
+\end{quote}
+}
+\begin{figure}[b]\raisebox{1em}{\hypertarget{cit2002}{}}[CIT2002]
+Sample Citation, 2017.
+\end{figure}
+
+\end{document}
--- /dev/null
+\documentclass[a4paper]{article}
+% generated by Docutils <http://docutils.sourceforge.net/>
+\usepackage{cmap} % fix search and cut-and-paste in Acrobat
+\usepackage{ifthen}
+\usepackage[T1]{fontenc}
+\usepackage[utf8]{inputenc}
+\usepackage{amsmath}
+\usepackage{graphicx}
+\usepackage{listings}
+\lstset{xleftmargin=\leftmargin}
+\usepackage{longtable,ltcaption,array}
+\setlength{\extrarowheight}{2pt}
+\newlength{\DUtablewidth} % internal use in tables
+
+%%% Custom LaTeX preamble
+
+% PDF Standard Fonts
+\usepackage{mathptmx} % Times
+\usepackage[scaled=.90]{helvet}
+\usepackage{courier}
+% LaTeX syntax highlight with "listings":
+\lstloadlanguages{[LaTeX]TeX} % comma separated list of languages
+\newcommand{\DUCLASSlatex}{\lstset{language=[LaTeX]TeX}}
+
+
+%%% User specified packages and stylesheets
+
+%%% Fallback definitions for Docutils-specific commands
+
+% 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]%
+ {\def\DocutilsClassFunctionName{DUCLASS#1}% arg cannot be used in end-part of environment.
+ \csname \DocutilsClassFunctionName \endcsname}%
+ {\csname end\DocutilsClassFunctionName \endcsname}%
+\fi
+
+% admonition (specially marked topic)
+\providecommand{\DUadmonition}[2][class-arg]{%
+ % try \DUadmonition#1{#2}:
+ \ifcsname DUadmonition#1\endcsname%
+ \csname DUadmonition#1\endcsname{#2}%
+ \else
+ \begin{center}
+ \fbox{\parbox{0.9\linewidth}{#2}}
+ \end{center}
+ \fi
+}
+% numeric or symbol footnotes with hyperlinks
+\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 markup (custom roles)
+% \DUrole{#1}{#2} tries \DUrole#1{#2}
+\providecommand*{\DUrole}[2]{%
+ \ifcsname DUrole#1\endcsname%
+ \csname DUrole#1\endcsname{#2}%
+ \else
+ % backwards compatibility: try \docutilsrole#1{#2}
+ \ifcsname docutilsrole#1\endcsname%
+ \PackageWarningNoLine{docutils}{Command prefix "docutilsrole" is
+ deprecated, \MessageBreak use `\protect\DUrole #1`}
+ \csname docutilsrole#1\endcsname{#2}%
+ \else%
+ #2%
+ \fi%
+ \fi%
+}
+
+% text mode subscript
+\ifx\textsubscript\undefined
+ \usepackage{fixltx2e} % since 2015 loaded by default
+\fi
+
+% title for topics, admonitions, unsupported section levels, and sidebar
+\providecommand*{\DUtitle}[2][class-arg]{%
+ % call \DUtitle#1{#2} if it exists:
+ \ifcsname DUtitle#1\endcsname%
+ \csname DUtitle#1\endcsname{#2}%
+ \else
+ \smallskip\noindent\textbf{#2}\smallskip%
+ \fi
+}
+
+% titlereference role
+\providecommand*{\DUroletitlereference}[1]{\textsl{#1}}
+
+% character width in monospaced font
+\newlength{\ttemwidth}
+\settowidth{\ttemwidth}{\ttfamily M}
+
+% hyperlinks:
+\ifthenelse{\isundefined{\hypersetup}}{
+ \usepackage[colorlinks=true,linkcolor=blue,urlcolor=blue]{hyperref}
+ \usepackage{bookmark}
+ \urlstyle{same} % normal text font (alternatives: tt, rm, sf)
+}{}
+
+%%% Body
+\begin{document}
+
+In LaTeX, literal blocks can be customized with the \textquotedbl{}literal-block-env\textquotedbl{}
+setting. This test file exists to check if the LaTeX writer output compiles
+and looks as expected.
+
+Start with a plain literal block:
+
+\begin{lstlisting}
+$\sin^2(x)$ and $\cos^2(x)$ equals one:
+
+\[
+ \sin^2(x) + \cos^2(x) = 1 % for all x
+\]
+\end{lstlisting}
+
+A latex \textquotedbl{}code-block\textquotedbl{} (set with \textquotedbl{}literal-block-env\textquotedbl{}, if syntax
+highlight is \textquotedbl{}none\textquotedbl{}):
+
+\begin{DUclass}{code}
+\begin{DUclass}{latex}
+\begin{lstlisting}
+$\sin^2(x)$ and $\cos^2(x)$ equals one:
+
+\[
+ \sin^2(x) + \cos^2(x) = 1 % for all x
+\]
+\end{lstlisting}
+\end{DUclass}
+\end{DUclass}
+
+A literal block in a table:
+
+\setlength{\DUtablewidth}{\linewidth}
+\begin{longtable*}[c]{|p{0.063\DUtablewidth}|p{0.145\DUtablewidth}|p{0.063\DUtablewidth}|}
+\hline
+
+test
+ &
+\begin{minipage}{8\ttemwidth}
+\lstset{xleftmargin=0pt}
+\begin{lstlisting}
+\sin^2 x
+\end{lstlisting}
+\end{minipage}
+ &
+test
+ \\
+\hline
+\end{longtable*}
+
+A literal block in a table with auto-width columns:
+
+\begin{longtable*}[c]{|l|l|l|}
+\hline
+test &
+\lstset{xleftmargin=0pt}
+\begin{lstlisting}
+\sin^2 x
+\end{lstlisting}
+ & test \\
+\hline
+\end{longtable*}
+
+\DUadmonition[note]{
+\DUtitle[note]{Note}
+
+A literal block in an admonition:
+
+\begin{quote}
+\ttfamily\raggedright
+\textbackslash{}sin\textasciicircum{}2~x
+\end{quote}
+}
+
+Parsed literal block with inline markup and leading whitespace:
+
+\begin{quote}
+\ttfamily\raggedright
+~~~\emph{emphasis},~\textbf{strong~emphasis},~\texttt{inline~literals},\\
+standalone~hyperlinks~(\url{http://www.python.org}),\\
+\hyperref[internal]{internal}~and~\href{http://www.python.org/}{external}~hyperlinks,\\
+%
+\phantomsection\label{internal}internal~hyperlink~targets,\\
+images~via~substitution~references~(\includegraphics{../../../docs/user/rst/images/biohazard.png}),\\
+footnote~references\DUfootnotemark{footnote-reference-1}{footnote-1}{*},\\
+citation~references~(\hyperlink{cit2002}{[CIT2002]}),~and~more.\\
+~\\
+~~~Here~are~some~explicit~interpreted~text~roles:\\
+a~PEP~reference~(\href{http://www.python.org/dev/peps/pep-0287}{PEP~287}),\\
+an~RFC~reference~(\href{http://tools.ietf.org/html/rfc2822.html}{RFC~2822}),\\
+an~abbreviation~(\DUrole{abbreviation}{abb.}),~an~acronym~(\DUrole{acronym}{reST}),\\
+code~(\texttt{\DUrole{code}{print~\textquotedbl{}hello~world\textquotedbl{}}}),\\
+maths~$\sin^2(x)$,\\
+\textsubscript{subscript}~and~\textsuperscript{superscript},\\
+\DUrole{custom}{custom}~\DUrole{custom-role}{roles},~and~explicit~roles~for\\
+\DUroletitlereference{Docutils}'~\emph{standard}~\textbf{inline}~\texttt{markup}.
+\end{quote}
+%
+\DUfootnotetext{footnote-1}{footnote-reference-1}{*}{%
+This footnote is referenced in a \DUroletitlereference{parsed literal} block.
+
+It contains a literal block:
+
+\begin{quote}
+\ttfamily\raggedright
+\textbackslash{}sin\textasciicircum{}2~x
+\end{quote}
+}
+\begin{figure}[b]\raisebox{1em}{\hypertarget{cit2002}{}}[CIT2002]
+Sample Citation, 2017.
+\end{figure}
+
+\end{document}
--- /dev/null
+\documentclass[a4paper]{article}
+% generated by Docutils <http://docutils.sourceforge.net/>
+\usepackage{cmap} % fix search and cut-and-paste in Acrobat
+\usepackage{ifthen}
+\usepackage[T1]{fontenc}
+\usepackage[utf8]{inputenc}
+\usepackage{amsmath}
+\usepackage{graphicx}
+\usepackage{longtable,ltcaption,array}
+\setlength{\extrarowheight}{2pt}
+\newlength{\DUtablewidth} % internal use in tables
+
+%%% Custom LaTeX preamble
+% PDF Standard Fonts
+\usepackage{mathptmx} % Times
+\usepackage[scaled=.90]{helvet}
+\usepackage{courier}
+
+%%% User specified packages and stylesheets
+
+%%% Fallback definitions for Docutils-specific commands
+
+% 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]%
+ {\def\DocutilsClassFunctionName{DUCLASS#1}% arg cannot be used in end-part of environment.
+ \csname \DocutilsClassFunctionName \endcsname}%
+ {\csname end\DocutilsClassFunctionName \endcsname}%
+\fi
+
+% admonition (specially marked topic)
+\providecommand{\DUadmonition}[2][class-arg]{%
+ % try \DUadmonition#1{#2}:
+ \ifcsname DUadmonition#1\endcsname%
+ \csname DUadmonition#1\endcsname{#2}%
+ \else
+ \begin{center}
+ \fbox{\parbox{0.9\linewidth}{#2}}
+ \end{center}
+ \fi
+}
+% numeric or symbol footnotes with hyperlinks
+\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 markup (custom roles)
+% \DUrole{#1}{#2} tries \DUrole#1{#2}
+\providecommand*{\DUrole}[2]{%
+ \ifcsname DUrole#1\endcsname%
+ \csname DUrole#1\endcsname{#2}%
+ \else
+ % backwards compatibility: try \docutilsrole#1{#2}
+ \ifcsname docutilsrole#1\endcsname%
+ \PackageWarningNoLine{docutils}{Command prefix "docutilsrole" is
+ deprecated, \MessageBreak use `\protect\DUrole #1`}
+ \csname docutilsrole#1\endcsname{#2}%
+ \else%
+ #2%
+ \fi%
+ \fi%
+}
+
+% text mode subscript
+\ifx\textsubscript\undefined
+ \usepackage{fixltx2e} % since 2015 loaded by default
+\fi
+
+% title for topics, admonitions, unsupported section levels, and sidebar
+\providecommand*{\DUtitle}[2][class-arg]{%
+ % call \DUtitle#1{#2} if it exists:
+ \ifcsname DUtitle#1\endcsname%
+ \csname DUtitle#1\endcsname{#2}%
+ \else
+ \smallskip\noindent\textbf{#2}\smallskip%
+ \fi
+}
+
+% titlereference role
+\providecommand*{\DUroletitlereference}[1]{\textsl{#1}}
+
+% character width in monospaced font
+\newlength{\ttemwidth}
+\settowidth{\ttemwidth}{\ttfamily M}
+
+% hyperlinks:
+\ifthenelse{\isundefined{\hypersetup}}{
+ \usepackage[colorlinks=true,linkcolor=blue,urlcolor=blue]{hyperref}
+ \usepackage{bookmark}
+ \urlstyle{same} % normal text font (alternatives: tt, rm, sf)
+}{}
+
+%%% Body
+\begin{document}
+
+In LaTeX, literal blocks can be customized with the \textquotedbl{}literal-block-env\textquotedbl{}
+setting. This test file exists to check if the LaTeX writer output compiles
+and looks as expected.
+
+Start with a plain literal block:
+
+\begin{quote}
+\begin{verbatim}
+$\sin^2(x)$ and $\cos^2(x)$ equals one:
+
+\[
+ \sin^2(x) + \cos^2(x) = 1 % for all x
+\]
+\end{verbatim}
+\end{quote}
+
+A latex \textquotedbl{}code-block\textquotedbl{} (set with \textquotedbl{}literal-block-env\textquotedbl{}, if syntax
+highlight is \textquotedbl{}none\textquotedbl{}):
+
+\begin{DUclass}{code}
+\begin{DUclass}{latex}
+\begin{quote}
+\begin{verbatim}
+$\sin^2(x)$ and $\cos^2(x)$ equals one:
+
+\[
+ \sin^2(x) + \cos^2(x) = 1 % for all x
+\]
+\end{verbatim}
+\end{quote}
+\end{DUclass}
+\end{DUclass}
+
+A literal block in a table:
+
+\setlength{\DUtablewidth}{\linewidth}
+\begin{longtable*}[c]{|p{0.063\DUtablewidth}|p{0.145\DUtablewidth}|p{0.063\DUtablewidth}|}
+\hline
+
+test
+ &
+\begin{minipage}{8\ttemwidth}
+\begin{verbatim}
+\sin^2 x
+\end{verbatim}
+\end{minipage}
+ &
+test
+ \\
+\hline
+\end{longtable*}
+
+A literal block in a table with auto-width columns:
+
+\begin{longtable*}[c]{|l|l|l|}
+\hline
+test &
+\ttfamily\raggedright
+\textbackslash{}sin\textasciicircum{}2~x
+ & test \\
+\hline
+\end{longtable*}
+
+\DUadmonition[note]{
+\DUtitle[note]{Note}
+
+A literal block in an admonition:
+
+\begin{quote}
+\ttfamily\raggedright
+\textbackslash{}sin\textasciicircum{}2~x
+\end{quote}
+}
+
+Parsed literal block with inline markup and leading whitespace:
+
+\begin{quote}
+\ttfamily\raggedright
+~~~\emph{emphasis},~\textbf{strong~emphasis},~\texttt{inline~literals},\\
+standalone~hyperlinks~(\url{http://www.python.org}),\\
+\hyperref[internal]{internal}~and~\href{http://www.python.org/}{external}~hyperlinks,\\
+%
+\phantomsection\label{internal}internal~hyperlink~targets,\\
+images~via~substitution~references~(\includegraphics{../../../docs/user/rst/images/biohazard.png}),\\
+footnote~references\DUfootnotemark{footnote-reference-1}{footnote-1}{*},\\
+citation~references~(\hyperlink{cit2002}{[CIT2002]}),~and~more.\\
+~\\
+~~~Here~are~some~explicit~interpreted~text~roles:\\
+a~PEP~reference~(\href{http://www.python.org/dev/peps/pep-0287}{PEP~287}),\\
+an~RFC~reference~(\href{http://tools.ietf.org/html/rfc2822.html}{RFC~2822}),\\
+an~abbreviation~(\DUrole{abbreviation}{abb.}),~an~acronym~(\DUrole{acronym}{reST}),\\
+code~(\texttt{\DUrole{code}{print~\textquotedbl{}hello~world\textquotedbl{}}}),\\
+maths~$\sin^2(x)$,\\
+\textsubscript{subscript}~and~\textsuperscript{superscript},\\
+\DUrole{custom}{custom}~\DUrole{custom-role}{roles},~and~explicit~roles~for\\
+\DUroletitlereference{Docutils}'~\emph{standard}~\textbf{inline}~\texttt{markup}.
+\end{quote}
+%
+\DUfootnotetext{footnote-1}{footnote-reference-1}{*}{%
+This footnote is referenced in a \DUroletitlereference{parsed literal} block.
+
+It contains a literal block:
+
+\begin{quote}
+\ttfamily\raggedright
+\textbackslash{}sin\textasciicircum{}2~x
+\end{quote}
+}
+\begin{figure}[b]\raisebox{1em}{\hypertarget{cit2002}{}}[CIT2002]
+Sample Citation, 2017.
+\end{figure}
+
+\end{document}
--- /dev/null
+\documentclass[a4paper]{article}
+% generated by Docutils <http://docutils.sourceforge.net/>
+\usepackage{cmap} % fix search and cut-and-paste in Acrobat
+\usepackage{ifthen}
+\usepackage[T1]{fontenc}
+\usepackage[utf8]{inputenc}
+\usepackage{amsmath}
+\usepackage{graphicx}
+\usepackage{moreverb}
+\usepackage{longtable,ltcaption,array}
+\setlength{\extrarowheight}{2pt}
+\newlength{\DUtablewidth} % internal use in tables
+
+%%% Custom LaTeX preamble
+% PDF Standard Fonts
+\usepackage{mathptmx} % Times
+\usepackage[scaled=.90]{helvet}
+\usepackage{courier}
+
+%%% User specified packages and stylesheets
+
+%%% Fallback definitions for Docutils-specific commands
+
+% 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]%
+ {\def\DocutilsClassFunctionName{DUCLASS#1}% arg cannot be used in end-part of environment.
+ \csname \DocutilsClassFunctionName \endcsname}%
+ {\csname end\DocutilsClassFunctionName \endcsname}%
+\fi
+
+% admonition (specially marked topic)
+\providecommand{\DUadmonition}[2][class-arg]{%
+ % try \DUadmonition#1{#2}:
+ \ifcsname DUadmonition#1\endcsname%
+ \csname DUadmonition#1\endcsname{#2}%
+ \else
+ \begin{center}
+ \fbox{\parbox{0.9\linewidth}{#2}}
+ \end{center}
+ \fi
+}
+% numeric or symbol footnotes with hyperlinks
+\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 markup (custom roles)
+% \DUrole{#1}{#2} tries \DUrole#1{#2}
+\providecommand*{\DUrole}[2]{%
+ \ifcsname DUrole#1\endcsname%
+ \csname DUrole#1\endcsname{#2}%
+ \else
+ % backwards compatibility: try \docutilsrole#1{#2}
+ \ifcsname docutilsrole#1\endcsname%
+ \PackageWarningNoLine{docutils}{Command prefix "docutilsrole" is
+ deprecated, \MessageBreak use `\protect\DUrole #1`}
+ \csname docutilsrole#1\endcsname{#2}%
+ \else%
+ #2%
+ \fi%
+ \fi%
+}
+
+% text mode subscript
+\ifx\textsubscript\undefined
+ \usepackage{fixltx2e} % since 2015 loaded by default
+\fi
+
+% title for topics, admonitions, unsupported section levels, and sidebar
+\providecommand*{\DUtitle}[2][class-arg]{%
+ % call \DUtitle#1{#2} if it exists:
+ \ifcsname DUtitle#1\endcsname%
+ \csname DUtitle#1\endcsname{#2}%
+ \else
+ \smallskip\noindent\textbf{#2}\smallskip%
+ \fi
+}
+
+% titlereference role
+\providecommand*{\DUroletitlereference}[1]{\textsl{#1}}
+
+% character width in monospaced font
+\newlength{\ttemwidth}
+\settowidth{\ttemwidth}{\ttfamily M}
+
+% hyperlinks:
+\ifthenelse{\isundefined{\hypersetup}}{
+ \usepackage[colorlinks=true,linkcolor=blue,urlcolor=blue]{hyperref}
+ \usepackage{bookmark}
+ \urlstyle{same} % normal text font (alternatives: tt, rm, sf)
+}{}
+
+%%% Body
+\begin{document}
+
+In LaTeX, literal blocks can be customized with the \textquotedbl{}literal-block-env\textquotedbl{}
+setting. This test file exists to check if the LaTeX writer output compiles
+and looks as expected.
+
+Start with a plain literal block:
+
+\begin{quote}
+\begin{verbatimtab}
+$\sin^2(x)$ and $\cos^2(x)$ equals one:
+
+\[
+ \sin^2(x) + \cos^2(x) = 1 % for all x
+\]
+\end{verbatimtab}
+\end{quote}
+
+A latex \textquotedbl{}code-block\textquotedbl{} (set with \textquotedbl{}literal-block-env\textquotedbl{}, if syntax
+highlight is \textquotedbl{}none\textquotedbl{}):
+
+\begin{DUclass}{code}
+\begin{DUclass}{latex}
+\begin{quote}
+\begin{verbatimtab}
+$\sin^2(x)$ and $\cos^2(x)$ equals one:
+
+\[
+ \sin^2(x) + \cos^2(x) = 1 % for all x
+\]
+\end{verbatimtab}
+\end{quote}
+\end{DUclass}
+\end{DUclass}
+
+A literal block in a table:
+
+\setlength{\DUtablewidth}{\linewidth}
+\begin{longtable*}[c]{|p{0.063\DUtablewidth}|p{0.145\DUtablewidth}|p{0.063\DUtablewidth}|}
+\hline
+
+test
+ &
+\begin{minipage}{8\ttemwidth}
+\begin{verbatimtab}
+\sin^2 x
+\end{verbatimtab}
+\end{minipage}
+ &
+test
+ \\
+\hline
+\end{longtable*}
+
+A literal block in a table with auto-width columns:
+
+\begin{longtable*}[c]{|l|l|l|}
+\hline
+test &
+\ttfamily\raggedright
+\textbackslash{}sin\textasciicircum{}2~x
+ & test \\
+\hline
+\end{longtable*}
+
+\DUadmonition[note]{
+\DUtitle[note]{Note}
+
+A literal block in an admonition:
+
+\begin{quote}
+\ttfamily\raggedright
+\textbackslash{}sin\textasciicircum{}2~x
+\end{quote}
+}
+
+Parsed literal block with inline markup and leading whitespace:
+
+\begin{quote}
+\ttfamily\raggedright
+~~~\emph{emphasis},~\textbf{strong~emphasis},~\texttt{inline~literals},\\
+standalone~hyperlinks~(\url{http://www.python.org}),\\
+\hyperref[internal]{internal}~and~\href{http://www.python.org/}{external}~hyperlinks,\\
+%
+\phantomsection\label{internal}internal~hyperlink~targets,\\
+images~via~substitution~references~(\includegraphics{../../../docs/user/rst/images/biohazard.png}),\\
+footnote~references\DUfootnotemark{footnote-reference-1}{footnote-1}{*},\\
+citation~references~(\hyperlink{cit2002}{[CIT2002]}),~and~more.\\
+~\\
+~~~Here~are~some~explicit~interpreted~text~roles:\\
+a~PEP~reference~(\href{http://www.python.org/dev/peps/pep-0287}{PEP~287}),\\
+an~RFC~reference~(\href{http://tools.ietf.org/html/rfc2822.html}{RFC~2822}),\\
+an~abbreviation~(\DUrole{abbreviation}{abb.}),~an~acronym~(\DUrole{acronym}{reST}),\\
+code~(\texttt{\DUrole{code}{print~\textquotedbl{}hello~world\textquotedbl{}}}),\\
+maths~$\sin^2(x)$,\\
+\textsubscript{subscript}~and~\textsuperscript{superscript},\\
+\DUrole{custom}{custom}~\DUrole{custom-role}{roles},~and~explicit~roles~for\\
+\DUroletitlereference{Docutils}'~\emph{standard}~\textbf{inline}~\texttt{markup}.
+\end{quote}
+%
+\DUfootnotetext{footnote-1}{footnote-reference-1}{*}{%
+This footnote is referenced in a \DUroletitlereference{parsed literal} block.
+
+It contains a literal block:
+
+\begin{quote}
+\ttfamily\raggedright
+\textbackslash{}sin\textasciicircum{}2~x
+\end{quote}
+}
+\begin{figure}[b]\raisebox{1em}{\hypertarget{cit2002}{}}[CIT2002]
+Sample Citation, 2017.
+\end{figure}
+
+\end{document}
--- /dev/null
+<?xml version="1.0" encoding="utf-8" ?>
+<!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">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<meta name="generator" content="Docutils 0.16: http://docutils.sourceforge.net/" />
+<title>Mathematics</title>
+<link rel="stylesheet" href="../input/data/html4css1.css" type="text/css" />
+<link rel="stylesheet" href="../input/data/math.css" type="text/css" />
+</head>
+<body>
+<div class="document" id="mathematics">
+<h1 class="title">Mathematics</h1>
+
+<p>Docutils supports inline math with the prefix or postfix <tt class="docutils literal">:math:</tt>
+role specificator, <span class="formula"><i>n</i>! + sin(<i>x</i><span class="scripts"><sup class="script">2</sup><sub class="script"><i>n</i></sub></span>)</span> and <span class="formula"><i>A</i><sub><span class="text">c</span></sub> = <span class="fraction"><span class="ignored">(</span><span class="numerator"><i>π</i></span><span class="ignored">)/(</span><span class="denominator">4</span><span class="ignored">)</span></span><i>d</i><sup>2</sup></span>, as well as displayed math via the
+<cite>math</cite> directive:</p>
+<div class="formula">
+<i>f</i>(<i>ϵ</i>) = <span class="fraction"><span class="ignored">(</span><span class="numerator">1</span><span class="ignored">)/(</span><span class="denominator">1 + exp<span class="array"><span class="arrayrow"><span class="bracket align-left">⎛</span></span><span class="arrayrow"><span class="bracket align-left">⎝</span></span></span><span class="fraction"><span class="ignored">(</span><span class="numerator"><i>ε</i></span><span class="ignored">)/(</span><span class="denominator"><i>k</i><sub><span class="text">B</span></sub><i>T</i></span><span class="ignored">)</span></span><span class="array"><span class="arrayrow"><span class="bracket align-right">⎞</span></span><span class="arrayrow"><span class="bracket align-right">⎠</span></span></span></span><span class="ignored">)</span></span>
+</div>
+<p>Content may start on the first line of the directive, e.g.</p>
+<div class="formula">
+<i>N</i> = <span class="fraction"><span class="ignored">(</span><span class="numerator"><span class="text">number of apples</span></span><span class="ignored">)/(</span><span class="denominator">7</span><span class="ignored">)</span></span>
+</div>
+<p>Equations can be labeled with a reference name using the <tt class="docutils literal">:name:</tt> option.
+See <a class="reference internal" href="#eq-m">eq:M</a> and <a class="reference internal" href="#eq-schrodinger">eq:schrödinger</a> below.</p>
+<p>The determinant of the matrix</p>
+<div class="formula" id="eq-m">
+<b>M</b> = <span class="array"><span class="arrayrow"><span class="bracket align-left">⎛</span></span><span class="arrayrow"><span class="bracket align-left">⎜</span></span><span class="arrayrow"><span class="bracket align-left">⎝</span></span></span><span class="array"><span class="arrayrow">
+<span class="arraycell align-c">
+<i>a</i>
+</span>
+<span class="arraycell align-c">
+<i>b</i>
+</span>
+
+</span>
+<span class="arrayrow">
+<span class="arraycell align-c">
+
+</span>
+<span class="arraycell align-c">
+
+</span>
+
+</span>
+<span class="arrayrow">
+<span class="arraycell align-c">
+<i>c</i>
+</span>
+<span class="arraycell align-c">
+<i>d</i>
+</span>
+
+</span>
+</span><span class="array"><span class="arrayrow"><span class="bracket align-right">⎞</span></span><span class="arrayrow"><span class="bracket align-right">⎟</span></span><span class="arrayrow"><span class="bracket align-right">⎠</span></span></span>
+</div>
+<p>is <span class="formula">|<b>M</b>| = <i>ad</i> − <i>bc</i></span>.</p>
+<p>More than one display math block can be put in one math directive.
+For example, the following sum and integral with limits:</p>
+<div class="formula">
+<span class="limits"><sup class="limit">1</sup><span class="limit">⌠</span><span class="limit">⌡</span><sub class="limit">0</sub></span><i>x</i><sup><i>n</i></sup><i>dx</i> = <span class="fraction"><span class="ignored">(</span><span class="numerator">1</span><span class="ignored">)/(</span><span class="denominator"><i>n</i> + 1</span><span class="ignored">)</span></span>
+</div>
+<div class="formula">
+<span class="limits"><sup class="limit"><i>m</i></sup><span class="limit">⎲</span><span class="limit">⎳</span><sub class="limit"><i>n</i> = 1</sub></span><i>n</i> = <span class="fraction"><span class="ignored">(</span><span class="numerator"><i>m</i>(<i>m</i> + 1)</span><span class="ignored">)/(</span><span class="denominator">2</span><span class="ignored">)</span></span>
+</div>
+<p>LaTeX-supported Unicode math symbols can be used in math roles and
+directives:</p>
+<p>The Schrödinger equation</p>
+<div class="formula" id="eq-schrodinger">
+<i>i</i>ℏ<span class="fraction"><span class="ignored">(</span><span class="numerator">∂</span><span class="ignored">)/(</span><span class="denominator">∂<i>t</i></span><span class="ignored">)</span></span>Ψ = <i>Ĥ</i>Ψ,
+</div>
+<p>with the <em>wave function</em> <span class="formula">Ψ</span>, describes how the quantum state of a
+physical system changes in time.</p>
+<dl class="docutils">
+<dt>Math-Accents:</dt>
+<dd><table border="1" class="colwidths-given borderless first last docutils">
+<colgroup>
+<col width="33%" />
+<col width="33%" />
+<col width="33%" />
+</colgroup>
+<tbody valign="top">
+<tr><td><span class="formula"><i>á</i></span> <tt class="docutils literal">\acute{a}</tt></td>
+<td><span class="formula"><i>ṫ</i></span> <tt class="docutils literal">\dot{t}</tt></td>
+<td><span class="formula"><i>γ̂</i></span> <tt class="docutils literal"><span class="pre">\hat{\gamma}</span></tt></td>
+</tr>
+<tr><td><span class="formula"><i>à</i></span> <tt class="docutils literal">\grave{a}</tt></td>
+<td><span class="formula"><i>ẗ</i></span> <tt class="docutils literal">\ddot{t}</tt></td>
+<td><span class="formula"><i>α̃</i></span> <tt class="docutils literal"><span class="pre">\tilde{\alpha}</span></tt></td>
+</tr>
+<tr><td><span class="formula"><i>x̆</i></span> <tt class="docutils literal">\breve{x}</tt></td>
+<td><span class="formula"><i>t⃛</i></span> <tt class="docutils literal">\dddot{t}</tt></td>
+<td><span class="formula"><i>ı⃗</i></span> <tt class="docutils literal"><span class="pre">\vec{\imath}</span></tt></td>
+</tr>
+<tr><td><span class="formula"><i>ǎ</i></span> <tt class="docutils literal">\check{a}</tt></td>
+<td><span class="formula"><span class="bar"><i>a</i></span></span> <tt class="docutils literal">\bar{a}</tt></td>
+<td><span class="formula"><i>R⃗</i></span> <tt class="docutils literal">\vec{R}</tt></td>
+</tr>
+</tbody>
+</table>
+</dd>
+</dl>
+<!-- \widetilde{xxx}
+\widehat{xxx} -->
+<p>Modulation Transfer Function:</p>
+<div class="formula">
+<span class="text">MTF</span> = <span class="array"><span class="arrayrow"><span class="bracket align-left">|</span></span><span class="arrayrow"><span class="bracket align-left">|</span></span></span><span class="fraction"><span class="ignored">(</span><span class="numerator">ℱ{<i>s</i>(<i>x</i>)}</span><span class="ignored">)/(</span><span class="denominator">ℱ{<i>s</i>(<i>x</i>)}|<sub><i>ω</i><sub><i>x</i></sub> = 0</sub></span><span class="ignored">)</span></span><span class="array"><span class="arrayrow"><span class="bracket align-right">|</span></span><span class="arrayrow"><span class="bracket align-right">|</span></span></span> = <span class="mathrm"> abs</span><span class="array"><span class="arrayrow"><span class="bracket align-left">⎛</span></span><span class="arrayrow"><span class="bracket align-left">⎝</span></span></span><span class="fraction"><span class="ignored">(</span><span class="numerator"><span class="limits"><span class="limit">⌠</span><span class="limit">⌡</span></span><span class="scripts"><sup class="script">∞</sup><sub class="script"> − ∞</sub></span><i>s</i>(<i>x</i>)<span class="mathrm">e</span><sup><span class="mathrm">i</span><i>ω</i><sub><i>x</i></sub><i>x</i></sup><span class="mathrm">d</span><i>x</i></span><span class="ignored">)/(</span><span class="denominator"><span class="limits"><span class="limit">⌠</span><span class="limit">⌡</span></span><span class="scripts"><sup class="script">∞</sup><sub class="script"> − ∞</sub></span><i>s</i>(<i>x</i>)<span class="mathrm">d</span><i>x</i></span><span class="ignored">)</span></span><span class="array"><span class="arrayrow"><span class="bracket align-right">⎞</span></span><span class="arrayrow"><span class="bracket align-right">⎠</span></span></span>.
+</div>
+<p>Math split over two lines: If a double backslash is detected outside a
+<tt class="docutils literal"><span class="pre">\begin{...}</span> <span class="pre">\end{...}</span></tt> pair, the math code is wrapped in an <a class="reference external" href="ftp://ftp.ams.org/ams/doc/amsmath/short-math-guide.pdf">AMSmath</a>
+<tt class="docutils literal">align</tt> environment:</p>
+<div class="formula">
+<span class="environment"><span class="arrayrow">
+<span class="arraycell align-r">
+<i>s</i><sub><span class="mathrm">out</span></sub>(<i>x</i>)
+</span>
+<span class="arraycell align-l">
+ = <i>s</i><sub><span class="mathrm">in</span></sub>(<i>x</i>’)*<i>s</i><sub><i>δ</i></sub>(<i>x</i> − <i>x</i>’)
+</span>
+
+</span>
+<span class="arrayrow">
+<span class="arraycell align-r">
+
+</span>
+<span class="arraycell align-l">
+
+</span>
+
+</span>
+<span class="arrayrow">
+<span class="arraycell align-r">
+
+</span>
+<span class="arraycell align-l">
+ = <span class="limits"><span class="limit">⌠</span><span class="limit">⌡</span></span><i>s</i><sub><span class="mathrm">in</span></sub>(<i>x</i>’)<i>s</i><sub><i>δ</i></sub>(<i>x</i> − <i>x</i>’)<span class="mathrm">d</span><i>x</i>’
+</span>
+
+</span>
+</span>
+</div>
+<p>Cases ("manually", with <tt class="docutils literal">matrix</tt> environment):</p>
+<div class="formula">
+<span class="mathrm">sgn</span>(<i>x</i>) = <span class="array"><span class="arrayrow"><span class="bracket align-left">⎧</span></span><span class="arrayrow"><span class="bracket align-left">⎨</span></span><span class="arrayrow"><span class="bracket align-left">⎩</span></span></span><span class="array"><span class="arrayrow">
+<span class="arraycell align-c">
+ − 1
+</span>
+<span class="arraycell align-c">
+<i>x</i> < 0
+</span>
+
+</span>
+<span class="arrayrow">
+<span class="arraycell align-c">
+
+</span>
+<span class="arraycell align-c">
+
+</span>
+
+</span>
+<span class="arrayrow">
+<span class="arraycell align-c">
+1
+</span>
+<span class="arraycell align-c">
+<i>x</i> > 0
+</span>
+
+</span>
+</span><span class="emptydot"></span>
+</div>
+<p>Cases with the <a class="reference external" href="ftp://ftp.ams.org/ams/doc/amsmath/short-math-guide.pdf">AMSmath</a> <tt class="docutils literal">cases</tt> environment (not (yet) supported by
+HTML writers with <tt class="docutils literal"><span class="pre">--math-output=MathML</span></tt>):</p>
+<div class="formula">
+<span class="mathrm">sgn</span>(<i>x</i>) = <span class="array"><span class="arrayrow"><span class="bracket align-l">⎧</span></span><span class="arrayrow"><span class="bracket align-l">⎨</span></span><span class="arrayrow"><span class="bracket align-l">⎩</span></span></span><span class="bracketcases">
+<span class="arrayrow">
+<span class="case align-l">
+ − 1
+</span>
+<span class="case align-l">
+<i>x</i> < 0
+</span>
+
+</span>
+<span class="arrayrow">
+<span class="case align-l">
+
+</span>
+<span class="case align-l">
+
+</span>
+
+</span>
+<span class="arrayrow">
+<span class="case align-l">
+1
+</span>
+<span class="case align-l">
+<i>x</i> > 0
+</span>
+
+</span>
+
+</span>
+
+</div>
+</div>
+</body>
+</html>
--- /dev/null
+<?xml version="1.0" encoding="utf-8" ?>
+<!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">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<meta name="generator" content="Docutils 0.16: http://docutils.sourceforge.net/" />
+<title>Mathematics</title>
+<link rel="stylesheet" href="../input/data/html4css1.css" type="text/css" />
+</head>
+<body>
+<div class="document" id="mathematics">
+<h1 class="title">Mathematics</h1>
+
+<p>Docutils supports inline math with the prefix or postfix <tt class="docutils literal">:math:</tt>
+role specificator, <tt class="math">n! + \sin(x_n^2)</tt> and <tt class="math">A_\text{c} =
+\frac{\pi}{4} d^2</tt>, as well as displayed math via the
+<cite>math</cite> directive:</p>
+<pre class="math">
+f(\epsilon) = \frac{1}{1 + \exp\left(\frac{\varepsilon}{k_\text{B}T}\right)}
+</pre>
+<p>Content may start on the first line of the directive, e.g.</p>
+<pre class="math">
+N = \frac{\text{number of apples}}{7}
+</pre>
+<p>Equations can be labeled with a reference name using the <tt class="docutils literal">:name:</tt> option.
+See <a class="reference internal" href="#eq-m">eq:M</a> and <a class="reference internal" href="#eq-schrodinger">eq:schrödinger</a> below.</p>
+<p>The determinant of the matrix</p>
+<pre class="math" id="eq-m">
+\mathbf{M} = \left(\begin{matrix}a&b\\c&d\end{matrix}\right)
+</pre>
+<p>is <tt class="math">|\mathbf{M}| = ad - bc</tt>.</p>
+<p>More than one display math block can be put in one math directive.
+For example, the following sum and integral with limits:</p>
+<pre class="math">
+\int_0^1 x^n dx = \frac{1}{n + 1}
+</pre>
+<pre class="math">
+\sum_{n=1}^m n = \frac{m(m+1)}{2}
+</pre>
+<p>LaTeX-supported Unicode math symbols can be used in math roles and
+directives:</p>
+<p>The Schrödinger equation</p>
+<pre class="math" id="eq-schrodinger">
+i\hbar \frac{\partial }{\partial t}\Psi = \hat{H}\Psi ,
+</pre>
+<p>with the <em>wave function</em> <tt class="math">\Psi </tt>, describes how the quantum state of a
+physical system changes in time.</p>
+<dl class="docutils">
+<dt>Math-Accents:</dt>
+<dd><table border="1" class="colwidths-given borderless first last docutils">
+<colgroup>
+<col width="33%" />
+<col width="33%" />
+<col width="33%" />
+</colgroup>
+<tbody valign="top">
+<tr><td><tt class="math">\acute{a}</tt> <tt class="docutils literal">\acute{a}</tt></td>
+<td><tt class="math">\dot{t}</tt> <tt class="docutils literal">\dot{t}</tt></td>
+<td><tt class="math">\hat{\gamma}</tt> <tt class="docutils literal"><span class="pre">\hat{\gamma}</span></tt></td>
+</tr>
+<tr><td><tt class="math">\grave{a}</tt> <tt class="docutils literal">\grave{a}</tt></td>
+<td><tt class="math">\ddot{t}</tt> <tt class="docutils literal">\ddot{t}</tt></td>
+<td><tt class="math">\tilde{\alpha}</tt> <tt class="docutils literal"><span class="pre">\tilde{\alpha}</span></tt></td>
+</tr>
+<tr><td><tt class="math">\breve{x}</tt> <tt class="docutils literal">\breve{x}</tt></td>
+<td><tt class="math">\dddot{t}</tt> <tt class="docutils literal">\dddot{t}</tt></td>
+<td><tt class="math">\vec{\imath}</tt> <tt class="docutils literal"><span class="pre">\vec{\imath}</span></tt></td>
+</tr>
+<tr><td><tt class="math">\check{a}</tt> <tt class="docutils literal">\check{a}</tt></td>
+<td><tt class="math">\bar{a}</tt> <tt class="docutils literal">\bar{a}</tt></td>
+<td><tt class="math">\vec{R}</tt> <tt class="docutils literal">\vec{R}</tt></td>
+</tr>
+</tbody>
+</table>
+</dd>
+</dl>
+<!-- \widetilde{xxx}
+\widehat{xxx} -->
+<p>Modulation Transfer Function:</p>
+<pre class="math">
+\text{MTF} = \left|\frac{\mathcal{F}\{s(x)\}}
+ {\mathcal{F}\{ s(x)\} |_{\omega _{x}=0}}\right|
+ = \mathrm{abs}\left(\frac
+ {\int _{-\infty }^{\infty }s(x) \mathrm{e}^{\mathrm{i}\omega _{x}x}\mathrm{d}{x}}
+ {\int _{-\infty }^{\infty }s(x)\mathrm{d}{x}}
+ \right).
+</pre>
+<p>Math split over two lines: If a double backslash is detected outside a
+<tt class="docutils literal"><span class="pre">\begin{...}</span> <span class="pre">\end{...}</span></tt> pair, the math code is wrapped in an <a class="reference external" href="ftp://ftp.ams.org/ams/doc/amsmath/short-math-guide.pdf">AMSmath</a>
+<tt class="docutils literal">align</tt> environment:</p>
+<pre class="math">
+s_{\mathrm{out}}(x) & = s_{\mathrm{in}}(x') * s_\delta (x-x') \\
+ & = \int s_{\mathrm{in}}(x')s_\delta (x-x')\mathrm{d}x'
+</pre>
+<p>Cases ("manually", with <tt class="docutils literal">matrix</tt> environment):</p>
+<pre class="math">
+\mathrm{sgn}(x) = \left\{\begin{matrix}
+ -1 & x<0\\
+ 1 & x>0
+ \end{matrix}\right.
+</pre>
+<p>Cases with the <a class="reference external" href="ftp://ftp.ams.org/ams/doc/amsmath/short-math-guide.pdf">AMSmath</a> <tt class="docutils literal">cases</tt> environment (not (yet) supported by
+HTML writers with <tt class="docutils literal"><span class="pre">--math-output=MathML</span></tt>):</p>
+<pre class="math">
+\mathrm{sgn}(x) = \begin{cases}
+ -1 & x<0\\
+ 1 & x>0
+ \end{cases}
+</pre>
+</div>
+</body>
+</html>
--- /dev/null
+<?xml version="1.0" encoding="utf-8" ?>
+<!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">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<meta name="generator" content="Docutils 0.16: http://docutils.sourceforge.net/" />
+<title>Mathematics</title>
+<script type="text/javascript" src="/usr/share/javascript/mathjax/MathJax.js?config=TeX-AMS_CHTML"></script>
+<link rel="stylesheet" href="../input/data/html4css1.css" type="text/css" />
+</head>
+<body>
+<div class="document" id="mathematics">
+<h1 class="title">Mathematics</h1>
+
+<p>Docutils supports inline math with the prefix or postfix <tt class="docutils literal">:math:</tt>
+role specificator, <span class="math">\(n! + \sin(x_n^2)\)</span> and <span class="math">\(A_\text{c} =
+\frac{\pi}{4} d^2\)</span>, as well as displayed math via the
+<cite>math</cite> directive:</p>
+<div class="math">
+\begin{equation*}
+f(\epsilon) = \frac{1}{1 + \exp\left(\frac{\varepsilon}{k_\text{B}T}\right)}
+\end{equation*}
+</div>
+<p>Content may start on the first line of the directive, e.g.</p>
+<div class="math">
+\begin{equation*}
+N = \frac{\text{number of apples}}{7}
+\end{equation*}
+</div>
+<p>Equations can be labeled with a reference name using the <tt class="docutils literal">:name:</tt> option.
+See <a class="reference internal" href="#eq-m">eq:M</a> and <a class="reference internal" href="#eq-schrodinger">eq:schrödinger</a> below.</p>
+<p>The determinant of the matrix</p>
+<div class="math" id="eq-m">
+\begin{equation*}
+\mathbf{M} = \left(\begin{matrix}a&b\\c&d\end{matrix}\right)
+\end{equation*}
+</div>
+<p>is <span class="math">\(|\mathbf{M}| = ad - bc\)</span>.</p>
+<p>More than one display math block can be put in one math directive.
+For example, the following sum and integral with limits:</p>
+<div class="math">
+\begin{equation*}
+\int_0^1 x^n dx = \frac{1}{n + 1}
+\end{equation*}
+</div>
+<div class="math">
+\begin{equation*}
+\sum_{n=1}^m n = \frac{m(m+1)}{2}
+\end{equation*}
+</div>
+<p>LaTeX-supported Unicode math symbols can be used in math roles and
+directives:</p>
+<p>The Schrödinger equation</p>
+<div class="math" id="eq-schrodinger">
+\begin{equation*}
+i\hbar \frac{\partial }{\partial t}\Psi = \hat{H}\Psi ,
+\end{equation*}
+</div>
+<p>with the <em>wave function</em> <span class="math">\(\Psi \)</span>, describes how the quantum state of a
+physical system changes in time.</p>
+<dl class="docutils">
+<dt>Math-Accents:</dt>
+<dd><table border="1" class="colwidths-given borderless first last docutils">
+<colgroup>
+<col width="33%" />
+<col width="33%" />
+<col width="33%" />
+</colgroup>
+<tbody valign="top">
+<tr><td><span class="math">\(\acute{a}\)</span> <tt class="docutils literal">\acute{a}</tt></td>
+<td><span class="math">\(\dot{t}\)</span> <tt class="docutils literal">\dot{t}</tt></td>
+<td><span class="math">\(\hat{\gamma}\)</span> <tt class="docutils literal"><span class="pre">\hat{\gamma}</span></tt></td>
+</tr>
+<tr><td><span class="math">\(\grave{a}\)</span> <tt class="docutils literal">\grave{a}</tt></td>
+<td><span class="math">\(\ddot{t}\)</span> <tt class="docutils literal">\ddot{t}</tt></td>
+<td><span class="math">\(\tilde{\alpha}\)</span> <tt class="docutils literal"><span class="pre">\tilde{\alpha}</span></tt></td>
+</tr>
+<tr><td><span class="math">\(\breve{x}\)</span> <tt class="docutils literal">\breve{x}</tt></td>
+<td><span class="math">\(\dddot{t}\)</span> <tt class="docutils literal">\dddot{t}</tt></td>
+<td><span class="math">\(\vec{\imath}\)</span> <tt class="docutils literal"><span class="pre">\vec{\imath}</span></tt></td>
+</tr>
+<tr><td><span class="math">\(\check{a}\)</span> <tt class="docutils literal">\check{a}</tt></td>
+<td><span class="math">\(\bar{a}\)</span> <tt class="docutils literal">\bar{a}</tt></td>
+<td><span class="math">\(\vec{R}\)</span> <tt class="docutils literal">\vec{R}</tt></td>
+</tr>
+</tbody>
+</table>
+</dd>
+</dl>
+<!-- \widetilde{xxx}
+\widehat{xxx} -->
+<p>Modulation Transfer Function:</p>
+<div class="math">
+\begin{equation*}
+\text{MTF} = \left|\frac{\mathcal{F}\{s(x)\}}
+ {\mathcal{F}\{ s(x)\} |_{\omega _{x}=0}}\right|
+ = \mathrm{abs}\left(\frac
+ {\int _{-\infty }^{\infty }s(x) \mathrm{e}^{\mathrm{i}\omega _{x}x}\mathrm{d}{x}}
+ {\int _{-\infty }^{\infty }s(x)\mathrm{d}{x}}
+ \right).
+\end{equation*}
+</div>
+<p>Math split over two lines: If a double backslash is detected outside a
+<tt class="docutils literal"><span class="pre">\begin{...}</span> <span class="pre">\end{...}</span></tt> pair, the math code is wrapped in an <a class="reference external" href="ftp://ftp.ams.org/ams/doc/amsmath/short-math-guide.pdf">AMSmath</a>
+<tt class="docutils literal">align</tt> environment:</p>
+<div class="math">
+\begin{align*}
+s_{\mathrm{out}}(x) & = s_{\mathrm{in}}(x') * s_\delta (x-x') \\
+ & = \int s_{\mathrm{in}}(x')s_\delta (x-x')\mathrm{d}x'
+\end{align*}
+</div>
+<p>Cases ("manually", with <tt class="docutils literal">matrix</tt> environment):</p>
+<div class="math">
+\begin{equation*}
+\mathrm{sgn}(x) = \left\{\begin{matrix}
+ -1 & x<0\\
+ 1 & x>0
+ \end{matrix}\right.
+\end{equation*}
+</div>
+<p>Cases with the <a class="reference external" href="ftp://ftp.ams.org/ams/doc/amsmath/short-math-guide.pdf">AMSmath</a> <tt class="docutils literal">cases</tt> environment (not (yet) supported by
+HTML writers with <tt class="docutils literal"><span class="pre">--math-output=MathML</span></tt>):</p>
+<div class="math">
+\begin{equation*}
+\mathrm{sgn}(x) = \begin{cases}
+ -1 & x<0\\
+ 1 & x>0
+ \end{cases}
+\end{equation*}
+</div>
+</div>
+</body>
+</html>
--- /dev/null
+<!DOCTYPE html>
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+<meta charset="utf-8"/>
+<meta name="generator" content="Docutils 0.16: http://docutils.sourceforge.net/" />
+<title>Mathematics</title>
+<link rel="stylesheet" href="../input/data/minimal.css" type="text/css" />
+<link rel="stylesheet" href="../input/data/plain.css" type="text/css" />
+</head>
+<body>
+<div class="document" id="mathematics">
+<h1 class="title">Mathematics</h1>
+
+<p>Docutils supports inline math with the prefix or postfix <span class="docutils literal">:math:</span>
+role specificator, <math xmlns="http://www.w3.org/1998/Math/MathML">
+<mrow><mi>n</mi><mo>!</mo><mo>+</mo><mo>sin</mo><mo>(</mo><msubsup><mi>x</mi><mi>n</mi><mn>2</mn></msubsup><mo>)</mo></mrow></math> and <math xmlns="http://www.w3.org/1998/Math/MathML">
+<mrow><msub><mi>A</mi><mtext>c</mtext></msub><mo>=</mo><mfrac>
+<mrow><mi>π</mi></mrow>
+<mrow><mn>4</mn></mrow></mfrac><msup><mi>d</mi><mn>2</mn></msup></mrow></math>, as well as displayed math via the
+<cite>math</cite> directive:</p>
+<div>
+<math xmlns="http://www.w3.org/1998/Math/MathML" mode="display">
+<mtable>
+<mtr>
+<mtd><mi>f</mi><mo>(</mo><mi>ϵ</mi><mo>)</mo><mo>=</mo><mfrac>
+<mrow><mn>1</mn></mrow>
+<mrow><mn>1</mn><mo>+</mo><mo>exp</mo><mfenced open="(" close=")">
+<mrow><mfrac>
+<mrow><mi>ε</mi></mrow>
+<mrow><msub><mi>k</mi><mtext>B</mtext></msub><mi>T</mi></mrow></mfrac></mrow></mfenced></mrow></mfrac></mtd></mtr></mtable></math>
+</div>
+<p>Content may start on the first line of the directive, e.g.</p>
+<div>
+<math xmlns="http://www.w3.org/1998/Math/MathML" mode="display">
+<mtable>
+<mtr>
+<mtd><mi>N</mi><mo>=</mo><mfrac>
+<mrow><mtext>number of apples</mtext></mrow>
+<mrow><mn>7</mn></mrow></mfrac></mtd></mtr></mtable></math>
+</div>
+<p>Equations can be labeled with a reference name using the <span class="docutils literal">:name:</span> option.
+See <a class="reference internal" href="#eq-m">eq:M</a> and <a class="reference internal" href="#eq-schrodinger">eq:schrödinger</a> below.</p>
+<p>The determinant of the matrix</p>
+<div id="eq-m">
+<math xmlns="http://www.w3.org/1998/Math/MathML" mode="display">
+<mtable>
+<mtr>
+<mtd><mstyle fontweight="bold">
+<mrow><mi>M</mi></mrow></mstyle><mo>=</mo><mfenced open="(" close=")">
+<mrow>
+<mtable>
+<mtr>
+<mtd><mi>a</mi></mtd>
+<mtd><mi>b</mi></mtd></mtr>
+<mtr>
+<mtd><mi>c</mi></mtd>
+<mtd><mi>d</mi></mtd></mtr></mtable></mrow></mfenced></mtd></mtr></mtable></math>
+</div>
+<p>is <math xmlns="http://www.w3.org/1998/Math/MathML">
+<mrow><mo>|</mo><mstyle fontweight="bold">
+<mrow><mi>M</mi></mrow></mstyle><mo>|</mo><mo>=</mo><mi>a</mi><mi>d</mi><mo>-</mo><mi>b</mi><mi>c</mi></mrow></math>.</p>
+<p>More than one display math block can be put in one math directive.
+For example, the following sum and integral with limits:</p>
+<div>
+<math xmlns="http://www.w3.org/1998/Math/MathML" mode="display">
+<mtable>
+<mtr>
+<mtd><munderover><mo>∫</mo><mn>0</mn><mn>1</mn></munderover><msup><mi>x</mi><mi>n</mi></msup><mi>d</mi><mi>x</mi><mo>=</mo><mfrac>
+<mrow><mn>1</mn></mrow>
+<mrow><mi>n</mi><mo>+</mo><mn>1</mn></mrow></mfrac></mtd></mtr></mtable></math>
+</div>
+<div>
+<math xmlns="http://www.w3.org/1998/Math/MathML" mode="display">
+<mtable>
+<mtr>
+<mtd><munderover><mo>∑</mo>
+<mrow><mi>n</mi><mo>=</mo><mn>1</mn></mrow><mi>m</mi></munderover><mi>n</mi><mo>=</mo><mfrac>
+<mrow><mi>m</mi><mo>(</mo><mi>m</mi><mo>+</mo><mn>1</mn><mo>)</mo></mrow>
+<mrow><mn>2</mn></mrow></mfrac></mtd></mtr></mtable></math>
+</div>
+<p>LaTeX-supported Unicode math symbols can be used in math roles and
+directives:</p>
+<p>The Schrödinger equation</p>
+<div id="eq-schrodinger">
+<math xmlns="http://www.w3.org/1998/Math/MathML" mode="display">
+<mtable>
+<mtr>
+<mtd><mi>i</mi><mi>ℏ</mi><mfrac>
+<mrow><mo>∂</mo></mrow>
+<mrow><mo>∂</mo><mi>t</mi></mrow></mfrac><mo>Ψ</mo><mo>=</mo><mover>
+<mrow><mi>H</mi></mrow><mo>^</mo></mover><mo>Ψ</mo><mo>,</mo></mtd></mtr></mtable></math>
+</div>
+<p>with the <em>wave function</em> <math xmlns="http://www.w3.org/1998/Math/MathML">
+<mrow><mo>Ψ</mo></mrow></math>, describes how the quantum state of a
+physical system changes in time.</p>
+<dl>
+<dt>Math-Accents:</dt>
+<dd><table class="colwidths-given borderless">
+<colgroup>
+<col style="width: 33%" />
+<col style="width: 33%" />
+<col style="width: 33%" />
+</colgroup>
+<tbody>
+<tr><td><p><math xmlns="http://www.w3.org/1998/Math/MathML">
+<mrow><mover>
+<mrow><mi>a</mi></mrow><mo>´</mo></mover></mrow></math> <span class="docutils literal">\acute{a}</span></p></td>
+<td><p><math xmlns="http://www.w3.org/1998/Math/MathML">
+<mrow><mover>
+<mrow><mi>t</mi></mrow><mo>˙</mo></mover></mrow></math> <span class="docutils literal">\dot{t}</span></p></td>
+<td><p><math xmlns="http://www.w3.org/1998/Math/MathML">
+<mrow><mover>
+<mrow><mi>γ</mi></mrow><mo>^</mo></mover></mrow></math> <span class="docutils literal"><span class="pre">\hat{\gamma}</span></span></p></td>
+</tr>
+<tr><td><p><math xmlns="http://www.w3.org/1998/Math/MathML">
+<mrow><mover>
+<mrow><mi>a</mi></mrow><mo>`</mo></mover></mrow></math> <span class="docutils literal">\grave{a}</span></p></td>
+<td><p><math xmlns="http://www.w3.org/1998/Math/MathML">
+<mrow><mover>
+<mrow><mi>t</mi></mrow><mo>¨</mo></mover></mrow></math> <span class="docutils literal">\ddot{t}</span></p></td>
+<td><p><math xmlns="http://www.w3.org/1998/Math/MathML">
+<mrow><mover>
+<mrow><mi>α</mi></mrow><mo>˜</mo></mover></mrow></math> <span class="docutils literal"><span class="pre">\tilde{\alpha}</span></span></p></td>
+</tr>
+<tr><td><p><math xmlns="http://www.w3.org/1998/Math/MathML">
+<mrow><mover>
+<mrow><mi>x</mi></mrow><mo>˘</mo></mover></mrow></math> <span class="docutils literal">\breve{x}</span></p></td>
+<td><p><math xmlns="http://www.w3.org/1998/Math/MathML">
+<mrow><mover>
+<mrow><mi>t</mi></mrow><mo>⃛</mo></mover></mrow></math> <span class="docutils literal">\dddot{t}</span></p></td>
+<td><p><math xmlns="http://www.w3.org/1998/Math/MathML">
+<mrow><mover>
+<mrow><mi>ı</mi></mrow><mo>⃗</mo></mover></mrow></math> <span class="docutils literal"><span class="pre">\vec{\imath}</span></span></p></td>
+</tr>
+<tr><td><p><math xmlns="http://www.w3.org/1998/Math/MathML">
+<mrow><mover>
+<mrow><mi>a</mi></mrow><mo>ˇ</mo></mover></mrow></math> <span class="docutils literal">\check{a}</span></p></td>
+<td><p><math xmlns="http://www.w3.org/1998/Math/MathML">
+<mrow><mover>
+<mrow><mi>a</mi></mrow><mo>¯</mo></mover></mrow></math> <span class="docutils literal">\bar{a}</span></p></td>
+<td><p><math xmlns="http://www.w3.org/1998/Math/MathML">
+<mrow><mover>
+<mrow><mi>R</mi></mrow><mo>⃗</mo></mover></mrow></math> <span class="docutils literal">\vec{R}</span></p></td>
+</tr>
+</tbody>
+</table>
+</dd>
+</dl>
+<!-- \widetilde{xxx}
+\widehat{xxx} -->
+<p>Modulation Transfer Function:</p>
+<div>
+<math xmlns="http://www.w3.org/1998/Math/MathML" mode="display">
+<mtable>
+<mtr>
+<mtd><mtext>MTF</mtext><mo>=</mo><mfenced open="|" close="|">
+<mrow><mfrac>
+<mrow><mi>ℱ</mi><mo>{</mo><mi>s</mi><mo>(</mo><mi>x</mi><mo>)</mo><mo>}</mo></mrow>
+<mrow><mi>ℱ</mi><mo>{</mo><mi>s</mi><mo>(</mo><mi>x</mi><mo>)</mo><mo>}</mo><msub><mo>|</mo>
+<mrow><msub><mi>ω</mi>
+<mrow><mi>x</mi></mrow></msub><mo>=</mo><mn>0</mn></mrow></msub></mrow></mfrac></mrow></mfenced><mo>=</mo><mtext>abs</mtext><mfenced open="(" close=")">
+<mrow><mfrac>
+<mrow><munderover><mo>∫</mo>
+<mrow><mo>-</mo><mo>∞</mo></mrow>
+<mrow><mo>∞</mo></mrow></munderover><mi>s</mi><mo>(</mo><mi>x</mi><mo>)</mo><msup><mtext>e</mtext>
+<mrow><mtext>i</mtext><msub><mi>ω</mi>
+<mrow><mi>x</mi></mrow></msub><mi>x</mi></mrow></msup><mtext>d</mtext>
+<mrow><mi>x</mi></mrow></mrow>
+<mrow><munderover><mo>∫</mo>
+<mrow><mo>-</mo><mo>∞</mo></mrow>
+<mrow><mo>∞</mo></mrow></munderover><mi>s</mi><mo>(</mo><mi>x</mi><mo>)</mo><mtext>d</mtext>
+<mrow><mi>x</mi></mrow></mrow></mfrac></mrow></mfenced><mo>.</mo></mtd></mtr></mtable></math>
+</div>
+<p>Math split over two lines: If a double backslash is detected outside a
+<span class="docutils literal"><span class="pre">\begin{...}</span> <span class="pre">\end{...}</span></span> pair, the math code is wrapped in an <a class="reference external" href="ftp://ftp.ams.org/ams/doc/amsmath/short-math-guide.pdf">AMSmath</a>
+<span class="docutils literal">align</span> environment:</p>
+<div>
+<math xmlns="http://www.w3.org/1998/Math/MathML" mode="display">
+<mtable>
+<mtr>
+<mtd><msub><mi>s</mi>
+<mrow><mtext>out</mtext></mrow></msub><mo>(</mo><mi>x</mi><mo>)</mo></mtd>
+<mtd><mo>=</mo><msub><mi>s</mi>
+<mrow><mtext>in</mtext></mrow></msub><mo>(</mo><mi>x</mi><mo>'</mo><mo>)</mo><mo>*</mo><msub><mi>s</mi><mi>δ</mi></msub><mo>(</mo><mi>x</mi><mo>-</mo><mi>x</mi><mo>'</mo><mo>)</mo></mtd></mtr>
+<mtr>
+<mtd></mtd>
+<mtd><mo>=</mo><mo>∫</mo><msub><mi>s</mi>
+<mrow><mtext>in</mtext></mrow></msub><mo>(</mo><mi>x</mi><mo>'</mo><mo>)</mo><msub><mi>s</mi><mi>δ</mi></msub><mo>(</mo><mi>x</mi><mo>-</mo><mi>x</mi><mo>'</mo><mo>)</mo><mtext>d</mtext><mi>x</mi><mo>'</mo></mtd></mtr></mtable></math>
+</div>
+<p>Cases ("manually", with <span class="docutils literal">matrix</span> environment):</p>
+<div>
+<math xmlns="http://www.w3.org/1998/Math/MathML" mode="display">
+<mtable>
+<mtr>
+<mtd><mtext>sgn</mtext><mo>(</mo><mi>x</mi><mo>)</mo><mo>=</mo><mfenced open="{" close="">
+<mrow>
+<mtable>
+<mtr>
+<mtd><mo>-</mo><mn>1</mn></mtd>
+<mtd><mi>x</mi><mo><</mo><mn>0</mn></mtd></mtr>
+<mtr>
+<mtd><mn>1</mn></mtd>
+<mtd><mi>x</mi><mo>></mo><mn>0</mn></mtd></mtr></mtable></mrow></mfenced></mtd></mtr></mtable></math>
+</div>
+<p>Cases with the <a class="reference external" href="ftp://ftp.ams.org/ams/doc/amsmath/short-math-guide.pdf">AMSmath</a> <span class="docutils literal">cases</span> environment (not (yet) supported by
+HTML writers with <span class="docutils literal"><span class="pre">--math-output=MathML</span></span>):</p>
+<div class="system-message">
+<p class="system-message-title">System Message: ERROR/3 (<span class="docutils literal">functional/input/data/math.txt</span>, line 108)</p>
+<p>
+Environment not supported! Supported environment: "matrix".</p>
+<pre class="literal-block">
+\mathrm{sgn}(x) = \begin{cases}
+ -1 & x<0\\
+ 1 & x>0
+ \end{cases}
+</pre>
+</div>
+</div>
+</body>
+</html>
--- /dev/null
+<?xml version="1.0" encoding="utf-8" ?>
+<!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">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<meta name="generator" content="Docutils 0.16: http://docutils.sourceforge.net/" />
+<title>link_in_substitution.txt</title>
+<link rel="stylesheet" href="foo&bar.css" type="text/css" />
+</head>
+<body>
+<div class="document">
+
+
+<p>Test the interaction of transforms.references.Substitutions and
+transforms.references.ExternalLinks.</p>
+<p><a class="reference external" href="http://docutils.sourceforge.net/rst.html">reStructuredText</a> is cool!</p>
+<p>There is a preferred alternative:</p>
+<p><a class="reference external" href="http://docutils.sourceforge.net/rst.html">reStructuredText</a> is cool!</p>
+<p>This only works for the case where the entire substitution is a
+reference, not when the reference is embedded as part of the
+substitution:</p>
+<p>unstructured <a class="reference external" href="http://docutils.sourceforge.net/rst.html">reStructuredText</a> is uncool!</p>
+</div>
+</body>
+</html>
--- /dev/null
+<?xml version="1.0" encoding="utf-8" ?>
+<!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://www.python.org/dev/peps/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=utf-8" />
+ <meta name="generator" content="Docutils 0.16: http://docutils.sourceforge.net/" />
+ <title>PEP 100 -- Test PEP</title>
+ <link rel="stylesheet" href="../input/data/html4css1.css" type="text/css" />
+</head>
+<body bgcolor="white">
+<table class="navigation" cellpadding="0" cellspacing="0"
+ width="100%" border="0">
+<tr><td class="navicon" width="150" height="35">
+<a href="http://www.python.org/" title="Python Home Page">
+<img src="http://www.python.org/pics/PyBanner000.gif" alt="[Python]"
+ border="0" width="150" height="35" /></a></td>
+<td class="textlinks" align="left">
+[<b><a href="http://www.python.org/">Python Home</a></b>]
+[<b><a href="http://www.python.org/dev/peps/">PEP Index</a></b>]
+[<b><a href="http://www.python.org/peps/pep-0100.txt">PEP Source</a></b>]
+</td></tr></table>
+<div class="document">
+<table class="rfc2822 docutils field-list" frame="void" rules="none">
+<col class="field-name" />
+<col class="field-body" />
+<tbody valign="top">
+<tr class="field"><th class="field-name">PEP:</th><td class="field-body">100</td>
+</tr>
+<tr class="field"><th class="field-name">Title:</th><td class="field-body">Test PEP</td>
+</tr>
+<tr class="field"><th class="field-name">Version:</th><td class="field-body">42</td>
+</tr>
+<tr class="field"><th class="field-name">Last-Modified:</th><td class="field-body"><a class="reference external" href="http://hg.python.org/peps/file/default/pep-0100.txt">A long time ago.</a></td>
+</tr>
+<tr class="field"><th class="field-name">Author:</th><td class="field-body">John Doe <john at example.org></td>
+</tr>
+<tr class="field"><th class="field-name">Discussions-To:</th><td class="field-body"><<a class="reference external" href="mailto:devnull%40example.org?subject=PEP%20100">devnull at example.org</a>></td>
+</tr>
+<tr class="field"><th class="field-name">Status:</th><td class="field-body">Draft</td>
+</tr>
+<tr class="field"><th class="field-name">Type:</th><td class="field-body">Standards Track</td>
+</tr>
+<tr class="field"><th class="field-name">Content-Type:</th><td class="field-body"><a class="reference external" href="http://www.python.org/dev/peps/pep-0012">text/x-rst</a></td>
+</tr>
+<tr class="field"><th class="field-name">Created:</th><td class="field-body">01-Jun-2001</td>
+</tr>
+<tr class="field"><th class="field-name">Post-History:</th><td class="field-body">13-Jun-2001</td>
+</tr>
+</tbody>
+</table>
+<hr />
+<div class="contents topic" id="contents">
+<p class="topic-title">Contents</p>
+<ul class="simple">
+<li><a class="reference internal" href="#abstract" id="toc-entry-1">Abstract</a></li>
+<li><a class="reference internal" href="#copyright" id="toc-entry-2">Copyright</a></li>
+<li><a class="reference internal" href="#references-and-footnotes" id="toc-entry-3">References and Footnotes</a></li>
+</ul>
+</div>
+<div class="section" id="abstract">
+<h1><a class="toc-backref" href="#toc-entry-1">Abstract</a></h1>
+<p>This is just a test <a class="footnote-reference" href="#footnote-1" id="footnote-reference-1">[1]</a>. See the <a class="reference external" href="http://www.python.org/peps/">PEP repository</a> <a class="footnote-reference" href="#footnote-2" id="footnote-reference-2">[2]</a> for the real
+thing.</p>
+</div>
+<div class="section" id="copyright">
+<h1><a class="toc-backref" href="#toc-entry-2">Copyright</a></h1>
+<p>This document has been placed in the public domain.</p>
+</div>
+<div class="section" id="references-and-footnotes">
+<h1><a class="toc-backref" href="#toc-entry-3">References and Footnotes</a></h1>
+<table class="docutils footnote" frame="void" id="footnote-1" rules="none">
+<colgroup><col class="label" /><col /></colgroup>
+<tbody valign="top">
+<tr><td class="label"><a class="fn-backref" href="#footnote-reference-1">[1]</a></td><td>PEP editors: <a class="reference external" href="mailto:peps%40python.org">peps<span>@</span>python<span>.</span>org</a></td></tr>
+</tbody>
+</table>
+<table class="docutils footnote" frame="void" id="footnote-2" rules="none">
+<colgroup><col class="label" /><col /></colgroup>
+<tbody valign="top">
+<tr><td class="label"><a class="fn-backref" href="#footnote-reference-2">[2]</a></td><td><a class="reference external" href="http://www.python.org/peps/">http://www.python.org/peps/</a></td></tr>
+</tbody>
+</table>
+</div>
+
+</div>
+</body>
+</html>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE document PUBLIC "+//IDN docutils.sourceforge.net//DTD Docutils Generic//EN//XML" "http://docutils.sourceforge.net/docs/ref/docutils.dtd">
+<!-- Generated by Docutils 0.16 -->
+<document ids="restructuredtext-test-document doctitle" names="restructuredtext\ test\ document doctitle" source="functional/input/standalone_rst_docutils_xml.txt" title="reStructuredText Test Document">
+ <title>reStructuredText Test Document</title>
+ <subtitle ids="examples-of-syntax-constructs subtitle" names="examples\ of\ syntax\ constructs subtitle">Examples of Syntax Constructs</subtitle>
+ <decoration>
+ <header>
+ <paragraph>Document header</paragraph>
+ </header>
+ <footer>
+ <paragraph>Document footer</paragraph>
+ </footer>
+ </decoration>
+ <docinfo>
+ <author>David Goodger</author>
+ <address xml:space="preserve">123 Example Street
+Example, EX Canada
+A1B 2C3</address>
+ <contact><reference refuri="mailto:goodger@python.org">goodger@python.org</reference></contact>
+ <authors>
+ <author>Me</author>
+ <author>Myself</author>
+ <author>I</author>
+ </authors>
+ <organization>humankind</organization>
+ <date>Now, or yesterday. Or maybe even <emphasis>before</emphasis> yesterday.</date>
+ <status>This is a "work in progress"</status>
+ <revision>is managed by a version control system.</revision>
+ <version>1</version>
+ <copyright>This document has been placed in the public domain. You
+ may do with it as you wish. You may copy, modify,
+ redistribute, reattribute, sell, buy, rent, lease,
+ destroy, or improve it, quote it at length, excerpt,
+ incorporate, collate, fold, staple, or mutilate it, or do
+ anything else to it that your or anyone else's heart
+ desires.</copyright>
+ <field classes="field-name">
+ <field_name>field name</field_name>
+ <field_body>
+ <paragraph>This is a "generic bibliographic field".</paragraph>
+ </field_body>
+ </field>
+ <field classes="field-name-2">
+ <field_name>field name "2"</field_name>
+ <field_body>
+ <paragraph>Generic bibliographic fields may contain multiple body elements.</paragraph>
+ <paragraph>Like this.</paragraph>
+ </field_body>
+ </field>
+ </docinfo>
+ <topic classes="dedication">
+ <title>Dedication</title>
+ <paragraph>For Docutils users & co-developers.</paragraph>
+ </topic>
+ <topic classes="abstract">
+ <title>Abstract</title>
+ <paragraph>This is a test document, containing at least one example of each
+ reStructuredText construct.</paragraph>
+ </topic>
+ <comment xml:space="preserve">This is a comment. Note how any initial comments are moved by
+transforms to after the document title, subtitle, and docinfo.</comment>
+ <target refid="doctitle"></target>
+ <comment xml:space="preserve">Above is the document title, and below is the subtitle.
+They are transformed from section titles after parsing.</comment>
+ <target refid="subtitle"></target>
+ <comment xml:space="preserve">bibliographic fields (which also require a transform):</comment>
+ <raw format="latex" xml:space="preserve">\pagebreak[4] % start ToC on new page</raw>
+ <topic classes="contents" ids="table-of-contents" names="table\ of\ contents">
+ <title>Table of Contents</title>
+ <bullet_list classes="auto-toc">
+ <list_item>
+ <paragraph><reference ids="toc-entry-1" refid="structural-elements"><generated classes="sectnum">1 </generated>Structural Elements</reference></paragraph>
+ <bullet_list classes="auto-toc">
+ <list_item>
+ <paragraph><reference ids="toc-entry-2" refid="section-title"><generated classes="sectnum">1.1 </generated>Section Title</reference></paragraph>
+ </list_item>
+ <list_item>
+ <paragraph><reference ids="toc-entry-3" refid="empty-section"><generated classes="sectnum">1.2 </generated>Empty Section</reference></paragraph>
+ </list_item>
+ <list_item>
+ <paragraph><reference ids="toc-entry-4" refid="transitions"><generated classes="sectnum">1.3 </generated>Transitions</reference></paragraph>
+ </list_item>
+ </bullet_list>
+ </list_item>
+ <list_item>
+ <paragraph><reference ids="toc-entry-5" refid="body-elements"><generated classes="sectnum">2 </generated>Body Elements</reference></paragraph>
+ <bullet_list classes="auto-toc">
+ <list_item>
+ <paragraph><reference ids="toc-entry-6" refid="paragraphs"><generated classes="sectnum">2.1 </generated>Paragraphs</reference></paragraph>
+ <bullet_list classes="auto-toc">
+ <list_item>
+ <paragraph><reference ids="toc-entry-7" refid="inline-markup"><generated classes="sectnum">2.1.1 </generated>Inline Markup</reference></paragraph>
+ </list_item>
+ </bullet_list>
+ </list_item>
+ <list_item>
+ <paragraph><reference ids="toc-entry-8" refid="bullet-lists"><generated classes="sectnum">2.2 </generated>Bullet Lists</reference></paragraph>
+ </list_item>
+ <list_item>
+ <paragraph><reference ids="toc-entry-9" refid="enumerated-lists"><generated classes="sectnum">2.3 </generated>Enumerated Lists</reference></paragraph>
+ </list_item>
+ <list_item>
+ <paragraph><reference ids="toc-entry-10" refid="definition-lists"><generated classes="sectnum">2.4 </generated>Definition Lists</reference></paragraph>
+ </list_item>
+ <list_item>
+ <paragraph><reference ids="toc-entry-11" refid="field-lists"><generated classes="sectnum">2.5 </generated>Field Lists</reference></paragraph>
+ </list_item>
+ <list_item>
+ <paragraph><reference ids="toc-entry-12" refid="option-lists"><generated classes="sectnum">2.6 </generated>Option Lists</reference></paragraph>
+ </list_item>
+ <list_item>
+ <paragraph><reference ids="toc-entry-13" refid="literal-blocks"><generated classes="sectnum">2.7 </generated>Literal Blocks</reference></paragraph>
+ </list_item>
+ <list_item>
+ <paragraph><reference ids="toc-entry-14" refid="line-blocks"><generated classes="sectnum">2.8 </generated>Line Blocks</reference></paragraph>
+ </list_item>
+ <list_item>
+ <paragraph><reference ids="toc-entry-15" refid="block-quotes"><generated classes="sectnum">2.9 </generated>Block Quotes</reference></paragraph>
+ </list_item>
+ <list_item>
+ <paragraph><reference ids="toc-entry-16" refid="doctest-blocks"><generated classes="sectnum">2.10 </generated>Doctest Blocks</reference></paragraph>
+ </list_item>
+ <list_item>
+ <paragraph><reference ids="toc-entry-17" refid="footnotes"><generated classes="sectnum">2.11 </generated>Footnotes</reference></paragraph>
+ </list_item>
+ <list_item>
+ <paragraph><reference ids="toc-entry-18" refid="citations"><generated classes="sectnum">2.12 </generated>Citations</reference></paragraph>
+ </list_item>
+ <list_item>
+ <paragraph><reference ids="toc-entry-19" refid="targets"><generated classes="sectnum">2.13 </generated>Targets</reference></paragraph>
+ <bullet_list classes="auto-toc">
+ <list_item>
+ <paragraph><reference ids="toc-entry-20" refid="duplicate-target-names"><generated classes="sectnum">2.13.1 </generated>Duplicate Target Names</reference></paragraph>
+ </list_item>
+ <list_item>
+ <paragraph><reference ids="toc-entry-21" refid="duplicate-target-names-1"><generated classes="sectnum">2.13.2 </generated>Duplicate Target Names</reference></paragraph>
+ </list_item>
+ </bullet_list>
+ </list_item>
+ <list_item>
+ <paragraph><reference ids="toc-entry-22" refid="directives"><generated classes="sectnum">2.14 </generated>Directives</reference></paragraph>
+ <bullet_list classes="auto-toc">
+ <list_item>
+ <paragraph><reference ids="toc-entry-23" refid="document-parts"><generated classes="sectnum">2.14.1 </generated>Document Parts</reference></paragraph>
+ </list_item>
+ <list_item>
+ <paragraph><reference ids="toc-entry-24" refid="images-and-figures"><generated classes="sectnum">2.14.2 </generated>Images and Figures</reference></paragraph>
+ </list_item>
+ <list_item>
+ <paragraph><reference ids="toc-entry-25" refid="admonitions"><generated classes="sectnum">2.14.3 </generated>Admonitions</reference></paragraph>
+ </list_item>
+ <list_item>
+ <paragraph><reference ids="toc-entry-26" refid="topics-sidebars-and-rubrics"><generated classes="sectnum">2.14.4 </generated>Topics, Sidebars, and Rubrics</reference></paragraph>
+ </list_item>
+ <list_item>
+ <paragraph><reference ids="toc-entry-27" refid="target-footnotes"><generated classes="sectnum">2.14.5 </generated>Target Footnotes</reference></paragraph>
+ </list_item>
+ <list_item>
+ <paragraph><reference ids="toc-entry-28" refid="replacement-text"><generated classes="sectnum">2.14.6 </generated>Replacement Text</reference></paragraph>
+ </list_item>
+ <list_item>
+ <paragraph><reference ids="toc-entry-29" refid="compound-paragraph"><generated classes="sectnum">2.14.7 </generated>Compound Paragraph</reference></paragraph>
+ </list_item>
+ <list_item>
+ <paragraph><reference ids="toc-entry-30" refid="parsed-literal-blocks"><generated classes="sectnum">2.14.8 </generated>Parsed Literal Blocks</reference></paragraph>
+ </list_item>
+ <list_item>
+ <paragraph><reference ids="toc-entry-31" refid="code"><generated classes="sectnum">2.14.9 </generated>Code</reference></paragraph>
+ </list_item>
+ </bullet_list>
+ </list_item>
+ <list_item>
+ <paragraph><reference ids="toc-entry-32" refid="substitution-definitions"><generated classes="sectnum">2.15 </generated>Substitution Definitions</reference></paragraph>
+ </list_item>
+ <list_item>
+ <paragraph><reference ids="toc-entry-33" refid="comments"><generated classes="sectnum">2.16 </generated>Comments</reference></paragraph>
+ </list_item>
+ <list_item>
+ <paragraph><reference ids="toc-entry-34" refid="raw-text"><generated classes="sectnum">2.17 </generated>Raw text</reference></paragraph>
+ </list_item>
+ <list_item>
+ <paragraph><reference ids="toc-entry-35" refid="container"><generated classes="sectnum">2.18 </generated>Container</reference></paragraph>
+ </list_item>
+ <list_item>
+ <paragraph><reference ids="toc-entry-36" refid="colspanning-tables"><generated classes="sectnum">2.19 </generated>Colspanning tables</reference></paragraph>
+ </list_item>
+ <list_item>
+ <paragraph><reference ids="toc-entry-37" refid="rowspanning-tables"><generated classes="sectnum">2.20 </generated>Rowspanning tables</reference></paragraph>
+ </list_item>
+ <list_item>
+ <paragraph><reference ids="toc-entry-38" refid="complex-tables"><generated classes="sectnum">2.21 </generated>Complex tables</reference></paragraph>
+ </list_item>
+ <list_item>
+ <paragraph><reference ids="toc-entry-39" refid="list-tables"><generated classes="sectnum">2.22 </generated>List Tables</reference></paragraph>
+ </list_item>
+ </bullet_list>
+ </list_item>
+ <list_item>
+ <paragraph><reference ids="toc-entry-40" refid="error-handling"><generated classes="sectnum">3 </generated>Error Handling</reference></paragraph>
+ </list_item>
+ </bullet_list>
+ </topic>
+ <section ids="structural-elements" names="structural\ elements">
+ <title auto="1" refid="toc-entry-1"><generated classes="sectnum">1 </generated>Structural Elements</title>
+ <section ids="section-title" names="section\ title">
+ <title auto="1" refid="toc-entry-2"><generated classes="sectnum">1.1 </generated>Section Title</title>
+ <subtitle ids="section-subtitle" names="section\ subtitle">Section Subtitle</subtitle>
+ <paragraph>Lone subsections are converted to a section subtitle by a transform
+ activated with the <literal>--section-subtitles</literal> command line option or the
+ <literal>sectsubtitle-xform</literal> configuration value.</paragraph>
+ </section>
+ <section ids="empty-section" names="empty\ section">
+ <title auto="1" refid="toc-entry-3"><generated classes="sectnum">1.2 </generated>Empty Section</title>
+ </section>
+ <section ids="transitions" names="transitions">
+ <title auto="1" refid="toc-entry-4"><generated classes="sectnum">1.3 </generated>Transitions</title>
+ <paragraph>Here's a transition:</paragraph>
+ <transition></transition>
+ <paragraph>It divides the section. Transitions may also occur between sections:</paragraph>
+ </section>
+ </section>
+ <transition></transition>
+ <section ids="body-elements" names="body\ elements">
+ <title auto="1" refid="toc-entry-5"><generated classes="sectnum">2 </generated>Body Elements</title>
+ <section ids="paragraphs" names="paragraphs">
+ <title auto="1" refid="toc-entry-6"><generated classes="sectnum">2.1 </generated>Paragraphs</title>
+ <paragraph>A paragraph.</paragraph>
+ <section ids="inline-markup" names="inline\ markup">
+ <title auto="1" refid="toc-entry-7"><generated classes="sectnum">2.1.1 </generated>Inline Markup</title>
+ <paragraph>Paragraphs contain text and may contain inline markup: <emphasis>emphasis</emphasis>,
+ <strong>strong emphasis</strong>, <literal>inline literals</literal>, standalone hyperlinks
+ (<reference refuri="http://www.python.org">http://www.python.org</reference>), external hyperlinks (<reference name="Python" refuri="http://www.python.org/">Python</reference> <footnote_reference auto="1" ids="footnote-reference-10" refid="footnote-6">5</footnote_reference>), internal
+ cross-references (<reference name="example" refid="example">example</reference>), external hyperlinks with embedded URIs
+ (<reference name="Python web site" refuri="http://www.python.org">Python web site</reference>), <reference anonymous="1" name="anonymous hyperlink references" refuri="http://www.python.org/">anonymous hyperlink
+ references</reference> <footnote_reference auto="1" ids="footnote-reference-14" refid="footnote-6">5</footnote_reference> (<reference anonymous="1" name="a second reference" refuri="http://docutils.sourceforge.net/">a second reference</reference> <footnote_reference auto="1" ids="footnote-reference-15" refid="footnote-8">7</footnote_reference>), footnote references (manually
+ numbered <footnote_reference ids="footnote-reference-1" refid="footnote-1">1</footnote_reference>, anonymous auto-numbered <footnote_reference auto="1" ids="footnote-reference-2" refid="footnote-2">3</footnote_reference>, labeled auto-numbered
+ <footnote_reference auto="1" ids="footnote-reference-3" refid="label">2</footnote_reference>, or symbolic <footnote_reference auto="*" ids="footnote-reference-4" refid="footnote-3">*</footnote_reference>), citation references (<citation_reference ids="citation-reference-1" refid="cit2002">CIT2002</citation_reference>),
+ substitution references (<image alt="EXAMPLE" uri="../../../docs/user/rst/images/biohazard.png"></image> &
+ a <emphasis>trimmed heart</emphasis> <literal>(U+2665):</literal>♥), and <target ids="inline-hyperlink-targets" names="inline\ hyperlink\ targets">inline hyperlink targets</target>
+ (see <reference name="Targets" refid="targets">Targets</reference> below for a reference back to here). Character-level
+ inline markup is also possible (although exceedingly ugly!) in <emphasis>re</emphasis><literal>Structured</literal><emphasis>Text</emphasis>. Problems are indicated by <problematic ids="problematic-1" refid="system-message-1">|problematic|</problematic> text
+ (generated by processing errors; this one is intentional). Here is a
+ reference to the <reference name="doctitle" refid="doctitle">doctitle</reference> and the <reference name="subtitle" refid="subtitle">subtitle</reference>.</paragraph>
+ <target anonymous="1" ids="target-1" refuri="http://www.python.org/"></target>
+ <target anonymous="1" ids="target-2" refuri="http://docutils.sourceforge.net/"></target>
+ <paragraph>The default role for interpreted text is <title_reference>Title Reference</title_reference>. Here are
+ some explicit interpreted text roles: a PEP reference (<reference refuri="http://www.python.org/dev/peps/pep-0287">PEP 287</reference>); an
+ RFC reference (<reference refuri="http://tools.ietf.org/html/rfc2822.html">RFC 2822</reference>); an abbreviation (<abbreviation>abb.</abbreviation>), an acronym
+ (<acronym>reST</acronym>), code (<literal classes="code">print "hello world"</literal>); a <subscript>subscript</subscript>;
+ a <superscript>superscript</superscript> and explicit roles for <title_reference>Docutils</title_reference>'
+ <emphasis>standard</emphasis> <strong>inline</strong> <literal>markup</literal>.</paragraph>
+ <comment xml:space="preserve">DO NOT RE-WRAP THE FOLLOWING PARAGRAPH!</comment>
+ <paragraph>Let's test wrapping and whitespace significance in inline literals:
+ <literal>This is an example of --inline-literal --text, --including some--
+strangely--hyphenated-words. Adjust-the-width-of-your-browser-window
+to see how the text is wrapped. -- ---- -------- Now note the
+spacing between the words of this sentence (words
+should be grouped in pairs).</literal></paragraph>
+ <paragraph>If the <literal>--pep-references</literal> option was supplied, there should be a
+ live link to PEP 258 here.</paragraph>
+ </section>
+ </section>
+ <section ids="bullet-lists" names="bullet\ lists">
+ <title auto="1" refid="toc-entry-8"><generated classes="sectnum">2.2 </generated>Bullet Lists</title>
+ <bullet_list bullet="-">
+ <list_item>
+ <paragraph>A bullet list</paragraph>
+ <bullet_list bullet="+">
+ <list_item>
+ <paragraph>Nested bullet list.</paragraph>
+ </list_item>
+ <list_item>
+ <paragraph>Nested item 2.</paragraph>
+ </list_item>
+ </bullet_list>
+ </list_item>
+ <list_item>
+ <paragraph>Item 2.</paragraph>
+ <paragraph>Paragraph 2 of item 2.</paragraph>
+ <bullet_list bullet="*">
+ <list_item>
+ <paragraph>Nested bullet list.</paragraph>
+ </list_item>
+ <list_item>
+ <paragraph>Nested item 2.</paragraph>
+ <bullet_list bullet="-">
+ <list_item>
+ <paragraph>Third level.</paragraph>
+ </list_item>
+ <list_item>
+ <paragraph>Item 2.</paragraph>
+ </list_item>
+ </bullet_list>
+ </list_item>
+ <list_item>
+ <paragraph>Nested item 3.</paragraph>
+ </list_item>
+ <list_item>
+ <paragraph>This nested list should be compacted by the HTML writer.</paragraph>
+ <target ids="target" names="target"></target>
+ <comment xml:space="preserve">Even if this item contains a target and a comment.</comment>
+ </list_item>
+ </bullet_list>
+ </list_item>
+ </bullet_list>
+ </section>
+ <section ids="enumerated-lists" names="enumerated\ lists">
+ <title auto="1" refid="toc-entry-9"><generated classes="sectnum">2.3 </generated>Enumerated Lists</title>
+ <enumerated_list enumtype="arabic" prefix="" suffix=".">
+ <list_item>
+ <paragraph>Arabic numerals.</paragraph>
+ <enumerated_list enumtype="loweralpha" prefix="" suffix=")">
+ <list_item>
+ <paragraph>lower alpha)</paragraph>
+ <enumerated_list enumtype="lowerroman" prefix="(" suffix=")">
+ <list_item>
+ <paragraph>(lower roman)</paragraph>
+ <enumerated_list enumtype="upperalpha" prefix="" suffix=".">
+ <list_item>
+ <paragraph>upper alpha.</paragraph>
+ <enumerated_list enumtype="upperroman" prefix="" suffix=")">
+ <list_item>
+ <paragraph>upper roman)</paragraph>
+ </list_item>
+ </enumerated_list>
+ </list_item>
+ </enumerated_list>
+ </list_item>
+ </enumerated_list>
+ </list_item>
+ </enumerated_list>
+ </list_item>
+ <list_item>
+ <paragraph>Lists that don't start at 1:</paragraph>
+ <enumerated_list enumtype="arabic" prefix="" start="3" suffix=".">
+ <list_item>
+ <paragraph>Three</paragraph>
+ </list_item>
+ <list_item>
+ <paragraph>Four</paragraph>
+ </list_item>
+ </enumerated_list>
+ <system_message level="1" line="8" source="functional/input/data/standard.txt" type="INFO">
+ <paragraph>Enumerated list start value not ordinal-1: "3" (ordinal 3)</paragraph>
+ </system_message>
+ <enumerated_list enumtype="upperalpha" prefix="" start="3" suffix=".">
+ <list_item>
+ <paragraph>C</paragraph>
+ </list_item>
+ <list_item>
+ <paragraph>D</paragraph>
+ </list_item>
+ </enumerated_list>
+ <system_message level="1" line="8" source="functional/input/data/standard.txt" type="INFO">
+ <paragraph>Enumerated list start value not ordinal-1: "C" (ordinal 3)</paragraph>
+ </system_message>
+ <enumerated_list enumtype="lowerroman" prefix="" start="3" suffix=".">
+ <list_item>
+ <paragraph>iii</paragraph>
+ </list_item>
+ <list_item>
+ <paragraph>iv</paragraph>
+ </list_item>
+ </enumerated_list>
+ <system_message level="1" line="8" source="functional/input/data/standard.txt" type="INFO">
+ <paragraph>Enumerated list start value not ordinal-1: "iii" (ordinal 3)</paragraph>
+ </system_message>
+ </list_item>
+ </enumerated_list>
+ </section>
+ <section ids="definition-lists" names="definition\ lists">
+ <title auto="1" refid="toc-entry-10"><generated classes="sectnum">2.4 </generated>Definition Lists</title>
+ <definition_list>
+ <definition_list_item>
+ <term>Term</term>
+ <definition>
+ <paragraph>Definition</paragraph>
+ </definition>
+ </definition_list_item>
+ <definition_list_item>
+ <term>Term</term>
+ <classifier>classifier</classifier>
+ <definition>
+ <paragraph>Definition paragraph 1.</paragraph>
+ <paragraph>Definition paragraph 2.</paragraph>
+ </definition>
+ </definition_list_item>
+ <definition_list_item>
+ <term>Term</term>
+ <definition>
+ <paragraph>Definition</paragraph>
+ </definition>
+ </definition_list_item>
+ <definition_list_item>
+ <term>Term</term>
+ <classifier>classifier one</classifier>
+ <classifier>classifier two</classifier>
+ <definition>
+ <paragraph>Definition</paragraph>
+ </definition>
+ </definition_list_item>
+ </definition_list>
+ </section>
+ <section ids="field-lists" names="field\ lists">
+ <title auto="1" refid="toc-entry-11"><generated classes="sectnum">2.5 </generated>Field Lists</title>
+ <field_list>
+ <field>
+ <field_name>what</field_name>
+ <field_body>
+ <paragraph>Field lists map field names to field bodies, like database
+ records. They are often part of an extension syntax. They are
+ an unambiguous variant of RFC 2822 fields.</paragraph>
+ </field_body>
+ </field>
+ <field>
+ <field_name>how arg1 arg2</field_name>
+ <field_body>
+ <paragraph>The field marker is a colon, the field name, and a colon.</paragraph>
+ <paragraph>The field body may contain one or more body elements, indented
+ relative to the field marker.</paragraph>
+ </field_body>
+ </field>
+ <field>
+ <field_name>credits</field_name>
+ <field_body>
+ <paragraph classes="credits">This paragraph has the <title_reference>credits</title_reference> class set. (This is actually not
+ about credits but just for ensuring that the class attribute
+ doesn't get stripped away.)</paragraph>
+ </field_body>
+ </field>
+ </field_list>
+ </section>
+ <section ids="option-lists" names="option\ lists">
+ <title auto="1" refid="toc-entry-12"><generated classes="sectnum">2.6 </generated>Option Lists</title>
+ <paragraph>For listing command-line options:</paragraph>
+ <option_list>
+ <option_list_item>
+ <option_group>
+ <option>
+ <option_string>-a</option_string>
+ </option>
+ </option_group>
+ <description>
+ <paragraph>command-line option "a"</paragraph>
+ </description>
+ </option_list_item>
+ <option_list_item>
+ <option_group>
+ <option>
+ <option_string>-b</option_string>
+ <option_argument delimiter=" ">file</option_argument>
+ </option>
+ </option_group>
+ <description>
+ <paragraph>options can have arguments
+ and long descriptions</paragraph>
+ </description>
+ </option_list_item>
+ <option_list_item>
+ <option_group>
+ <option>
+ <option_string>--long</option_string>
+ </option>
+ </option_group>
+ <description>
+ <paragraph>options can be long also</paragraph>
+ </description>
+ </option_list_item>
+ <option_list_item>
+ <option_group>
+ <option>
+ <option_string>--input</option_string>
+ <option_argument delimiter="=">file</option_argument>
+ </option>
+ </option_group>
+ <description>
+ <paragraph>long options can also have
+ arguments</paragraph>
+ </description>
+ </option_list_item>
+ <option_list_item>
+ <option_group>
+ <option>
+ <option_string>--very-long-option</option_string>
+ </option>
+ </option_group>
+ <description>
+ <paragraph>The description can also start on the next line.</paragraph>
+ <paragraph>The description may contain multiple body elements,
+ regardless of where it starts.</paragraph>
+ </description>
+ </option_list_item>
+ <option_list_item>
+ <option_group>
+ <option>
+ <option_string>-x</option_string>
+ </option>
+ <option>
+ <option_string>-y</option_string>
+ </option>
+ <option>
+ <option_string>-z</option_string>
+ </option>
+ </option_group>
+ <description>
+ <paragraph>Multiple options are an "option group".</paragraph>
+ </description>
+ </option_list_item>
+ <option_list_item>
+ <option_group>
+ <option>
+ <option_string>-v</option_string>
+ </option>
+ <option>
+ <option_string>--verbose</option_string>
+ </option>
+ </option_group>
+ <description>
+ <paragraph>Commonly-seen: short & long options.</paragraph>
+ </description>
+ </option_list_item>
+ <option_list_item>
+ <option_group>
+ <option>
+ <option_string>-1</option_string>
+ <option_argument delimiter=" ">file</option_argument>
+ </option>
+ <option>
+ <option_string>--one</option_string>
+ <option_argument delimiter="=">file</option_argument>
+ </option>
+ <option>
+ <option_string>--two</option_string>
+ <option_argument delimiter=" ">file</option_argument>
+ </option>
+ </option_group>
+ <description>
+ <paragraph>Multiple options with arguments.</paragraph>
+ </description>
+ </option_list_item>
+ <option_list_item>
+ <option_group>
+ <option>
+ <option_string>/V</option_string>
+ </option>
+ </option_group>
+ <description>
+ <paragraph>DOS/VMS-style options too</paragraph>
+ </description>
+ </option_list_item>
+ </option_list>
+ <paragraph>There must be at least two spaces between the option and the
+ description.</paragraph>
+ </section>
+ <section ids="literal-blocks" names="literal\ blocks">
+ <title auto="1" refid="toc-entry-13"><generated classes="sectnum">2.7 </generated>Literal Blocks</title>
+ <paragraph>Literal blocks are indicated with a double-colon ("::") at the end of
+ the preceding paragraph (over there <literal>--></literal>). They can be indented:</paragraph>
+ <literal_block xml:space="preserve">if literal_block:
+ text = 'is left as-is'
+ spaces_and_linebreaks = 'are preserved'
+ markup_processing = None</literal_block>
+ <paragraph>Or they can be quoted without indentation:</paragraph>
+ <literal_block xml:space="preserve">>> Great idea!
+>
+> Why didn't I think of that?</literal_block>
+ </section>
+ <section ids="line-blocks" names="line\ blocks">
+ <title auto="1" refid="toc-entry-14"><generated classes="sectnum">2.8 </generated>Line Blocks</title>
+ <paragraph>This section tests line blocks. Line blocks are body elements which
+ consist of lines and other line blocks. Nested line blocks cause
+ indentation.</paragraph>
+ <line_block>
+ <line>This is a line block. It ends with a blank line.</line>
+ <line_block>
+ <line>New lines begin with a vertical bar ("|").</line>
+ <line>Line breaks and initial indent are significant, and preserved.</line>
+ <line_block>
+ <line>Continuation lines are also possible. A long line that is intended
+ to wrap should begin with a space in place of the vertical bar.</line>
+ </line_block>
+ <line>The left edge of a continuation line need not be aligned with
+ the left edge of the text above it.</line>
+ </line_block>
+ </line_block>
+ <line_block>
+ <line>This is a second line block.</line>
+ <line></line>
+ <line>Blank lines are permitted internally, but they must begin with a "|".</line>
+ </line_block>
+ <paragraph>Another line block, surrounded by paragraphs:</paragraph>
+ <line_block>
+ <line>And it's no good waiting by the window</line>
+ <line>It's no good waiting for the sun</line>
+ <line>Please believe me, the things you dream of</line>
+ <line>They don't fall in the lap of no-one</line>
+ </line_block>
+ <paragraph>Take it away, Eric the Orchestra Leader!</paragraph>
+ <block_quote>
+ <line_block>
+ <line>A one, two, a one two three four</line>
+ <line></line>
+ <line>Half a bee, philosophically,</line>
+ <line_block>
+ <line>must, <emphasis>ipso facto</emphasis>, half not be.</line>
+ </line_block>
+ <line>But half the bee has got to be,</line>
+ <line_block>
+ <line><emphasis>vis a vis</emphasis> its entity. D'you see?</line>
+ <line></line>
+ </line_block>
+ <line>But can a bee be said to be</line>
+ <line_block>
+ <line>or not to be an entire bee,</line>
+ <line_block>
+ <line>when half the bee is not a bee,</line>
+ <line_block>
+ <line>due to some ancient injury?</line>
+ <line></line>
+ </line_block>
+ </line_block>
+ </line_block>
+ <line>Singing...</line>
+ </line_block>
+ </block_quote>
+ <paragraph>A line block, like the following poem by Christian Morgenstern, can
+ also be centre-aligned:</paragraph>
+ <line_block classes="language-de align-center">
+ <line><strong>Die Trichter</strong></line>
+ <line></line>
+ <line>Zwei Trichter wandeln durch die Nacht.</line>
+ <line>Durch ihres Rumpfs verengten Schacht</line>
+ <line>fließt weißes Mondlicht</line>
+ <line>still und heiter</line>
+ <line>auf ihren</line>
+ <line>Waldweg</line>
+ <line>u. s.</line>
+ <line>w.</line>
+ <line></line>
+ </line_block>
+ </section>
+ <section ids="block-quotes" names="block\ quotes">
+ <title auto="1" refid="toc-entry-15"><generated classes="sectnum">2.9 </generated>Block Quotes</title>
+ <paragraph>Block quotes consist of indented body elements:</paragraph>
+ <block_quote>
+ <paragraph>My theory by A. Elk. Brackets Miss, brackets. This theory goes
+ as follows and begins now. All brontosauruses are thin at one
+ end, much much thicker in the middle and then thin again at the
+ far end. That is my theory, it is mine, and belongs to me and I
+ own it, and what it is too.</paragraph>
+ <attribution>Anne Elk (Miss)</attribution>
+ </block_quote>
+ <paragraph>The language of a quote (like any other object) can be specified by
+ a class attribute:</paragraph>
+ <comment xml:space="preserve"></comment>
+ <block_quote classes="language-fr">
+ <paragraph>ReStructuredText est un langage de balisage léger utilisé
+ notamment dans la documentation du langage Python.</paragraph>
+ </block_quote>
+ </section>
+ <section ids="doctest-blocks" names="doctest\ blocks">
+ <title auto="1" refid="toc-entry-16"><generated classes="sectnum">2.10 </generated>Doctest Blocks</title>
+ <doctest_block xml:space="preserve">>>> print 'Python-specific usage examples; begun with ">>>"'
+Python-specific usage examples; begun with ">>>"
+>>> print '(cut and pasted from interactive Python sessions)'
+(cut and pasted from interactive Python sessions)</doctest_block>
+ </section>
+ <section ids="footnotes" names="footnotes">
+ <title auto="1" refid="toc-entry-17"><generated classes="sectnum">2.11 </generated>Footnotes</title>
+ <footnote backrefs="footnote-reference-1 footnote-reference-5 footnote-reference-9" ids="footnote-1" names="1">
+ <label>1</label>
+ <paragraph>A footnote contains body elements, consistently indented by at
+ least 3 spaces.</paragraph>
+ <paragraph>This is the footnote's second paragraph.</paragraph>
+ </footnote>
+ <footnote auto="1" backrefs="footnote-reference-3 footnote-reference-6" ids="label" names="label">
+ <label>2</label>
+ <paragraph>Footnotes may be numbered, either manually (as in <footnote_reference ids="footnote-reference-5" refid="footnote-1">1</footnote_reference>) or
+ automatically using a "#"-prefixed label. This footnote has a
+ label so it can be referred to from multiple places, both as a
+ footnote reference (<footnote_reference auto="1" ids="footnote-reference-6" refid="label">2</footnote_reference>) and as a <reference anonymous="1" name="hyperlink reference" refid="label">hyperlink reference</reference>.</paragraph>
+ <target anonymous="1" ids="target-3" refid="label"></target>
+ </footnote>
+ <footnote auto="1" backrefs="footnote-reference-2" ids="footnote-2" names="3">
+ <label>3</label>
+ <paragraph>This footnote is numbered automatically and anonymously using a
+ label of "#" only.</paragraph>
+ <paragraph>This is the second paragraph.</paragraph>
+ <paragraph>And this is the third paragraph.</paragraph>
+ </footnote>
+ <footnote auto="*" backrefs="footnote-reference-4" ids="footnote-3">
+ <label>*</label>
+ <paragraph>Footnotes may also use symbols, specified with a "*" label.
+ Here's a reference to the next footnote: <footnote_reference auto="*" ids="footnote-reference-7" refid="footnote-4">†</footnote_reference>.</paragraph>
+ </footnote>
+ <footnote auto="*" backrefs="footnote-reference-7" ids="footnote-4">
+ <label>†</label>
+ <paragraph>This footnote shows the next symbol in the sequence.</paragraph>
+ </footnote>
+ <footnote ids="footnote-5" names="4">
+ <label>4</label>
+ <paragraph>Here's an unreferenced footnote, with a reference to a
+ nonexistent footnote: <problematic ids="footnote-reference-8" refid="system-message-2">[5]_</problematic>.</paragraph>
+ </footnote>
+ </section>
+ <section ids="citations" names="citations">
+ <title auto="1" refid="toc-entry-18"><generated classes="sectnum">2.12 </generated>Citations</title>
+ <citation backrefs="citation-reference-1 citation-reference-2" ids="cit2002" names="cit2002">
+ <label>CIT2002</label>
+ <paragraph>Citations are text-labeled footnotes. They may be
+ rendered separately and differently from footnotes.</paragraph>
+ </citation>
+ <paragraph>Here's a reference to the above, <citation_reference ids="citation-reference-2" refid="cit2002">CIT2002</citation_reference>, and a <problematic ids="citation-reference-3" refid="system-message-3">[nonexistent]_</problematic>
+ citation.</paragraph>
+ <target refid="another-target"></target>
+ </section>
+ <section ids="targets another-target" names="targets another\ target">
+ <title auto="1" refid="toc-entry-19"><generated classes="sectnum">2.13 </generated>Targets</title>
+ <target refid="example"></target>
+ <paragraph ids="example" names="example">This paragraph is pointed to by the explicit "example" target. A
+ reference can be found under <reference name="Inline Markup" refid="inline-markup">Inline Markup</reference>, above. <reference name="Inline hyperlink targets" refid="inline-hyperlink-targets">Inline
+ hyperlink targets</reference> are also possible.</paragraph>
+ <paragraph>Section headers are implicit targets, referred to by name. See
+ <reference name="Targets" refid="targets">Targets</reference>, which is a subsection of <reference name="Body Elements" refid="body-elements">Body Elements</reference>.</paragraph>
+ <paragraph>Explicit external targets are interpolated into references such as
+ "<reference name="Python" refuri="http://www.python.org/">Python</reference> <footnote_reference auto="1" ids="footnote-reference-11" refid="footnote-6">5</footnote_reference>".</paragraph>
+ <target ids="python" names="python" refuri="http://www.python.org/"></target>
+ <paragraph>Targets may be indirect and anonymous. Thus <reference anonymous="1" name="this phrase" refid="targets">this phrase</reference> may also
+ refer to the <reference name="Targets" refid="targets">Targets</reference> section.</paragraph>
+ <target anonymous="1" ids="target-4" refid="targets"></target>
+ <paragraph>Here's a <problematic ids="problematic-2" refid="system-message-4">`hyperlink reference without a target`_</problematic>, which generates an
+ error.</paragraph>
+ <section dupnames="duplicate\ target\ names" ids="duplicate-target-names">
+ <title auto="1" refid="toc-entry-20"><generated classes="sectnum">2.13.1 </generated>Duplicate Target Names</title>
+ <paragraph>Duplicate names in section headers or other implicit targets will
+ generate "info" (level-1) system messages. Duplicate names in
+ explicit targets will generate "warning" (level-2) system messages.</paragraph>
+ </section>
+ <section dupnames="duplicate\ target\ names" ids="duplicate-target-names-1">
+ <title auto="1" refid="toc-entry-21"><generated classes="sectnum">2.13.2 </generated>Duplicate Target Names</title>
+ <system_message backrefs="duplicate-target-names-1" level="1" line="439" source="functional/input/data/standard.txt" type="INFO">
+ <paragraph>Duplicate implicit target name: "duplicate target names".</paragraph>
+ </system_message>
+ <paragraph>Since there are two "Duplicate Target Names" section headers, we
+ cannot uniquely refer to either of them by name. If we try to (like
+ this: <problematic ids="problematic-3" refid="system-message-5">`Duplicate Target Names`_</problematic>), an error is generated.</paragraph>
+ </section>
+ </section>
+ <section ids="directives" names="directives">
+ <title auto="1" refid="toc-entry-22"><generated classes="sectnum">2.14 </generated>Directives</title>
+ <topic classes="contents local" ids="contents" names="contents">
+ <bullet_list classes="auto-toc">
+ <list_item>
+ <paragraph><reference ids="toc-entry-41" refid="document-parts"><generated classes="sectnum">2.14.1 </generated>Document Parts</reference></paragraph>
+ </list_item>
+ <list_item>
+ <paragraph><reference ids="toc-entry-42" refid="images-and-figures"><generated classes="sectnum">2.14.2 </generated>Images and Figures</reference></paragraph>
+ </list_item>
+ <list_item>
+ <paragraph><reference ids="toc-entry-43" refid="admonitions"><generated classes="sectnum">2.14.3 </generated>Admonitions</reference></paragraph>
+ </list_item>
+ <list_item>
+ <paragraph><reference ids="toc-entry-44" refid="topics-sidebars-and-rubrics"><generated classes="sectnum">2.14.4 </generated>Topics, Sidebars, and Rubrics</reference></paragraph>
+ </list_item>
+ <list_item>
+ <paragraph><reference ids="toc-entry-45" refid="target-footnotes"><generated classes="sectnum">2.14.5 </generated>Target Footnotes</reference></paragraph>
+ </list_item>
+ <list_item>
+ <paragraph><reference ids="toc-entry-46" refid="replacement-text"><generated classes="sectnum">2.14.6 </generated>Replacement Text</reference></paragraph>
+ </list_item>
+ <list_item>
+ <paragraph><reference ids="toc-entry-47" refid="compound-paragraph"><generated classes="sectnum">2.14.7 </generated>Compound Paragraph</reference></paragraph>
+ </list_item>
+ <list_item>
+ <paragraph><reference ids="toc-entry-48" refid="parsed-literal-blocks"><generated classes="sectnum">2.14.8 </generated>Parsed Literal Blocks</reference></paragraph>
+ </list_item>
+ <list_item>
+ <paragraph><reference ids="toc-entry-49" refid="code"><generated classes="sectnum">2.14.9 </generated>Code</reference></paragraph>
+ </list_item>
+ </bullet_list>
+ </topic>
+ <paragraph>These are just a sample of the many reStructuredText Directives. For
+ others, please see
+ <reference refuri="http://docutils.sourceforge.net/docs/ref/rst/directives.html">http://docutils.sourceforge.net/docs/ref/rst/directives.html</reference>.</paragraph>
+ <section ids="document-parts" names="document\ parts">
+ <title auto="1" refid="toc-entry-41"><generated classes="sectnum">2.14.1 </generated>Document Parts</title>
+ <paragraph>An example of the "contents" directive can be seen above this section
+ (a local, untitled table of <reference name="contents" refid="contents">contents</reference>) and at the beginning of the
+ document (a document-wide <reference name="table of contents" refid="table-of-contents">table of contents</reference>).</paragraph>
+ </section>
+ <section ids="images-and-figures" names="images\ and\ figures">
+ <title auto="1" refid="toc-entry-42"><generated classes="sectnum">2.14.2 </generated>Images and Figures</title>
+ <paragraph>An image directive (also clickable -- a hyperlink reference):</paragraph>
+ <reference name="directives" refid="directives"><image classes="class1 class2" uri="../../../docs/user/rst/images/title.png"></image></reference>
+ <paragraph>Image with multiple IDs:</paragraph>
+ <target refid="image-target-1"></target>
+ <target refid="image-target-2"></target>
+ <target refid="image-target-3"></target>
+ <image ids="image-target-3 image-target-2 image-target-1" names="image\ target\ 3 image\ target\ 2 image\ target\ 1" uri="../../../docs/user/rst/images/title.png"></image>
+ <paragraph>A centered image:</paragraph>
+ <image align="center" uri="../../../docs/user/rst/images/biohazard.png"></image>
+ <paragraph>A left-aligned image:</paragraph>
+ <image align="left" uri="../../../docs/user/rst/images/biohazard.png"></image>
+ <paragraph>This paragraph might flow around the image.
+ The specific behavior depends upon the style sheet and
+ the browser or rendering software used.</paragraph>
+ <paragraph>A right-aligned image:</paragraph>
+ <image align="right" uri="../../../docs/user/rst/images/biohazard.png"></image>
+ <paragraph>This paragraph might flow around the image.
+ The specific behavior depends upon the style sheet and
+ the browser or rendering software used.</paragraph>
+ <paragraph>For inline images see <reference name="Substitution Definitions" refid="substitution-definitions">Substitution Definitions</reference>.</paragraph>
+ <paragraph>Image size:</paragraph>
+ <paragraph>An image 2 em wide:</paragraph>
+ <image uri="../../../docs/user/rst/images/biohazard.png" width="2em"></image>
+ <paragraph>An image 2 em wide and 15 pixel high:</paragraph>
+ <image height="15px" uri="../../../docs/user/rst/images/biohazard.png" width="2em"></image>
+ <paragraph>An image occupying 50% of the line width:</paragraph>
+ <image uri="../../../docs/user/rst/images/title.png" width="50%"></image>
+ <paragraph>An image 2 cm high:</paragraph>
+ <image height="2cm" uri="../../../docs/user/rst/images/biohazard.png"></image>
+ <paragraph>A <emphasis>figure</emphasis> is an image with a caption and/or a legend. With page-based output
+ media, figures might float to a different position if this helps the page
+ layout.</paragraph>
+ <figure classes="figclass1 figclass2">
+ <image alt="reStructuredText, the markup syntax" classes="class1 class2" uri="../../../docs/user/rst/images/title.png" width="258"></image>
+ <caption>Plaintext markup syntax and parser system.</caption>
+ <legend>
+ <table>
+ <tgroup cols="2">
+ <colspec colwidth="12"></colspec>
+ <colspec colwidth="47"></colspec>
+ <tbody>
+ <row>
+ <entry>
+ <paragraph>re</paragraph>
+ </entry>
+ <entry>
+ <paragraph>Revised, revisited, based on 're' module.</paragraph>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <paragraph>Structured</paragraph>
+ </entry>
+ <entry>
+ <paragraph>Structure-enhanced text, structuredtext.</paragraph>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <paragraph>Text</paragraph>
+ </entry>
+ <entry>
+ <paragraph>Well it is, isn't it?</paragraph>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ <paragraph>This paragraph is also part of the legend.</paragraph>
+ </legend>
+ </figure>
+ <paragraph>A left-aligned figure:</paragraph>
+ <figure align="left" classes="figclass1 figclass2" width="70%">
+ <image alt="reStructuredText, the markup syntax" classes="class1 class2" uri="../../../docs/user/rst/images/biohazard.png" width="40px"></image>
+ <caption>This is the caption.</caption>
+ <legend>
+ <paragraph>This is the legend.</paragraph>
+ <paragraph>The legend may consist of several paragraphs.</paragraph>
+ </legend>
+ </figure>
+ <paragraph>This paragraph might flow around the figure.</paragraph>
+ <paragraph>The specific behavior depends upon the style sheet and the browser or
+ rendering software used.</paragraph>
+ <paragraph>A centered figure:</paragraph>
+ <figure align="center">
+ <image uri="../../../docs/user/rst/images/biohazard.png" width="40px"></image>
+ <caption>This is the caption.</caption>
+ <legend>
+ <paragraph>This is the legend.</paragraph>
+ <paragraph>The legend may consist of several paragraphs.</paragraph>
+ </legend>
+ </figure>
+ <paragraph>This paragraph might flow around the figure.</paragraph>
+ <paragraph>The specific behavior depends upon the style sheet and the browser or
+ rendering software used.</paragraph>
+ <paragraph>A right-aligned figure:</paragraph>
+ <figure align="right">
+ <image uri="../../../docs/user/rst/images/biohazard.png" width="40px"></image>
+ <caption>This is the caption.</caption>
+ <legend>
+ <paragraph>This is the legend.</paragraph>
+ <paragraph>The legend may consist of several paragraphs.</paragraph>
+ </legend>
+ </figure>
+ <paragraph>This paragraph might flow around the figure. The specific behavior depends
+ upon the style sheet and the browser or rendering software used.</paragraph>
+ <paragraph>Tables may be given titles and additional arguments with the <emphasis>table</emphasis>
+ directive:</paragraph>
+ <table align="left">
+ <title>left-aligned table</title>
+ <tgroup cols="2">
+ <colspec colwidth="5"></colspec>
+ <colspec colwidth="5"></colspec>
+ <thead>
+ <row>
+ <entry>
+ <paragraph>A</paragraph>
+ </entry>
+ <entry>
+ <paragraph>not A</paragraph>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <paragraph>False</paragraph>
+ </entry>
+ <entry>
+ <paragraph>True</paragraph>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <paragraph>True</paragraph>
+ </entry>
+ <entry>
+ <paragraph>False</paragraph>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ <table align="center">
+ <title>center-aligned table</title>
+ <tgroup cols="2">
+ <colspec colwidth="5"></colspec>
+ <colspec colwidth="5"></colspec>
+ <thead>
+ <row>
+ <entry>
+ <paragraph>A</paragraph>
+ </entry>
+ <entry>
+ <paragraph>not A</paragraph>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <paragraph>False</paragraph>
+ </entry>
+ <entry>
+ <paragraph>True</paragraph>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <paragraph>True</paragraph>
+ </entry>
+ <entry>
+ <paragraph>False</paragraph>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ <table align="right">
+ <title>right-aligned table</title>
+ <tgroup cols="2">
+ <colspec colwidth="5"></colspec>
+ <colspec colwidth="5"></colspec>
+ <thead>
+ <row>
+ <entry>
+ <paragraph>A</paragraph>
+ </entry>
+ <entry>
+ <paragraph>not A</paragraph>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <paragraph>False</paragraph>
+ </entry>
+ <entry>
+ <paragraph>True</paragraph>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <paragraph>True</paragraph>
+ </entry>
+ <entry>
+ <paragraph>False</paragraph>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ <paragraph>With the "widths" argument "auto" (or "class" value "colwidths-auto"),
+ column widths are determined by the backend (if supported by the
+ writer/backend).</paragraph>
+ <target refid="target1"></target>
+ <target refid="target2"></target>
+ <table classes="colwidths-auto" ids="target2 target1" names="target2 target1">
+ <tgroup cols="3">
+ <colspec colwidth="7"></colspec>
+ <colspec colwidth="7"></colspec>
+ <colspec colwidth="10"></colspec>
+ <thead>
+ <row>
+ <entry>
+ <paragraph>A</paragraph>
+ </entry>
+ <entry>
+ <paragraph>B</paragraph>
+ </entry>
+ <entry>
+ <paragraph>A or B</paragraph>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <paragraph>False</paragraph>
+ </entry>
+ <entry>
+ <paragraph>False</paragraph>
+ </entry>
+ <entry>
+ <paragraph>False</paragraph>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <paragraph>True</paragraph>
+ </entry>
+ <entry>
+ <paragraph>False</paragraph>
+ </entry>
+ <entry>
+ <paragraph>True</paragraph>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <paragraph>False</paragraph>
+ </entry>
+ <entry>
+ <paragraph>True</paragraph>
+ </entry>
+ <entry>
+ <paragraph>True</paragraph>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <paragraph>True</paragraph>
+ </entry>
+ <entry>
+ <paragraph>True</paragraph>
+ </entry>
+ <entry>
+ <paragraph>True</paragraph>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ </section>
+ <section ids="admonitions" names="admonitions">
+ <title auto="1" refid="toc-entry-43"><generated classes="sectnum">2.14.3 </generated>Admonitions</title>
+ <attention>
+ <paragraph>Directives at large.</paragraph>
+ </attention>
+ <caution>
+ <paragraph>Don't take any wooden nickels.</paragraph>
+ </caution>
+ <danger>
+ <paragraph>Mad scientist at work!</paragraph>
+ </danger>
+ <error>
+ <paragraph>Does not compute.</paragraph>
+ </error>
+ <hint>
+ <paragraph>It's bigger than a bread box.</paragraph>
+ </hint>
+ <important>
+ <bullet_list bullet="-">
+ <list_item>
+ <paragraph>Wash behind your ears.</paragraph>
+ </list_item>
+ <list_item>
+ <paragraph>Clean up your room.</paragraph>
+ </list_item>
+ <list_item>
+ <paragraph>Call your mother.</paragraph>
+ </list_item>
+ <list_item>
+ <paragraph>Back up your data.</paragraph>
+ </list_item>
+ </bullet_list>
+ </important>
+ <note>
+ <paragraph>This is a note.</paragraph>
+ </note>
+ <tip>
+ <paragraph>15% if the service is good.</paragraph>
+ </tip>
+ <warning>
+ <paragraph>Strong prose may provoke extreme mental exertion.
+ Reader discretion is strongly advised.</paragraph>
+ </warning>
+ <admonition classes="admonition-and-by-the-way">
+ <title>And, by the way...</title>
+ <paragraph>You can make up your own admonition too.</paragraph>
+ <target ids="docutils" names="docutils" refuri="http://docutils.sourceforge.net/"></target>
+ </admonition>
+ </section>
+ <section ids="topics-sidebars-and-rubrics" names="topics,\ sidebars,\ and\ rubrics">
+ <title auto="1" refid="toc-entry-44"><generated classes="sectnum">2.14.4 </generated>Topics, Sidebars, and Rubrics</title>
+ <paragraph><emphasis>Sidebars</emphasis> are like miniature, parallel documents.</paragraph>
+ <sidebar>
+ <title>Sidebar Title</title>
+ <subtitle>Optional Subtitle</subtitle>
+ <paragraph>This is a sidebar. It is for text outside the flow of the main
+ text.</paragraph>
+ <rubric>This is a rubric inside a sidebar</rubric>
+ <paragraph>Sidebars often appear beside the main text with a border and a different
+ background or font color.</paragraph>
+ </sidebar>
+ <paragraph>A <emphasis>topic</emphasis> is like a block quote with a title, or a self-contained section
+ with no subsections.</paragraph>
+ <topic>
+ <title>Topic Title</title>
+ <paragraph>This is a topic.</paragraph>
+ </topic>
+ <paragraph>A <emphasis>rubric</emphasis> is like an informal heading that doesn't correspond to the
+ document's structure. It is typically highlighted in red (hence the name).</paragraph>
+ <rubric>This is a rubric</rubric>
+ <paragraph>Topics and rubrics can be used at places where a <reference name="section title" refid="section-title">section title</reference> is not
+ allowed (e.g. inside a directive).</paragraph>
+ </section>
+ <section ids="target-footnotes" names="target\ footnotes">
+ <title auto="1" refid="toc-entry-45"><generated classes="sectnum">2.14.5 </generated>Target Footnotes</title>
+ <footnote auto="1" backrefs="footnote-reference-10 footnote-reference-11 footnote-reference-12 footnote-reference-14" ids="footnote-6" names="TARGET_NOTE:\ footnote-6">
+ <label>5</label>
+ <paragraph><reference refuri="http://www.python.org/">http://www.python.org/</reference></paragraph>
+ </footnote>
+ <footnote auto="1" backrefs="footnote-reference-13" ids="footnote-7" names="TARGET_NOTE:\ footnote-7">
+ <label>6</label>
+ <paragraph><reference refuri="http://pygments.org/">http://pygments.org/</reference></paragraph>
+ </footnote>
+ <footnote auto="1" backrefs="footnote-reference-15" ids="footnote-8" names="TARGET_NOTE:\ footnote-8">
+ <label>7</label>
+ <paragraph><reference refuri="http://docutils.sourceforge.net/">http://docutils.sourceforge.net/</reference></paragraph>
+ </footnote>
+ </section>
+ <section ids="replacement-text" names="replacement\ text">
+ <title auto="1" refid="toc-entry-46"><generated classes="sectnum">2.14.6 </generated>Replacement Text</title>
+ <paragraph>I recommend you try <reference refuri="http://www.python.org/">Python, <emphasis>the</emphasis> best language around</reference> <footnote_reference auto="1" ids="footnote-reference-12" refid="footnote-6">5</footnote_reference>.</paragraph>
+ <substitution_definition names="Python">Python, <emphasis>the</emphasis> best language around</substitution_definition>
+ </section>
+ <section ids="compound-paragraph" names="compound\ paragraph">
+ <title auto="1" refid="toc-entry-47"><generated classes="sectnum">2.14.7 </generated>Compound Paragraph</title>
+ <paragraph>The <emphasis>compound</emphasis> directive is used to create a "compound paragraph", which
+ is a single logical paragraph containing multiple physical body
+ elements. For example:</paragraph>
+ <compound>
+ <paragraph>The 'rm' command is very dangerous. If you are logged
+ in as root and enter</paragraph>
+ <literal_block xml:space="preserve">cd /
+rm -rf *</literal_block>
+ <paragraph>you will erase the entire contents of your file system.</paragraph>
+ </compound>
+ <paragraph>Test the handling and display of compound paragraphs:</paragraph>
+ <compound classes="some-class">
+ <paragraph>Compound 2, paragraph 1,</paragraph>
+ <paragraph>compound 2, paragraph 2,</paragraph>
+ <bullet_list bullet="*">
+ <list_item>
+ <paragraph>list item 1,</paragraph>
+ </list_item>
+ <list_item>
+ <paragraph>list item 2,</paragraph>
+ </list_item>
+ </bullet_list>
+ <paragraph>compound 2, paragraph 3.</paragraph>
+ </compound>
+ <compound>
+ <paragraph>Compound 3, only consisting of one paragraph.</paragraph>
+ </compound>
+ <compound>
+ <literal_block xml:space="preserve">Compound 4.
+This one starts with a literal block.</literal_block>
+ <paragraph>Compound 4, paragraph following the literal block.</paragraph>
+ </compound>
+ <paragraph>Now something <emphasis>really</emphasis> perverted -- a nested compound block. This is
+ just to test that it works at all; the results don't have to be
+ meaningful.</paragraph>
+ <compound>
+ <paragraph>Compound 5, block 1 (a paragraph).</paragraph>
+ <compound>
+ <paragraph>Compound 6 is block 2 in compound 5.</paragraph>
+ <paragraph>Compound 6, another paragraph.</paragraph>
+ </compound>
+ <paragraph>Compound 5, block 3 (a paragraph).</paragraph>
+ </compound>
+ <compound>
+ <paragraph>Compound 7, tests the inclusion of various block-level
+ elements in one logical paragraph. First a table,</paragraph>
+ <table>
+ <tgroup cols="3">
+ <colspec colwidth="20"></colspec>
+ <colspec colwidth="20"></colspec>
+ <colspec colwidth="20"></colspec>
+ <tbody>
+ <row>
+ <entry>
+ <paragraph>Left cell, first
+ paragraph.</paragraph>
+ <paragraph>Left cell, second
+ paragraph.</paragraph>
+ </entry>
+ <entry>
+ <paragraph>Middle cell,
+ consisting of
+ exactly one
+ paragraph.</paragraph>
+ </entry>
+ <entry>
+ <paragraph>Right cell.</paragraph>
+ <paragraph>Paragraph 2.</paragraph>
+ <paragraph>Paragraph 3.</paragraph>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ <paragraph>followed by a paragraph. This physical paragraph is
+ actually a continuation of the paragraph before the table. It is followed
+ by</paragraph>
+ <block_quote>
+ <paragraph>a quote and</paragraph>
+ </block_quote>
+ <enumerated_list enumtype="arabic" prefix="" suffix=".">
+ <list_item>
+ <paragraph>an enumerated list,</paragraph>
+ </list_item>
+ </enumerated_list>
+ <paragraph>a paragraph,</paragraph>
+ <option_list>
+ <option_list_item>
+ <option_group>
+ <option>
+ <option_string>--an</option_string>
+ </option>
+ </option_group>
+ <description>
+ <paragraph>option list,</paragraph>
+ </description>
+ </option_list_item>
+ </option_list>
+ <paragraph>a paragraph,</paragraph>
+ <field_list>
+ <field>
+ <field_name>a field</field_name>
+ <field_body>
+ <paragraph>list,</paragraph>
+ </field_body>
+ </field>
+ </field_list>
+ <paragraph>a paragraph,</paragraph>
+ <definition_list>
+ <definition_list_item>
+ <term>a definition</term>
+ <definition>
+ <paragraph>list,</paragraph>
+ </definition>
+ </definition_list_item>
+ </definition_list>
+ <paragraph>a paragraph, an image:</paragraph>
+ <image uri="../../../docs/user/rst/images/biohazard.png"></image>
+ <paragraph>a paragraph,</paragraph>
+ <line_block>
+ <line>a line</line>
+ <line>block,</line>
+ </line_block>
+ <paragraph>a paragraph followed by a comment,</paragraph>
+ <comment xml:space="preserve">this is a comment</comment>
+ <paragraph>a paragraph, a</paragraph>
+ <note>
+ <paragraph>with content</paragraph>
+ </note>
+ <paragraph>and the final paragraph of the compound 7.</paragraph>
+ </compound>
+ </section>
+ <section ids="parsed-literal-blocks" names="parsed\ literal\ blocks">
+ <title auto="1" refid="toc-entry-48"><generated classes="sectnum">2.14.8 </generated>Parsed Literal Blocks</title>
+ <literal_block xml:space="preserve">This is a parsed literal block.
+ This line is indented. The next line is blank.
+
+Inline markup is supported, e.g. <emphasis>emphasis</emphasis>, <strong>strong</strong>, <literal>literal
+text</literal>, <subscript>sub-</subscript> and <superscript>super</superscript>scripts,
+inline formulas: <math>A = 2 \pi r^2</math>,
+footnotes <footnote_reference ids="footnote-reference-9" refid="footnote-1">1</footnote_reference>, <target ids="hyperlink-targets" names="hyperlink\ targets">hyperlink targets</target>, and <reference name="references" refuri="http://www.python.org/">references</reference><target ids="references" names="references" refuri="http://www.python.org/"></target>.</literal_block>
+ </section>
+ <section ids="code" names="code">
+ <title auto="1" refid="toc-entry-49"><generated classes="sectnum">2.14.9 </generated>Code</title>
+ <paragraph>Blocks of source code can be set with the <title_reference>code</title_reference> directive. If the code
+ language is specified, the content is parsed and tagged by the <reference name="Pygments" refuri="http://pygments.org/">Pygments</reference> <footnote_reference auto="1" ids="footnote-reference-13" refid="footnote-7">6</footnote_reference>
+ syntax highlighter and can be formatted with a style sheet. (Code parsing
+ is turned off using the <literal>syntax-highlight</literal> config setting in the test
+ conversions in order to get identical results with/without installed
+ Pygments highlighter.)</paragraph>
+ <literal_block classes="code python" xml:space="preserve">print 'This is Python code.'</literal_block>
+ <paragraph>The <literal>:number-lines:</literal> option (with optional start value) generates line
+ numbers:</paragraph>
+ <literal_block classes="code python" xml:space="preserve"><inline classes="ln"> 8 </inline># print integers from 0 to 9:
+<inline classes="ln"> 9 </inline>for i in range(10):
+<inline classes="ln">10 </inline> print i</literal_block>
+ <paragraph>For inline code snippets, there is the <title_reference>code</title_reference> role, which can be used
+ directly (the code will not be parsed/tagged, as the language is not known)
+ or as base for special code roles, e.g. the LaTeX code in the next
+ paragraph.</paragraph>
+ <paragraph>Docutils uses LaTeX syntax for math directives and roles:
+ <literal classes="code tex">\alpha = f(x)</literal> prints <math>\alpha = f(x)</math>.</paragraph>
+ <paragraph>The <literal>:code:</literal> option of the <title_reference>include</title_reference> directive sets the included content
+ as a code block, here the rst file <literal>header_footer.txt</literal> with line numbers:</paragraph>
+ <literal_block classes="code rst" source="functional/input/data/header_footer.txt" xml:space="preserve"><inline classes="ln">1 </inline>.. header:: Document header
+<inline classes="ln">2 </inline>.. footer:: Document footer</literal_block>
+ <target ids="pygments" names="pygments" refuri="http://pygments.org/"></target>
+ </section>
+ </section>
+ <section ids="substitution-definitions" names="substitution\ definitions">
+ <title auto="1" refid="toc-entry-32"><generated classes="sectnum">2.15 </generated>Substitution Definitions</title>
+ <paragraph>An inline image (<image alt="EXAMPLE" uri="../../../docs/user/rst/images/biohazard.png"></image>) example:</paragraph>
+ <substitution_definition names="EXAMPLE"><image alt="EXAMPLE" uri="../../../docs/user/rst/images/biohazard.png"></image></substitution_definition>
+ <paragraph>A Unicode example:</paragraph>
+ <substitution_definition ltrim="1" names="heart" rtrim="1">♥</substitution_definition>
+ <paragraph>(Substitution definitions are not visible in the HTML source.)</paragraph>
+ </section>
+ <section ids="comments" names="comments">
+ <title auto="1" refid="toc-entry-33"><generated classes="sectnum">2.16 </generated>Comments</title>
+ <paragraph>Here's one:</paragraph>
+ <comment xml:space="preserve">Comments begin with two dots and a space. Anything may
+follow, except for the syntax of footnotes, hyperlink
+targets, directives, or substitution definitions.
+
+Double-dashes -- "--" -- must be escaped somehow in HTML output.
+
+Comments may contain non-ASCII characters: ä ö ü æ ø å</comment>
+ <paragraph>(View the HTML source to see the comment.)</paragraph>
+ </section>
+ <section ids="raw-text" names="raw\ text">
+ <title auto="1" refid="toc-entry-34"><generated classes="sectnum">2.17 </generated>Raw text</title>
+ <paragraph>This does not necessarily look nice, because there may be missing white space.</paragraph>
+ <paragraph>It's just there to freeze the behavior.</paragraph>
+ <raw format="html latex" xml:space="preserve">A test.</raw>
+ <raw format="html latex" xml:space="preserve">Second test.</raw>
+ <raw classes="myclass" format="html latex" xml:space="preserve">Another test with myclass set.</raw>
+ <paragraph>This is the <raw classes="myrawroleclass" format="html latex" xml:space="preserve">fourth test</raw> with myrawroleclass set.</paragraph>
+ <raw format="html" xml:space="preserve">Fifth test in HTML.<br />Line two.</raw>
+ <raw format="latex" xml:space="preserve">Fifth test in LaTeX.\\Line two.</raw>
+ </section>
+ <section ids="container" names="container">
+ <title auto="1" refid="toc-entry-35"><generated classes="sectnum">2.18 </generated>Container</title>
+ <container classes="custom">
+ <paragraph>paragraph 1</paragraph>
+ <paragraph>paragraph 2</paragraph>
+ </container>
+ </section>
+ <section ids="colspanning-tables" names="colspanning\ tables">
+ <title auto="1" refid="toc-entry-36"><generated classes="sectnum">2.19 </generated>Colspanning tables</title>
+ <paragraph>This table has a cell spanning two columns:</paragraph>
+ <table>
+ <tgroup cols="3">
+ <colspec colwidth="5"></colspec>
+ <colspec colwidth="5"></colspec>
+ <colspec colwidth="6"></colspec>
+ <thead>
+ <row>
+ <entry morecols="1">
+ <paragraph>Inputs</paragraph>
+ </entry>
+ <entry>
+ <paragraph>Output</paragraph>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <paragraph>A</paragraph>
+ </entry>
+ <entry>
+ <paragraph>B</paragraph>
+ </entry>
+ <entry>
+ <paragraph>A or B</paragraph>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <paragraph>False</paragraph>
+ </entry>
+ <entry>
+ <paragraph>False</paragraph>
+ </entry>
+ <entry>
+ <paragraph>False</paragraph>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <paragraph>True</paragraph>
+ </entry>
+ <entry>
+ <paragraph>False</paragraph>
+ </entry>
+ <entry>
+ <paragraph>True</paragraph>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <paragraph>False</paragraph>
+ </entry>
+ <entry>
+ <paragraph>True</paragraph>
+ </entry>
+ <entry>
+ <paragraph>True</paragraph>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <paragraph>True</paragraph>
+ </entry>
+ <entry>
+ <paragraph>True</paragraph>
+ </entry>
+ <entry>
+ <paragraph>True</paragraph>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ </section>
+ <section ids="rowspanning-tables" names="rowspanning\ tables">
+ <title auto="1" refid="toc-entry-37"><generated classes="sectnum">2.20 </generated>Rowspanning tables</title>
+ <paragraph>Here's a table with cells spanning several rows:</paragraph>
+ <table>
+ <tgroup cols="3">
+ <colspec colwidth="24"></colspec>
+ <colspec colwidth="12"></colspec>
+ <colspec colwidth="18"></colspec>
+ <thead>
+ <row>
+ <entry>
+ <paragraph>Header row, column 1
+ (header rows optional)</paragraph>
+ </entry>
+ <entry>
+ <paragraph>Header 2</paragraph>
+ </entry>
+ <entry>
+ <paragraph>Header 3</paragraph>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <paragraph>body row 1, column 1</paragraph>
+ </entry>
+ <entry>
+ <paragraph>column 2</paragraph>
+ </entry>
+ <entry>
+ <paragraph>column 3</paragraph>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <paragraph>body row 2</paragraph>
+ </entry>
+ <entry morerows="1">
+ <paragraph>Cells may
+ span rows.</paragraph>
+ </entry>
+ <entry morerows="1">
+ <paragraph>Another
+ rowspanning
+ cell.</paragraph>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <paragraph>body row 3</paragraph>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ </section>
+ <section ids="complex-tables" names="complex\ tables">
+ <title auto="1" refid="toc-entry-38"><generated classes="sectnum">2.21 </generated>Complex tables</title>
+ <paragraph>Here's a complex table, which should test all features.</paragraph>
+ <table>
+ <tgroup cols="4">
+ <colspec colwidth="24"></colspec>
+ <colspec colwidth="12"></colspec>
+ <colspec colwidth="10"></colspec>
+ <colspec colwidth="10"></colspec>
+ <thead>
+ <row>
+ <entry>
+ <paragraph>Header row, column 1
+ (header rows optional)</paragraph>
+ </entry>
+ <entry>
+ <paragraph>Header 2</paragraph>
+ </entry>
+ <entry>
+ <paragraph>Header 3</paragraph>
+ </entry>
+ <entry>
+ <paragraph>Header 4</paragraph>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <paragraph>body row 1, column 1</paragraph>
+ </entry>
+ <entry>
+ <paragraph>column 2</paragraph>
+ </entry>
+ <entry>
+ <paragraph>column 3</paragraph>
+ </entry>
+ <entry>
+ <paragraph>column 4</paragraph>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <paragraph>body row 2</paragraph>
+ </entry>
+ <entry morecols="2">
+ <paragraph>Cells may span columns.</paragraph>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <paragraph>body row 3</paragraph>
+ </entry>
+ <entry morerows="1">
+ <paragraph>Cells may
+ span rows.</paragraph>
+ <paragraph>Paragraph.</paragraph>
+ </entry>
+ <entry morecols="1" morerows="1">
+ <bullet_list bullet="-">
+ <list_item>
+ <paragraph>Table cells</paragraph>
+ </list_item>
+ <list_item>
+ <paragraph>contain</paragraph>
+ </list_item>
+ <list_item>
+ <paragraph>body elements.</paragraph>
+ </list_item>
+ </bullet_list>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <paragraph>body row 4</paragraph>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <paragraph>body row 5</paragraph>
+ </entry>
+ <entry morecols="1">
+ <paragraph>Cells may also be
+ empty: <literal>--></literal></paragraph>
+ </entry>
+ <entry>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ </section>
+ <section ids="list-tables" names="list\ tables">
+ <title auto="1" refid="toc-entry-39"><generated classes="sectnum">2.22 </generated>List Tables</title>
+ <paragraph>Here's a list table exercising all features:</paragraph>
+ <table classes="colwidths-given test" width="40em">
+ <title>list table with integral header</title>
+ <tgroup cols="3">
+ <colspec colwidth="10" stub="1"></colspec>
+ <colspec colwidth="20"></colspec>
+ <colspec colwidth="30"></colspec>
+ <thead>
+ <row>
+ <entry>
+ <paragraph>Treat</paragraph>
+ </entry>
+ <entry>
+ <paragraph>Quantity</paragraph>
+ </entry>
+ <entry>
+ <paragraph>Description</paragraph>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <paragraph>Albatross</paragraph>
+ </entry>
+ <entry>
+ <paragraph>2.99</paragraph>
+ </entry>
+ <entry>
+ <paragraph>On a stick!</paragraph>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <paragraph>Crunchy Frog</paragraph>
+ </entry>
+ <entry>
+ <paragraph>1.49</paragraph>
+ </entry>
+ <entry>
+ <paragraph>If we took the bones out, it wouldn't be
+ crunchy, now would it?</paragraph>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <paragraph>Gannet Ripple</paragraph>
+ </entry>
+ <entry>
+ <paragraph>1.99</paragraph>
+ </entry>
+ <entry>
+ <paragraph>On a stick!</paragraph>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ <table align="center" classes="colwidths-auto">
+ <title>center aligned list table</title>
+ <tgroup cols="2">
+ <colspec colwidth="50"></colspec>
+ <colspec colwidth="50"></colspec>
+ <tbody>
+ <row>
+ <entry>
+ <paragraph>Albatross</paragraph>
+ </entry>
+ <entry>
+ <paragraph>2.99</paragraph>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <paragraph>Crunchy Frog</paragraph>
+ </entry>
+ <entry>
+ <paragraph>1.49</paragraph>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <paragraph>Gannet Ripple</paragraph>
+ </entry>
+ <entry>
+ <paragraph>1.99</paragraph>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ </section>
+ </section>
+ <section ids="error-handling" names="error\ handling">
+ <title auto="1" refid="toc-entry-40"><generated classes="sectnum">3 </generated>Error Handling</title>
+ <paragraph>Any errors caught during processing will generate system messages.</paragraph>
+ <paragraph>There should be five messages in the following, auto-generated
+ section, "Docutils System Messages":</paragraph>
+ <comment xml:space="preserve">section should be added by Docutils automatically</comment>
+ </section>
+ <section classes="system-messages">
+ <title>Docutils System Messages</title>
+ <system_message backrefs="problematic-1" ids="system-message-1" level="3" line="104" source="functional/input/data/standard.txt" type="ERROR">
+ <paragraph>Undefined substitution referenced: "problematic".</paragraph>
+ </system_message>
+ <system_message backrefs="footnote-reference-8" ids="system-message-2" level="3" line="392" source="functional/input/data/standard.txt" type="ERROR">
+ <paragraph>Unknown target name: "5".</paragraph>
+ </system_message>
+ <system_message backrefs="citation-reference-3" ids="system-message-3" level="3" line="401" source="functional/input/data/standard.txt" type="ERROR">
+ <paragraph>Unknown target name: "nonexistent".</paragraph>
+ </system_message>
+ <system_message backrefs="problematic-2" ids="system-message-4" level="3" line="428" source="functional/input/data/standard.txt" type="ERROR">
+ <paragraph>Unknown target name: "hyperlink reference without a target".</paragraph>
+ </system_message>
+ <system_message backrefs="problematic-3" ids="system-message-5" level="3" line="441" source="functional/input/data/standard.txt" type="ERROR">
+ <paragraph>Duplicate target name, cannot be used as a unique reference: "duplicate target names".</paragraph>
+ </system_message>
+ <system_message level="1" line="164" source="functional/input/data/standard.txt" type="INFO">
+ <paragraph>Hyperlink target "target" is not referenced.</paragraph>
+ </system_message>
+ <system_message level="1" line="406" source="functional/input/data/standard.txt" type="INFO">
+ <paragraph>Hyperlink target "another-target" is not referenced.</paragraph>
+ </system_message>
+ <system_message level="1" line="474" source="functional/input/data/standard.txt" type="INFO">
+ <paragraph>Hyperlink target "image-target-1" is not referenced.</paragraph>
+ </system_message>
+ <system_message level="1" line="475" source="functional/input/data/standard.txt" type="INFO">
+ <paragraph>Hyperlink target "image-target-2" is not referenced.</paragraph>
+ </system_message>
+ <system_message level="1" line="476" source="functional/input/data/standard.txt" type="INFO">
+ <paragraph>Hyperlink target "image-target-3" is not referenced.</paragraph>
+ </system_message>
+ <system_message level="1" line="640" source="functional/input/data/standard.txt" type="INFO">
+ <paragraph>Hyperlink target "target1" is not referenced.</paragraph>
+ </system_message>
+ <system_message level="1" line="641" source="functional/input/data/standard.txt" type="INFO">
+ <paragraph>Hyperlink target "target2" is not referenced.</paragraph>
+ </system_message>
+ <system_message level="1" line="686" source="functional/input/data/standard.txt" type="INFO">
+ <paragraph>Hyperlink target "docutils" is not referenced.</paragraph>
+ </system_message>
+ <system_message level="1" line="852" source="functional/input/data/standard.txt" type="INFO">
+ <paragraph>Hyperlink target "hyperlink targets" is not referenced.</paragraph>
+ </system_message>
+ </section>
+</document>
--- /dev/null
+<?xml version="1.0" encoding="utf-8" ?>
+<!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">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<meta name="generator" content="Docutils 0.16: http://docutils.sourceforge.net/" />
+<title>reStructuredText Test Document</title>
+<meta name="author" content="David Goodger" />
+<meta name="authors" content="Me Myself I" />
+<meta name="organization" content="humankind" />
+<meta name="date" content="Now, or yesterday. Or maybe even before yesterday." />
+<meta name="copyright" content="This document has been placed in the public domain. You may do with it as you wish. You may copy, modify, redistribute, reattribute, sell, buy, rent, lease, destroy, or improve it, quote it at length, excerpt, incorporate, collate, fold, staple, or mutilate it, or do anything else to it that your or anyone else's heart desires." />
+<meta content="reStructuredText, test, parser" name="keywords" />
+<meta content="A test document, containing at least one example of each reStructuredText construct." lang="en" name="description" />
+<link rel="stylesheet" href="../input/data/html4css1.css" type="text/css" />
+<link rel="stylesheet" href="../input/data/math.css" type="text/css" />
+</head>
+<body>
+<div class="header">
+Document header
+<hr class="header"/>
+</div>
+<div class="document" id="restructuredtext-test-document">
+<span id="doctitle"></span>
+<h1 class="title">reStructuredText Test Document</h1>
+<h2 class="subtitle" id="examples-of-syntax-constructs"><span id="subtitle"></span>Examples of Syntax Constructs</h2>
+<table class="docinfo" frame="void" rules="none">
+<col class="docinfo-name" />
+<col class="docinfo-content" />
+<tbody valign="top">
+<tr><th class="docinfo-name">Author:</th>
+<td>David Goodger</td></tr>
+<tr><th class="docinfo-name">Address:</th>
+<td><pre class="address">
+123 Example Street
+Example, EX Canada
+A1B 2C3
+</pre>
+</td></tr>
+<tr><th class="docinfo-name">Contact:</th>
+<td><a class="first last reference external" href="mailto:goodger@python.org">goodger@python.org</a></td></tr>
+<tr><th class="docinfo-name">Authors:</th>
+<td>Me
+<br />Myself
+<br />I</td></tr>
+<tr><th class="docinfo-name">Organization:</th>
+<td>humankind</td></tr>
+<tr><th class="docinfo-name">Date:</th>
+<td>Now, or yesterday. Or maybe even <em>before</em> yesterday.</td></tr>
+<tr><th class="docinfo-name">Status:</th>
+<td>This is a "work in progress"</td></tr>
+<tr><th class="docinfo-name">Revision:</th>
+<td>is managed by a version control system.</td></tr>
+<tr><th class="docinfo-name">Version:</th>
+<td>1</td></tr>
+<tr><th class="docinfo-name">Copyright:</th>
+<td>This document has been placed in the public domain. You
+may do with it as you wish. You may copy, modify,
+redistribute, reattribute, sell, buy, rent, lease,
+destroy, or improve it, quote it at length, excerpt,
+incorporate, collate, fold, staple, or mutilate it, or do
+anything else to it that your or anyone else's heart
+desires.</td></tr>
+<tr class="field-name field"><th class="docinfo-name">field name:</th><td class="field-body">This is a "generic bibliographic field".</td>
+</tr>
+<tr class="field-name-2 field"><th class="docinfo-name">field name "2":</th><td class="field-body"><p class="first">Generic bibliographic fields may contain multiple body elements.</p>
+<p class="last">Like this.</p>
+</td>
+</tr>
+</tbody>
+</table>
+<div class="dedication topic">
+<p class="topic-title">Dedication</p>
+<p>For Docutils users & co-developers.</p>
+</div>
+<div class="abstract topic">
+<p class="topic-title">Abstract</p>
+<p>This is a test document, containing at least one example of each
+reStructuredText construct.</p>
+</div>
+<!-- This is a comment. Note how any initial comments are moved by
+transforms to after the document title, subtitle, and docinfo. -->
+<!-- Above is the document title, and below is the subtitle.
+They are transformed from section titles after parsing. -->
+<!-- bibliographic fields (which also require a transform): -->
+<div class="contents topic" id="table-of-contents">
+<p class="topic-title">Table of Contents</p>
+<ul class="auto-toc simple">
+<li><a class="reference internal" href="#structural-elements" id="toc-entry-1">1 Structural Elements</a><ul class="auto-toc">
+<li><a class="reference internal" href="#section-title" id="toc-entry-2">1.1 Section Title</a></li>
+<li><a class="reference internal" href="#empty-section" id="toc-entry-3">1.2 Empty Section</a></li>
+<li><a class="reference internal" href="#transitions" id="toc-entry-4">1.3 Transitions</a></li>
+</ul>
+</li>
+<li><a class="reference internal" href="#body-elements" id="toc-entry-5">2 Body Elements</a><ul class="auto-toc">
+<li><a class="reference internal" href="#paragraphs" id="toc-entry-6">2.1 Paragraphs</a><ul class="auto-toc">
+<li><a class="reference internal" href="#inline-markup" id="toc-entry-7">2.1.1 Inline Markup</a></li>
+</ul>
+</li>
+<li><a class="reference internal" href="#bullet-lists" id="toc-entry-8">2.2 Bullet Lists</a></li>
+<li><a class="reference internal" href="#enumerated-lists" id="toc-entry-9">2.3 Enumerated Lists</a></li>
+<li><a class="reference internal" href="#definition-lists" id="toc-entry-10">2.4 Definition Lists</a></li>
+<li><a class="reference internal" href="#field-lists" id="toc-entry-11">2.5 Field Lists</a></li>
+<li><a class="reference internal" href="#option-lists" id="toc-entry-12">2.6 Option Lists</a></li>
+<li><a class="reference internal" href="#literal-blocks" id="toc-entry-13">2.7 Literal Blocks</a></li>
+<li><a class="reference internal" href="#line-blocks" id="toc-entry-14">2.8 Line Blocks</a></li>
+<li><a class="reference internal" href="#block-quotes" id="toc-entry-15">2.9 Block Quotes</a></li>
+<li><a class="reference internal" href="#doctest-blocks" id="toc-entry-16">2.10 Doctest Blocks</a></li>
+<li><a class="reference internal" href="#footnotes" id="toc-entry-17">2.11 Footnotes</a></li>
+<li><a class="reference internal" href="#citations" id="toc-entry-18">2.12 Citations</a></li>
+<li><a class="reference internal" href="#targets" id="toc-entry-19">2.13 Targets</a><ul class="auto-toc">
+<li><a class="reference internal" href="#duplicate-target-names" id="toc-entry-20">2.13.1 Duplicate Target Names</a></li>
+<li><a class="reference internal" href="#duplicate-target-names-1" id="toc-entry-21">2.13.2 Duplicate Target Names</a></li>
+</ul>
+</li>
+<li><a class="reference internal" href="#directives" id="toc-entry-22">2.14 Directives</a><ul class="auto-toc">
+<li><a class="reference internal" href="#document-parts" id="toc-entry-23">2.14.1 Document Parts</a></li>
+<li><a class="reference internal" href="#images-and-figures" id="toc-entry-24">2.14.2 Images and Figures</a></li>
+<li><a class="reference internal" href="#admonitions" id="toc-entry-25">2.14.3 Admonitions</a></li>
+<li><a class="reference internal" href="#topics-sidebars-and-rubrics" id="toc-entry-26">2.14.4 Topics, Sidebars, and Rubrics</a></li>
+<li><a class="reference internal" href="#target-footnotes" id="toc-entry-27">2.14.5 Target Footnotes</a></li>
+<li><a class="reference internal" href="#replacement-text" id="toc-entry-28">2.14.6 Replacement Text</a></li>
+<li><a class="reference internal" href="#compound-paragraph" id="toc-entry-29">2.14.7 Compound Paragraph</a></li>
+<li><a class="reference internal" href="#parsed-literal-blocks" id="toc-entry-30">2.14.8 Parsed Literal Blocks</a></li>
+<li><a class="reference internal" href="#code" id="toc-entry-31">2.14.9 Code</a></li>
+</ul>
+</li>
+<li><a class="reference internal" href="#substitution-definitions" id="toc-entry-32">2.15 Substitution Definitions</a></li>
+<li><a class="reference internal" href="#comments" id="toc-entry-33">2.16 Comments</a></li>
+<li><a class="reference internal" href="#raw-text" id="toc-entry-34">2.17 Raw text</a></li>
+<li><a class="reference internal" href="#container" id="toc-entry-35">2.18 Container</a></li>
+<li><a class="reference internal" href="#colspanning-tables" id="toc-entry-36">2.19 Colspanning tables</a></li>
+<li><a class="reference internal" href="#rowspanning-tables" id="toc-entry-37">2.20 Rowspanning tables</a></li>
+<li><a class="reference internal" href="#complex-tables" id="toc-entry-38">2.21 Complex tables</a></li>
+<li><a class="reference internal" href="#list-tables" id="toc-entry-39">2.22 List Tables</a></li>
+<li><a class="reference internal" href="#custom-roles" id="toc-entry-40">2.23 Custom Roles</a></li>
+<li><a class="reference internal" href="#svg-images" id="toc-entry-41">2.24 SVG Images</a></li>
+<li><a class="reference internal" href="#swf-images" id="toc-entry-42">2.25 SWF Images</a></li>
+</ul>
+</li>
+<li><a class="reference internal" href="#error-handling" id="toc-entry-43">3 Error Handling</a></li>
+</ul>
+</div>
+<div class="section" id="structural-elements">
+<h1><a class="toc-backref" href="#toc-entry-1">1 Structural Elements</a></h1>
+<div class="section" id="section-title">
+<h2 class="with-subtitle"><a class="toc-backref" href="#toc-entry-2">1.1 Section Title</a></h2>
+<h2 class="section-subtitle" id="section-subtitle"><span class="section-subtitle">Section Subtitle</span></h2>
+<p>Lone subsections are converted to a section subtitle by a transform
+activated with the <tt class="docutils literal"><span class="pre">--section-subtitles</span></tt> command line option or the
+<tt class="docutils literal"><span class="pre">sectsubtitle-xform</span></tt> configuration value.</p>
+</div>
+<div class="section" id="empty-section">
+<h2><a class="toc-backref" href="#toc-entry-3">1.2 Empty Section</a></h2>
+</div>
+<div class="section" id="transitions">
+<h2><a class="toc-backref" href="#toc-entry-4">1.3 Transitions</a></h2>
+<p>Here's a transition:</p>
+<hr class="docutils" />
+<p>It divides the section. Transitions may also occur between sections:</p>
+</div>
+</div>
+<hr class="docutils" />
+<div class="section" id="body-elements">
+<h1><a class="toc-backref" href="#toc-entry-5">2 Body Elements</a></h1>
+<div class="section" id="paragraphs">
+<h2><a class="toc-backref" href="#toc-entry-6">2.1 Paragraphs</a></h2>
+<p>A paragraph.</p>
+<div class="section" id="inline-markup">
+<h3><a class="toc-backref" href="#toc-entry-7">2.1.1 Inline Markup</a></h3>
+<p>Paragraphs contain text and may contain inline markup: <em>emphasis</em>,
+<strong>strong emphasis</strong>, <tt class="docutils literal">inline literals</tt>, standalone hyperlinks
+(<a class="reference external" href="http://www.python.org">http://www.python.org</a>), external hyperlinks (<a class="reference external" href="http://www.python.org/">Python</a> <a class="footnote-reference" href="#footnote-6" id="footnote-reference-10">[5]</a>), internal
+cross-references (<a class="reference internal" href="#example">example</a>), external hyperlinks with embedded URIs
+(<a class="reference external" href="http://www.python.org">Python web site</a>), <a class="reference external" href="http://www.python.org/">anonymous hyperlink
+references</a> <a class="footnote-reference" href="#footnote-6" id="footnote-reference-14">[5]</a> (<a class="reference external" href="http://docutils.sourceforge.net/">a second reference</a> <a class="footnote-reference" href="#footnote-8" id="footnote-reference-15">[7]</a>), footnote references (manually
+numbered <a class="footnote-reference" href="#footnote-1" id="footnote-reference-1">[1]</a>, anonymous auto-numbered <a class="footnote-reference" href="#footnote-2" id="footnote-reference-2">[3]</a>, labeled auto-numbered
+<a class="footnote-reference" href="#label" id="footnote-reference-3">[2]</a>, or symbolic <a class="footnote-reference" href="#footnote-3" id="footnote-reference-4">[*]</a>), citation references (<a class="citation-reference" href="#cit2002" id="citation-reference-1">[CIT2002]</a>),
+substitution references (<img alt="EXAMPLE" src="../../../docs/user/rst/images/biohazard.png" /> &
+a <em>trimmed heart</em> <tt class="docutils literal">(U+2665):</tt>♥), and <span class="target" id="inline-hyperlink-targets">inline hyperlink targets</span>
+(see <a class="reference internal" href="#targets">Targets</a> below for a reference back to here). Character-level
+inline markup is also possible (although exceedingly ugly!) in <em>re</em><tt class="docutils literal">Structured</tt><em>Text</em>. Problems are indicated by <a href="#system-message-1"><span class="problematic" id="problematic-1">|problematic|</span></a> text
+(generated by processing errors; this one is intentional). Here is a
+reference to the <a class="reference internal" href="#doctitle">doctitle</a> and the <a class="reference internal" href="#subtitle">subtitle</a>.</p>
+<p>The default role for interpreted text is <cite>Title Reference</cite>. Here are
+some explicit interpreted text roles: a PEP reference (<a class="reference external" href="http://www.python.org/dev/peps/pep-0287">PEP 287</a>); an
+RFC reference (<a class="reference external" href="http://tools.ietf.org/html/rfc2822.html">RFC 2822</a>); an abbreviation (<abbr>abb.</abbr>), an acronym
+(<acronym>reST</acronym>), code (<code>print "hello world"</code>); a <sub>subscript</sub>;
+a <sup>superscript</sup> and explicit roles for <cite>Docutils</cite>'
+<em>standard</em> <strong>inline</strong> <tt class="docutils literal">markup</tt>.</p>
+<!-- DO NOT RE-WRAP THE FOLLOWING PARAGRAPH! -->
+<p>Let's test wrapping and whitespace significance in inline literals:
+<tt class="docutils literal">This is an example of <span class="pre">--inline-literal</span> <span class="pre">--text,</span> <span class="pre">--including</span> <span class="pre">some--</span>
+<span class="pre">strangely--hyphenated-words.</span> <span class="pre">Adjust-the-width-of-your-browser-window</span>
+to see how the text is wrapped. <span class="pre">--</span> <span class="pre">----</span> <span class="pre">--------</span> Now note the
+spacing between the words of this sentence (words
+should be grouped in pairs).</tt></p>
+<p>If the <tt class="docutils literal"><span class="pre">--pep-references</span></tt> option was supplied, there should be a
+live link to PEP 258 here.</p>
+</div>
+</div>
+<div class="section" id="bullet-lists">
+<h2><a class="toc-backref" href="#toc-entry-8">2.2 Bullet Lists</a></h2>
+<ul>
+<li><p class="first">A bullet list</p>
+<ul class="simple">
+<li>Nested bullet list.</li>
+<li>Nested item 2.</li>
+</ul>
+</li>
+<li><p class="first">Item 2.</p>
+<p>Paragraph 2 of item 2.</p>
+<ul class="simple">
+<li>Nested bullet list.</li>
+<li>Nested item 2.<ul>
+<li>Third level.</li>
+<li>Item 2.</li>
+</ul>
+</li>
+<li>Nested item 3.</li>
+<li>This nested list should be compacted by the HTML writer.<span class="target" id="target"></span><!-- Even if this item contains a target and a comment. -->
+</li>
+</ul>
+</li>
+</ul>
+</div>
+<div class="section" id="enumerated-lists">
+<h2><a class="toc-backref" href="#toc-entry-9">2.3 Enumerated Lists</a></h2>
+<ol class="arabic">
+<li><p class="first">Arabic numerals.</p>
+<ol class="loweralpha simple">
+<li>lower alpha)<ol class="lowerroman">
+<li>(lower roman)<ol class="upperalpha">
+<li>upper alpha.<ol class="upperroman">
+<li>upper roman)</li>
+</ol>
+</li>
+</ol>
+</li>
+</ol>
+</li>
+</ol>
+</li>
+<li><p class="first">Lists that don't start at 1:</p>
+<ol class="arabic simple" start="3">
+<li>Three</li>
+<li>Four</li>
+</ol>
+<ol class="upperalpha simple" start="3">
+<li>C</li>
+<li>D</li>
+</ol>
+<ol class="lowerroman simple" start="3">
+<li>iii</li>
+<li>iv</li>
+</ol>
+</li>
+</ol>
+</div>
+<div class="section" id="definition-lists">
+<h2><a class="toc-backref" href="#toc-entry-10">2.4 Definition Lists</a></h2>
+<dl class="docutils">
+<dt>Term</dt>
+<dd>Definition</dd>
+<dt>Term <span class="classifier-delimiter">:</span> <span class="classifier">classifier</span></dt>
+<dd><p class="first">Definition paragraph 1.</p>
+<p class="last">Definition paragraph 2.</p>
+</dd>
+<dt>Term</dt>
+<dd>Definition</dd>
+<dt>Term <span class="classifier-delimiter">:</span> <span class="classifier">classifier one</span> <span class="classifier-delimiter">:</span> <span class="classifier">classifier two</span></dt>
+<dd>Definition</dd>
+</dl>
+</div>
+<div class="section" id="field-lists">
+<h2><a class="toc-backref" href="#toc-entry-11">2.5 Field Lists</a></h2>
+<table class="docutils field-list" frame="void" rules="none">
+<col class="field-name" />
+<col class="field-body" />
+<tbody valign="top">
+<tr class="field"><th class="field-name">what:</th><td class="field-body"><p class="first">Field lists map field names to field bodies, like database
+records. They are often part of an extension syntax. They are
+an unambiguous variant of RFC 2822 fields.</p>
+</td>
+</tr>
+<tr class="field"><th class="field-name">how arg1 arg2:</th><td class="field-body"><p class="first">The field marker is a colon, the field name, and a colon.</p>
+<p>The field body may contain one or more body elements, indented
+relative to the field marker.</p>
+</td>
+</tr>
+<tr class="field"><th class="field-name">credits:</th><td class="field-body"><p class="credits first last">This paragraph has the <cite>credits</cite> class set. (This is actually not
+about credits but just for ensuring that the class attribute
+doesn't get stripped away.)</p>
+</td>
+</tr>
+</tbody>
+</table>
+</div>
+<div class="section" id="option-lists">
+<h2><a class="toc-backref" href="#toc-entry-12">2.6 Option Lists</a></h2>
+<p>For listing command-line options:</p>
+<table class="docutils option-list" frame="void" rules="none">
+<col class="option" />
+<col class="description" />
+<tbody valign="top">
+<tr><td class="option-group">
+<kbd><span class="option">-a</span></kbd></td>
+<td>command-line option "a"</td></tr>
+<tr><td class="option-group">
+<kbd><span class="option">-b <var>file</var></span></kbd></td>
+<td>options can have arguments
+and long descriptions</td></tr>
+<tr><td class="option-group">
+<kbd><span class="option">--long</span></kbd></td>
+<td>options can be long also</td></tr>
+<tr><td class="option-group">
+<kbd><span class="option">--input=<var>file</var></span></kbd></td>
+<td>long options can also have
+arguments</td></tr>
+<tr><td class="option-group" colspan="2">
+<kbd><span class="option">--very-long-option</span></kbd></td>
+</tr>
+<tr><td> </td><td><p class="first">The description can also start on the next line.</p>
+<p class="last">The description may contain multiple body elements,
+regardless of where it starts.</p>
+</td></tr>
+<tr><td class="option-group">
+<kbd><span class="option">-x</span>, <span class="option">-y</span>, <span class="option">-z</span></kbd></td>
+<td>Multiple options are an "option group".</td></tr>
+<tr><td class="option-group">
+<kbd><span class="option">-v</span>, <span class="option">--verbose</span></kbd></td>
+<td>Commonly-seen: short & long options.</td></tr>
+<tr><td class="option-group" colspan="2">
+<kbd><span class="option">-1 <var>file</var></span>, <span class="option">--one=<var>file</var></span>, <span class="option">--two <var>file</var></span></kbd></td>
+</tr>
+<tr><td> </td><td>Multiple options with arguments.</td></tr>
+<tr><td class="option-group">
+<kbd><span class="option">/V</span></kbd></td>
+<td>DOS/VMS-style options too</td></tr>
+</tbody>
+</table>
+<p>There must be at least two spaces between the option and the
+description.</p>
+</div>
+<div class="section" id="literal-blocks">
+<h2><a class="toc-backref" href="#toc-entry-13">2.7 Literal Blocks</a></h2>
+<p>Literal blocks are indicated with a double-colon ("::") at the end of
+the preceding paragraph (over there <tt class="docutils literal"><span class="pre">--></span></tt>). They can be indented:</p>
+<pre class="literal-block">
+if literal_block:
+ text = 'is left as-is'
+ spaces_and_linebreaks = 'are preserved'
+ markup_processing = None
+</pre>
+<p>Or they can be quoted without indentation:</p>
+<pre class="literal-block">
+>> Great idea!
+>
+> Why didn't I think of that?
+</pre>
+</div>
+<div class="section" id="line-blocks">
+<h2><a class="toc-backref" href="#toc-entry-14">2.8 Line Blocks</a></h2>
+<p>This section tests line blocks. Line blocks are body elements which
+consist of lines and other line blocks. Nested line blocks cause
+indentation.</p>
+<div class="line-block">
+<div class="line">This is a line block. It ends with a blank line.</div>
+<div class="line-block">
+<div class="line">New lines begin with a vertical bar ("|").</div>
+<div class="line">Line breaks and initial indent are significant, and preserved.</div>
+<div class="line-block">
+<div class="line">Continuation lines are also possible. A long line that is intended
+to wrap should begin with a space in place of the vertical bar.</div>
+</div>
+<div class="line">The left edge of a continuation line need not be aligned with
+the left edge of the text above it.</div>
+</div>
+</div>
+<div class="line-block">
+<div class="line">This is a second line block.</div>
+<div class="line"><br /></div>
+<div class="line">Blank lines are permitted internally, but they must begin with a "|".</div>
+</div>
+<p>Another line block, surrounded by paragraphs:</p>
+<div class="line-block">
+<div class="line">And it's no good waiting by the window</div>
+<div class="line">It's no good waiting for the sun</div>
+<div class="line">Please believe me, the things you dream of</div>
+<div class="line">They don't fall in the lap of no-one</div>
+</div>
+<p>Take it away, Eric the Orchestra Leader!</p>
+<blockquote>
+<div class="line-block">
+<div class="line">A one, two, a one two three four</div>
+<div class="line"><br /></div>
+<div class="line">Half a bee, philosophically,</div>
+<div class="line-block">
+<div class="line">must, <em>ipso facto</em>, half not be.</div>
+</div>
+<div class="line">But half the bee has got to be,</div>
+<div class="line-block">
+<div class="line"><em>vis a vis</em> its entity. D'you see?</div>
+<div class="line"><br /></div>
+</div>
+<div class="line">But can a bee be said to be</div>
+<div class="line-block">
+<div class="line">or not to be an entire bee,</div>
+<div class="line-block">
+<div class="line">when half the bee is not a bee,</div>
+<div class="line-block">
+<div class="line">due to some ancient injury?</div>
+<div class="line"><br /></div>
+</div>
+</div>
+</div>
+<div class="line">Singing...</div>
+</div>
+</blockquote>
+<p>A line block, like the following poem by Christian Morgenstern, can
+also be centre-aligned:</p>
+<div class="align-center line-block" lang="de">
+<div class="line"><strong>Die Trichter</strong></div>
+<div class="line"><br /></div>
+<div class="line">Zwei Trichter wandeln durch die Nacht.</div>
+<div class="line">Durch ihres Rumpfs verengten Schacht</div>
+<div class="line">fließt weißes Mondlicht</div>
+<div class="line">still und heiter</div>
+<div class="line">auf ihren</div>
+<div class="line">Waldweg</div>
+<div class="line">u. s.</div>
+<div class="line">w.</div>
+<div class="line"><br /></div>
+</div>
+</div>
+<div class="section" id="block-quotes">
+<h2><a class="toc-backref" href="#toc-entry-15">2.9 Block Quotes</a></h2>
+<p>Block quotes consist of indented body elements:</p>
+<blockquote>
+<p>My theory by A. Elk. Brackets Miss, brackets. This theory goes
+as follows and begins now. All brontosauruses are thin at one
+end, much much thicker in the middle and then thin again at the
+far end. That is my theory, it is mine, and belongs to me and I
+own it, and what it is too.</p>
+<p class="attribution">—Anne Elk (Miss)</p>
+</blockquote>
+<p>The language of a quote (like any other object) can be specified by
+a class attribute:</p>
+<!-- -->
+<blockquote lang="fr">
+ReStructuredText est un langage de balisage léger utilisé
+notamment dans la documentation du langage Python.</blockquote>
+</div>
+<div class="section" id="doctest-blocks">
+<h2><a class="toc-backref" href="#toc-entry-16">2.10 Doctest Blocks</a></h2>
+<pre class="doctest-block">
+>>> print 'Python-specific usage examples; begun with ">>>"'
+Python-specific usage examples; begun with ">>>"
+>>> print '(cut and pasted from interactive Python sessions)'
+(cut and pasted from interactive Python sessions)
+</pre>
+</div>
+<div class="section" id="footnotes">
+<h2><a class="toc-backref" href="#toc-entry-17">2.11 Footnotes</a></h2>
+<table class="docutils footnote" frame="void" id="footnote-1" rules="none">
+<colgroup><col class="label" /><col /></colgroup>
+<tbody valign="top">
+<tr><td class="label">[1]</td><td><em>(<a class="fn-backref" href="#footnote-reference-1">1</a>, <a class="fn-backref" href="#footnote-reference-5">2</a>, <a class="fn-backref" href="#footnote-reference-9">3</a>)</em> <p>A footnote contains body elements, consistently indented by at
+least 3 spaces.</p>
+<p class="last">This is the footnote's second paragraph.</p>
+</td></tr>
+</tbody>
+</table>
+<table class="docutils footnote" frame="void" id="label" rules="none">
+<colgroup><col class="label" /><col /></colgroup>
+<tbody valign="top">
+<tr><td class="label">[2]</td><td><em>(<a class="fn-backref" href="#footnote-reference-3">1</a>, <a class="fn-backref" href="#footnote-reference-6">2</a>)</em> Footnotes may be numbered, either manually (as in <a class="footnote-reference" href="#footnote-1" id="footnote-reference-5">[1]</a>) or
+automatically using a "#"-prefixed label. This footnote has a
+label so it can be referred to from multiple places, both as a
+footnote reference (<a class="footnote-reference" href="#label" id="footnote-reference-6">[2]</a>) and as a <a class="reference internal" href="#label">hyperlink reference</a>.</td></tr>
+</tbody>
+</table>
+<table class="docutils footnote" frame="void" id="footnote-2" rules="none">
+<colgroup><col class="label" /><col /></colgroup>
+<tbody valign="top">
+<tr><td class="label"><a class="fn-backref" href="#footnote-reference-2">[3]</a></td><td><p class="first">This footnote is numbered automatically and anonymously using a
+label of "#" only.</p>
+<p>This is the second paragraph.</p>
+<p class="last">And this is the third paragraph.</p>
+</td></tr>
+</tbody>
+</table>
+<table class="docutils footnote" frame="void" id="footnote-3" rules="none">
+<colgroup><col class="label" /><col /></colgroup>
+<tbody valign="top">
+<tr><td class="label"><a class="fn-backref" href="#footnote-reference-4">[*]</a></td><td>Footnotes may also use symbols, specified with a "*" label.
+Here's a reference to the next footnote: <a class="footnote-reference" href="#footnote-4" id="footnote-reference-7">[†]</a>.</td></tr>
+</tbody>
+</table>
+<table class="docutils footnote" frame="void" id="footnote-4" rules="none">
+<colgroup><col class="label" /><col /></colgroup>
+<tbody valign="top">
+<tr><td class="label"><a class="fn-backref" href="#footnote-reference-7">[†]</a></td><td>This footnote shows the next symbol in the sequence.</td></tr>
+</tbody>
+</table>
+<table class="docutils footnote" frame="void" id="footnote-5" rules="none">
+<colgroup><col class="label" /><col /></colgroup>
+<tbody valign="top">
+<tr><td class="label">[4]</td><td>Here's an unreferenced footnote, with a reference to a
+nonexistent footnote: <a href="#system-message-2"><span class="problematic" id="footnote-reference-8">[5]_</span></a>.</td></tr>
+</tbody>
+</table>
+</div>
+<div class="section" id="citations">
+<h2><a class="toc-backref" href="#toc-entry-18">2.12 Citations</a></h2>
+<table class="docutils citation" frame="void" id="cit2002" rules="none">
+<colgroup><col class="label" /><col /></colgroup>
+<tbody valign="top">
+<tr><td class="label">[CIT2002]</td><td><em>(<a class="fn-backref" href="#citation-reference-1">1</a>, <a class="fn-backref" href="#citation-reference-2">2</a>)</em> Citations are text-labeled footnotes. They may be
+rendered separately and differently from footnotes.</td></tr>
+</tbody>
+</table>
+<p>Here's a reference to the above, <a class="citation-reference" href="#cit2002" id="citation-reference-2">[CIT2002]</a>, and a <a href="#system-message-3"><span class="problematic" id="citation-reference-3">[nonexistent]_</span></a>
+citation.</p>
+</div>
+<div class="section" id="targets">
+<span id="another-target"></span><h2><a class="toc-backref" href="#toc-entry-19">2.13 Targets</a></h2>
+<p id="example">This paragraph is pointed to by the explicit "example" target. A
+reference can be found under <a class="reference internal" href="#inline-markup">Inline Markup</a>, above. <a class="reference internal" href="#inline-hyperlink-targets">Inline
+hyperlink targets</a> are also possible.</p>
+<p>Section headers are implicit targets, referred to by name. See
+<a class="reference internal" href="#targets">Targets</a>, which is a subsection of <a class="reference internal" href="#body-elements">Body Elements</a>.</p>
+<p>Explicit external targets are interpolated into references such as
+"<a class="reference external" href="http://www.python.org/">Python</a> <a class="footnote-reference" href="#footnote-6" id="footnote-reference-11">[5]</a>".</p>
+<p>Targets may be indirect and anonymous. Thus <a class="reference internal" href="#targets">this phrase</a> may also
+refer to the <a class="reference internal" href="#targets">Targets</a> section.</p>
+<p>Here's a <a href="#system-message-4"><span class="problematic" id="problematic-2">`hyperlink reference without a target`_</span></a>, which generates an
+error.</p>
+<div class="section" id="duplicate-target-names">
+<h3><a class="toc-backref" href="#toc-entry-20">2.13.1 Duplicate Target Names</a></h3>
+<p>Duplicate names in section headers or other implicit targets will
+generate "info" (level-1) system messages. Duplicate names in
+explicit targets will generate "warning" (level-2) system messages.</p>
+</div>
+<div class="section" id="duplicate-target-names-1">
+<h3><a class="toc-backref" href="#toc-entry-21">2.13.2 Duplicate Target Names</a></h3>
+<p>Since there are two "Duplicate Target Names" section headers, we
+cannot uniquely refer to either of them by name. If we try to (like
+this: <a href="#system-message-5"><span class="problematic" id="problematic-3">`Duplicate Target Names`_</span></a>), an error is generated.</p>
+</div>
+</div>
+<div class="section" id="directives">
+<h2><a class="toc-backref" href="#toc-entry-22">2.14 Directives</a></h2>
+<div class="contents local topic" id="contents">
+<ul class="auto-toc simple">
+<li><a class="reference internal" href="#document-parts" id="toc-entry-44">2.14.1 Document Parts</a></li>
+<li><a class="reference internal" href="#images-and-figures" id="toc-entry-45">2.14.2 Images and Figures</a></li>
+<li><a class="reference internal" href="#admonitions" id="toc-entry-46">2.14.3 Admonitions</a></li>
+<li><a class="reference internal" href="#topics-sidebars-and-rubrics" id="toc-entry-47">2.14.4 Topics, Sidebars, and Rubrics</a></li>
+<li><a class="reference internal" href="#target-footnotes" id="toc-entry-48">2.14.5 Target Footnotes</a></li>
+<li><a class="reference internal" href="#replacement-text" id="toc-entry-49">2.14.6 Replacement Text</a></li>
+<li><a class="reference internal" href="#compound-paragraph" id="toc-entry-50">2.14.7 Compound Paragraph</a></li>
+<li><a class="reference internal" href="#parsed-literal-blocks" id="toc-entry-51">2.14.8 Parsed Literal Blocks</a></li>
+<li><a class="reference internal" href="#code" id="toc-entry-52">2.14.9 Code</a></li>
+</ul>
+</div>
+<p>These are just a sample of the many reStructuredText Directives. For
+others, please see
+<a class="reference external" href="http://docutils.sourceforge.net/docs/ref/rst/directives.html">http://docutils.sourceforge.net/docs/ref/rst/directives.html</a>.</p>
+<div class="section" id="document-parts">
+<h3><a class="toc-backref" href="#toc-entry-44">2.14.1 Document Parts</a></h3>
+<p>An example of the "contents" directive can be seen above this section
+(a local, untitled table of <a class="reference internal" href="#contents">contents</a>) and at the beginning of the
+document (a document-wide <a class="reference internal" href="#table-of-contents">table of contents</a>).</p>
+</div>
+<div class="section" id="images-and-figures">
+<h3><a class="toc-backref" href="#toc-entry-45">2.14.2 Images and Figures</a></h3>
+<p>An image directive (also clickable -- a hyperlink reference):</p>
+<a class="reference internal image-reference" href="#directives"><img alt="../../../docs/user/rst/images/title.png" class="class1 class2" src="../../../docs/user/rst/images/title.png" /></a>
+<p>Image with multiple IDs:</p>
+<span id="image-target-2"></span><span id="image-target-1"></span><img alt="../../../docs/user/rst/images/title.png" id="image-target-3" src="../../../docs/user/rst/images/title.png" />
+<p>A centered image:</p>
+<img alt="../../../docs/user/rst/images/biohazard.png" class="align-center" src="../../../docs/user/rst/images/biohazard.png" />
+<p>A left-aligned image:</p>
+<img alt="../../../docs/user/rst/images/biohazard.png" class="align-left" src="../../../docs/user/rst/images/biohazard.png" />
+<p>This paragraph might flow around the image.
+The specific behavior depends upon the style sheet and
+the browser or rendering software used.</p>
+<p>A right-aligned image:</p>
+<img alt="../../../docs/user/rst/images/biohazard.png" class="align-right" src="../../../docs/user/rst/images/biohazard.png" />
+<p>This paragraph might flow around the image.
+The specific behavior depends upon the style sheet and
+the browser or rendering software used.</p>
+<p>For inline images see <a class="reference internal" href="#substitution-definitions">Substitution Definitions</a>.</p>
+<p>Image size:</p>
+<p>An image 2 em wide:</p>
+<img alt="../../../docs/user/rst/images/biohazard.png" src="../../../docs/user/rst/images/biohazard.png" style="width: 2em;" />
+<p>An image 2 em wide and 15 pixel high:</p>
+<img alt="../../../docs/user/rst/images/biohazard.png" src="../../../docs/user/rst/images/biohazard.png" style="width: 2em; height: 15px;" />
+<p>An image occupying 50% of the line width:</p>
+<img alt="../../../docs/user/rst/images/title.png" src="../../../docs/user/rst/images/title.png" style="width: 50%;" />
+<p>An image 2 cm high:</p>
+<img alt="../../../docs/user/rst/images/biohazard.png" src="../../../docs/user/rst/images/biohazard.png" style="height: 2cm;" />
+<p>A <em>figure</em> is an image with a caption and/or a legend. With page-based output
+media, figures might float to a different position if this helps the page
+layout.</p>
+<div class="figclass1 figclass2 figure">
+<img alt="reStructuredText, the markup syntax" class="class1 class2" src="../../../docs/user/rst/images/title.png" style="width: 258px;" />
+<p class="caption">Plaintext markup syntax and parser system.</p>
+<div class="legend">
+<table border="1" class="docutils">
+<colgroup>
+<col width="20%" />
+<col width="80%" />
+</colgroup>
+<tbody valign="top">
+<tr><td>re</td>
+<td>Revised, revisited, based on 're' module.</td>
+</tr>
+<tr><td>Structured</td>
+<td>Structure-enhanced text, structuredtext.</td>
+</tr>
+<tr><td>Text</td>
+<td>Well it is, isn't it?</td>
+</tr>
+</tbody>
+</table>
+<p>This paragraph is also part of the legend.</p>
+</div>
+</div>
+<p>A left-aligned figure:</p>
+<div class="figclass1 figclass2 figure align-left" style="width: 70%">
+<img alt="reStructuredText, the markup syntax" class="class1 class2" src="../../../docs/user/rst/images/biohazard.png" style="width: 40px;" />
+<p class="caption">This is the caption.</p>
+<div class="legend">
+<p>This is the legend.</p>
+<p>The legend may consist of several paragraphs.</p>
+</div>
+</div>
+<p>This paragraph might flow around the figure.</p>
+<p>The specific behavior depends upon the style sheet and the browser or
+rendering software used.</p>
+<p>A centered figure:</p>
+<div class="figure align-center">
+<img alt="../../../docs/user/rst/images/biohazard.png" src="../../../docs/user/rst/images/biohazard.png" style="width: 40px;" />
+<p class="caption">This is the caption.</p>
+<div class="legend">
+<p>This is the legend.</p>
+<p>The legend may consist of several paragraphs.</p>
+</div>
+</div>
+<p>This paragraph might flow around the figure.</p>
+<p>The specific behavior depends upon the style sheet and the browser or
+rendering software used.</p>
+<p>A right-aligned figure:</p>
+<div class="figure align-right">
+<img alt="../../../docs/user/rst/images/biohazard.png" src="../../../docs/user/rst/images/biohazard.png" style="width: 40px;" />
+<p class="caption">This is the caption.</p>
+<div class="legend">
+<p>This is the legend.</p>
+<p>The legend may consist of several paragraphs.</p>
+</div>
+</div>
+<p>This paragraph might flow around the figure. The specific behavior depends
+upon the style sheet and the browser or rendering software used.</p>
+<p>Tables may be given titles and additional arguments with the <em>table</em>
+directive:</p>
+<table border="1" class="docutils align-left">
+<caption>left-aligned table</caption>
+<colgroup>
+<col width="50%" />
+<col width="50%" />
+</colgroup>
+<thead valign="bottom">
+<tr><th class="head">A</th>
+<th class="head">not A</th>
+</tr>
+</thead>
+<tbody valign="top">
+<tr><td>False</td>
+<td>True</td>
+</tr>
+<tr><td>True</td>
+<td>False</td>
+</tr>
+</tbody>
+</table>
+<table border="1" class="docutils align-center">
+<caption>center-aligned table</caption>
+<colgroup>
+<col width="50%" />
+<col width="50%" />
+</colgroup>
+<thead valign="bottom">
+<tr><th class="head">A</th>
+<th class="head">not A</th>
+</tr>
+</thead>
+<tbody valign="top">
+<tr><td>False</td>
+<td>True</td>
+</tr>
+<tr><td>True</td>
+<td>False</td>
+</tr>
+</tbody>
+</table>
+<table border="1" class="docutils align-right">
+<caption>right-aligned table</caption>
+<colgroup>
+<col width="50%" />
+<col width="50%" />
+</colgroup>
+<thead valign="bottom">
+<tr><th class="head">A</th>
+<th class="head">not A</th>
+</tr>
+</thead>
+<tbody valign="top">
+<tr><td>False</td>
+<td>True</td>
+</tr>
+<tr><td>True</td>
+<td>False</td>
+</tr>
+</tbody>
+</table>
+<p>With the "widths" argument "auto" (or "class" value "colwidths-auto"),
+column widths are determined by the backend (if supported by the
+writer/backend).</p>
+<span id="target1"></span><table border="1" class="colwidths-auto docutils" id="target2">
+<thead valign="bottom">
+<tr><th class="head">A</th>
+<th class="head">B</th>
+<th class="head">A or B</th>
+</tr>
+</thead>
+<tbody valign="top">
+<tr><td>False</td>
+<td>False</td>
+<td>False</td>
+</tr>
+<tr><td>True</td>
+<td>False</td>
+<td>True</td>
+</tr>
+<tr><td>False</td>
+<td>True</td>
+<td>True</td>
+</tr>
+<tr><td>True</td>
+<td>True</td>
+<td>True</td>
+</tr>
+</tbody>
+</table>
+</div>
+<div class="section" id="admonitions">
+<h3><a class="toc-backref" href="#toc-entry-46">2.14.3 Admonitions</a></h3>
+<div class="admonition attention">
+<p class="first admonition-title">Attention!</p>
+<p class="last">Directives at large.</p>
+</div>
+<div class="admonition caution">
+<p class="first admonition-title">Caution!</p>
+<p class="last">Don't take any wooden nickels.</p>
+</div>
+<div class="admonition danger">
+<p class="first admonition-title">!DANGER!</p>
+<p class="last">Mad scientist at work!</p>
+</div>
+<div class="admonition error">
+<p class="first admonition-title">Error</p>
+<p class="last">Does not compute.</p>
+</div>
+<div class="admonition hint">
+<p class="first admonition-title">Hint</p>
+<p class="last">It's bigger than a bread box.</p>
+</div>
+<div class="admonition important">
+<p class="first admonition-title">Important</p>
+<ul class="last simple">
+<li>Wash behind your ears.</li>
+<li>Clean up your room.</li>
+<li>Call your mother.</li>
+<li>Back up your data.</li>
+</ul>
+</div>
+<div class="admonition note">
+<p class="first admonition-title">Note</p>
+<p class="last">This is a note.</p>
+</div>
+<div class="admonition tip">
+<p class="first admonition-title">Tip</p>
+<p class="last">15% if the service is good.</p>
+</div>
+<div class="admonition warning">
+<p class="first admonition-title">Warning</p>
+<p class="last">Strong prose may provoke extreme mental exertion.
+Reader discretion is strongly advised.</p>
+</div>
+<div class="admonition admonition-and-by-the-way">
+<p class="first admonition-title">And, by the way...</p>
+<p class="last">You can make up your own admonition too.</p>
+</div>
+</div>
+<div class="section" id="topics-sidebars-and-rubrics">
+<h3><a class="toc-backref" href="#toc-entry-47">2.14.4 Topics, Sidebars, and Rubrics</a></h3>
+<p><em>Sidebars</em> are like miniature, parallel documents.</p>
+<div class="sidebar">
+<p class="first sidebar-title">Sidebar Title</p>
+<p class="sidebar-subtitle">Optional Subtitle</p>
+<p>This is a sidebar. It is for text outside the flow of the main
+text.</p>
+<p class="rubric">This is a rubric inside a sidebar</p>
+<p class="last">Sidebars often appear beside the main text with a border and a different
+background or font color.</p>
+</div>
+<p>A <em>topic</em> is like a block quote with a title, or a self-contained section
+with no subsections.</p>
+<div class="topic">
+<p class="topic-title">Topic Title</p>
+<p>This is a topic.</p>
+</div>
+<p>A <em>rubric</em> is like an informal heading that doesn't correspond to the
+document's structure. It is typically highlighted in red (hence the name).</p>
+<p class="rubric">This is a rubric</p>
+<p>Topics and rubrics can be used at places where a <a class="reference internal" href="#section-title">section title</a> is not
+allowed (e.g. inside a directive).</p>
+</div>
+<div class="section" id="target-footnotes">
+<h3><a class="toc-backref" href="#toc-entry-48">2.14.5 Target Footnotes</a></h3>
+<table class="docutils footnote" frame="void" id="footnote-6" rules="none">
+<colgroup><col class="label" /><col /></colgroup>
+<tbody valign="top">
+<tr><td class="label">[5]</td><td><em>(<a class="fn-backref" href="#footnote-reference-10">1</a>, <a class="fn-backref" href="#footnote-reference-11">2</a>, <a class="fn-backref" href="#footnote-reference-12">3</a>, <a class="fn-backref" href="#footnote-reference-14">4</a>)</em> <a class="reference external" href="http://www.python.org/">http://www.python.org/</a></td></tr>
+</tbody>
+</table>
+<table class="docutils footnote" frame="void" id="footnote-7" rules="none">
+<colgroup><col class="label" /><col /></colgroup>
+<tbody valign="top">
+<tr><td class="label"><a class="fn-backref" href="#footnote-reference-13">[6]</a></td><td><a class="reference external" href="http://pygments.org/">http://pygments.org/</a></td></tr>
+</tbody>
+</table>
+<table class="docutils footnote" frame="void" id="footnote-8" rules="none">
+<colgroup><col class="label" /><col /></colgroup>
+<tbody valign="top">
+<tr><td class="label"><a class="fn-backref" href="#footnote-reference-15">[7]</a></td><td><a class="reference external" href="http://docutils.sourceforge.net/">http://docutils.sourceforge.net/</a></td></tr>
+</tbody>
+</table>
+</div>
+<div class="section" id="replacement-text">
+<h3><a class="toc-backref" href="#toc-entry-49">2.14.6 Replacement Text</a></h3>
+<p>I recommend you try <a class="reference external" href="http://www.python.org/">Python, <em>the</em> best language around</a> <a class="footnote-reference" href="#footnote-6" id="footnote-reference-12">[5]</a>.</p>
+</div>
+<div class="section" id="compound-paragraph">
+<h3><a class="toc-backref" href="#toc-entry-50">2.14.7 Compound Paragraph</a></h3>
+<p>The <em>compound</em> directive is used to create a "compound paragraph", which
+is a single logical paragraph containing multiple physical body
+elements. For example:</p>
+<div class="compound">
+<p class="compound-first">The 'rm' command is very dangerous. If you are logged
+in as root and enter</p>
+<pre class="compound-middle literal-block">
+cd /
+rm -rf *
+</pre>
+<p class="compound-last">you will erase the entire contents of your file system.</p>
+</div>
+<p>Test the handling and display of compound paragraphs:</p>
+<div class="some-class compound">
+<p class="compound-first">Compound 2, paragraph 1,</p>
+<p class="compound-middle">compound 2, paragraph 2,</p>
+<ul class="compound-middle simple">
+<li>list item 1,</li>
+<li>list item 2,</li>
+</ul>
+<p class="compound-last">compound 2, paragraph 3.</p>
+</div>
+<div class="compound">
+<p>Compound 3, only consisting of one paragraph.</p>
+</div>
+<div class="compound">
+<pre class="compound-first literal-block">
+Compound 4.
+This one starts with a literal block.
+</pre>
+<p class="compound-last">Compound 4, paragraph following the literal block.</p>
+</div>
+<p>Now something <em>really</em> perverted -- a nested compound block. This is
+just to test that it works at all; the results don't have to be
+meaningful.</p>
+<div class="compound">
+<p class="compound-first">Compound 5, block 1 (a paragraph).</p>
+<div class="compound-middle compound">
+<p class="compound-first">Compound 6 is block 2 in compound 5.</p>
+<p class="compound-last">Compound 6, another paragraph.</p>
+</div>
+<p class="compound-last">Compound 5, block 3 (a paragraph).</p>
+</div>
+<div class="compound">
+<p class="compound-first">Compound 7, tests the inclusion of various block-level
+elements in one logical paragraph. First a table,</p>
+<table border="1" class="compound-middle docutils">
+<colgroup>
+<col width="33%" />
+<col width="33%" />
+<col width="33%" />
+</colgroup>
+<tbody valign="top">
+<tr><td><p class="first">Left cell, first
+paragraph.</p>
+<p class="last">Left cell, second
+paragraph.</p>
+</td>
+<td>Middle cell,
+consisting of
+exactly one
+paragraph.</td>
+<td><p class="first">Right cell.</p>
+<p>Paragraph 2.</p>
+<p class="last">Paragraph 3.</p>
+</td>
+</tr>
+</tbody>
+</table>
+<p class="compound-middle">followed by a paragraph. This physical paragraph is
+actually a continuation of the paragraph before the table. It is followed
+by</p>
+<blockquote class="compound-middle">
+a quote and</blockquote>
+<ol class="compound-middle arabic simple">
+<li>an enumerated list,</li>
+</ol>
+<p class="compound-middle">a paragraph,</p>
+<table class="compound-middle docutils option-list" frame="void" rules="none">
+<col class="option" />
+<col class="description" />
+<tbody valign="top">
+<tr><td class="option-group">
+<kbd><span class="option">--an</span></kbd></td>
+<td>option list,</td></tr>
+</tbody>
+</table>
+<p class="compound-middle">a paragraph,</p>
+<table class="compound-middle docutils field-list" frame="void" rules="none">
+<col class="field-name" />
+<col class="field-body" />
+<tbody valign="top">
+<tr class="field"><th class="field-name">a field:</th><td class="field-body">list,</td>
+</tr>
+</tbody>
+</table>
+<p class="compound-middle">a paragraph,</p>
+<dl class="compound-middle docutils">
+<dt>a definition</dt>
+<dd>list,</dd>
+</dl>
+<p class="compound-middle">a paragraph, an image:</p>
+<img alt="../../../docs/user/rst/images/biohazard.png" class="compound-middle" src="../../../docs/user/rst/images/biohazard.png" />
+<p class="compound-middle">a paragraph,</p>
+<div class="compound-middle line-block">
+<div class="line">a line</div>
+<div class="line">block,</div>
+</div>
+<p class="compound-middle">a paragraph followed by a comment,</p>
+<!-- this is a comment -->
+<p class="compound-middle">a paragraph, a</p>
+<div class="admonition note compound-middle">
+<p class="first admonition-title">Note</p>
+<p class="last">with content</p>
+</div>
+<p class="compound-last">and the final paragraph of the compound 7.</p>
+</div>
+</div>
+<div class="section" id="parsed-literal-blocks">
+<h3><a class="toc-backref" href="#toc-entry-51">2.14.8 Parsed Literal Blocks</a></h3>
+<pre class="literal-block">
+This is a parsed literal block.
+ This line is indented. The next line is blank.
+
+Inline markup is supported, e.g. <em>emphasis</em>, <strong>strong</strong>, <tt class="docutils literal">literal
+text</tt>, <span class="subscript">sub-</span> and <span class="superscript">super</span>scripts,
+inline formulas: <span class="formula"><i>A</i> = 2<i>π</i><i>r</i><sup>2</sup></span>,
+footnotes <a class="footnote-reference" href="#footnote-1" id="footnote-reference-9">[1]</a>, <span class="target" id="hyperlink-targets">hyperlink targets</span>, and <a class="reference external" href="http://www.python.org/">references</a>.
+</pre>
+</div>
+<div class="section" id="code">
+<h3><a class="toc-backref" href="#toc-entry-52">2.14.9 Code</a></h3>
+<p>Blocks of source code can be set with the <cite>code</cite> directive. If the code
+language is specified, the content is parsed and tagged by the <a class="reference external" href="http://pygments.org/">Pygments</a> <a class="footnote-reference" href="#footnote-7" id="footnote-reference-13">[6]</a>
+syntax highlighter and can be formatted with a style sheet. (Code parsing
+is turned off using the <tt class="docutils literal"><span class="pre">syntax-highlight</span></tt> config setting in the test
+conversions in order to get identical results with/without installed
+Pygments highlighter.)</p>
+<pre class="code python literal-block">
+print 'This is Python code.'
+</pre>
+<p>The <tt class="docutils literal"><span class="pre">:number-lines:</span></tt> option (with optional start value) generates line
+numbers:</p>
+<pre class="code python literal-block">
+<span class="ln"> 8 </span># print integers from 0 to 9:
+<span class="ln"> 9 </span>for i in range(10):
+<span class="ln">10 </span> print i
+</pre>
+<p>For inline code snippets, there is the <cite>code</cite> role, which can be used
+directly (the code will not be parsed/tagged, as the language is not known)
+or as base for special code roles, e.g. the LaTeX code in the next
+paragraph.</p>
+<p>Docutils uses LaTeX syntax for math directives and roles:
+<code class="tex">\alpha = f(x)</code> prints <span class="formula"><i>α</i> = <i>f</i>(<i>x</i>)</span>.</p>
+<p>The <tt class="docutils literal">:code:</tt> option of the <cite>include</cite> directive sets the included content
+as a code block, here the rst file <tt class="docutils literal">header_footer.txt</tt> with line numbers:</p>
+<pre class="code rst literal-block">
+<span class="ln">1 </span>.. header:: Document header
+<span class="ln">2 </span>.. footer:: Document footer
+</pre>
+</div>
+</div>
+<div class="section" id="substitution-definitions">
+<h2><a class="toc-backref" href="#toc-entry-32">2.15 Substitution Definitions</a></h2>
+<p>An inline image (<img alt="EXAMPLE" src="../../../docs/user/rst/images/biohazard.png" />) example:</p>
+<p>A Unicode example:</p>
+<p>(Substitution definitions are not visible in the HTML source.)</p>
+</div>
+<div class="section" id="comments">
+<h2><a class="toc-backref" href="#toc-entry-33">2.16 Comments</a></h2>
+<p>Here's one:</p>
+<!-- Comments begin with two dots and a space. Anything may
+follow, except for the syntax of footnotes, hyperlink
+targets, directives, or substitution definitions.
+
+Double-dashes - - "- -" - - must be escaped somehow in HTML output.
+
+Comments may contain non-ASCII characters: ä ö ü æ ø å -->
+<p>(View the HTML source to see the comment.)</p>
+</div>
+<div class="section" id="raw-text">
+<h2><a class="toc-backref" href="#toc-entry-34">2.17 Raw text</a></h2>
+<p>This does not necessarily look nice, because there may be missing white space.</p>
+<p>It's just there to freeze the behavior.</p>
+A test.Second test.<div class="myclass">Another test with myclass set.</div><p>This is the <span class="myrawroleclass">fourth test</span> with myrawroleclass set.</p>
+Fifth test in HTML.<br />Line two.</div>
+<div class="section" id="container">
+<h2><a class="toc-backref" href="#toc-entry-35">2.18 Container</a></h2>
+<div class="custom docutils container">
+<p>paragraph 1</p>
+<p>paragraph 2</p>
+</div>
+</div>
+<div class="section" id="colspanning-tables">
+<h2><a class="toc-backref" href="#toc-entry-36">2.19 Colspanning tables</a></h2>
+<p>This table has a cell spanning two columns:</p>
+<table border="1" class="docutils">
+<colgroup>
+<col width="31%" />
+<col width="31%" />
+<col width="38%" />
+</colgroup>
+<thead valign="bottom">
+<tr><th class="head" colspan="2">Inputs</th>
+<th class="head">Output</th>
+</tr>
+<tr><th class="head">A</th>
+<th class="head">B</th>
+<th class="head">A or B</th>
+</tr>
+</thead>
+<tbody valign="top">
+<tr><td>False</td>
+<td>False</td>
+<td>False</td>
+</tr>
+<tr><td>True</td>
+<td>False</td>
+<td>True</td>
+</tr>
+<tr><td>False</td>
+<td>True</td>
+<td>True</td>
+</tr>
+<tr><td>True</td>
+<td>True</td>
+<td>True</td>
+</tr>
+</tbody>
+</table>
+</div>
+<div class="section" id="rowspanning-tables">
+<h2><a class="toc-backref" href="#toc-entry-37">2.20 Rowspanning tables</a></h2>
+<p>Here's a table with cells spanning several rows:</p>
+<table border="1" class="docutils">
+<colgroup>
+<col width="44%" />
+<col width="22%" />
+<col width="33%" />
+</colgroup>
+<thead valign="bottom">
+<tr><th class="head">Header row, column 1
+(header rows optional)</th>
+<th class="head">Header 2</th>
+<th class="head">Header 3</th>
+</tr>
+</thead>
+<tbody valign="top">
+<tr><td>body row 1, column 1</td>
+<td>column 2</td>
+<td>column 3</td>
+</tr>
+<tr><td>body row 2</td>
+<td rowspan="2">Cells may
+span rows.</td>
+<td rowspan="2">Another
+rowspanning
+cell.</td>
+</tr>
+<tr><td>body row 3</td>
+</tr>
+</tbody>
+</table>
+</div>
+<div class="section" id="complex-tables">
+<h2><a class="toc-backref" href="#toc-entry-38">2.21 Complex tables</a></h2>
+<p>Here's a complex table, which should test all features.</p>
+<table border="1" class="docutils">
+<colgroup>
+<col width="43%" />
+<col width="21%" />
+<col width="18%" />
+<col width="18%" />
+</colgroup>
+<thead valign="bottom">
+<tr><th class="head">Header row, column 1
+(header rows optional)</th>
+<th class="head">Header 2</th>
+<th class="head">Header 3</th>
+<th class="head">Header 4</th>
+</tr>
+</thead>
+<tbody valign="top">
+<tr><td>body row 1, column 1</td>
+<td>column 2</td>
+<td>column 3</td>
+<td>column 4</td>
+</tr>
+<tr><td>body row 2</td>
+<td colspan="3">Cells may span columns.</td>
+</tr>
+<tr><td>body row 3</td>
+<td rowspan="2"><p class="first">Cells may
+span rows.</p>
+<p class="last">Paragraph.</p>
+</td>
+<td colspan="2" rowspan="2"><ul class="first last simple">
+<li>Table cells</li>
+<li>contain</li>
+<li>body elements.</li>
+</ul>
+</td>
+</tr>
+<tr><td>body row 4</td>
+</tr>
+<tr><td>body row 5</td>
+<td colspan="2">Cells may also be
+empty: <tt class="docutils literal"><span class="pre">--></span></tt></td>
+<td> </td>
+</tr>
+</tbody>
+</table>
+</div>
+<div class="section" id="list-tables">
+<h2><a class="toc-backref" href="#toc-entry-39">2.22 List Tables</a></h2>
+<p>Here's a list table exercising all features:</p>
+<table border="1" class="colwidths-given test docutils" style="width: 40em">
+<caption>list table with integral header</caption>
+<colgroup>
+<col width="17%" />
+<col width="33%" />
+<col width="50%" />
+</colgroup>
+<thead valign="bottom">
+<tr><th class="head stub">Treat</th>
+<th class="head">Quantity</th>
+<th class="head">Description</th>
+</tr>
+</thead>
+<tbody valign="top">
+<tr><th class="stub">Albatross</th>
+<td>2.99</td>
+<td>On a stick!</td>
+</tr>
+<tr><th class="stub">Crunchy Frog</th>
+<td>1.49</td>
+<td>If we took the bones out, it wouldn't be
+crunchy, now would it?</td>
+</tr>
+<tr><th class="stub">Gannet Ripple</th>
+<td>1.99</td>
+<td>On a stick!</td>
+</tr>
+</tbody>
+</table>
+<table border="1" class="colwidths-auto docutils align-center">
+<caption>center aligned list table</caption>
+<tbody valign="top">
+<tr><td>Albatross</td>
+<td>2.99</td>
+</tr>
+<tr><td>Crunchy Frog</td>
+<td>1.49</td>
+</tr>
+<tr><td>Gannet Ripple</td>
+<td>1.99</td>
+</tr>
+</tbody>
+</table>
+</div>
+<div class="section" id="custom-roles">
+<h2><a class="toc-backref" href="#toc-entry-40">2.23 Custom Roles</a></h2>
+<ul>
+<li><p class="first">A role based on an existing role.</p>
+<p><tt class="custom docutils literal">one</tt> <tt class="custom docutils literal">two</tt> <tt class="custom docutils literal">three</tt></p>
+</li>
+<li><p class="first">A new role.</p>
+<p><span class="customnew">one two three</span></p>
+</li>
+<li><p class="first">A role with class attribute.</p>
+<p><span class="special">interpreted text</span></p>
+</li>
+<li><p class="first">A language-switching role:</p>
+<p>Let's count in German <span lang="de">eins zwei drei</span>.</p>
+</li>
+<li><p class="first">A role with multiple class attributes, styled with raw directives:</p>
+<p>The following works in most browsers but does not validate
+(<tt class="docutils literal"><style></tt> is only allowed in the document head):</p>
+<pre class="literal-block">
+.. raw:: html
+
+ <style type="text/css"><!--
+ .green {color: green;}
+ .sc {font-variant: small-caps;}
+ --></style>
+</pre>
+<p><span class="green sc" lang="en-gb">British colourful text in small-caps</span>.</p>
+</li>
+</ul>
+</div>
+<div class="section" id="svg-images">
+<h2><a class="toc-backref" href="#toc-entry-41">2.24 SVG Images</a></h2>
+<object class="align-left" data="../../../docs/user/rst/images/biohazard.svg" style="width: 48px; height: 48px;" type="image/svg+xml">
+../../../docs/user/rst/images/biohazard.svg</object>
+<p>Scalable vector graphics (SVG) images are the only standards-compliable way
+to include vector graphics in HTML documents. However, they are not
+supported by all backends/output formats. (E.g., LaTeX supports the
+PDF or Postscript formats for vector graphics instead.)</p>
+<p>Rendering behaviour varies, depending on</p>
+<ol class="loweralpha">
+<li><p class="first">The SVG image itself, e.g. fixed-size vs. scaling:</p>
+<pre class="literal-block">
+width="280" viewBox="0 0 280 27"
+height="27" width="100%"
+ height="100%"
+</pre>
+</li>
+<li><p class="first">The method used to put the image in the document.</p>
+<p>For HTML, there are several alternatives including:</p>
+<ul class="simple">
+<li>using the HTML <tt class="docutils literal"><img></tt> tag (not for interactive/animated SVG),</li>
+<li>using the HTML <tt class="docutils literal"><object></tt> tag,</li>
+<li>including within SVG using the SVG <tt class="docutils literal"><image></tt> tag,</li>
+<li>embedd the SVG code within HTML (inlining).</li>
+</ul>
+<p>The <cite>html4css1</cite> writer uses <tt class="docutils literal"><object></tt> tags, the <cite>html5</cite>
+writer uses <tt class="docutils literal"><img></tt> tags.</p>
+<!-- cf. http://edutechwiki.unige.ch/en/Using_SVG_with_HTML5_tutorial -->
+</li>
+<li><p class="first">The viewing agent.</p>
+<p>All up-to-date HTML browsers support SVG, however not all do this fully
+and in the same manner. Many older versions, especially IE < 9, have
+deficiencies or require plug-ins (i.e. don't support the <tt class="docutils literal"><img></tt> tag).</p>
+</li>
+</ol>
+<p>If the image is wrapped in <tt class="docutils literal"><object></tt> or <tt class="docutils literal"><svg></tt> tags, it depends on the
+<tt class="docutils literal">viewBox</tt> declaration inside the images root <tt class="docutils literal"><svg></tt> element whether an
+SVG image is scaled or clipped/padded. Images wrapped in <tt class="docutils literal"><img></tt> are
+always scaled.</p>
+<ul>
+<li><object class="first align-right" data="../../../docs/user/rst/images/title-scaling.svg" style="width: 50%;" type="image/svg+xml">
+../../../docs/user/rst/images/title-scaling.svg</object>
+<p>A scaling image (scales with the browser window), occupying 50% of the line
+width. The <tt class="docutils literal">viewBox</tt> setting in the image file enables auto-scaling also in
+<tt class="docutils literal"><object></tt> tags and embedded SVG (if width and hight are set to 100% in the
+SVG <image> tag).</p>
+</li>
+<li><object class="first align-right" data="../../../docs/user/rst/images/title.svg" style="width: 50%; height: 15px;" type="image/svg+xml">
+../../../docs/user/rst/images/title.svg</object>
+<p>A fixed-size image in a box 50% wide and 15 pixles high. This image is
+scaled, if wrapped in an <tt class="docutils literal"><img></tt> tag but clipped in an <tt class="docutils literal"><object></tt> tag
+or within SVG.</p>
+</li>
+<li><object class="first align-right" data="../../../docs/user/rst/images/title-scaling.svg" style="width: 50%; height: 1.5em;" type="image/svg+xml">
+../../../docs/user/rst/images/title-scaling.svg</object>
+<p>A right aligned, scaling image 50% wide and 1.5 em high. (This SVG image
+keeps the aspect ratio.)</p>
+</li>
+<li><p class="first">An inline image <object data="../../../docs/user/rst/images/biohazard-scaling.svg" style="height: 0.8em;" type="image/svg+xml">inline-svg</object> scaled to a height of 0.8 em.</p>
+</li>
+<li><object class="first align-right" data="../../../docs/user/rst/images/biohazard-scaling.svg" style="height: 1em;" type="image/svg+xml">
+../../../docs/user/rst/images/biohazard-scaling.svg</object>
+<p>A scaling image 1 em high, right aligned:</p>
+</li>
+<li><p class="first">A scaling image 5 mm x 5 mm, centered, with hyperlink reference:</p>
+<a class="reference internal image-reference" href="#svg-images"><object class="align-center" data="../../../docs/user/rst/images/biohazard-scaling.svg" style="width: 5mm; height: 5mm;" type="image/svg+xml">../../../docs/user/rst/images/biohazard-scaling.svg</object></a>
+</li>
+<li><object class="first align-right" data="../../../docs/user/rst/images/biohazard.svg" style="width: 4cm; height: 2em;" type="image/svg+xml">
+../../../docs/user/rst/images/biohazard.svg</object>
+<p>A fixed-size image in a 4 cm x 2 em box.</p>
+</li>
+</ul>
+<p>Older versions of <cite>webkit</cite> based browsers (chromium, safari, midori,
+konqueror) support the <tt class="docutils literal"><img></tt> tag but don't display contained bitmap
+images in this case.</p>
+<ul>
+<li><object class="first align-right" data="../../../docs/user/rst/images/biohazard-bitmap.svg" style="width: 3em;" type="image/svg+xml">
+../../../docs/user/rst/images/biohazard-bitmap.svg</object>
+<p>A small, fixed-size SVG image with embedded bitmap, The <tt class="docutils literal">:width:</tt> is
+set to 3 em in the rST source. Does not scale if wrapped in <tt class="docutils literal"><object></tt>
+tags.</p>
+</li>
+<li><object class="first align-right" data="../../../docs/user/rst/images/biohazard-bitmap-scaling.svg" style="width: 3em;" type="image/svg+xml">
+../../../docs/user/rst/images/biohazard-bitmap-scaling.svg</object>
+<p>A scaling SVG image with embedded bitmap, 3 em wide.</p>
+</li>
+</ul>
+<p>SVG images can also be put in figures:</p>
+<blockquote>
+<div class="figure align-center">
+<object data="../../../docs/user/rst/images/title.svg" style="width: 290px; height: 28px;" type="image/svg+xml">
+reStructuredText, the markup syntax</object>
+<p class="caption"><strong>Figure:</strong> SVG image in a figure.</p>
+</div>
+</blockquote>
+</div>
+<div class="section" id="swf-images">
+<h2><a class="toc-backref" href="#toc-entry-42">2.25 SWF Images</a></h2>
+<p>Shockwave Flash is an image/movie format that most modern web browsers
+support via a plugin. It is sometimes blocked due to privacy/security
+concerns.</p>
+<p>Images with extension <tt class="docutils literal">.swf</tt> are placed inside <object> elements.
+For complete control over display options use raw HTML.</p>
+<object class="align-left" data="../../../docs/user/rst/images/biohazard.swf" style="width: 4cm; height: 2em;" type="application/x-shockwave-flash">
+[biohazard.swf]</object>
+<p>An SWF image in a 4 cm x 2 em box, left aligned.</p>
+<p>An inline SWF image <object data="../../../docs/user/rst/images/biohazard.swf" style="width: 0.8em; height: 0.8em;" type="application/x-shockwave-flash">inline-swf</object> scaled to 0.8 em x 0.8 em.</p>
+</div>
+</div>
+<div class="section" id="error-handling">
+<h1><a class="toc-backref" href="#toc-entry-43">3 Error Handling</a></h1>
+<p>Any errors caught during processing will generate system messages.</p>
+<p>There should be five messages in the following, auto-generated
+section, "Docutils System Messages":</p>
+<!-- section should be added by Docutils automatically -->
+</div>
+<div class="system-messages section">
+<h1>Docutils System Messages</h1>
+<div class="system-message" id="system-message-1">
+<p class="system-message-title">System Message: ERROR/3 (<tt class="docutils">functional/input/data/standard.txt</tt>, line 104); <em><a href="#problematic-1">backlink</a></em></p>
+Undefined substitution referenced: "problematic".</div>
+<div class="system-message" id="system-message-2">
+<p class="system-message-title">System Message: ERROR/3 (<tt class="docutils">functional/input/data/standard.txt</tt>, line 392); <em><a href="#footnote-reference-8">backlink</a></em></p>
+Unknown target name: "5".</div>
+<div class="system-message" id="system-message-3">
+<p class="system-message-title">System Message: ERROR/3 (<tt class="docutils">functional/input/data/standard.txt</tt>, line 401); <em><a href="#citation-reference-3">backlink</a></em></p>
+Unknown target name: "nonexistent".</div>
+<div class="system-message" id="system-message-4">
+<p class="system-message-title">System Message: ERROR/3 (<tt class="docutils">functional/input/data/standard.txt</tt>, line 428); <em><a href="#problematic-2">backlink</a></em></p>
+Unknown target name: "hyperlink reference without a target".</div>
+<div class="system-message" id="system-message-5">
+<p class="system-message-title">System Message: ERROR/3 (<tt class="docutils">functional/input/data/standard.txt</tt>, line 441); <em><a href="#problematic-3">backlink</a></em></p>
+Duplicate target name, cannot be used as a unique reference: "duplicate target names".</div>
+</div>
+</div>
+<div class="footer">
+<hr class="footer" />
+<p>Document footer</p>
+<p><a class="reference external" href="http://validator.w3.org/check?uri=referer"><img alt="Valid XHTML 1.0!" src="http://www.w3.org/Icons/valid-xhtml10" style="width: 88px; height: 31px;" /></a> <a class="reference external" href="http://jigsaw.w3.org/css-validator/check/referer"><img alt="Valid CSS 2.1!" src="http://jigsaw.w3.org/css-validator/images/vcss" style="width: 88px; height: 31px;" /></a></p>
+
+</div>
+</body>
+</html>
--- /dev/null
+<!DOCTYPE html>
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+<meta charset="utf-8"/>
+<meta name="generator" content="Docutils 0.16: http://docutils.sourceforge.net/" />
+<title>reStructuredText Test Document</title>
+<meta name="author" content="David Goodger" />
+<meta name="author" content="Me" />
+<meta name="author" content="Myself" />
+<meta name="author" content="I" />
+<meta name="dcterms.date" content="Now, or yesterday. Or maybe even before yesterday." />
+<meta name="dcterms.rights" content="This document has been placed in the public domain. You may do with it as you wish. You may copy, modify, redistribute, reattribute, sell, buy, rent, lease, destroy, or improve it, quote it at length, excerpt, incorporate, collate, fold, staple, or mutilate it, or do anything else to it that your or anyone else's heart desires." />
+<meta content="reStructuredText, test, parser" name="keywords" />
+<meta content="A test document, containing at least one example of each reStructuredText construct." lang="en" name="description" xml:lang="en" />
+<link rel="schema.dcterms" href="http://purl.org/dc/terms/">
+<link rel="stylesheet" href="../input/data/minimal.css" type="text/css" />
+<link rel="stylesheet" href="../input/data/plain.css" type="text/css" />
+<link rel="stylesheet" href="../input/data/math.css" type="text/css" />
+</head>
+<body>
+<div class="header">
+<p>Document header</p>
+
+<hr class="header"/>
+</div>
+<div class="document" id="restructuredtext-test-document">
+<span id="doctitle"></span>
+<h1 class="title">reStructuredText Test Document</h1>
+<p class="subtitle" id="examples-of-syntax-constructs"><span id="subtitle"></span>Examples of Syntax Constructs</p>
+<dl class="docinfo">
+<dt class="author">Author</dt>
+<dd class="author"><p>David Goodger</p></dd>
+<dt class="address">Address</dt>
+<dd class="address"><pre class="address">123 Example Street
+Example, EX Canada
+A1B 2C3
+</pre>
+</dd>
+<dt class="contact">Contact</dt>
+<dd class="contact"><a class="reference external" href="mailto:goodger@python.org">goodger@python.org</a></dd>
+<dt class="authors">Authors</dt>
+<dd class="authors"><p>Me</p>
+<p>Myself</p>
+<p>I</p>
+</dd>
+<dt class="organization">Organization</dt>
+<dd class="organization">humankind</dd>
+<dt class="date">Date</dt>
+<dd class="date">Now, or yesterday. Or maybe even <em>before</em> yesterday.</dd>
+<dt class="status">Status</dt>
+<dd class="status">This is a "work in progress"</dd>
+<dt class="revision">Revision</dt>
+<dd class="revision">is managed by a version control system.</dd>
+<dt class="version">Version</dt>
+<dd class="version">1</dd>
+<dt class="copyright">Copyright</dt>
+<dd class="copyright">This document has been placed in the public domain. You
+may do with it as you wish. You may copy, modify,
+redistribute, reattribute, sell, buy, rent, lease,
+destroy, or improve it, quote it at length, excerpt,
+incorporate, collate, fold, staple, or mutilate it, or do
+anything else to it that your or anyone else's heart
+desires.</dd>
+<dt class="field-name">field name</dt>
+<dd class="field-name"><p>This is a "generic bibliographic field".</p>
+</dd>
+<dt class="field-name-2">field name "2"</dt>
+<dd class="field-name-2"><p>Generic bibliographic fields may contain multiple body elements.</p>
+<p>Like this.</p>
+</dd>
+</dl>
+<div class="dedication topic">
+<p class="topic-title">Dedication</p>
+<p>For Docutils users & co-developers.</p>
+</div>
+<div class="abstract topic">
+<p class="topic-title">Abstract</p>
+<p>This is a test document, containing at least one example of each
+reStructuredText construct.</p>
+</div>
+<!-- This is a comment. Note how any initial comments are moved by
+transforms to after the document title, subtitle, and docinfo. -->
+<!-- Above is the document title, and below is the subtitle.
+They are transformed from section titles after parsing. -->
+<!-- bibliographic fields (which also require a transform): -->
+<div class="contents topic" id="table-of-contents">
+<p class="topic-title">Table of Contents</p>
+<ul class="auto-toc simple">
+<li><p><a class="reference internal" href="#structural-elements" id="toc-entry-1"><span class="sectnum">1</span> Structural Elements</a></p>
+<ul class="auto-toc">
+<li><p><a class="reference internal" href="#section-title" id="toc-entry-2"><span class="sectnum">1.1</span> Section Title</a></p></li>
+<li><p><a class="reference internal" href="#empty-section" id="toc-entry-3"><span class="sectnum">1.2</span> Empty Section</a></p></li>
+<li><p><a class="reference internal" href="#transitions" id="toc-entry-4"><span class="sectnum">1.3</span> Transitions</a></p></li>
+</ul>
+</li>
+<li><p><a class="reference internal" href="#body-elements" id="toc-entry-5"><span class="sectnum">2</span> Body Elements</a></p>
+<ul class="auto-toc">
+<li><p><a class="reference internal" href="#paragraphs" id="toc-entry-6"><span class="sectnum">2.1</span> Paragraphs</a></p>
+<ul class="auto-toc">
+<li><p><a class="reference internal" href="#inline-markup" id="toc-entry-7"><span class="sectnum">2.1.1</span> Inline Markup</a></p></li>
+</ul>
+</li>
+<li><p><a class="reference internal" href="#bullet-lists" id="toc-entry-8"><span class="sectnum">2.2</span> Bullet Lists</a></p></li>
+<li><p><a class="reference internal" href="#enumerated-lists" id="toc-entry-9"><span class="sectnum">2.3</span> Enumerated Lists</a></p></li>
+<li><p><a class="reference internal" href="#definition-lists" id="toc-entry-10"><span class="sectnum">2.4</span> Definition Lists</a></p></li>
+<li><p><a class="reference internal" href="#field-lists" id="toc-entry-11"><span class="sectnum">2.5</span> Field Lists</a></p></li>
+<li><p><a class="reference internal" href="#option-lists" id="toc-entry-12"><span class="sectnum">2.6</span> Option Lists</a></p></li>
+<li><p><a class="reference internal" href="#literal-blocks" id="toc-entry-13"><span class="sectnum">2.7</span> Literal Blocks</a></p></li>
+<li><p><a class="reference internal" href="#line-blocks" id="toc-entry-14"><span class="sectnum">2.8</span> Line Blocks</a></p></li>
+<li><p><a class="reference internal" href="#block-quotes" id="toc-entry-15"><span class="sectnum">2.9</span> Block Quotes</a></p></li>
+<li><p><a class="reference internal" href="#doctest-blocks" id="toc-entry-16"><span class="sectnum">2.10</span> Doctest Blocks</a></p></li>
+<li><p><a class="reference internal" href="#footnotes" id="toc-entry-17"><span class="sectnum">2.11</span> Footnotes</a></p></li>
+<li><p><a class="reference internal" href="#citations" id="toc-entry-18"><span class="sectnum">2.12</span> Citations</a></p></li>
+<li><p><a class="reference internal" href="#targets" id="toc-entry-19"><span class="sectnum">2.13</span> Targets</a></p>
+<ul class="auto-toc">
+<li><p><a class="reference internal" href="#duplicate-target-names" id="toc-entry-20"><span class="sectnum">2.13.1</span> Duplicate Target Names</a></p></li>
+<li><p><a class="reference internal" href="#duplicate-target-names-1" id="toc-entry-21"><span class="sectnum">2.13.2</span> Duplicate Target Names</a></p></li>
+</ul>
+</li>
+<li><p><a class="reference internal" href="#directives" id="toc-entry-22"><span class="sectnum">2.14</span> Directives</a></p>
+<ul class="auto-toc">
+<li><p><a class="reference internal" href="#document-parts" id="toc-entry-23"><span class="sectnum">2.14.1</span> Document Parts</a></p></li>
+<li><p><a class="reference internal" href="#images-and-figures" id="toc-entry-24"><span class="sectnum">2.14.2</span> Images and Figures</a></p></li>
+<li><p><a class="reference internal" href="#admonitions" id="toc-entry-25"><span class="sectnum">2.14.3</span> Admonitions</a></p></li>
+<li><p><a class="reference internal" href="#topics-sidebars-and-rubrics" id="toc-entry-26"><span class="sectnum">2.14.4</span> Topics, Sidebars, and Rubrics</a></p></li>
+<li><p><a class="reference internal" href="#target-footnotes" id="toc-entry-27"><span class="sectnum">2.14.5</span> Target Footnotes</a></p></li>
+<li><p><a class="reference internal" href="#replacement-text" id="toc-entry-28"><span class="sectnum">2.14.6</span> Replacement Text</a></p></li>
+<li><p><a class="reference internal" href="#compound-paragraph" id="toc-entry-29"><span class="sectnum">2.14.7</span> Compound Paragraph</a></p></li>
+<li><p><a class="reference internal" href="#parsed-literal-blocks" id="toc-entry-30"><span class="sectnum">2.14.8</span> Parsed Literal Blocks</a></p></li>
+<li><p><a class="reference internal" href="#code" id="toc-entry-31"><span class="sectnum">2.14.9</span> Code</a></p></li>
+</ul>
+</li>
+<li><p><a class="reference internal" href="#substitution-definitions" id="toc-entry-32"><span class="sectnum">2.15</span> Substitution Definitions</a></p></li>
+<li><p><a class="reference internal" href="#comments" id="toc-entry-33"><span class="sectnum">2.16</span> Comments</a></p></li>
+<li><p><a class="reference internal" href="#raw-text" id="toc-entry-34"><span class="sectnum">2.17</span> Raw text</a></p></li>
+<li><p><a class="reference internal" href="#container" id="toc-entry-35"><span class="sectnum">2.18</span> Container</a></p></li>
+<li><p><a class="reference internal" href="#colspanning-tables" id="toc-entry-36"><span class="sectnum">2.19</span> Colspanning tables</a></p></li>
+<li><p><a class="reference internal" href="#rowspanning-tables" id="toc-entry-37"><span class="sectnum">2.20</span> Rowspanning tables</a></p></li>
+<li><p><a class="reference internal" href="#complex-tables" id="toc-entry-38"><span class="sectnum">2.21</span> Complex tables</a></p></li>
+<li><p><a class="reference internal" href="#list-tables" id="toc-entry-39"><span class="sectnum">2.22</span> List Tables</a></p></li>
+<li><p><a class="reference internal" href="#custom-roles" id="toc-entry-40"><span class="sectnum">2.23</span> Custom Roles</a></p></li>
+</ul>
+</li>
+<li><p><a class="reference internal" href="#html-specific" id="toc-entry-41"><span class="sectnum">3</span> HTML specific</a></p>
+<ul class="auto-toc">
+<li><p><a class="reference internal" href="#svg-images" id="toc-entry-42"><span class="sectnum">3.1</span> SVG Images</a></p></li>
+<li><p><a class="reference internal" href="#swf-images" id="toc-entry-43"><span class="sectnum">3.2</span> SWF Images</a></p></li>
+<li><p><a class="reference internal" href="#text-level-semantics" id="toc-entry-44"><span class="sectnum">3.3</span> Text-level semantics</a></p></li>
+<li><p><a class="reference internal" href="#indicating-edits" id="toc-entry-45"><span class="sectnum">3.4</span> Indicating Edits</a></p></li>
+</ul>
+</li>
+<li><p><a class="reference internal" href="#changes-to-the-html4css1-writer" id="toc-entry-46"><span class="sectnum">4</span> Changes to the html4css1 writer</a></p>
+<ul class="auto-toc">
+<li><p><a class="reference internal" href="#field-list-handling" id="toc-entry-47"><span class="sectnum">4.1</span> Field list handling</a></p></li>
+<li><p><a class="reference internal" href="#styling-with-class-arguments" id="toc-entry-48"><span class="sectnum">4.2</span> Styling with class arguments</a></p>
+<ul class="auto-toc">
+<li><p><a class="reference internal" href="#description-lists" id="toc-entry-49"><span class="sectnum">4.2.1</span> Description lists</a></p></li>
+<li><p><a class="reference internal" href="#field-list-variants" id="toc-entry-50"><span class="sectnum">4.2.2</span> Field list variants</a></p></li>
+<li><p><a class="reference internal" href="#table-variants" id="toc-entry-51"><span class="sectnum">4.2.3</span> Table variants</a></p></li>
+</ul>
+</li>
+</ul>
+</li>
+<li><p><a class="reference internal" href="#error-handling" id="toc-entry-52"><span class="sectnum">5</span> Error Handling</a></p></li>
+</ul>
+</div>
+<div class="section" id="structural-elements">
+<h1><a class="toc-backref" href="#toc-entry-1"><span class="sectnum">1</span> Structural Elements</a></h1>
+<div class="section" id="section-title">
+<h2 class="with-subtitle"><a class="toc-backref" href="#toc-entry-2"><span class="sectnum">1.1</span> Section Title</a></h2>
+<p class="section-subtitle" id="section-subtitle">Section Subtitle</p>
+<p>Lone subsections are converted to a section subtitle by a transform
+activated with the <span class="docutils literal"><span class="pre">--section-subtitles</span></span> command line option or the
+<span class="docutils literal"><span class="pre">sectsubtitle-xform</span></span> configuration value.</p>
+</div>
+<div class="section" id="empty-section">
+<h2><a class="toc-backref" href="#toc-entry-3"><span class="sectnum">1.2</span> Empty Section</a></h2>
+</div>
+<div class="section" id="transitions">
+<h2><a class="toc-backref" href="#toc-entry-4"><span class="sectnum">1.3</span> Transitions</a></h2>
+<p>Here's a transition:</p>
+<hr class="docutils" />
+<p>It divides the section. Transitions may also occur between sections:</p>
+</div>
+</div>
+<hr class="docutils" />
+<div class="section" id="body-elements">
+<h1><a class="toc-backref" href="#toc-entry-5"><span class="sectnum">2</span> Body Elements</a></h1>
+<div class="section" id="paragraphs">
+<h2><a class="toc-backref" href="#toc-entry-6"><span class="sectnum">2.1</span> Paragraphs</a></h2>
+<p>A paragraph.</p>
+<div class="section" id="inline-markup">
+<h3><a class="toc-backref" href="#toc-entry-7"><span class="sectnum">2.1.1</span> Inline Markup</a></h3>
+<p>Paragraphs contain text and may contain inline markup: <em>emphasis</em>,
+<strong>strong emphasis</strong>, <span class="docutils literal">inline literals</span>, standalone hyperlinks
+(<a class="reference external" href="http://www.python.org">http://www.python.org</a>), external hyperlinks (<a class="reference external" href="http://www.python.org/">Python</a> <a class="footnote-reference brackets" href="#footnote-7" id="footnote-reference-18">7</a>), internal
+cross-references (<a class="reference internal" href="#example">example</a>), external hyperlinks with embedded URIs
+(<a class="reference external" href="http://www.python.org">Python web site</a>), <a class="reference external" href="http://www.python.org/">anonymous hyperlink
+references</a> <a class="footnote-reference brackets" href="#footnote-7" id="footnote-reference-25">7</a> (<a class="reference external" href="http://docutils.sourceforge.net/">a second reference</a> <a class="footnote-reference brackets" href="#footnote-12" id="footnote-reference-26">12</a>), footnote references (manually
+numbered <a class="footnote-reference brackets" href="#footnote-1" id="footnote-reference-1">1</a>, anonymous auto-numbered <a class="footnote-reference brackets" href="#footnote-2" id="footnote-reference-2">3</a>, labeled auto-numbered
+<a class="footnote-reference brackets" href="#label" id="footnote-reference-3">2</a>, or symbolic <a class="footnote-reference brackets" href="#footnote-3" id="footnote-reference-4">*</a>), citation references (<a class="citation-reference" href="#cit2002" id="citation-reference-1">[CIT2002]</a>),
+substitution references (<img alt="EXAMPLE" src="../../../docs/user/rst/images/biohazard.png" /> &
+a <em>trimmed heart</em> <span class="docutils literal">(U+2665):</span>♥), and <span class="target" id="inline-hyperlink-targets">inline hyperlink targets</span>
+(see <a class="reference internal" href="#targets">Targets</a> below for a reference back to here). Character-level
+inline markup is also possible (although exceedingly ugly!) in <em>re</em><span class="docutils literal">Structured</span><em>Text</em>. Problems are indicated by <a href="#system-message-1"><span class="problematic" id="problematic-1">|problematic|</span></a> text
+(generated by processing errors; this one is intentional). Here is a
+reference to the <a class="reference internal" href="#doctitle">doctitle</a> and the <a class="reference internal" href="#subtitle">subtitle</a>.</p>
+<p>The default role for interpreted text is <cite>Title Reference</cite>. Here are
+some explicit interpreted text roles: a PEP reference (<a class="reference external" href="http://www.python.org/dev/peps/pep-0287">PEP 287</a>); an
+RFC reference (<a class="reference external" href="http://tools.ietf.org/html/rfc2822.html">RFC 2822</a>); an abbreviation (<abbr>abb.</abbr>), an acronym
+(<abbr>reST</abbr>), code (<code>print "hello world"</code>); a <sub>subscript</sub>;
+a <sup>superscript</sup> and explicit roles for <cite>Docutils</cite>'
+<em>standard</em> <strong>inline</strong> <span class="docutils literal">markup</span>.</p>
+<!-- DO NOT RE-WRAP THE FOLLOWING PARAGRAPH! -->
+<p>Let's test wrapping and whitespace significance in inline literals:
+<span class="docutils literal">This is an example of <span class="pre">--inline-literal</span> <span class="pre">--text,</span> <span class="pre">--including</span> <span class="pre">some--</span> <span class="pre">strangely--hyphenated-words.</span> <span class="pre">Adjust-the-width-of-your-browser-window</span> to see how the text is wrapped. <span class="pre">--</span> <span class="pre">----</span> <span class="pre">--------</span> Now note the spacing between the words of this sentence (words should be grouped in pairs).</span></p>
+<p>If the <span class="docutils literal"><span class="pre">--pep-references</span></span> option was supplied, there should be a
+live link to PEP 258 here.</p>
+</div>
+</div>
+<div class="section" id="bullet-lists">
+<h2><a class="toc-backref" href="#toc-entry-8"><span class="sectnum">2.2</span> Bullet Lists</a></h2>
+<ul>
+<li><p>A bullet list</p>
+<ul class="simple">
+<li><p>Nested bullet list.</p></li>
+<li><p>Nested item 2.</p></li>
+</ul>
+</li>
+<li><p>Item 2.</p>
+<p>Paragraph 2 of item 2.</p>
+<ul class="simple">
+<li><p>Nested bullet list.</p></li>
+<li><p>Nested item 2.</p>
+<ul>
+<li><p>Third level.</p></li>
+<li><p>Item 2.</p></li>
+</ul>
+</li>
+<li><p>Nested item 3.</p></li>
+<li><p>This nested list should be compacted by the HTML writer.</p>
+<span class="target" id="target"></span><!-- Even if this item contains a target and a comment. -->
+</li>
+</ul>
+</li>
+</ul>
+</div>
+<div class="section" id="enumerated-lists">
+<h2><a class="toc-backref" href="#toc-entry-9"><span class="sectnum">2.3</span> Enumerated Lists</a></h2>
+<ol class="arabic">
+<li><p>Arabic numerals.</p>
+<ol class="loweralpha simple">
+<li><p>lower alpha)</p>
+<ol class="lowerroman simple">
+<li><p>(lower roman)</p>
+<ol class="upperalpha simple">
+<li><p>upper alpha.</p>
+<ol class="upperroman simple">
+<li><p>upper roman)</p></li>
+</ol>
+</li>
+</ol>
+</li>
+</ol>
+</li>
+</ol>
+</li>
+<li><p>Lists that don't start at 1:</p>
+<ol class="arabic simple" start="3">
+<li><p>Three</p></li>
+<li><p>Four</p></li>
+</ol>
+<ol class="upperalpha simple" start="3">
+<li><p>C</p></li>
+<li><p>D</p></li>
+</ol>
+<ol class="lowerroman simple" start="3">
+<li><p>iii</p></li>
+<li><p>iv</p></li>
+</ol>
+</li>
+</ol>
+</div>
+<div class="section" id="definition-lists">
+<h2><a class="toc-backref" href="#toc-entry-10"><span class="sectnum">2.4</span> Definition Lists</a></h2>
+<dl>
+<dt>Term</dt>
+<dd><p>Definition</p>
+</dd>
+<dt>Term<span class="classifier">classifier</span></dt>
+<dd><p>Definition paragraph 1.</p>
+<p>Definition paragraph 2.</p>
+</dd>
+<dt>Term</dt>
+<dd><p>Definition</p>
+</dd>
+<dt>Term<span class="classifier">classifier one</span><span class="classifier">classifier two</span></dt>
+<dd><p>Definition</p>
+</dd>
+</dl>
+</div>
+<div class="section" id="field-lists">
+<h2><a class="toc-backref" href="#toc-entry-11"><span class="sectnum">2.5</span> Field Lists</a></h2>
+<dl class="field-list">
+<dt>what</dt>
+<dd><p>Field lists map field names to field bodies, like database
+records. They are often part of an extension syntax. They are
+an unambiguous variant of RFC 2822 fields.</p>
+</dd>
+<dt>how arg1 arg2</dt>
+<dd><p>The field marker is a colon, the field name, and a colon.</p>
+<p>The field body may contain one or more body elements, indented
+relative to the field marker.</p>
+</dd>
+<dt>credits</dt>
+<dd><p class="credits">This paragraph has the <cite>credits</cite> class set. (This is actually not
+about credits but just for ensuring that the class attribute
+doesn't get stripped away.)</p>
+</dd>
+</dl>
+</div>
+<div class="section" id="option-lists">
+<h2><a class="toc-backref" href="#toc-entry-12"><span class="sectnum">2.6</span> Option Lists</a></h2>
+<p>For listing command-line options:</p>
+<dl class="option-list">
+<dt><kbd><span class="option">-a</span></kbd></dt>
+<dd><p>command-line option "a"</p>
+</dd>
+<dt><kbd><span class="option">-b <var>file</var></span></kbd></dt>
+<dd><p>options can have arguments
+and long descriptions</p>
+</dd>
+<dt><kbd><span class="option">--long</span></kbd></dt>
+<dd><p>options can be long also</p>
+</dd>
+<dt><kbd><span class="option">--input=<var>file</var></span></kbd></dt>
+<dd><p>long options can also have
+arguments</p>
+</dd>
+<dt><kbd><span class="option">--very-long-option</span></kbd></dt>
+<dd><p>The description can also start on the next line.</p>
+<p>The description may contain multiple body elements,
+regardless of where it starts.</p>
+</dd>
+<dt><kbd><span class="option">-x</span>, <span class="option">-y</span>, <span class="option">-z</span></kbd></dt>
+<dd><p>Multiple options are an "option group".</p>
+</dd>
+<dt><kbd><span class="option">-v</span>, <span class="option">--verbose</span></kbd></dt>
+<dd><p>Commonly-seen: short & long options.</p>
+</dd>
+<dt><kbd><span class="option">-1 <var>file</var></span>, <span class="option">--one=<var>file</var></span>, <span class="option">--two <var>file</var></span></kbd></dt>
+<dd><p>Multiple options with arguments.</p>
+</dd>
+<dt><kbd><span class="option">/V</span></kbd></dt>
+<dd><p>DOS/VMS-style options too</p>
+</dd>
+</dl>
+<p>There must be at least two spaces between the option and the
+description.</p>
+</div>
+<div class="section" id="literal-blocks">
+<h2><a class="toc-backref" href="#toc-entry-13"><span class="sectnum">2.7</span> Literal Blocks</a></h2>
+<p>Literal blocks are indicated with a double-colon ("::") at the end of
+the preceding paragraph (over there <span class="docutils literal"><span class="pre">--></span></span>). They can be indented:</p>
+<pre class="literal-block">if literal_block:
+ text = 'is left as-is'
+ spaces_and_linebreaks = 'are preserved'
+ markup_processing = None</pre>
+<p>Or they can be quoted without indentation:</p>
+<pre class="literal-block">>> Great idea!
+>
+> Why didn't I think of that?</pre>
+</div>
+<div class="section" id="line-blocks">
+<h2><a class="toc-backref" href="#toc-entry-14"><span class="sectnum">2.8</span> Line Blocks</a></h2>
+<p>This section tests line blocks. Line blocks are body elements which
+consist of lines and other line blocks. Nested line blocks cause
+indentation.</p>
+<div class="line-block">
+<div class="line">This is a line block. It ends with a blank line.</div>
+<div class="line-block">
+<div class="line">New lines begin with a vertical bar ("|").</div>
+<div class="line">Line breaks and initial indent are significant, and preserved.</div>
+<div class="line-block">
+<div class="line">Continuation lines are also possible. A long line that is intended
+to wrap should begin with a space in place of the vertical bar.</div>
+</div>
+<div class="line">The left edge of a continuation line need not be aligned with
+the left edge of the text above it.</div>
+</div>
+</div>
+<div class="line-block">
+<div class="line">This is a second line block.</div>
+<div class="line"><br /></div>
+<div class="line">Blank lines are permitted internally, but they must begin with a "|".</div>
+</div>
+<p>Another line block, surrounded by paragraphs:</p>
+<div class="line-block">
+<div class="line">And it's no good waiting by the window</div>
+<div class="line">It's no good waiting for the sun</div>
+<div class="line">Please believe me, the things you dream of</div>
+<div class="line">They don't fall in the lap of no-one</div>
+</div>
+<p>Take it away, Eric the Orchestra Leader!</p>
+<blockquote>
+<div class="line-block">
+<div class="line">A one, two, a one two three four</div>
+<div class="line"><br /></div>
+<div class="line">Half a bee, philosophically,</div>
+<div class="line-block">
+<div class="line">must, <em>ipso facto</em>, half not be.</div>
+</div>
+<div class="line">But half the bee has got to be,</div>
+<div class="line-block">
+<div class="line"><em>vis a vis</em> its entity. D'you see?</div>
+<div class="line"><br /></div>
+</div>
+<div class="line">But can a bee be said to be</div>
+<div class="line-block">
+<div class="line">or not to be an entire bee,</div>
+<div class="line-block">
+<div class="line">when half the bee is not a bee,</div>
+<div class="line-block">
+<div class="line">due to some ancient injury?</div>
+<div class="line"><br /></div>
+</div>
+</div>
+</div>
+<div class="line">Singing...</div>
+</div>
+</blockquote>
+<p>A line block, like the following poem by Christian Morgenstern, can
+also be centre-aligned:</p>
+<div class="align-center line-block" lang="de">
+<div class="line"><strong>Die Trichter</strong></div>
+<div class="line"><br /></div>
+<div class="line">Zwei Trichter wandeln durch die Nacht.</div>
+<div class="line">Durch ihres Rumpfs verengten Schacht</div>
+<div class="line">fließt weißes Mondlicht</div>
+<div class="line">still und heiter</div>
+<div class="line">auf ihren</div>
+<div class="line">Waldweg</div>
+<div class="line">u. s.</div>
+<div class="line">w.</div>
+<div class="line"><br /></div>
+</div>
+</div>
+<div class="section" id="block-quotes">
+<h2><a class="toc-backref" href="#toc-entry-15"><span class="sectnum">2.9</span> Block Quotes</a></h2>
+<p>Block quotes consist of indented body elements:</p>
+<blockquote>
+<p>My theory by A. Elk. Brackets Miss, brackets. This theory goes
+as follows and begins now. All brontosauruses are thin at one
+end, much much thicker in the middle and then thin again at the
+far end. That is my theory, it is mine, and belongs to me and I
+own it, and what it is too.</p>
+<p class="attribution">—Anne Elk (Miss)</p>
+</blockquote>
+<p>The language of a quote (like any other object) can be specified by
+a class attribute:</p>
+<!-- -->
+<blockquote lang="fr">
+<p>ReStructuredText est un langage de balisage léger utilisé
+notamment dans la documentation du langage Python.</p>
+</blockquote>
+</div>
+<div class="section" id="doctest-blocks">
+<h2><a class="toc-backref" href="#toc-entry-16"><span class="sectnum">2.10</span> Doctest Blocks</a></h2>
+<pre class="code python doctest">>>> print 'Python-specific usage examples; begun with ">>>"'
+Python-specific usage examples; begun with ">>>"
+>>> print '(cut and pasted from interactive Python sessions)'
+(cut and pasted from interactive Python sessions)
+</pre>
+</div>
+<div class="section" id="footnotes">
+<h2><a class="toc-backref" href="#toc-entry-17"><span class="sectnum">2.11</span> Footnotes</a></h2>
+<dl class="footnote brackets">
+<dt class="label" id="footnote-1"><span class="brackets">1</span><span class="fn-backref">(<a href="#footnote-reference-1">1</a>,<a href="#footnote-reference-5">2</a>,<a href="#footnote-reference-9">3</a>)</span></dt>
+<dd><p>A footnote contains body elements, consistently indented by at
+least 3 spaces.</p>
+<p>This is the footnote's second paragraph.</p>
+</dd>
+<dt class="label" id="label"><span class="brackets">2</span><span class="fn-backref">(<a href="#footnote-reference-3">1</a>,<a href="#footnote-reference-6">2</a>)</span></dt>
+<dd><p>Footnotes may be numbered, either manually (as in <a class="footnote-reference brackets" href="#footnote-1" id="footnote-reference-5">1</a>) or
+automatically using a "#"-prefixed label. This footnote has a
+label so it can be referred to from multiple places, both as a
+footnote reference (<a class="footnote-reference brackets" href="#label" id="footnote-reference-6">2</a>) and as a <a class="reference internal" href="#label">hyperlink reference</a>.</p>
+</dd>
+<dt class="label" id="footnote-2"><span class="brackets"><a class="fn-backref" href="#footnote-reference-2">3</a></span></dt>
+<dd><p>This footnote is numbered automatically and anonymously using a
+label of "#" only.</p>
+<p>This is the second paragraph.</p>
+<p>And this is the third paragraph.</p>
+</dd>
+<dt class="label" id="footnote-3"><span class="brackets"><a class="fn-backref" href="#footnote-reference-4">*</a></span></dt>
+<dd><p>Footnotes may also use symbols, specified with a "*" label.
+Here's a reference to the next footnote: <a class="footnote-reference brackets" href="#footnote-4" id="footnote-reference-7">†</a>.</p>
+</dd>
+<dt class="label" id="footnote-4"><span class="brackets"><a class="fn-backref" href="#footnote-reference-7">†</a></span></dt>
+<dd><p>This footnote shows the next symbol in the sequence.</p>
+</dd>
+<dt class="label" id="footnote-5"><span class="brackets">4</span></dt>
+<dd><p>Here's an unreferenced footnote, with a reference to a
+nonexistent footnote: <a href="#system-message-2"><span class="problematic" id="footnote-reference-8">[5]_</span></a>.</p>
+</dd>
+</dl>
+</div>
+<div class="section" id="citations">
+<h2><a class="toc-backref" href="#toc-entry-18"><span class="sectnum">2.12</span> Citations</a></h2>
+<dl class="citation">
+<dt class="label" id="cit2002"><span class="brackets">CIT2002</span><span class="fn-backref">(<a href="#citation-reference-1">1</a>,<a href="#citation-reference-2">2</a>)</span></dt>
+<dd><p>Citations are text-labeled footnotes. They may be
+rendered separately and differently from footnotes.</p>
+</dd>
+</dl>
+<p>Here's a reference to the above, <a class="citation-reference" href="#cit2002" id="citation-reference-2">[CIT2002]</a>, and a <a href="#system-message-3"><span class="problematic" id="citation-reference-3">[nonexistent]_</span></a>
+citation.</p>
+</div>
+<div class="section" id="targets">
+<span id="another-target"></span><h2><a class="toc-backref" href="#toc-entry-19"><span class="sectnum">2.13</span> Targets</a></h2>
+<p id="example">This paragraph is pointed to by the explicit "example" target. A
+reference can be found under <a class="reference internal" href="#inline-markup">Inline Markup</a>, above. <a class="reference internal" href="#inline-hyperlink-targets">Inline
+hyperlink targets</a> are also possible.</p>
+<p>Section headers are implicit targets, referred to by name. See
+<a class="reference internal" href="#targets">Targets</a>, which is a subsection of <a class="reference internal" href="#body-elements">Body Elements</a>.</p>
+<p>Explicit external targets are interpolated into references such as
+"<a class="reference external" href="http://www.python.org/">Python</a> <a class="footnote-reference brackets" href="#footnote-7" id="footnote-reference-19">7</a>".</p>
+<p>Targets may be indirect and anonymous. Thus <a class="reference internal" href="#targets">this phrase</a> may also
+refer to the <a class="reference internal" href="#targets">Targets</a> section.</p>
+<p>Here's a <a href="#system-message-4"><span class="problematic" id="problematic-2">`hyperlink reference without a target`_</span></a>, which generates an
+error.</p>
+<div class="section" id="duplicate-target-names">
+<h3><a class="toc-backref" href="#toc-entry-20"><span class="sectnum">2.13.1</span> Duplicate Target Names</a></h3>
+<p>Duplicate names in section headers or other implicit targets will
+generate "info" (level-1) system messages. Duplicate names in
+explicit targets will generate "warning" (level-2) system messages.</p>
+</div>
+<div class="section" id="duplicate-target-names-1">
+<h3><a class="toc-backref" href="#toc-entry-21"><span class="sectnum">2.13.2</span> Duplicate Target Names</a></h3>
+<p>Since there are two "Duplicate Target Names" section headers, we
+cannot uniquely refer to either of them by name. If we try to (like
+this: <a href="#system-message-5"><span class="problematic" id="problematic-3">`Duplicate Target Names`_</span></a>), an error is generated.</p>
+</div>
+</div>
+<div class="section" id="directives">
+<h2><a class="toc-backref" href="#toc-entry-22"><span class="sectnum">2.14</span> Directives</a></h2>
+<div class="contents local topic" id="contents">
+<ul class="auto-toc simple">
+<li><p><a class="reference internal" href="#document-parts" id="toc-entry-53"><span class="sectnum">2.14.1</span> Document Parts</a></p></li>
+<li><p><a class="reference internal" href="#images-and-figures" id="toc-entry-54"><span class="sectnum">2.14.2</span> Images and Figures</a></p></li>
+<li><p><a class="reference internal" href="#admonitions" id="toc-entry-55"><span class="sectnum">2.14.3</span> Admonitions</a></p></li>
+<li><p><a class="reference internal" href="#topics-sidebars-and-rubrics" id="toc-entry-56"><span class="sectnum">2.14.4</span> Topics, Sidebars, and Rubrics</a></p></li>
+<li><p><a class="reference internal" href="#target-footnotes" id="toc-entry-57"><span class="sectnum">2.14.5</span> Target Footnotes</a></p></li>
+<li><p><a class="reference internal" href="#replacement-text" id="toc-entry-58"><span class="sectnum">2.14.6</span> Replacement Text</a></p></li>
+<li><p><a class="reference internal" href="#compound-paragraph" id="toc-entry-59"><span class="sectnum">2.14.7</span> Compound Paragraph</a></p></li>
+<li><p><a class="reference internal" href="#parsed-literal-blocks" id="toc-entry-60"><span class="sectnum">2.14.8</span> Parsed Literal Blocks</a></p></li>
+<li><p><a class="reference internal" href="#code" id="toc-entry-61"><span class="sectnum">2.14.9</span> Code</a></p></li>
+</ul>
+</div>
+<p>These are just a sample of the many reStructuredText Directives. For
+others, please see
+<a class="reference external" href="http://docutils.sourceforge.net/docs/ref/rst/directives.html">http://docutils.sourceforge.net/docs/ref/rst/directives.html</a>.</p>
+<div class="section" id="document-parts">
+<h3><a class="toc-backref" href="#toc-entry-53"><span class="sectnum">2.14.1</span> Document Parts</a></h3>
+<p>An example of the "contents" directive can be seen above this section
+(a local, untitled table of <a class="reference internal" href="#contents">contents</a>) and at the beginning of the
+document (a document-wide <a class="reference internal" href="#table-of-contents">table of contents</a>).</p>
+</div>
+<div class="section" id="images-and-figures">
+<h3><a class="toc-backref" href="#toc-entry-54"><span class="sectnum">2.14.2</span> Images and Figures</a></h3>
+<p>An image directive (also clickable -- a hyperlink reference):</p>
+<a class="reference internal image-reference" href="#directives"><img alt="../../../docs/user/rst/images/title.png" class="class1 class2" src="../../../docs/user/rst/images/title.png" /></a>
+<p>Image with multiple IDs:</p>
+<span id="image-target-2"></span><span id="image-target-1"></span><img alt="../../../docs/user/rst/images/title.png" id="image-target-3" src="../../../docs/user/rst/images/title.png" />
+<p>A centered image:</p>
+<img alt="../../../docs/user/rst/images/biohazard.png" class="align-center" src="../../../docs/user/rst/images/biohazard.png" />
+<p>A left-aligned image:</p>
+<img alt="../../../docs/user/rst/images/biohazard.png" class="align-left" src="../../../docs/user/rst/images/biohazard.png" />
+<p>This paragraph might flow around the image.
+The specific behavior depends upon the style sheet and
+the browser or rendering software used.</p>
+<p>A right-aligned image:</p>
+<img alt="../../../docs/user/rst/images/biohazard.png" class="align-right" src="../../../docs/user/rst/images/biohazard.png" />
+<p>This paragraph might flow around the image.
+The specific behavior depends upon the style sheet and
+the browser or rendering software used.</p>
+<p>For inline images see <a class="reference internal" href="#substitution-definitions">Substitution Definitions</a>.</p>
+<p>Image size:</p>
+<p>An image 2 em wide:</p>
+<img alt="../../../docs/user/rst/images/biohazard.png" src="../../../docs/user/rst/images/biohazard.png" style="width: 2em;" />
+<p>An image 2 em wide and 15 pixel high:</p>
+<img alt="../../../docs/user/rst/images/biohazard.png" src="../../../docs/user/rst/images/biohazard.png" style="width: 2em; height: 15px;" />
+<p>An image occupying 50% of the line width:</p>
+<img alt="../../../docs/user/rst/images/title.png" src="../../../docs/user/rst/images/title.png" style="width: 50%;" />
+<p>An image 2 cm high:</p>
+<img alt="../../../docs/user/rst/images/biohazard.png" src="../../../docs/user/rst/images/biohazard.png" style="height: 2cm;" />
+<p>A <em>figure</em> is an image with a caption and/or a legend. With page-based output
+media, figures might float to a different position if this helps the page
+layout.</p>
+<div class="figclass1 figclass2 figure">
+<img alt="reStructuredText, the markup syntax" class="class1 class2" src="../../../docs/user/rst/images/title.png" style="width: 258px;" />
+<p class="caption">Plaintext markup syntax and parser system.</p>
+<div class="legend">
+<table>
+<colgroup>
+<col style="width: 20%" />
+<col style="width: 80%" />
+</colgroup>
+<tbody>
+<tr><td><p>re</p></td>
+<td><p>Revised, revisited, based on 're' module.</p></td>
+</tr>
+<tr><td><p>Structured</p></td>
+<td><p>Structure-enhanced text, structuredtext.</p></td>
+</tr>
+<tr><td><p>Text</p></td>
+<td><p>Well it is, isn't it?</p></td>
+</tr>
+</tbody>
+</table>
+<p>This paragraph is also part of the legend.</p>
+</div>
+</div>
+<p>A left-aligned figure:</p>
+<div class="figclass1 figclass2 figure align-left" style="width: 70%">
+<img alt="reStructuredText, the markup syntax" class="class1 class2" src="../../../docs/user/rst/images/biohazard.png" style="width: 40px;" />
+<p class="caption">This is the caption.</p>
+<div class="legend">
+<p>This is the legend.</p>
+<p>The legend may consist of several paragraphs.</p>
+</div>
+</div>
+<p>This paragraph might flow around the figure.</p>
+<p>The specific behavior depends upon the style sheet and the browser or
+rendering software used.</p>
+<p>A centered figure:</p>
+<div class="figure align-center">
+<img alt="../../../docs/user/rst/images/biohazard.png" src="../../../docs/user/rst/images/biohazard.png" style="width: 40px;" />
+<p class="caption">This is the caption.</p>
+<div class="legend">
+<p>This is the legend.</p>
+<p>The legend may consist of several paragraphs.</p>
+</div>
+</div>
+<p>This paragraph might flow around the figure.</p>
+<p>The specific behavior depends upon the style sheet and the browser or
+rendering software used.</p>
+<p>A right-aligned figure:</p>
+<div class="figure align-right">
+<img alt="../../../docs/user/rst/images/biohazard.png" src="../../../docs/user/rst/images/biohazard.png" style="width: 40px;" />
+<p class="caption">This is the caption.</p>
+<div class="legend">
+<p>This is the legend.</p>
+<p>The legend may consist of several paragraphs.</p>
+</div>
+</div>
+<p>This paragraph might flow around the figure. The specific behavior depends
+upon the style sheet and the browser or rendering software used.</p>
+<p>Tables may be given titles and additional arguments with the <em>table</em>
+directive:</p>
+<table class="align-left">
+<caption>left-aligned table</caption>
+<colgroup>
+<col style="width: 50%" />
+<col style="width: 50%" />
+</colgroup>
+<thead>
+<tr><th class="head"><p>A</p></th>
+<th class="head"><p>not A</p></th>
+</tr>
+</thead>
+<tbody>
+<tr><td><p>False</p></td>
+<td><p>True</p></td>
+</tr>
+<tr><td><p>True</p></td>
+<td><p>False</p></td>
+</tr>
+</tbody>
+</table>
+<table class="align-center">
+<caption>center-aligned table</caption>
+<colgroup>
+<col style="width: 50%" />
+<col style="width: 50%" />
+</colgroup>
+<thead>
+<tr><th class="head"><p>A</p></th>
+<th class="head"><p>not A</p></th>
+</tr>
+</thead>
+<tbody>
+<tr><td><p>False</p></td>
+<td><p>True</p></td>
+</tr>
+<tr><td><p>True</p></td>
+<td><p>False</p></td>
+</tr>
+</tbody>
+</table>
+<table class="align-right">
+<caption>right-aligned table</caption>
+<colgroup>
+<col style="width: 50%" />
+<col style="width: 50%" />
+</colgroup>
+<thead>
+<tr><th class="head"><p>A</p></th>
+<th class="head"><p>not A</p></th>
+</tr>
+</thead>
+<tbody>
+<tr><td><p>False</p></td>
+<td><p>True</p></td>
+</tr>
+<tr><td><p>True</p></td>
+<td><p>False</p></td>
+</tr>
+</tbody>
+</table>
+<p>With the "widths" argument "auto" (or "class" value "colwidths-auto"),
+column widths are determined by the backend (if supported by the
+writer/backend).</p>
+<span id="target1"></span><table class="colwidths-auto" id="target2">
+<thead>
+<tr><th class="head"><p>A</p></th>
+<th class="head"><p>B</p></th>
+<th class="head"><p>A or B</p></th>
+</tr>
+</thead>
+<tbody>
+<tr><td><p>False</p></td>
+<td><p>False</p></td>
+<td><p>False</p></td>
+</tr>
+<tr><td><p>True</p></td>
+<td><p>False</p></td>
+<td><p>True</p></td>
+</tr>
+<tr><td><p>False</p></td>
+<td><p>True</p></td>
+<td><p>True</p></td>
+</tr>
+<tr><td><p>True</p></td>
+<td><p>True</p></td>
+<td><p>True</p></td>
+</tr>
+</tbody>
+</table>
+</div>
+<div class="section" id="admonitions">
+<h3><a class="toc-backref" href="#toc-entry-55"><span class="sectnum">2.14.3</span> Admonitions</a></h3>
+<div class="admonition attention">
+<p class="admonition-title">Attention!</p>
+<p>Directives at large.</p>
+</div>
+<div class="admonition caution">
+<p class="admonition-title">Caution!</p>
+<p>Don't take any wooden nickels.</p>
+</div>
+<div class="admonition danger">
+<p class="admonition-title">!DANGER!</p>
+<p>Mad scientist at work!</p>
+</div>
+<div class="admonition error">
+<p class="admonition-title">Error</p>
+<p>Does not compute.</p>
+</div>
+<div class="admonition hint">
+<p class="admonition-title">Hint</p>
+<p>It's bigger than a bread box.</p>
+</div>
+<div class="admonition important">
+<p class="admonition-title">Important</p>
+<ul class="simple">
+<li><p>Wash behind your ears.</p></li>
+<li><p>Clean up your room.</p></li>
+<li><p>Call your mother.</p></li>
+<li><p>Back up your data.</p></li>
+</ul>
+</div>
+<div class="admonition note">
+<p class="admonition-title">Note</p>
+<p>This is a note.</p>
+</div>
+<div class="admonition tip">
+<p class="admonition-title">Tip</p>
+<p>15% if the service is good.</p>
+</div>
+<div class="admonition warning">
+<p class="admonition-title">Warning</p>
+<p>Strong prose may provoke extreme mental exertion.
+Reader discretion is strongly advised.</p>
+</div>
+<div class="admonition admonition-and-by-the-way">
+<p class="admonition-title">And, by the way...</p>
+<p>You can make up your own admonition too.</p>
+</div>
+</div>
+<div class="section" id="topics-sidebars-and-rubrics">
+<h3><a class="toc-backref" href="#toc-entry-56"><span class="sectnum">2.14.4</span> Topics, Sidebars, and Rubrics</a></h3>
+<p><em>Sidebars</em> are like miniature, parallel documents.</p>
+<div class="sidebar">
+<p class="sidebar-title">Sidebar Title</p>
+<p class="sidebar-subtitle">Optional Subtitle</p>
+<p>This is a sidebar. It is for text outside the flow of the main
+text.</p>
+<p class="rubric">This is a rubric inside a sidebar</p>
+<p>Sidebars often appear beside the main text with a border and a different
+background or font color.</p>
+</div>
+<p>A <em>topic</em> is like a block quote with a title, or a self-contained section
+with no subsections.</p>
+<div class="topic">
+<p class="topic-title">Topic Title</p>
+<p>This is a topic.</p>
+</div>
+<p>A <em>rubric</em> is like an informal heading that doesn't correspond to the
+document's structure. It is typically highlighted in red (hence the name).</p>
+<p class="rubric">This is a rubric</p>
+<p>Topics and rubrics can be used at places where a <a class="reference internal" href="#section-title">section title</a> is not
+allowed (e.g. inside a directive).</p>
+</div>
+<div class="section" id="target-footnotes">
+<h3><a class="toc-backref" href="#toc-entry-57"><span class="sectnum">2.14.5</span> Target Footnotes</a></h3>
+<dl class="footnote brackets">
+<dt class="label" id="footnote-7"><span class="brackets">7</span><span class="fn-backref">(<a href="#footnote-reference-18">1</a>,<a href="#footnote-reference-19">2</a>,<a href="#footnote-reference-20">3</a>,<a href="#footnote-reference-25">4</a>)</span></dt>
+<dd><p><a class="reference external" href="http://www.python.org/">http://www.python.org/</a></p>
+</dd>
+<dt class="label" id="footnote-8"><span class="brackets"><a class="fn-backref" href="#footnote-reference-21">8</a></span></dt>
+<dd><p><a class="reference external" href="http://pygments.org/">http://pygments.org/</a></p>
+</dd>
+<dt class="label" id="footnote-9"><span class="brackets"><a class="fn-backref" href="#footnote-reference-22">9</a></span></dt>
+<dd><p><a class="reference external" href="http://docutils.sourceforge.net/docs/dev/todo.html#interpreted-text">http://docutils.sourceforge.net/docs/dev/todo.html#interpreted-text</a></p>
+</dd>
+<dt class="label" id="footnote-10"><span class="brackets"><a class="fn-backref" href="#footnote-reference-23">10</a></span></dt>
+<dd><p><a class="reference external" href="http://docutils.sourceforge.net/docs/user/config.html#table-style">http://docutils.sourceforge.net/docs/user/config.html#table-style</a></p>
+</dd>
+<dt class="label" id="footnote-11"><span class="brackets"><a class="fn-backref" href="#footnote-reference-24">11</a></span></dt>
+<dd><p><a class="reference external" href="http://tug.ctan.org/tex-archive/macros/latex/contrib/booktabs/booktabs.pdf">http://tug.ctan.org/tex-archive/macros/latex/contrib/booktabs/booktabs.pdf</a></p>
+</dd>
+<dt class="label" id="footnote-12"><span class="brackets"><a class="fn-backref" href="#footnote-reference-26">12</a></span></dt>
+<dd><p><a class="reference external" href="http://docutils.sourceforge.net/">http://docutils.sourceforge.net/</a></p>
+</dd>
+<dt class="label" id="footnote-13"><span class="brackets"><a class="fn-backref" href="#footnote-reference-27">13</a></span></dt>
+<dd><p><a class="reference external" href="https://html.spec.whatwg.org/#text-level-semantics">https://html.spec.whatwg.org/#text-level-semantics</a></p>
+</dd>
+<dt class="label" id="footnote-14"><span class="brackets"><a class="fn-backref" href="#footnote-reference-28">14</a></span></dt>
+<dd><p><a class="reference external" href="https://html.spec.whatwg.org/multipage/edits.html">https://html.spec.whatwg.org/multipage/edits.html</a></p>
+</dd>
+</dl>
+</div>
+<div class="section" id="replacement-text">
+<h3><a class="toc-backref" href="#toc-entry-58"><span class="sectnum">2.14.6</span> Replacement Text</a></h3>
+<p>I recommend you try <a class="reference external" href="http://www.python.org/">Python, <em>the</em> best language around</a> <a class="footnote-reference brackets" href="#footnote-7" id="footnote-reference-20">7</a>.</p>
+</div>
+<div class="section" id="compound-paragraph">
+<h3><a class="toc-backref" href="#toc-entry-59"><span class="sectnum">2.14.7</span> Compound Paragraph</a></h3>
+<p>The <em>compound</em> directive is used to create a "compound paragraph", which
+is a single logical paragraph containing multiple physical body
+elements. For example:</p>
+<div class="compound">
+<p class="compound-first">The 'rm' command is very dangerous. If you are logged
+in as root and enter</p>
+<pre class="compound-middle literal-block">cd /
+rm -rf *</pre>
+<p class="compound-last">you will erase the entire contents of your file system.</p>
+</div>
+<p>Test the handling and display of compound paragraphs:</p>
+<div class="some-class compound">
+<p class="compound-first">Compound 2, paragraph 1,</p>
+<p class="compound-middle">compound 2, paragraph 2,</p>
+<ul class="compound-middle simple">
+<li><p>list item 1,</p></li>
+<li><p>list item 2,</p></li>
+</ul>
+<p class="compound-last">compound 2, paragraph 3.</p>
+</div>
+<div class="compound">
+<p>Compound 3, only consisting of one paragraph.</p>
+</div>
+<div class="compound">
+<pre class="compound-first literal-block">Compound 4.
+This one starts with a literal block.</pre>
+<p class="compound-last">Compound 4, paragraph following the literal block.</p>
+</div>
+<p>Now something <em>really</em> perverted -- a nested compound block. This is
+just to test that it works at all; the results don't have to be
+meaningful.</p>
+<div class="compound">
+<p class="compound-first">Compound 5, block 1 (a paragraph).</p>
+<div class="compound-middle compound">
+<p class="compound-first">Compound 6 is block 2 in compound 5.</p>
+<p class="compound-last">Compound 6, another paragraph.</p>
+</div>
+<p class="compound-last">Compound 5, block 3 (a paragraph).</p>
+</div>
+<div class="compound">
+<p class="compound-first">Compound 7, tests the inclusion of various block-level
+elements in one logical paragraph. First a table,</p>
+<table class="compound-middle">
+<colgroup>
+<col style="width: 33%" />
+<col style="width: 33%" />
+<col style="width: 33%" />
+</colgroup>
+<tbody>
+<tr><td><p>Left cell, first
+paragraph.</p>
+<p>Left cell, second
+paragraph.</p>
+</td>
+<td><p>Middle cell,
+consisting of
+exactly one
+paragraph.</p></td>
+<td><p>Right cell.</p>
+<p>Paragraph 2.</p>
+<p>Paragraph 3.</p>
+</td>
+</tr>
+</tbody>
+</table>
+<p class="compound-middle">followed by a paragraph. This physical paragraph is
+actually a continuation of the paragraph before the table. It is followed
+by</p>
+<blockquote class="compound-middle">
+<p>a quote and</p>
+</blockquote>
+<ol class="compound-middle arabic simple">
+<li><p>an enumerated list,</p></li>
+</ol>
+<p class="compound-middle">a paragraph,</p>
+<dl class="compound-middle option-list">
+<dt><kbd><span class="option">--an</span></kbd></dt>
+<dd><p>option list,</p>
+</dd>
+</dl>
+<p class="compound-middle">a paragraph,</p>
+<dl class="compound-middle field-list simple">
+<dt>a field</dt>
+<dd><p>list,</p>
+</dd>
+</dl>
+<p class="compound-middle">a paragraph,</p>
+<dl class="compound-middle simple">
+<dt>a definition</dt>
+<dd><p>list,</p>
+</dd>
+</dl>
+<p class="compound-middle">a paragraph, an image:</p>
+<img alt="../../../docs/user/rst/images/biohazard.png" class="compound-middle" src="../../../docs/user/rst/images/biohazard.png" />
+<p class="compound-middle">a paragraph,</p>
+<div class="compound-middle line-block">
+<div class="line">a line</div>
+<div class="line">block,</div>
+</div>
+<p class="compound-middle">a paragraph followed by a comment,</p>
+<!-- this is a comment -->
+<p class="compound-middle">a paragraph, a</p>
+<div class="admonition note compound-middle">
+<p class="admonition-title">Note</p>
+<p>with content</p>
+</div>
+<p class="compound-last">and the final paragraph of the compound 7.</p>
+</div>
+</div>
+<div class="section" id="parsed-literal-blocks">
+<h3><a class="toc-backref" href="#toc-entry-60"><span class="sectnum">2.14.8</span> Parsed Literal Blocks</a></h3>
+<pre class="literal-block">This is a parsed literal block.
+ This line is indented. The next line is blank.
+
+Inline markup is supported, e.g. <em>emphasis</em>, <strong>strong</strong>, <span class="docutils literal">literal
+text</span>, <sub>sub-</sub> and <sup>super</sup>scripts,
+inline formulas: <span class="formula"><i>A</i> = 2<i>π</i><i>r</i><sup>2</sup></span>,
+footnotes <a class="footnote-reference brackets" href="#footnote-1" id="footnote-reference-9">1</a>, <span class="target" id="hyperlink-targets">hyperlink targets</span>, and <a class="reference external" href="http://www.python.org/">references</a>.</pre>
+</div>
+<div class="section" id="code">
+<h3><a class="toc-backref" href="#toc-entry-61"><span class="sectnum">2.14.9</span> Code</a></h3>
+<p>Blocks of source code can be set with the <cite>code</cite> directive. If the code
+language is specified, the content is parsed and tagged by the <a class="reference external" href="http://pygments.org/">Pygments</a> <a class="footnote-reference brackets" href="#footnote-8" id="footnote-reference-21">8</a>
+syntax highlighter and can be formatted with a style sheet. (Code parsing
+is turned off using the <span class="docutils literal"><span class="pre">syntax-highlight</span></span> config setting in the test
+conversions in order to get identical results with/without installed
+Pygments highlighter.)</p>
+<pre class="code python literal-block"><code>print 'This is Python code.'</code></pre>
+<p>The <span class="docutils literal"><span class="pre">:number-lines:</span></span> option (with optional start value) generates line
+numbers:</p>
+<pre class="code python literal-block"><code><span class="ln"> 8 </span># print integers from 0 to 9:
+<span class="ln"> 9 </span>for i in range(10):
+<span class="ln">10 </span> print i</code></pre>
+<p>For inline code snippets, there is the <cite>code</cite> role, which can be used
+directly (the code will not be parsed/tagged, as the language is not known)
+or as base for special code roles, e.g. the LaTeX code in the next
+paragraph.</p>
+<p>Docutils uses LaTeX syntax for math directives and roles:
+<code class="tex">\alpha = f(x)</code> prints <span class="formula"><i>α</i> = <i>f</i>(<i>x</i>)</span>.</p>
+<p>The <span class="docutils literal">:code:</span> option of the <cite>include</cite> directive sets the included content
+as a code block, here the rst file <span class="docutils literal">header_footer.txt</span> with line numbers:</p>
+<pre class="code rst literal-block"><code><span class="ln">1 </span>.. header:: Document header
+<span class="ln">2 </span>.. footer:: Document footer</code></pre>
+</div>
+</div>
+<div class="section" id="substitution-definitions">
+<h2><a class="toc-backref" href="#toc-entry-32"><span class="sectnum">2.15</span> Substitution Definitions</a></h2>
+<p>An inline image (<img alt="EXAMPLE" src="../../../docs/user/rst/images/biohazard.png" />) example:</p>
+<p>A Unicode example:</p>
+<p>(Substitution definitions are not visible in the HTML source.)</p>
+</div>
+<div class="section" id="comments">
+<h2><a class="toc-backref" href="#toc-entry-33"><span class="sectnum">2.16</span> Comments</a></h2>
+<p>Here's one:</p>
+<!-- Comments begin with two dots and a space. Anything may
+follow, except for the syntax of footnotes, hyperlink
+targets, directives, or substitution definitions.
+
+Double-dashes - - "- -" - - must be escaped somehow in HTML output.
+
+Comments may contain non-ASCII characters: ä ö ü æ ø å -->
+<p>(View the HTML source to see the comment.)</p>
+</div>
+<div class="section" id="raw-text">
+<h2><a class="toc-backref" href="#toc-entry-34"><span class="sectnum">2.17</span> Raw text</a></h2>
+<p>This does not necessarily look nice, because there may be missing white space.</p>
+<p>It's just there to freeze the behavior.</p>
+A test.Second test.<div class="myclass">Another test with myclass set.</div><p>This is the <span class="myrawroleclass">fourth test</span> with myrawroleclass set.</p>
+Fifth test in HTML.<br />Line two.</div>
+<div class="section" id="container">
+<h2><a class="toc-backref" href="#toc-entry-35"><span class="sectnum">2.18</span> Container</a></h2>
+<div class="custom docutils container">
+<p>paragraph 1</p>
+<p>paragraph 2</p>
+</div>
+</div>
+<div class="section" id="colspanning-tables">
+<h2><a class="toc-backref" href="#toc-entry-36"><span class="sectnum">2.19</span> Colspanning tables</a></h2>
+<p>This table has a cell spanning two columns:</p>
+<table>
+<colgroup>
+<col style="width: 31%" />
+<col style="width: 31%" />
+<col style="width: 38%" />
+</colgroup>
+<thead>
+<tr><th class="head" colspan="2"><p>Inputs</p></th>
+<th class="head"><p>Output</p></th>
+</tr>
+<tr><th class="head"><p>A</p></th>
+<th class="head"><p>B</p></th>
+<th class="head"><p>A or B</p></th>
+</tr>
+</thead>
+<tbody>
+<tr><td><p>False</p></td>
+<td><p>False</p></td>
+<td><p>False</p></td>
+</tr>
+<tr><td><p>True</p></td>
+<td><p>False</p></td>
+<td><p>True</p></td>
+</tr>
+<tr><td><p>False</p></td>
+<td><p>True</p></td>
+<td><p>True</p></td>
+</tr>
+<tr><td><p>True</p></td>
+<td><p>True</p></td>
+<td><p>True</p></td>
+</tr>
+</tbody>
+</table>
+</div>
+<div class="section" id="rowspanning-tables">
+<h2><a class="toc-backref" href="#toc-entry-37"><span class="sectnum">2.20</span> Rowspanning tables</a></h2>
+<p>Here's a table with cells spanning several rows:</p>
+<table>
+<colgroup>
+<col style="width: 44%" />
+<col style="width: 22%" />
+<col style="width: 33%" />
+</colgroup>
+<thead>
+<tr><th class="head"><p>Header row, column 1
+(header rows optional)</p></th>
+<th class="head"><p>Header 2</p></th>
+<th class="head"><p>Header 3</p></th>
+</tr>
+</thead>
+<tbody>
+<tr><td><p>body row 1, column 1</p></td>
+<td><p>column 2</p></td>
+<td><p>column 3</p></td>
+</tr>
+<tr><td><p>body row 2</p></td>
+<td rowspan="2"><p>Cells may
+span rows.</p></td>
+<td rowspan="2"><p>Another
+rowspanning
+cell.</p></td>
+</tr>
+<tr><td><p>body row 3</p></td>
+</tr>
+</tbody>
+</table>
+</div>
+<div class="section" id="complex-tables">
+<h2><a class="toc-backref" href="#toc-entry-38"><span class="sectnum">2.21</span> Complex tables</a></h2>
+<p>Here's a complex table, which should test all features.</p>
+<table>
+<colgroup>
+<col style="width: 43%" />
+<col style="width: 21%" />
+<col style="width: 18%" />
+<col style="width: 18%" />
+</colgroup>
+<thead>
+<tr><th class="head"><p>Header row, column 1
+(header rows optional)</p></th>
+<th class="head"><p>Header 2</p></th>
+<th class="head"><p>Header 3</p></th>
+<th class="head"><p>Header 4</p></th>
+</tr>
+</thead>
+<tbody>
+<tr><td><p>body row 1, column 1</p></td>
+<td><p>column 2</p></td>
+<td><p>column 3</p></td>
+<td><p>column 4</p></td>
+</tr>
+<tr><td><p>body row 2</p></td>
+<td colspan="3"><p>Cells may span columns.</p></td>
+</tr>
+<tr><td><p>body row 3</p></td>
+<td rowspan="2"><p>Cells may
+span rows.</p>
+<p>Paragraph.</p>
+</td>
+<td colspan="2" rowspan="2"><ul class="simple">
+<li><p>Table cells</p></li>
+<li><p>contain</p></li>
+<li><p>body elements.</p></li>
+</ul>
+</td>
+</tr>
+<tr><td><p>body row 4</p></td>
+</tr>
+<tr><td><p>body row 5</p></td>
+<td colspan="2"><p>Cells may also be
+empty: <span class="docutils literal"><span class="pre">--></span></span></p></td>
+<td></td>
+</tr>
+</tbody>
+</table>
+</div>
+<div class="section" id="list-tables">
+<h2><a class="toc-backref" href="#toc-entry-39"><span class="sectnum">2.22</span> List Tables</a></h2>
+<p>Here's a list table exercising all features:</p>
+<table class="colwidths-given test" style="width: 40em">
+<caption>list table with integral header</caption>
+<colgroup>
+<col style="width: 17%" />
+<col style="width: 33%" />
+<col style="width: 50%" />
+</colgroup>
+<thead>
+<tr><th class="head stub"><p>Treat</p></th>
+<th class="head"><p>Quantity</p></th>
+<th class="head"><p>Description</p></th>
+</tr>
+</thead>
+<tbody>
+<tr><th class="stub"><p>Albatross</p></th>
+<td><p>2.99</p></td>
+<td><p>On a stick!</p></td>
+</tr>
+<tr><th class="stub"><p>Crunchy Frog</p></th>
+<td><p>1.49</p></td>
+<td><p>If we took the bones out, it wouldn't be
+crunchy, now would it?</p></td>
+</tr>
+<tr><th class="stub"><p>Gannet Ripple</p></th>
+<td><p>1.99</p></td>
+<td><p>On a stick!</p></td>
+</tr>
+</tbody>
+</table>
+<table class="colwidths-auto align-center">
+<caption>center aligned list table</caption>
+<tbody>
+<tr><td><p>Albatross</p></td>
+<td><p>2.99</p></td>
+</tr>
+<tr><td><p>Crunchy Frog</p></td>
+<td><p>1.49</p></td>
+</tr>
+<tr><td><p>Gannet Ripple</p></td>
+<td><p>1.99</p></td>
+</tr>
+</tbody>
+</table>
+</div>
+<div class="section" id="custom-roles">
+<h2><a class="toc-backref" href="#toc-entry-40"><span class="sectnum">2.23</span> Custom Roles</a></h2>
+<ul>
+<li><p>A role based on an existing role.</p>
+<p><span class="custom docutils literal">one</span> <span class="custom docutils literal">two</span> <span class="custom docutils literal">three</span></p>
+</li>
+<li><p>A new role.</p>
+<p><span class="customnew">one two three</span></p>
+</li>
+<li><p>A role with class attribute.</p>
+<p><span class="special">interpreted text</span></p>
+</li>
+<li><p>A language-switching role:</p>
+<p>Let's count in German <span lang="de">eins zwei drei</span>.</p>
+</li>
+<li><p>A role with multiple class attributes, styled with raw directives:</p>
+<p>The following works in most browsers but does not validate
+(<span class="docutils literal"><style></span> is only allowed in the document head):</p>
+<pre class="literal-block">.. raw:: html
+
+ <style type="text/css"><!--
+ .green {color: green;}
+ .sc {font-variant: small-caps;}
+ --></style></pre>
+<p><span class="green sc" lang="en-gb">British colourful text in small-caps</span>.</p>
+</li>
+</ul>
+</div>
+</div>
+<div class="section" id="html-specific">
+<h1><a class="toc-backref" href="#toc-entry-41"><span class="sectnum">3</span> HTML specific</a></h1>
+<div class="section" id="svg-images">
+<h2><a class="toc-backref" href="#toc-entry-42"><span class="sectnum">3.1</span> SVG Images</a></h2>
+<img alt="../../../docs/user/rst/images/biohazard.svg" class="align-left" src="../../../docs/user/rst/images/biohazard.svg" style="width: 48px; height: 48px;" />
+<p>Scalable vector graphics (SVG) images are the only standards-compliable way
+to include vector graphics in HTML documents. However, they are not
+supported by all backends/output formats. (E.g., LaTeX supports the
+PDF or Postscript formats for vector graphics instead.)</p>
+<p>Rendering behaviour varies, depending on</p>
+<ol class="loweralpha">
+<li><p>The SVG image itself, e.g. fixed-size vs. scaling:</p>
+<pre class="literal-block">width="280" viewBox="0 0 280 27"
+height="27" width="100%"
+ height="100%"</pre>
+</li>
+<li><p>The method used to put the image in the document.</p>
+<p>For HTML, there are several alternatives including:</p>
+<ul class="simple">
+<li><p>using the HTML <span class="docutils literal"><img></span> tag (not for interactive/animated SVG),</p></li>
+<li><p>using the HTML <span class="docutils literal"><object></span> tag,</p></li>
+<li><p>including within SVG using the SVG <span class="docutils literal"><image></span> tag,</p></li>
+<li><p>embedd the SVG code within HTML (inlining).</p></li>
+</ul>
+<p>The <cite>html4css1</cite> writer uses <span class="docutils literal"><object></span> tags, the <cite>html5</cite>
+writer uses <span class="docutils literal"><img></span> tags.</p>
+<!-- cf. http://edutechwiki.unige.ch/en/Using_SVG_with_HTML5_tutorial -->
+</li>
+<li><p>The viewing agent.</p>
+<p>All up-to-date HTML browsers support SVG, however not all do this fully
+and in the same manner. Many older versions, especially IE < 9, have
+deficiencies or require plug-ins (i.e. don't support the <span class="docutils literal"><img></span> tag).</p>
+</li>
+</ol>
+<p>If the image is wrapped in <span class="docutils literal"><object></span> or <span class="docutils literal"><svg></span> tags, it depends on the
+<span class="docutils literal">viewBox</span> declaration inside the images root <span class="docutils literal"><svg></span> element whether an
+SVG image is scaled or clipped/padded. Images wrapped in <span class="docutils literal"><img></span> are
+always scaled.</p>
+<ul>
+<li><img alt="../../../docs/user/rst/images/title-scaling.svg" class="align-right" src="../../../docs/user/rst/images/title-scaling.svg" style="width: 50%;" />
+<p>A scaling image (scales with the browser window), occupying 50% of the line
+width. The <span class="docutils literal">viewBox</span> setting in the image file enables auto-scaling also in
+<span class="docutils literal"><object></span> tags and embedded SVG (if width and hight are set to 100% in the
+SVG <image> tag).</p>
+</li>
+<li><img alt="../../../docs/user/rst/images/title.svg" class="align-right" src="../../../docs/user/rst/images/title.svg" style="width: 50%; height: 15px;" />
+<p>A fixed-size image in a box 50% wide and 15 pixles high. This image is
+scaled, if wrapped in an <span class="docutils literal"><img></span> tag but clipped in an <span class="docutils literal"><object></span> tag
+or within SVG.</p>
+</li>
+<li><img alt="../../../docs/user/rst/images/title-scaling.svg" class="align-right" src="../../../docs/user/rst/images/title-scaling.svg" style="width: 50%; height: 1.5em;" />
+<p>A right aligned, scaling image 50% wide and 1.5 em high. (This SVG image
+keeps the aspect ratio.)</p>
+</li>
+<li><p>An inline image <img alt="inline-svg" src="../../../docs/user/rst/images/biohazard-scaling.svg" style="height: 0.8em;" /> scaled to a height of 0.8 em.</p>
+</li>
+<li><img alt="../../../docs/user/rst/images/biohazard-scaling.svg" class="align-right" src="../../../docs/user/rst/images/biohazard-scaling.svg" style="height: 1em;" />
+<p>A scaling image 1 em high, right aligned:</p>
+</li>
+<li><p>A scaling image 5 mm x 5 mm, centered, with hyperlink reference:</p>
+<a class="reference internal image-reference" href="#svg-images"><img alt="../../../docs/user/rst/images/biohazard-scaling.svg" class="align-center" src="../../../docs/user/rst/images/biohazard-scaling.svg" style="width: 5mm; height: 5mm;" /></a>
+</li>
+<li><img alt="../../../docs/user/rst/images/biohazard.svg" class="align-right" src="../../../docs/user/rst/images/biohazard.svg" style="width: 4cm; height: 2em;" />
+<p>A fixed-size image in a 4 cm x 2 em box.</p>
+</li>
+</ul>
+<p>Older versions of <cite>webkit</cite> based browsers (chromium, safari, midori,
+konqueror) support the <span class="docutils literal"><img></span> tag but don't display contained bitmap
+images in this case.</p>
+<ul>
+<li><img alt="../../../docs/user/rst/images/biohazard-bitmap.svg" class="align-right" src="../../../docs/user/rst/images/biohazard-bitmap.svg" style="width: 3em;" />
+<p>A small, fixed-size SVG image with embedded bitmap, The <span class="docutils literal">:width:</span> is
+set to 3 em in the rST source. Does not scale if wrapped in <span class="docutils literal"><object></span>
+tags.</p>
+</li>
+<li><img alt="../../../docs/user/rst/images/biohazard-bitmap-scaling.svg" class="align-right" src="../../../docs/user/rst/images/biohazard-bitmap-scaling.svg" style="width: 3em;" />
+<p>A scaling SVG image with embedded bitmap, 3 em wide.</p>
+</li>
+</ul>
+<p>SVG images can also be put in figures:</p>
+<blockquote>
+<div class="figure align-center">
+<img alt="reStructuredText, the markup syntax" src="../../../docs/user/rst/images/title.svg" style="width: 290px; height: 28px;" />
+<p class="caption"><strong>Figure:</strong> SVG image in a figure.</p>
+</div>
+</blockquote>
+</div>
+<div class="section" id="swf-images">
+<h2><a class="toc-backref" href="#toc-entry-43"><span class="sectnum">3.2</span> SWF Images</a></h2>
+<p>Shockwave Flash is an image/movie format that most modern web browsers
+support via a plugin. It is sometimes blocked due to privacy/security
+concerns.</p>
+<p>Images with extension <span class="docutils literal">.swf</span> are placed inside <object> elements.
+For complete control over display options use raw HTML.</p>
+<object class="align-left" data="../../../docs/user/rst/images/biohazard.swf" style="width: 4cm; height: 2em;" type="application/x-shockwave-flash">
+[biohazard.swf]</object>
+<p>An SWF image in a 4 cm x 2 em box, left aligned.</p>
+<p>An inline SWF image <object data="../../../docs/user/rst/images/biohazard.swf" style="width: 0.8em; height: 0.8em;" type="application/x-shockwave-flash">inline-swf</object> scaled to 0.8 em x 0.8 em.</p>
+</div>
+<div class="section" id="text-level-semantics">
+<h2><a class="toc-backref" href="#toc-entry-44"><span class="sectnum">3.3</span> Text-level semantics</a></h2>
+<p><a class="reference external" href="https://html.spec.whatwg.org/#text-level-semantics">HTML 5 tags for representation of text-level semantics</a> <a class="footnote-reference brackets" href="#footnote-13" id="footnote-reference-27">13</a> and their
+reStructuredText equivalents.</p>
+<dl class="narrow field-list">
+<dt>a</dt>
+<dd><p>Hyperlinks</p>
+<blockquote>
+<p>Visit my <a class="reference external" href="example.org:drinks.html">drinks</a> page.</p>
+</blockquote>
+</dd>
+<dt>em</dt>
+<dd><p>Stress emphasis</p>
+<blockquote>
+<p>I must say I <em>adore</em> lemonade. I's <em>sooo</em> sweet.</p>
+</blockquote>
+</dd>
+<dt>strong</dt>
+<dd><p>Importance</p>
+<blockquote>
+<p><strong>Warning</strong>: This tea is <strong>very hot</strong>.</p>
+</blockquote>
+</dd>
+<dt>small</dt>
+<dd><p>Side comments</p>
+<blockquote>
+<p>These grapes are made into wine.
+<span class="small">Alcohol is addictive.</span></p>
+</blockquote>
+</dd>
+<dt>s</dt>
+<dd><p>Inaccurate text</p>
+<blockquote>
+<p>Price: <span class="s">£4.50</span> £2.00!</p>
+</blockquote>
+</dd>
+<dt>cite</dt>
+<dd><p>Titles of works</p>
+<blockquote>
+<p>The case <cite>Hugo v. Danielle</cite> is relevant here.
+I recommend reading <cite>Harry Potter</cite>.</p>
+</blockquote>
+</dd>
+<dt>q</dt>
+<dd><p>Quotations</p>
+<blockquote>
+<p>The judge said <span class="q">You can drink water from the fish tank</span>
+but advised against it.</p>
+</blockquote>
+</dd>
+<dt>dfn</dt>
+<dd><p>Defining instance</p>
+<blockquote>
+<p>The term <span class="dfn">organic food</span> refers to food produced without synthetic
+chemicals.</p>
+</blockquote>
+</dd>
+<dt>abbr</dt>
+<dd><p>Abbreviations <a class="footnote-reference brackets" href="#attribute-optional" id="footnote-reference-10">5</a></p>
+<blockquote>
+<p>Organic food in Ireland is certified by the <abbr>IOFGA</abbr> <a class="footnote-reference brackets" href="#footnote-6" id="footnote-reference-11">‡</a></p>
+</blockquote>
+<p>In rST there are separate roles for <cite>abbreviations</cite> <abbr>rsp.</abbr>
+<cite>acronymes</cite>. In HTML, the <acronym> tag is obsolete and authors are
+advised to use <abbr> instead. The HTML5 writer uses <abbr> for Docutil's
+<abbreviation> element.</p>
+<dl class="footnote brackets">
+<dt class="label" id="footnote-6"><span class="brackets"><a class="fn-backref" href="#footnote-reference-11">‡</a></span></dt>
+<dd><p>Irish Organic Farmers and Growers Association</p>
+</dd>
+</dl>
+</dd>
+<dt>ruby, rt, rp</dt>
+<dd><p>Ruby annotations</p>
+<p>Require inline nesting, currently not supported in rST.</p>
+<blockquote>
+<p><ruby> OJ <rp>(</rp><rt>Orange Juice</rt><rp>)</rp></ruby></p>
+</blockquote>
+</dd>
+<dt>data</dt>
+<dd><p>Machine-readable equivalent <a class="footnote-reference brackets" href="#attribute-required" id="footnote-reference-12">6</a></p>
+<blockquote>
+<p>Available starting today! <data value="UPC:022014640201">North Coast
+Organic Apple Cider</data></p>
+</blockquote>
+</dd>
+<dt>time</dt>
+<dd><p>Machine-readable equivalent of date- or time-related data <a class="footnote-reference brackets" href="#attribute-required" id="footnote-reference-13">6</a></p>
+<blockquote>
+<p>Available starting on <time datetime="2011-11-18">November 18th</time>!</p>
+</blockquote>
+</dd>
+<dt>code</dt>
+<dd><p>Computer code</p>
+<blockquote>
+<p>The <code>fruitdb</code> program can be used for tracking fruit production.</p>
+</blockquote>
+</dd>
+<dt>var</dt>
+<dd><p>Variables</p>
+<blockquote>
+<p>If there are <span class="var">n</span> fruit in the bowl, at least <span class="var">n</span>÷2 will be
+ripe.</p>
+</blockquote>
+</dd>
+<dt>samp</dt>
+<dd><p>Computer output</p>
+<blockquote>
+<p>The computer said <span class="samp docutils literal">Unknown error <span class="pre">-3</span></span>.</p>
+</blockquote>
+</dd>
+<dt>kbd</dt>
+<dd><p>User input</p>
+<blockquote>
+<p>Hit <span class="kbd">F1</span> to continue.</p>
+</blockquote>
+</dd>
+<dt>sub</dt>
+<dd><p>Subscripts</p>
+<blockquote>
+<p>Water is H<sub>2</sub>O.</p>
+</blockquote>
+</dd>
+<dt>sup</dt>
+<dd><p>Superscripts</p>
+<blockquote>
+<p>The Hydrogen in heavy water is usually <sup>2</sup>H.</p>
+</blockquote>
+</dd>
+<dt>i</dt>
+<dd><p>Alternative voice</p>
+<blockquote>
+<p>Lemonade consists primarily of <span class="i" lang="la">Citrus limon</span>.</p>
+</blockquote>
+</dd>
+<dt>b</dt>
+<dd><p>Keywords</p>
+<blockquote>
+<p>Take a <span class="b">lemon</span> and squeeze it with a <span class="b">juicer</span>.</p>
+</blockquote>
+</dd>
+<dt>u</dt>
+<dd><p>Annotations</p>
+<blockquote>
+<p>The mixture of apple juice and <span class="u spelling">eldeflower</span> juice is very
+pleasant.</p>
+</blockquote>
+</dd>
+<dt>mark</dt>
+<dd><p>Highlight</p>
+<blockquote>
+<p>Elderflower cordial, with one <span class="mark">part</span> cordial to ten
+<span class="mark">part</span>s water, stands a<span class="mark">part</span> from the rest.</p>
+</blockquote>
+</dd>
+<dt>bdi</dt>
+<dd><p>Text directionality isolation <a class="footnote-reference brackets" href="#attribute-optional" id="footnote-reference-14">5</a></p>
+<blockquote>
+<p>The recommended restaurant is <span class="bdi">My Juice Café (At The Beach)</span>.</p>
+</blockquote>
+<p>The <cite>dir</cite> global attribute defaults to "auto" (not "inherit") on this
+element.</p>
+</dd>
+<dt>bdo</dt>
+<dd><p>Text directionality formatting <a class="footnote-reference brackets" href="#attribute-required" id="footnote-reference-15">6</a></p>
+<blockquote>
+<p>The proposal is to write English, but in reverse order. "Juice" would
+become "<bdo dir=rtl>Juice</bdo>"></p>
+</blockquote>
+<p>Authors must specify the dir attribute on this element.</p>
+</dd>
+<dt>span</dt>
+<dd><p>Other</p>
+<blockquote>
+<p>In French we call it <span lang="fr">sirop de sureau</span>.</p>
+</blockquote>
+</dd>
+<dt>br</dt>
+<dd><p>Line break</p>
+<p>For complete paragraphs, use a line-block:</p>
+<blockquote>
+<div class="line-block">
+<div class="line">Simply Orange Juice Company</div>
+<div class="line">Apopka, FL 32703</div>
+<div class="line">U.S.A.</div>
+</div>
+</blockquote>
+<p>rST does not natively support an exceptional hard line break in a floating
+paragraph. You may use a HTML-only substitution.</p>
+<blockquote>
+<p>I want to break this line after the colon: <br /> but allow other
+linebreaks in this paragraph according to the width of the containing
+block.</p>
+</blockquote>
+</dd>
+<dt>wbr</dt>
+<dd><p>Line breaking opportunity</p>
+<p>Not supported by rST. You may use a ZWSP character (u200B), literal or via
+a substitution.</p>
+<blockquote>
+<p>www.simplyorangejuice.com</p>
+</blockquote>
+</dd>
+</dl>
+</div>
+<div class="section" id="indicating-edits">
+<h2><a class="toc-backref" href="#toc-entry-45"><span class="sectnum">3.4</span> Indicating Edits</a></h2>
+<p><a class="reference external" href="https://html.spec.whatwg.org/multipage/edits.html">HTML tags for representation of edits to the document</a> <a class="footnote-reference brackets" href="#footnote-14" id="footnote-reference-28">14</a> and their
+reStructuredText equivalents.</p>
+<dl class="field-list">
+<dt>ins</dt>
+<dd><p>Additions <a class="footnote-reference brackets" href="#attribute-optional" id="footnote-reference-16">5</a></p>
+<blockquote>
+<p>This text has "always" been here. <span class="ins">This text has been inserted.</span></p>
+<div class="ins docutils container">
+<p>This paragraph has been inserted.</p>
+</div>
+</blockquote>
+</dd>
+<dt>del</dt>
+<dd><p>Removed content <a class="footnote-reference brackets" href="#attribute-optional" id="footnote-reference-17">5</a></p>
+<blockquote>
+<p><span class="del">This text has been deleted</span>, here is the rest of the paragraph.</p>
+<div class="del docutils container">
+<p>This paragraph has been deleted.</p>
+</div>
+</blockquote>
+</dd>
+</dl>
+<dl class="footnote brackets">
+<dt class="label" id="attribute-optional"><span class="brackets">5</span><span class="fn-backref">(<a href="#footnote-reference-10">1</a>,<a href="#footnote-reference-14">2</a>,<a href="#footnote-reference-16">3</a>,<a href="#footnote-reference-17">4</a>)</span></dt>
+<dd><p>Would gain from support for attributes/arguments
+to inline roles. See <a class="reference external" href="http://docutils.sourceforge.net/docs/dev/todo.html#interpreted-text">TODO</a> <a class="footnote-reference brackets" href="#footnote-9" id="footnote-reference-22">9</a></p>
+</dd>
+<dt class="label" id="attribute-required"><span class="brackets">6</span><span class="fn-backref">(<a href="#footnote-reference-12">1</a>,<a href="#footnote-reference-13">2</a>,<a href="#footnote-reference-15">3</a>)</span></dt>
+<dd><p>Requires support for attributes to inline
+roles to make sense.</p>
+</dd>
+</dl>
+</div>
+</div>
+<div class="section" id="changes-to-the-html4css1-writer">
+<h1><a class="toc-backref" href="#toc-entry-46"><span class="sectnum">4</span> Changes to the html4css1 writer</a></h1>
+<ul class="simple">
+<li><p>Use only meta keywords recognized by HTML 5.</p></li>
+<li><p>Set table column widths with <style="width: ...">, not "width" argument.</p></li>
+<li><p>Horizontal alignment of table heads with CSS.</p></li>
+<li><p>Field lists as styled definition lists.</p></li>
+<li><p>Do not drop paragraph objects, use CSS rules to prevent unwanted vertical
+space.</p></li>
+<li><p>Put subtitles in <p> elements.</p></li>
+</ul>
+<div class="section" id="field-list-handling">
+<h2><a class="toc-backref" href="#toc-entry-47"><span class="sectnum">4.1</span> Field list handling</a></h2>
+<p>The following list demonstrates the problems with the html4css1
+approach: the <cite>field-name-limit</cite> setting is given in "number of
+characters" but the field name uses a proportional font.</p>
+<dl class="field-list simple">
+<dt>The field name</dt>
+<dd><p>is typeset on the same line, unless it is "long".</p>
+</dd>
+<dt>this field name</dt>
+<dd><p>is considered "long" in the html table rendering by
+the html4css1 writer with the default setting of
+<span class="docutils literal"><span class="pre">--field-name-limit=14</span></span>.</p>
+</dd>
+<dt>iiiiiiiiiiiiiii</dt>
+<dd><p>a field name that is considered "long" by html4css1
+with the default setting of <cite>field-name-limit: 14</cite>.</p>
+</dd>
+<dt>MMMMMMMMMMMMMM</dt>
+<dd><p>a field name that is actually longer than the
+previous one but regarded "short" by html4css1.</p>
+</dd>
+</dl>
+<p>With <span class="docutils literal">html_plain</span>, a <cite>field list</cite> is typeset as CSS-styled <cite>definition
+list</cite>. The default layout is similar to the look with <cite>html4css1</cite>:</p>
+<dl class="open field-list">
+<dt>A long field name</dt>
+<dd><p>sticks into the field body.</p>
+<p>The field body is pushed to the next line (you can suppress
+this behaviour with the <a class="reference internal" href="#run-in">run-in</a> class argument).</p>
+</dd>
+<dt>Customization</dt>
+<dd><p>of the field name width is possible with CSS instead
+of the <cite>field-name-limit</cite> configuration setting, for
+example:</p>
+<pre class="literal-block">dl.field-list > dd { margin-left: 6em; }</pre>
+</dd>
+<dt>Empty</dt>
+<dd><p></p></dd>
+<dt>fields</dt>
+<dd><p>must not lead to misalignment of the following content.</p>
+</dd>
+</dl>
+</div>
+<div class="section" id="styling-with-class-arguments">
+<h2><a class="toc-backref" href="#toc-entry-48"><span class="sectnum">4.2</span> Styling with class arguments</a></h2>
+<p>The <span class="docutils literal">plain.css</span> style sheet comes with some pre-defined style variants
+that can be choosen via a class argument.</p>
+<div class="section" id="description-lists">
+<h3><a class="toc-backref" href="#toc-entry-49"><span class="sectnum">4.2.1</span> Description lists</a></h3>
+<p>Definition lists with the "description" class argument:</p>
+<dl class="description simple">
+<dt>description lists</dt>
+<dd><p>Definition lists that are styled like in most dictionaries,
+encyclopedias etc. (as well as the LaTeX <cite>description</cite> environment).</p>
+</dd>
+<dt>label</dt>
+<dd><p>The term to be described. Put in boldface.</p>
+</dd>
+<dt>content</dt>
+<dd><p>Starts on the same line and has a hanging indent.</p>
+</dd>
+</dl>
+</div>
+<div class="section" id="field-list-variants">
+<h3><a class="toc-backref" href="#toc-entry-50"><span class="sectnum">4.2.2</span> Field list variants</a></h3>
+<p>For field lists, the "compact/open", "narrow" and "run-in" styles are defined
+in the style sheet <span class="docutils literal">plain.css</span>.</p>
+<dl class="simple">
+<dt><em>compact</em></dt>
+<dd><dl class="compact field-list simple">
+<dt>Feature</dt>
+<dd><p>No additional space between list items.</p>
+</dd>
+<dt>Option</dt>
+<dd><p>The <span class="docutils literal"><span class="pre">--compact-field-lists</span></span> command line option (and the
+corresponding configuration setting) set the <cite>compact</cite>
+class argument on all "simple" field lists, if not
+overridden with <cite>open</cite>.</p>
+</dd>
+<dt>Use</dt>
+<dd><p>For lists with short field body.</p>
+</dd>
+</dl>
+</dd>
+<dt><em>open</em></dt>
+<dd><dl class="open field-list">
+<dt>Feature</dt>
+<dd><p>Additional space between list items also in "simple" lists.
+(Overrides the <span class="docutils literal"><span class="pre">--compact-field-lists</span></span> command line
+option and the corresponding configuration setting)</p>
+</dd>
+<dt>Use</dt>
+<dd><p>For "simple" lists that should keep the space between list items.</p>
+</dd>
+</dl>
+</dd>
+<dt><em>narrow</em></dt>
+<dd><dl class="narrow field-list simple">
+<dt>Feature</dt>
+<dd><p>Less indented field body.</p>
+</dd>
+<dt>Use</dt>
+<dd><p>For lists with short field names.</p>
+</dd>
+<dt>A long field name</dt>
+<dd><p>sticks into the field body and the field body starts on a
+new line (if not combined with <a class="reference internal" href="#run-in">run-in</a>).</p>
+</dd>
+</dl>
+</dd>
+</dl>
+<dl class="simple" id="run-in">
+<dt><em>run-in</em></dt>
+<dd><dl class="run-in field-list simple">
+<dt>Feature</dt>
+<dd><p>Field body starts on the same line also after long field
+names.</p>
+</dd>
+<dt>A long field name</dt>
+<dd><p>sticks into the field body which continues on
+the same line.</p>
+</dd>
+<dt>The next field name</dt>
+<dd><p>and field body should align. Long text in the field
+body is wrapped and aligns with other fields.</p>
+</dd>
+</dl>
+</dd>
+</dl>
+</div>
+<div class="section" id="table-variants">
+<h3><a class="toc-backref" href="#toc-entry-51"><span class="sectnum">4.2.3</span> Table variants</a></h3>
+<p>The following styles can be applied to individual tables via a class
+argument or as document wide setting with the <a class="reference external" href="http://docutils.sourceforge.net/docs/user/config.html#table-style">table-style</a> <a class="footnote-reference brackets" href="#footnote-10" id="footnote-reference-23">10</a> configuration
+setting (or command line argument).</p>
+<ul>
+<li><p>Numbered tables can be achieved with the "numbered" class option:</p>
+<table class="numbered">
+<caption>truth values</caption>
+<colgroup>
+<col style="width: 29%" />
+<col style="width: 29%" />
+<col style="width: 42%" />
+</colgroup>
+<thead>
+<tr><th class="head"><p>A</p></th>
+<th class="head"><p>B</p></th>
+<th class="head"><p>A or B</p></th>
+</tr>
+</thead>
+<tbody>
+<tr><td><p>False</p></td>
+<td><p>False</p></td>
+<td><p>False</p></td>
+</tr>
+<tr><td><p>True</p></td>
+<td><p>False</p></td>
+<td><p>True</p></td>
+</tr>
+<tr><td><p>False</p></td>
+<td><p>True</p></td>
+<td><p>True</p></td>
+</tr>
+<tr><td><p>True</p></td>
+<td><p>True</p></td>
+<td><p>True</p></td>
+</tr>
+</tbody>
+</table>
+<p>Currently, referencing to the table by number is not supported. This is a
+common request and already on the <cite>TODO list</cite>.</p>
+</li>
+<li><p>A table with "booktabs" class value, is rendered similar to the style
+from the <a class="reference external" href="http://tug.ctan.org/tex-archive/macros/latex/contrib/booktabs/booktabs.pdf">booktabs</a> <a class="footnote-reference brackets" href="#footnote-11" id="footnote-reference-24">11</a> LaTeX package.</p>
+</li>
+</ul>
+<p>"Booktabs" style table, numbered, centre-aligned, with auto-sized columns:</p>
+<blockquote>
+<table class="booktabs numbered colwidths-auto align-center">
+<caption>I/O values</caption>
+<thead>
+<tr><th class="head" colspan="2"><p>Input</p></th>
+<th class="head"><p>Output</p></th>
+</tr>
+<tr><th class="head"><p>A</p></th>
+<th class="head"><p>B</p></th>
+<th class="head"><p>A or B</p></th>
+</tr>
+</thead>
+<tbody>
+<tr><td><p>False</p></td>
+<td><p>False</p></td>
+<td><p>False</p></td>
+</tr>
+<tr><td><p>True</p></td>
+<td><p>False</p></td>
+<td><p>True</p></td>
+</tr>
+<tr><td><p>False</p></td>
+<td><p>True</p></td>
+<td><p>True</p></td>
+</tr>
+<tr><td><p>True</p></td>
+<td><p>True</p></td>
+<td><p>True</p></td>
+</tr>
+</tbody>
+</table>
+</blockquote>
+</div>
+</div>
+</div>
+<div class="section" id="error-handling">
+<h1><a class="toc-backref" href="#toc-entry-52"><span class="sectnum">5</span> Error Handling</a></h1>
+<p>Any errors caught during processing will generate system messages.</p>
+<p>There should be five messages in the following, auto-generated
+section, "Docutils System Messages":</p>
+<!-- section should be added by Docutils automatically -->
+</div>
+<div class="system-messages section">
+<h1>Docutils System Messages</h1>
+<div class="system-message" id="system-message-1">
+<p class="system-message-title">System Message: ERROR/3 (<span class="docutils literal">functional/input/data/standard.txt</span>, line 104); <em><a href="#problematic-1">backlink</a></em></p>
+<p>Undefined substitution referenced: "problematic".</p>
+</div>
+<div class="system-message" id="system-message-2">
+<p class="system-message-title">System Message: ERROR/3 (<span class="docutils literal">functional/input/data/standard.txt</span>, line 392); <em><a href="#footnote-reference-8">backlink</a></em></p>
+<p>Unknown target name: "5".</p>
+</div>
+<div class="system-message" id="system-message-3">
+<p class="system-message-title">System Message: ERROR/3 (<span class="docutils literal">functional/input/data/standard.txt</span>, line 401); <em><a href="#citation-reference-3">backlink</a></em></p>
+<p>Unknown target name: "nonexistent".</p>
+</div>
+<div class="system-message" id="system-message-4">
+<p class="system-message-title">System Message: ERROR/3 (<span class="docutils literal">functional/input/data/standard.txt</span>, line 428); <em><a href="#problematic-2">backlink</a></em></p>
+<p>Unknown target name: "hyperlink reference without a target".</p>
+</div>
+<div class="system-message" id="system-message-5">
+<p class="system-message-title">System Message: ERROR/3 (<span class="docutils literal">functional/input/data/standard.txt</span>, line 441); <em><a href="#problematic-3">backlink</a></em></p>
+<p>Duplicate target name, cannot be used as a unique reference: "duplicate target names".</p>
+</div>
+</div>
+</div>
+<div class="footer">
+<hr class="footer" />
+<p>Document footer</p>
+<p><a class="reference external" href="http://www.w3.org/TR/html5/"><img alt="Conforms to HTML 5" src="http://www.w3.org/html/logo/badge/html5-badge-h-css3-semantics.png" style="width: 88px; height: 31px;" /></a> <a class="reference external" href="http://validator.w3.org/check?uri=referer"><img alt="Check validity!" src="https://www.w3.org/Icons/ValidatorSuite/vs-blue-190.png" style="width: 88px; height: 31px;" /></a> <a class="reference external" href="http://jigsaw.w3.org/css-validator/check/referer"><img alt="Valid CSS 2.1!" src="http://jigsaw.w3.org/css-validator/images/vcss" style="width: 88px; height: 31px;" /></a></p>
+
+</div>
+</body>
+</html>
--- /dev/null
+\documentclass[a4paper]{article}
+% generated by Docutils <http://docutils.sourceforge.net/>
+\usepackage{cmap} % fix search and cut-and-paste in Acrobat
+\usepackage{ifthen}
+\usepackage[T1]{fontenc}
+\usepackage[utf8]{inputenc}
+\DeclareUnicodeCharacter{21D4}{\ensuremath{\Leftrightarrow}}
+\DeclareUnicodeCharacter{2660}{\ensuremath{\spadesuit}}
+\DeclareUnicodeCharacter{2663}{\ensuremath{\clubsuit}}
+\usepackage{alltt}
+\usepackage{amsmath}
+\usepackage[british,french,ngerman,english]{babel}
+% Prevent side-effects if French hyphenation patterns are not loaded:
+\frenchbsetup{StandardLayout}
+\AtBeginDocument{\selectlanguage{english}\noextrasfrench}
+\usepackage{color}
+\usepackage{float} % float configuration
+\floatplacement{figure}{H} % place figures here definitely
+\usepackage{graphicx}
+\usepackage{multirow}
+\usepackage{pifont}
+\setcounter{secnumdepth}{0}
+\usepackage{longtable,ltcaption,array}
+\setlength{\extrarowheight}{2pt}
+\newlength{\DUtablewidth} % internal use in tables
+\usepackage{tabularx}
+\usepackage{textcomp} % text symbol macros
+
+%%% Custom LaTeX preamble
+% PDF Standard Fonts
+\usepackage{mathptmx} % Times
+\usepackage[scaled=.90]{helvet}
+\usepackage{courier}
+
+%%% User specified packages and stylesheets
+
+%%% Fallback definitions for Docutils-specific commands
+
+% 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]%
+ {\def\DocutilsClassFunctionName{DUCLASS#1}% arg cannot be used in end-part of environment.
+ \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}}{}
+}
+
+% abstract title
+\providecommand*{\DUtitleabstract}[1]{\centerline{\textbf{#1}}}
+
+% admonition (specially marked topic)
+\providecommand{\DUadmonition}[2][class-arg]{%
+ % try \DUadmonition#1{#2}:
+ \ifcsname DUadmonition#1\endcsname%
+ \csname DUadmonition#1\endcsname{#2}%
+ \else
+ \begin{center}
+ \fbox{\parbox{0.9\linewidth}{#2}}
+ \end{center}
+ \fi
+}
+
+% dedication topic
+\providecommand*{\DUCLASSdedication}{%
+ \renewenvironment{quote}{\begin{center}}{\end{center}}%
+}
+
+% docinfo (width of docinfo table)
+\DUprovidelength{\DUdocinfowidth}{0.9\linewidth}
+
+% subtitle (in document title)
+\providecommand*{\DUdocumentsubtitle}[1]{{\large #1}}
+\newcounter{enumv}
+
+% error admonition title
+\providecommand*{\DUtitleerror}[1]{\DUtitle{\color{red}#1}}
+
+% fieldlist environment
+\ifthenelse{\isundefined{\DUfieldlist}}{
+ \newenvironment{DUfieldlist}%
+ {\quote\description}
+ {\enddescription\endquote}
+}{}
+% numeric or symbol footnotes with hyperlinks
+\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 markup (custom roles)
+% \DUrole{#1}{#2} tries \DUrole#1{#2}
+\providecommand*{\DUrole}[2]{%
+ \ifcsname DUrole#1\endcsname%
+ \csname DUrole#1\endcsname{#2}%
+ \else
+ % backwards compatibility: try \docutilsrole#1{#2}
+ \ifcsname docutilsrole#1\endcsname%
+ \PackageWarningNoLine{docutils}{Command prefix "docutilsrole" is
+ deprecated, \MessageBreak use `\protect\DUrole #1`}
+ \csname docutilsrole#1\endcsname{#2}%
+ \else%
+ #2%
+ \fi%
+ \fi%
+}
+
+% legend environment
+\ifthenelse{\isundefined{\DUlegend}}{
+ \newenvironment{DUlegend}{\small}{}
+}{}
+
+% lineblock 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 environment
+\providecommand*{\DUoptionlistlabel}[1]{\bf #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}
+}
+
+% subtitle (for sidebar)
+\providecommand*{\DUsubtitle}[1]{\par\emph{#1}\smallskip}
+
+% text mode subscript
+\ifx\textsubscript\undefined
+ \usepackage{fixltx2e} % since 2015 loaded by default
+\fi
+
+% title for topics, admonitions, unsupported section levels, and sidebar
+\providecommand*{\DUtitle}[2][class-arg]{%
+ % call \DUtitle#1{#2} if it exists:
+ \ifcsname DUtitle#1\endcsname%
+ \csname DUtitle#1\endcsname{#2}%
+ \else
+ \smallskip\noindent\textbf{#2}\smallskip%
+ \fi
+}
+
+% titlereference role
+\providecommand*{\DUroletitlereference}[1]{\textsl{#1}}
+
+% transition (break, fancybreak, anonymous section)
+\providecommand*{\DUtransition}{%
+ \hspace*{\fill}\hrulefill\hspace*{\fill}
+ \vskip 0.5\baselineskip
+}
+
+% hyperlinks:
+\ifthenelse{\isundefined{\hypersetup}}{
+ \usepackage[colorlinks=true,linkcolor=blue,urlcolor=blue]{hyperref}
+ \usepackage{bookmark}
+ \urlstyle{same} % normal text font (alternatives: tt, rm, sf)
+}{}
+\hypersetup{
+ pdftitle={reStructuredText Test Document},
+ pdfauthor={David Goodger;Me;Myself;I}
+}
+
+%%% Body
+\begin{document}
+\title{reStructuredText Test Document%
+ \label{restructuredtext-test-document}%
+ \label{doctitle}%
+ \\%
+ \DUdocumentsubtitle{Examples of Syntax Constructs}%
+ \label{examples-of-syntax-constructs}%
+ \label{subtitle}}
+\author{}
+\date{}
+\maketitle
+
+% Docinfo
+\begin{center}
+\begin{tabularx}{\DUdocinfowidth}{lX}
+\textbf{Author}: &
+ David Goodger \\
+\textbf{Address}: &
+ {\raggedright
+123 Example Street\\
+Example, EX Canada\\
+A1B 2C3 } \\
+\textbf{Contact}: &
+ \href{mailto:goodger@python.org}{goodger@python.org} \\
+\textbf{Author}: &
+ Me \\
+\textbf{Author}: &
+ Myself \\
+\textbf{Author}: &
+ I \\
+\textbf{Organization}: &
+ humankind \\
+\textbf{Date}: &
+ Now, or yesterday. Or maybe even \emph{before} yesterday. \\
+\textbf{Status}: &
+ This is a “work in progress” \\
+\textbf{Revision}: &
+ is managed by a version control system. \\
+\textbf{Version}: &
+ 1 \\
+\textbf{Copyright}: &
+ This document has been placed in the public domain. You
+may do with it as you wish. You may copy, modify,
+redistribute, reattribute, sell, buy, rent, lease,
+destroy, or improve it, quote it at length, excerpt,
+incorporate, collate, fold, staple, or mutilate it, or do
+anything else to it that your or anyone else’s heart
+desires. \\
+\textbf{field name}: &
+This is a “generic bibliographic field”.
+\\
+\textbf{field name “2”}: &
+Generic bibliographic fields may contain multiple body elements.
+
+Like this.
+\\
+\end{tabularx}
+\end{center}
+
+\begin{DUclass}{dedication}
+\begin{quote}
+\DUtitle[dedication]{Dedication}
+
+For Docutils users \& co-developers.
+\end{quote}
+\end{DUclass}
+
+\begin{DUclass}{abstract}
+\begin{quote}
+\DUtitle[abstract]{Abstract}
+
+This is a test document, containing at least one example of each
+reStructuredText construct.
+\end{quote}
+\end{DUclass}
+
+% This is a comment. Note how any initial comments are moved by
+% transforms to after the document title, subtitle, and docinfo.
+
+% Above is the document title, and below is the subtitle.
+% They are transformed from section titles after parsing.
+
+% bibliographic fields (which also require a transform):
+
+\pagebreak[4] % start ToC on new page
+
+\phantomsection\label{table-of-contents}
+\pdfbookmark[1]{Table of Contents}{table-of-contents}
+\renewcommand{\contentsname}{Table of Contents}
+\tableofcontents
+
+
+\section{1 Structural Elements%
+ \label{structural-elements}%
+}
+
+
+\subsection{1.1 Section Title%
+ \label{section-title}%
+}
+\subsubsection*{Section Subtitle}
+
+Lone subsections are converted to a section subtitle by a transform
+activated with the \texttt{-{}-section-subtitles} command line option or the
+\texttt{sectsubtitle-xform} configuration value.
+
+
+\subsection{1.2 Empty Section%
+ \label{empty-section}%
+}
+
+
+\subsection{1.3 Transitions%
+ \label{transitions}%
+}
+
+Here’s a transition:
+
+%___________________________________________________________________________
+\DUtransition
+
+It divides the section. Transitions may also occur between sections:
+
+%___________________________________________________________________________
+\DUtransition
+
+
+\section{2 Body Elements%
+ \label{body-elements}%
+}
+
+
+\subsection{2.1 Paragraphs%
+ \label{paragraphs}%
+}
+
+A paragraph.
+
+
+\subsubsection{2.1.1 Inline Markup%
+ \label{inline-markup}%
+}
+
+Paragraphs contain text and may contain inline markup: \emph{emphasis},
+\textbf{strong emphasis}, \texttt{inline literals}, standalone hyperlinks
+(\url{http://www.python.org}), external hyperlinks (\href{http://www.python.org/}{Python}\DUfootnotemark{footnote-reference-10}{footnote-6}{5}), internal
+cross-references (\hyperref[example]{example}), external hyperlinks with embedded URIs
+(\href{http://www.python.org}{Python web site}), \href{http://www.python.org/}{anonymous hyperlink
+references}\DUfootnotemark{footnote-reference-16}{footnote-6}{5} (\href{http://docutils.sourceforge.net/}{a second reference}\DUfootnotemark{footnote-reference-17}{footnote-9}{8}), footnote references (manually
+numbered\DUfootnotemark{footnote-reference-1}{footnote-1}{1}, anonymous auto-numbered\DUfootnotemark{footnote-reference-2}{footnote-2}{3}, labeled auto-numbered\DUfootnotemark{footnote-reference-3}{label}{2}, or symbolic\DUfootnotemark{footnote-reference-4}{footnote-3}{*}), citation references (\hyperlink{cit2002}{[CIT2002]}),
+substitution references (\includegraphics{../../../docs/user/rst/images/biohazard.png} \&
+a \emph{trimmed heart} \texttt{(U+2665):}\ding{170}), and %
+\phantomsection\label{inline-hyperlink-targets}inline hyperlink targets
+(see \hyperref[targets]{Targets} below for a reference back to here). Character-level
+inline markup is also possible (although exceedingly ugly!) in \emph{re}\texttt{Structured}\emph{Text}. Problems are indicated by %
+\raisebox{1em}{\hypertarget{problematic-1}{}}\hyperlink{system-message-1}{\textbf{\color{red}|problematic|}} text
+(generated by processing errors; this one is intentional). Here is a
+reference to the \hyperref[doctitle]{doctitle} and the \hyperref[subtitle]{subtitle}.
+
+The default role for interpreted text is \DUroletitlereference{Title Reference}. Here are
+some explicit interpreted text roles: a PEP reference (\href{http://www.python.org/dev/peps/pep-0287}{PEP 287}); an
+RFC reference (\href{http://tools.ietf.org/html/rfc2822.html}{RFC 2822}); an abbreviation (\DUrole{abbreviation}{abb.}), an acronym
+(\DUrole{acronym}{reST}), code (\texttt{\DUrole{code}{print \textquotedbl{}hello world\textquotedbl{}}}); a \textsubscript{subscript};
+a \textsuperscript{superscript} and explicit roles for \DUroletitlereference{Docutils}’
+\emph{standard} \textbf{inline} \texttt{markup}.
+
+% DO NOT RE-WRAP THE FOLLOWING PARAGRAPH!
+
+Let’s test wrapping and whitespace significance in inline literals:
+\texttt{This is an example of -{}-inline-literal -{}-text, -{}-including some-{}-
+strangely-{}-hyphenated-words. ~Adjust-the-width-of-your-browser-window
+to see how the text is wrapped. ~-{}- -{}-{}-{}- -{}-{}-{}-{}-{}-{}-{}- ~Now note ~ ~the
+spacing ~ ~between the ~ ~words of ~ ~this sentence ~ ~(words
+should ~ ~be grouped ~ ~in pairs).}
+
+If the \texttt{-{}-pep-references} option was supplied, there should be a
+live link to PEP 258 here.
+
+
+\subsection{2.2 Bullet Lists%
+ \label{bullet-lists}%
+}
+
+\begin{itemize}
+\item A bullet list
+
+\begin{itemize}
+\item Nested bullet list.
+
+\item Nested item 2.
+\end{itemize}
+
+\item Item 2.
+
+Paragraph 2 of item 2.
+
+\begin{itemize}
+\item Nested bullet list.
+
+\item Nested item 2.
+
+\begin{itemize}
+\item Third level.
+
+\item Item 2.
+\end{itemize}
+
+\item Nested item 3.
+
+\item This nested list should be compacted by the HTML writer.
+%
+\phantomsection\label{target}
+% Even if this item contains a target and a comment.
+\end{itemize}
+\end{itemize}
+
+
+\subsection{2.3 Enumerated Lists%
+ \label{enumerated-lists}%
+}
+
+\begin{enumerate}
+\item Arabic numerals.
+
+\begin{enumerate}
+\renewcommand{\labelenumii}{\alph{enumii})}
+\item lower alpha)
+
+\begin{enumerate}
+\renewcommand{\labelenumiii}{(\roman{enumiii})}
+\item (lower roman)
+
+\begin{enumerate}
+\item upper alpha.
+
+\begin{list}{\Roman{enumv})}{\usecounter{enumv}}
+\item upper roman)
+\end{list}
+\end{enumerate}
+\end{enumerate}
+\end{enumerate}
+
+\item Lists that don’t start at 1:
+
+\begin{enumerate}
+\renewcommand{\labelenumii}{\arabic{enumii}.}
+\setcounter{enumii}{2}
+\item Three
+
+\item Four
+\end{enumerate}
+
+\begin{enumerate}
+\renewcommand{\labelenumii}{\Alph{enumii}.}
+\setcounter{enumii}{2}
+\item C
+
+\item D
+\end{enumerate}
+
+\begin{enumerate}
+\renewcommand{\labelenumii}{\roman{enumii}.}
+\setcounter{enumii}{2}
+\item iii
+
+\item iv
+\end{enumerate}
+\end{enumerate}
+
+
+\subsection{2.4 Definition Lists%
+ \label{definition-lists}%
+}
+
+\begin{description}
+\item[{Term}] \leavevmode
+Definition
+
+\item[{Term}] \leavevmode (\textbf{classifier})
+Definition paragraph 1.
+
+Definition paragraph 2.
+
+\item[{Term}] \leavevmode
+Definition
+
+\item[{Term}] \leavevmode (\textbf{classifier one})(\textbf{classifier two})
+Definition
+
+\end{description}
+
+
+\subsection{2.5 Field Lists%
+ \label{field-lists}%
+}
+
+\begin{DUfieldlist}
+\item[{what:}]
+Field lists map field names to field bodies, like database
+records. They are often part of an extension syntax. They are
+an unambiguous variant of RFC 2822 fields.
+
+\item[{how arg1 arg2:}]
+The field marker is a colon, the field name, and a colon.
+
+The field body may contain one or more body elements, indented
+relative to the field marker.
+
+\item[{credits:}]
+\DUrole{credits}{This paragraph has the \DUroletitlereference{credits} class set. (This is actually not
+about credits but just for ensuring that the class attribute
+doesn’t get stripped away.)}
+\end{DUfieldlist}
+
+
+\subsection{2.6 Option Lists%
+ \label{option-lists}%
+}
+
+For listing command-line options:
+
+\begin{DUoptionlist}
+\item[-a] command-line option “a”
+
+\item[-b file] options can have arguments
+and long descriptions
+
+\item[-{}-long] options can be long also
+
+\item[-{}-input=file] long options can also have
+arguments
+
+\item[-{}-very-long-option] The description can also start on the next line.
+
+The description may contain multiple body elements,
+regardless of where it starts.
+
+\item[-x, -y, -z] Multiple options are an “option group”.
+
+\item[-v, -{}-verbose] Commonly-seen: short \& long options.
+
+\item[-1 file, -{}-one=file, -{}-two file] Multiple options with arguments.
+
+\item[/V] DOS/VMS-style options too
+\end{DUoptionlist}
+
+There must be at least two spaces between the option and the
+description.
+
+
+\subsection{2.7 Literal Blocks%
+ \label{literal-blocks}%
+}
+
+Literal blocks are indicated with a double-colon (“::”) at the end of
+the preceding paragraph (over there \texttt{-{}->}). They can be indented:
+
+\begin{quote}
+\begin{alltt}
+if literal_block:
+ text = 'is left as-is'
+ spaces_and_linebreaks = 'are preserved'
+ markup_processing = None
+\end{alltt}
+\end{quote}
+
+Or they can be quoted without indentation:
+
+\begin{quote}
+\begin{alltt}
+>> Great idea!
+>
+> Why didn't I think of that?
+\end{alltt}
+\end{quote}
+
+
+\subsection{2.8 Line Blocks%
+ \label{line-blocks}%
+}
+
+This section tests line blocks. Line blocks are body elements which
+consist of lines and other line blocks. Nested line blocks cause
+indentation.
+
+\begin{DUlineblock}{0em}
+\item[] This is a line block. It ends with a blank line.
+\item[]
+\begin{DUlineblock}{\DUlineblockindent}
+\item[] New lines begin with a vertical bar (“|”).
+\item[] Line breaks and initial indent are significant, and preserved.
+\item[]
+\begin{DUlineblock}{\DUlineblockindent}
+\item[] Continuation lines are also possible. A long line that is intended
+to wrap should begin with a space in place of the vertical bar.
+\end{DUlineblock}
+\item[] The left edge of a continuation line need not be aligned with
+the left edge of the text above it.
+\end{DUlineblock}
+\end{DUlineblock}
+
+\begin{DUlineblock}{0em}
+\item[] This is a second line block.
+\item[]
+\item[] Blank lines are permitted internally, but they must begin with a “|”.
+\end{DUlineblock}
+
+Another line block, surrounded by paragraphs:
+
+\begin{DUlineblock}{0em}
+\item[] And it’s no good waiting by the window
+\item[] It’s no good waiting for the sun
+\item[] Please believe me, the things you dream of
+\item[] They don’t fall in the lap of no-one
+\end{DUlineblock}
+
+Take it away, Eric the Orchestra Leader!
+
+\begin{quote}
+\begin{DUlineblock}{0em}
+\item[] A one, two, a one two three four
+\item[]
+\item[] Half a bee, philosophically,
+\item[]
+\begin{DUlineblock}{\DUlineblockindent}
+\item[] must, \emph{ipso facto}, half not be.
+\end{DUlineblock}
+\item[] But half the bee has got to be,
+\item[]
+\begin{DUlineblock}{\DUlineblockindent}
+\item[] \emph{vis a vis} its entity. D’you see?
+\item[]
+\end{DUlineblock}
+\item[] But can a bee be said to be
+\item[]
+\begin{DUlineblock}{\DUlineblockindent}
+\item[] or not to be an entire bee,
+\item[]
+\begin{DUlineblock}{\DUlineblockindent}
+\item[] when half the bee is not a bee,
+\item[]
+\begin{DUlineblock}{\DUlineblockindent}
+\item[] due to some ancient injury?
+\item[]
+\end{DUlineblock}
+\end{DUlineblock}
+\end{DUlineblock}
+\item[] Singing…
+\end{DUlineblock}
+\end{quote}
+
+A line block, like the following poem by Christian Morgenstern, can
+also be centre-aligned:
+
+\begin{selectlanguage}{ngerman}
+\begin{DUlineblock}{0em}
+\centering
+\item[] \textbf{Die Trichter}
+\item[]
+\item[] Zwei Trichter wandeln durch die Nacht.
+\item[] Durch ihres Rumpfs verengten Schacht
+\item[] fließt weißes Mondlicht
+\item[] still und heiter
+\item[] auf ihren
+\item[] Waldweg
+\item[] u. s.
+\item[] w.
+\item[]
+\end{DUlineblock}
+\end{selectlanguage}
+
+
+\subsection{2.9 Block Quotes%
+ \label{block-quotes}%
+}
+
+Block quotes consist of indented body elements:
+
+\begin{quote}
+My theory by A. Elk. Brackets Miss, brackets. This theory goes
+as follows and begins now. All brontosauruses are thin at one
+end, much much thicker in the middle and then thin again at the
+far end. That is my theory, it is mine, and belongs to me and I
+own it, and what it is too.
+\nopagebreak
+
+\raggedleft —Anne Elk (Miss)
+\end{quote}
+
+The language of a quote (like any other object) can be specified by
+a class attribute:
+
+%
+
+\begin{selectlanguage}{french}
+\begin{quote}
+ReStructuredText est un langage de balisage léger utilisé
+notamment dans la documentation du langage Python.
+\end{quote}
+\end{selectlanguage}
+
+
+\subsection{2.10 Doctest Blocks%
+ \label{doctest-blocks}%
+}
+
+\begin{quote}
+\begin{alltt}
+>>> print 'Python-specific usage examples; begun with ">>>"'
+Python-specific usage examples; begun with ">>>"
+>>> print '(cut and pasted from interactive Python sessions)'
+(cut and pasted from interactive Python sessions)
+\end{alltt}
+\end{quote}
+
+
+\subsection{2.11 Footnotes%
+ \label{footnotes}%
+}
+%
+\DUfootnotetext{footnote-1}{footnote-reference-1}{1}{%
+A footnote contains body elements, consistently indented by at
+least 3 spaces.
+
+This is the footnote’s second paragraph.
+}
+%
+\DUfootnotetext{label}{footnote-reference-3}{2}{\phantomsection\label{label}%
+Footnotes may be numbered, either manually (as in\DUfootnotemark{footnote-reference-5}{footnote-1}{1}) or
+automatically using a “\#”-prefixed label. This footnote has a
+label so it can be referred to from multiple places, both as a
+footnote reference (\DUfootnotemark{footnote-reference-6}{label}{2}) and as a \hyperref[label]{hyperlink reference}.
+}
+%
+\DUfootnotetext{footnote-2}{footnote-reference-2}{3}{%
+This footnote is numbered automatically and anonymously using a
+label of “\#” only.
+
+This is the second paragraph.
+
+And this is the third paragraph.
+}
+%
+\DUfootnotetext{footnote-3}{footnote-reference-4}{*}{%
+Footnotes may also use symbols, specified with a “*” label.
+Here’s a reference to the next footnote:\DUfootnotemark{footnote-reference-7}{footnote-4}{†}.
+}
+%
+\DUfootnotetext{footnote-4}{footnote-reference-7}{†}{%
+This footnote shows the next symbol in the sequence.
+}
+%
+\DUfootnotetext{footnote-5}{footnote-5}{4}{%
+Here’s an unreferenced footnote, with a reference to a
+nonexistent footnote:%
+\raisebox{1em}{\hypertarget{footnote-reference-8}{}}\hyperlink{system-message-2}{\textbf{\color{red}{[}5{]}\_}}.
+}
+
+
+\subsection{2.12 Citations%
+ \label{citations}%
+}
+\begin{figure}[b]\raisebox{1em}{\hypertarget{cit2002}{}}[CIT2002]
+Citations are text-labeled footnotes. They may be
+rendered separately and differently from footnotes.
+\end{figure}
+
+Here’s a reference to the above, \hyperlink{cit2002}{[CIT2002]}, and a %
+\raisebox{1em}{\hypertarget{citation-reference-3}{}}\hyperlink{system-message-3}{\textbf{\color{red}{[}nonexistent{]}\_}}
+citation.
+
+
+\subsection{2.13 Targets%
+ \label{targets}%
+ \label{another-target}%
+}
+
+\phantomsection\label{example}
+This paragraph is pointed to by the explicit “example” target. A
+reference can be found under \hyperref[inline-markup]{Inline Markup}, above. \hyperref[inline-hyperlink-targets]{Inline
+hyperlink targets} are also possible.
+
+Section headers are implicit targets, referred to by name. See
+\hyperref[targets]{Targets}, which is a subsection of \hyperref[body-elements]{Body Elements}.
+
+Explicit external targets are interpolated into references such as
+“\href{http://www.python.org/}{Python}\DUfootnotemark{footnote-reference-11}{footnote-6}{5}”.
+
+Targets may be indirect and anonymous. Thus \hyperref[targets]{this phrase} may also
+refer to the \hyperref[targets]{Targets} section.
+
+Here’s a %
+\raisebox{1em}{\hypertarget{problematic-2}{}}\hyperlink{system-message-4}{\textbf{\color{red}`hyperlink reference without a target`\_}}, which generates an
+error.
+
+
+\subsubsection{2.13.1 Duplicate Target Names%
+ \label{duplicate-target-names}%
+}
+
+Duplicate names in section headers or other implicit targets will
+generate “info” (level-1) system messages. Duplicate names in
+explicit targets will generate “warning” (level-2) system messages.
+
+
+\subsubsection{2.13.2 Duplicate Target Names%
+ \label{duplicate-target-names-1}%
+}
+
+Since there are two “Duplicate Target Names” section headers, we
+cannot uniquely refer to either of them by name. If we try to (like
+this: %
+\raisebox{1em}{\hypertarget{problematic-3}{}}\hyperlink{system-message-5}{\textbf{\color{red}`Duplicate Target Names`\_}}), an error is generated.
+
+
+\subsection{2.14 Directives%
+ \label{directives}%
+}
+
+\phantomsection\label{contents}
+These are just a sample of the many reStructuredText Directives. For
+others, please see
+\url{http://docutils.sourceforge.net/docs/ref/rst/directives.html}.
+
+
+\subsubsection{2.14.1 Document Parts%
+ \label{document-parts}%
+}
+
+An example of the “contents” directive can be seen above this section
+(a local, untitled table of \hyperref[contents]{contents}) and at the beginning of the
+document (a document-wide \hyperref[table-of-contents]{table of contents}).
+
+
+\subsubsection{2.14.2 Images and Figures%
+ \label{images-and-figures}%
+}
+
+An image directive (also clickable – a hyperlink reference):
+
+\hyperref[directives]{\includegraphics{../../../docs/user/rst/images/title.png}}
+
+Image with multiple IDs:
+
+\includegraphics{../../../docs/user/rst/images/title.png}
+\phantomsection\label{image-target-3}\label{image-target-2}\label{image-target-1}
+
+A centered image:
+
+\noindent\makebox[\linewidth][c]{\includegraphics{../../../docs/user/rst/images/biohazard.png}}
+
+A left-aligned image:
+
+\noindent{\includegraphics{../../../docs/user/rst/images/biohazard.png}\hfill}
+
+This paragraph might flow around the image.
+The specific behavior depends upon the style sheet and
+the browser or rendering software used.
+
+A right-aligned image:
+
+\noindent{\hfill\includegraphics{../../../docs/user/rst/images/biohazard.png}}
+
+This paragraph might flow around the image.
+The specific behavior depends upon the style sheet and
+the browser or rendering software used.
+
+For inline images see \hyperref[substitution-definitions]{Substitution Definitions}.
+
+Image size:
+
+An image 2 em wide:
+
+\includegraphics[width=2em]{../../../docs/user/rst/images/biohazard.png}
+
+An image 2 em wide and 15 pixel high:
+
+\includegraphics[height=15px,width=2em]{../../../docs/user/rst/images/biohazard.png}
+
+An image occupying 50\% of the line width:
+
+\includegraphics[width=0.500\linewidth]{../../../docs/user/rst/images/title.png}
+
+An image 2 cm high:
+
+\includegraphics[height=2cm]{../../../docs/user/rst/images/biohazard.png}
+
+A \emph{figure} is an image with a caption and/or a legend. With page-based output
+media, figures might float to a different position if this helps the page
+layout.
+
+\begin{DUclass}{figclass1}
+\begin{DUclass}{figclass2}
+\begin{figure}
+\noindent\makebox[\linewidth][c]{\includegraphics[width=258bp]{../../../docs/user/rst/images/title.png}}
+\caption{Plaintext markup syntax and parser system.}
+\begin{DUlegend}
+\setlength{\DUtablewidth}{\linewidth}
+\begin{longtable*}[c]{|p{0.156\DUtablewidth}|p{0.563\DUtablewidth}|}
+\hline
+
+re
+ &
+Revised, revisited, based on ‘re’ module.
+ \\
+\hline
+
+Structured
+ &
+Structure-enhanced text, structuredtext.
+ \\
+\hline
+
+Text
+ &
+Well it is, isn’t it?
+ \\
+\hline
+\end{longtable*}
+
+This paragraph is also part of the legend.
+\end{DUlegend}
+\end{figure}
+\end{DUclass}
+\end{DUclass}
+
+A left-aligned figure:
+
+\begin{DUclass}{figclass1}
+\begin{DUclass}{figclass2}
+\begin{figure} % align = "left"
+\noindent\makebox[\linewidth][c]{\includegraphics[width=40px]{../../../docs/user/rst/images/biohazard.png}}
+\caption{This is the caption.}
+\begin{DUlegend}
+This is the legend.
+
+The legend may consist of several paragraphs.
+\end{DUlegend}
+\end{figure}
+\end{DUclass}
+\end{DUclass}
+
+This paragraph might flow around the figure.
+
+The specific behavior depends upon the style sheet and the browser or
+rendering software used.
+
+A centered figure:
+
+\begin{figure}
+\noindent\makebox[\linewidth][c]{\includegraphics[width=40px]{../../../docs/user/rst/images/biohazard.png}}
+\caption{This is the caption.}
+\begin{DUlegend}
+This is the legend.
+
+The legend may consist of several paragraphs.
+\end{DUlegend}
+\end{figure}
+
+This paragraph might flow around the figure.
+
+The specific behavior depends upon the style sheet and the browser or
+rendering software used.
+
+A right-aligned figure:
+
+\begin{figure} % align = "right"
+\noindent\makebox[\linewidth][c]{\includegraphics[width=40px]{../../../docs/user/rst/images/biohazard.png}}
+\caption{This is the caption.}
+\begin{DUlegend}
+This is the legend.
+
+The legend may consist of several paragraphs.
+\end{DUlegend}
+\end{figure}
+
+This paragraph might flow around the figure. The specific behavior depends
+upon the style sheet and the browser or rendering software used.
+
+Tables may be given titles and additional arguments with the \emph{table}
+directive:
+
+\setlength{\DUtablewidth}{\linewidth}
+\begin{longtable}[l]{|p{0.075\DUtablewidth}|p{0.075\DUtablewidth}|}
+\caption{left-aligned table}\\
+\hline
+\textbf{%
+A
+} & \textbf{%
+not A
+} \\
+\hline
+\endfirsthead
+\caption[]{left-aligned table (... continued)}\\
+\hline
+\textbf{%
+A
+} & \textbf{%
+not A
+} \\
+\hline
+\endhead
+\multicolumn{2}{c}{\hfill ... continued on next page} \\
+\endfoot
+\endlastfoot
+
+False
+ &
+True
+ \\
+\hline
+
+True
+ &
+False
+ \\
+\hline
+\end{longtable}
+
+\setlength{\DUtablewidth}{\linewidth}
+\begin{longtable}[c]{|p{0.075\DUtablewidth}|p{0.075\DUtablewidth}|}
+\caption{center-aligned table}\\
+\hline
+\textbf{%
+A
+} & \textbf{%
+not A
+} \\
+\hline
+\endfirsthead
+\caption[]{center-aligned table (... continued)}\\
+\hline
+\textbf{%
+A
+} & \textbf{%
+not A
+} \\
+\hline
+\endhead
+\multicolumn{2}{c}{\hfill ... continued on next page} \\
+\endfoot
+\endlastfoot
+
+False
+ &
+True
+ \\
+\hline
+
+True
+ &
+False
+ \\
+\hline
+\end{longtable}
+
+\setlength{\DUtablewidth}{\linewidth}
+\begin{longtable}[r]{|p{0.075\DUtablewidth}|p{0.075\DUtablewidth}|}
+\caption{right-aligned table}\\
+\hline
+\textbf{%
+A
+} & \textbf{%
+not A
+} \\
+\hline
+\endfirsthead
+\caption[]{right-aligned table (... continued)}\\
+\hline
+\textbf{%
+A
+} & \textbf{%
+not A
+} \\
+\hline
+\endhead
+\multicolumn{2}{c}{\hfill ... continued on next page} \\
+\endfoot
+\endlastfoot
+
+False
+ &
+True
+ \\
+\hline
+
+True
+ &
+False
+ \\
+\hline
+\end{longtable}
+
+With the “widths” argument “auto” (or “class” value “colwidths-auto”),
+column widths are determined by the backend (if supported by the
+writer/backend).
+
+\begin{longtable*}[c]{|l|l|l|}
+\hline
+\textbf{A} & \textbf{B} & \textbf{A or B} \\
+\hline
+\endfirsthead
+\hline
+\textbf{A} & \textbf{B} & \textbf{A or B} \\
+\hline
+\endhead
+\multicolumn{3}{c}{\hfill ... continued on next page} \\
+\endfoot
+\endlastfoot
+False & False & False \\
+\hline
+True & False & True \\
+\hline
+False & True & True \\
+\hline
+True & True & True \\
+\hline
+\end{longtable*}
+\label{target2}\label{target1}
+
+
+\subsubsection{2.14.3 Admonitions%
+ \label{admonitions}%
+}
+
+\DUadmonition[attention]{
+\DUtitle[attention]{Attention!}
+
+Directives at large.
+}
+
+\DUadmonition[caution]{
+\DUtitle[caution]{Caution!}
+
+Don’t take any wooden nickels.
+}
+
+\DUadmonition[danger]{
+\DUtitle[danger]{!DANGER!}
+
+Mad scientist at work!
+}
+
+\DUadmonition[error]{
+\DUtitle[error]{Error}
+
+Does not compute.
+}
+
+\DUadmonition[hint]{
+\DUtitle[hint]{Hint}
+
+It’s bigger than a bread box.
+}
+
+\DUadmonition[important]{
+\DUtitle[important]{Important}
+
+\begin{itemize}
+\item Wash behind your ears.
+
+\item Clean up your room.
+
+\item Call your mother.
+
+\item Back up your data.
+\end{itemize}
+}
+
+\DUadmonition[note]{
+\DUtitle[note]{Note}
+
+This is a note.
+}
+
+\DUadmonition[tip]{
+\DUtitle[tip]{Tip}
+
+15\% if the service is good.
+}
+
+\DUadmonition[warning]{
+\DUtitle[warning]{Warning}
+
+Strong prose may provoke extreme mental exertion.
+Reader discretion is strongly advised.
+}
+
+\DUadmonition[admonition-and-by-the-way]{
+\DUtitle[admonition-and-by-the-way]{And, by the way…}
+
+You can make up your own admonition too.
+}
+
+
+\subsubsection{2.14.4 Topics, Sidebars, and Rubrics%
+ \label{topics-sidebars-and-rubrics}%
+}
+
+\emph{Sidebars} are like miniature, parallel documents.
+
+\DUsidebar{
+\DUtitle[sidebar]{Sidebar Title}
+
+\DUsubtitle{Optional Subtitle}
+
+This is a sidebar. It is for text outside the flow of the main
+text.
+
+\DUrubric{This is a rubric inside a sidebar}
+
+Sidebars often appear beside the main text with a border and a different
+background or font color.
+}
+
+A \emph{topic} is like a block quote with a title, or a self-contained section
+with no subsections.
+
+\begin{DUclass}{topic}
+\begin{quote}
+\DUtitle[topic]{Topic Title}
+
+This is a topic.
+\end{quote}
+\end{DUclass}
+
+A \emph{rubric} is like an informal heading that doesn’t correspond to the
+document’s structure. It is typically highlighted in red (hence the name).
+
+\DUrubric{This is a rubric}
+
+Topics and rubrics can be used at places where a \hyperref[section-title]{section title} is not
+allowed (e.g. inside a directive).
+
+
+\subsubsection{2.14.5 Target Footnotes%
+ \label{target-footnotes}%
+}
+%
+\DUfootnotetext{footnote-6}{footnote-reference-10}{5}{%
+\url{http://www.python.org/}
+}
+%
+\DUfootnotetext{footnote-7}{footnote-reference-13}{6}{%
+\url{http://pygments.org/}
+}
+%
+\DUfootnotetext{footnote-8}{footnote-reference-14}{7}{%
+\url{ftp://ftp.ams.org/ams/doc/amsmath/short-math-guide.pdf}
+}
+%
+\DUfootnotetext{footnote-9}{footnote-reference-17}{8}{%
+\url{http://docutils.sourceforge.net/}
+}
+%
+\DUfootnotetext{footnote-10}{footnote-reference-18}{9}{%
+\url{A:DOS\\path\\}
+}
+
+
+\subsubsection{2.14.6 Replacement Text%
+ \label{replacement-text}%
+}
+
+I recommend you try \href{http://www.python.org/}{Python, \emph{the} best language around}\DUfootnotemark{footnote-reference-12}{footnote-6}{5}.
+
+
+\subsubsection{2.14.7 Compound Paragraph%
+ \label{compound-paragraph}%
+}
+
+The \emph{compound} directive is used to create a “compound paragraph”, which
+is a single logical paragraph containing multiple physical body
+elements. For example:
+
+\begin{DUclass}{compound}
+The ‘rm’ command is very dangerous. If you are logged
+in as root and enter
+\begin{quote}
+\begin{alltt}
+cd /
+rm -rf *
+\end{alltt}
+\end{quote}
+you will erase the entire contents of your file system.
+\end{DUclass}
+
+Test the handling and display of compound paragraphs:
+
+\begin{DUclass}{compound}
+\begin{DUclass}{some-class}
+Compound 2, paragraph 1,
+
+compound 2, paragraph 2,
+\begin{itemize}
+\item list item 1,
+
+\item list item 2,
+\end{itemize}
+compound 2, paragraph 3.
+\end{DUclass}
+\end{DUclass}
+
+\begin{DUclass}{compound}
+Compound 3, only consisting of one paragraph.
+\end{DUclass}
+
+\begin{DUclass}{compound}
+\begin{quote}
+\begin{alltt}
+Compound 4.
+This one starts with a literal block.
+\end{alltt}
+\end{quote}
+Compound 4, paragraph following the literal block.
+\end{DUclass}
+
+Now something \emph{really} perverted – a nested compound block. This is
+just to test that it works at all; the results don’t have to be
+meaningful.
+
+\begin{DUclass}{compound}
+Compound 5, block 1 (a paragraph).
+
+\begin{DUclass}{compound}
+Compound 6 is block 2 in compound 5.
+
+Compound 6, another paragraph.
+\end{DUclass}
+
+Compound 5, block 3 (a paragraph).
+\end{DUclass}
+
+\begin{DUclass}{compound}
+Compound 7, tests the inclusion of various block-level
+elements in one logical paragraph. First a table,
+
+\setlength{\DUtablewidth}{\linewidth}
+\begin{longtable*}[c]{|p{0.249\DUtablewidth}|p{0.249\DUtablewidth}|p{0.249\DUtablewidth}|}
+\hline
+
+Left cell, first
+paragraph.
+
+Left cell, second
+paragraph.
+ &
+Middle cell,
+consisting of
+exactly one
+paragraph.
+ &
+Right cell.
+
+Paragraph 2.
+
+Paragraph 3.
+ \\
+\hline
+\end{longtable*}
+followed by a paragraph. This physical paragraph is
+actually a continuation of the paragraph before the table. It is followed
+by
+\begin{quote}
+a quote and
+\end{quote}
+\begin{enumerate}
+\item an enumerated list,
+\end{enumerate}
+a paragraph,
+\begin{DUoptionlist}
+\item[-{}-an] option list,
+\end{DUoptionlist}
+a paragraph,
+\begin{DUfieldlist}
+\item[{a field:}]
+list,
+\end{DUfieldlist}
+a paragraph,
+\begin{description}
+\item[{a definition}] \leavevmode
+list,
+
+\end{description}
+a paragraph, an image:
+\includegraphics{../../../docs/user/rst/images/biohazard.png}
+a paragraph,
+\begin{DUlineblock}{0em}
+\item[] a line
+\item[] block,
+\end{DUlineblock}
+a paragraph followed by a comment,
+% this is a comment
+a paragraph, a
+
+\DUadmonition[note]{
+\DUtitle[note]{Note}
+
+with content
+}
+and the final paragraph of the compound 7.
+\end{DUclass}
+
+
+\subsubsection{2.14.8 Parsed Literal Blocks%
+ \label{parsed-literal-blocks}%
+}
+
+\begin{quote}
+\ttfamily\raggedright
+This~is~a~parsed~literal~block.\\
+~~~~This~line~is~indented.~~The~next~line~is~blank.\\
+~\\
+Inline~markup~is~supported,~e.g.~\emph{emphasis},~\textbf{strong},~\texttt{literal\\
+text},~\textsubscript{sub-}~and~\textsuperscript{super}scripts,\\
+inline~formulas:~$A = 2 \pi r^2$,\\
+footnotes\DUfootnotemark{footnote-reference-9}{footnote-1}{1},~%
+\phantomsection\label{hyperlink-targets}hyperlink~targets,~and~\href{http://www.python.org/}{references}.
+\end{quote}
+
+
+\subsubsection{2.14.9 Code%
+ \label{code}%
+}
+
+Blocks of source code can be set with the \DUroletitlereference{code} directive. If the code
+language is specified, the content is parsed and tagged by the \href{http://pygments.org/}{Pygments}\DUfootnotemark{footnote-reference-13}{footnote-7}{6}
+syntax highlighter and can be formatted with a style sheet. (Code parsing
+is turned off using the \texttt{syntax-highlight} config setting in the test
+conversions in order to get identical results with/without installed
+Pygments highlighter.)
+
+\begin{DUclass}{code}
+\begin{DUclass}{python}
+\begin{quote}
+\begin{alltt}
+print 'This is Python code.'
+\end{alltt}
+\end{quote}
+\end{DUclass}
+\end{DUclass}
+
+The \texttt{:number-lines:} option (with optional start value) generates line
+numbers:
+
+\begin{DUclass}{code}
+\begin{DUclass}{python}
+\begin{quote}
+\ttfamily\raggedright
+\DUrole{ln}{~8~}\#~print~integers~from~0~to~9:\\
+\DUrole{ln}{~9~}for~i~in~range(10):\\
+\DUrole{ln}{10~}~~~~print~i
+\end{quote}
+\end{DUclass}
+\end{DUclass}
+
+For inline code snippets, there is the \DUroletitlereference{code} role, which can be used
+directly (the code will not be parsed/tagged, as the language is not known)
+or as base for special code roles, e.g. the LaTeX code in the next
+paragraph.
+
+Docutils uses LaTeX syntax for math directives and roles:
+\texttt{\DUrole{code}{\DUrole{tex}{\textbackslash{}alpha = f(x)}}} prints $\alpha = f(x)$.
+
+The \texttt{:code:} option of the \DUroletitlereference{include} directive sets the included content
+as a code block, here the rst file \texttt{header\_footer.txt} with line numbers:
+
+\begin{DUclass}{code}
+\begin{DUclass}{rst}
+\begin{quote}
+\ttfamily\raggedright
+\DUrole{ln}{1~}..~header::~Document~header\\
+\DUrole{ln}{2~}..~footer::~Document~footer
+\end{quote}
+\end{DUclass}
+\end{DUclass}
+
+
+\subsection{2.15 Substitution Definitions%
+ \label{substitution-definitions}%
+}
+
+An inline image (\includegraphics{../../../docs/user/rst/images/biohazard.png}) example:
+
+A Unicode example:
+
+(Substitution definitions are not visible in the HTML source.)
+
+
+\subsection{2.16 Comments%
+ \label{comments}%
+}
+
+Here’s one:
+
+% Comments begin with two dots and a space. Anything may
+% follow, except for the syntax of footnotes, hyperlink
+% targets, directives, or substitution definitions.
+%
+% Double-dashes -- "--" -- must be escaped somehow in HTML output.
+%
+% Comments may contain non-ASCII characters: ä ö ü æ ø å
+
+(View the HTML source to see the comment.)
+
+
+\subsection{2.17 Raw text%
+ \label{raw-text}%
+}
+
+This does not necessarily look nice, because there may be missing white space.
+
+It’s just there to freeze the behavior.
+
+A test.
+
+Second test.
+
+\DUrole{myclass}{Another test with myclass set.}
+
+This is the \DUrole{myrawroleclass}{fourth test} with myrawroleclass set.
+
+Fifth test in LaTeX.\\Line two.
+
+
+\subsection{2.18 Container%
+ \label{container}%
+}
+
+\begin{DUclass}{custom}
+
+paragraph 1
+
+paragraph 2
+\end{DUclass}
+
+% currently not implemented in LaTeX:
+% .. include:: data/header_footer.txt
+
+
+\subsection{2.19 Colspanning tables%
+ \label{colspanning-tables}%
+}
+
+This table has a cell spanning two columns:
+
+\setlength{\DUtablewidth}{\linewidth}
+\begin{longtable*}[c]{|p{0.075\DUtablewidth}|p{0.075\DUtablewidth}|p{0.086\DUtablewidth}|}
+\hline
+\multicolumn{2}{|p{0.15\DUtablewidth}|}{\textbf{%
+Inputs
+}} & \textbf{%
+Output
+} \\
+\hline
+\textbf{%
+A
+} & \textbf{%
+B
+} & \textbf{%
+A or B
+} \\
+\hline
+\endfirsthead
+\hline
+\multicolumn{2}{|p{0.15\DUtablewidth}|}{\textbf{%
+Inputs
+}} & \textbf{%
+Output
+} \\
+\hline
+\textbf{%
+A
+} & \textbf{%
+B
+} & \textbf{%
+A or B
+} \\
+\hline
+\endhead
+\multicolumn{3}{c}{\hfill ... continued on next page} \\
+\endfoot
+\endlastfoot
+
+False
+ &
+False
+ &
+False
+ \\
+\hline
+
+True
+ &
+False
+ &
+True
+ \\
+\hline
+
+False
+ &
+True
+ &
+True
+ \\
+\hline
+
+True
+ &
+True
+ &
+True
+ \\
+\hline
+\end{longtable*}
+
+
+\subsection{2.20 Rowspanning tables%
+ \label{rowspanning-tables}%
+}
+
+Here’s a table with cells spanning several rows:
+
+\setlength{\DUtablewidth}{\linewidth}
+\begin{longtable*}[c]{|p{0.296\DUtablewidth}|p{0.156\DUtablewidth}|p{0.226\DUtablewidth}|}
+\hline
+\textbf{%
+Header row, column 1
+(header rows optional)
+} & \textbf{%
+Header 2
+} & \textbf{%
+Header 3
+} \\
+\hline
+\endfirsthead
+\hline
+\textbf{%
+Header row, column 1
+(header rows optional)
+} & \textbf{%
+Header 2
+} & \textbf{%
+Header 3
+} \\
+\hline
+\endhead
+\multicolumn{3}{c}{\hfill ... continued on next page} \\
+\endfoot
+\endlastfoot
+
+body row 1, column 1
+ &
+column 2
+ &
+column 3
+ \\
+\hline
+
+body row 2
+ & \multirow{2}{0.16\DUtablewidth}{%
+Cells may
+span rows.
+} & \multirow{2}{0.23\DUtablewidth}{%
+Another
+rowspanning
+cell.
+} \\
+\cline{1-1}
+
+body row 3
+ & & \\
+\hline
+\end{longtable*}
+
+
+\subsection{2.21 List Tables%
+ \label{list-tables}%
+}
+
+Here’s a list table exercising all features:
+
+\setlength{\DUtablewidth}{40em}
+\begin{longtable}[c]{|p{0.133\DUtablewidth}|p{0.249\DUtablewidth}|p{0.365\DUtablewidth}|}
+\caption{list table with integral header}\\
+\hline
+\textbf{%
+Treat
+} & \textbf{%
+Quantity
+} & \textbf{%
+Description
+} \\
+\hline
+\endfirsthead
+\caption[]{list table with integral header (... continued)}\\
+\hline
+\textbf{%
+Treat
+} & \textbf{%
+Quantity
+} & \textbf{%
+Description
+} \\
+\hline
+\endhead
+\multicolumn{3}{c}{\hfill ... continued on next page} \\
+\endfoot
+\endlastfoot
+\textbf{%
+Albatross
+} &
+2.99
+ &
+On a stick!
+ \\
+\hline
+\textbf{%
+Crunchy Frog
+} &
+1.49
+ &
+If we took the bones out, it wouldn’t be
+crunchy, now would it?
+ \\
+\hline
+\textbf{%
+Gannet Ripple
+} &
+1.99
+ &
+On a stick!
+ \\
+\hline
+\end{longtable}
+
+\begin{longtable}[c]{|l|l|}
+\caption{center aligned list table}\\
+\hline
+Albatross & 2.99 \\
+\hline
+Crunchy Frog & 1.49 \\
+\hline
+Gannet Ripple & 1.99 \\
+\hline
+\end{longtable}
+
+
+\subsection{2.22 Custom Roles%
+ \label{custom-roles}%
+}
+
+\begin{itemize}
+\item A role based on an existing role.
+
+\texttt{\DUrole{custom}{one}} \texttt{\DUrole{custom}{two}} \texttt{\DUrole{custom}{three}}
+
+\item A new role.
+
+\DUrole{customnew}{one two three}
+
+\item A role with class attribute.
+
+\DUrole{special}{interpreted text}
+
+\item A language-switching role:
+
+Let’s count in German \foreignlanguage{ngerman}{eins zwei drei}.
+
+\item A role with multiple class attributes, styled with raw directives:
+
+\newcommand{\DUrolegreen}[1]{\textcolor{green}{#1}}
+\newcommand{\DUrolesc}[1]{\textsc{#1}}
+
+The following works in most browsers but does not validate
+(\texttt{<style>} is only allowed in the document head):
+
+\begin{quote}
+\begin{alltt}
+.. raw:: html
+
+ <style type="text/css"><!-{}-
+ .green \{color: green;\}
+ .sc \{font-variant: small-caps;\}
+ -{}-></style>
+\end{alltt}
+\end{quote}
+
+\DUrole{green}{\DUrole{sc}{\foreignlanguage{british}{British colourful text in small-caps}}}.
+\end{itemize}
+
+
+\subsection{2.23 Mathematics%
+ \label{mathematics}%
+}
+
+Docutils supports inline math with the prefix or postfix \texttt{:math:}
+role specificator, $n! + \sin(x_n^2)$ and $A_\text{c} =
+\frac{\pi}{4} d^2$, as well as displayed math via the
+\DUroletitlereference{math} directive:
+%
+\begin{equation*}
+f(\epsilon) = \frac{1}{1 + \exp\left(\frac{\varepsilon}{k_\text{B}T}\right)}
+\end{equation*}
+Content may start on the first line of the directive, e.g.
+%
+\begin{equation*}
+N = \frac{\text{number of apples}}{7}
+\end{equation*}
+Equations can be labeled with a reference name using the \texttt{:name:} option.
+See \hyperref[eq-m]{eq:M} and \hyperref[eq-schrodinger]{eq:schrödinger} below.
+
+The determinant of the matrix
+%
+\begin{equation*}
+\mathbf{M} = \left(\begin{matrix}a&b\\c&d\end{matrix}\right)
+\phantomsection
+\label{eq-m}
+\end{equation*}
+is $|\mathbf{M}| = ad - bc$.
+
+More than one display math block can be put in one math directive.
+For example, the following sum and integral with limits:
+%
+\begin{equation*}
+\int_0^1 x^n dx = \frac{1}{n + 1}
+\end{equation*}%
+\begin{equation*}
+\sum_{n=1}^m n = \frac{m(m+1)}{2}
+\end{equation*}
+LaTeX-supported Unicode math symbols can be used in math roles and
+directives:
+
+The Schrödinger equation
+%
+\begin{equation*}
+i\hbar \frac{\partial }{\partial t}\Psi = \hat{H}\Psi ,
+\phantomsection
+\label{eq-schrodinger}
+\end{equation*}
+with the \emph{wave function} $\Psi $, describes how the quantum state of a
+physical system changes in time.
+
+\begin{description}
+\item[{Math-Accents:}] \leavevmode
+\setlength{\DUtablewidth}{\linewidth}
+\begin{longtable*}[c]{p{0.315\DUtablewidth}p{0.315\DUtablewidth}p{0.315\DUtablewidth}}
+
+$\acute{a}$ \texttt{\textbackslash{}acute\{a\}}
+ &
+$\dot{t}$ \texttt{\textbackslash{}dot\{t\}}
+ &
+$\hat{\gamma}$ \texttt{\textbackslash{}hat\{\textbackslash{}gamma\}}
+ \\
+
+$\grave{a}$ \texttt{\textbackslash{}grave\{a\}}
+ &
+$\ddot{t}$ \texttt{\textbackslash{}ddot\{t\}}
+ &
+$\tilde{\alpha}$ \texttt{\textbackslash{}tilde\{\textbackslash{}alpha\}}
+ \\
+
+$\breve{x}$ \texttt{\textbackslash{}breve\{x\}}
+ &
+$\dddot{t}$ \texttt{\textbackslash{}dddot\{t\}}
+ &
+$\vec{\imath}$ \texttt{\textbackslash{}vec\{\textbackslash{}imath\}}
+ \\
+
+$\check{a}$ \texttt{\textbackslash{}check\{a\}}
+ &
+$\bar{a}$ \texttt{\textbackslash{}bar\{a\}}
+ &
+$\vec{R}$ \texttt{\textbackslash{}vec\{R\}}
+ \\
+\end{longtable*}
+
+\end{description}
+
+% \widetilde{xxx}
+% \widehat{xxx}
+
+Modulation Transfer Function:
+%
+\begin{equation*}
+\text{MTF} = \left|\frac{\mathcal{F}\{s(x)\}}
+ {\mathcal{F}\{ s(x)\} |_{\omega _{x}=0}}\right|
+ = \mathrm{abs}\left(\frac
+ {\int _{-\infty }^{\infty }s(x) \mathrm{e}^{\mathrm{i}\omega _{x}x}\mathrm{d}{x}}
+ {\int _{-\infty }^{\infty }s(x)\mathrm{d}{x}}
+ \right).
+\end{equation*}
+Math split over two lines: If a double backslash is detected outside a
+\texttt{\textbackslash{}begin\{...\} \textbackslash{}end\{...\}} pair, the math code is wrapped in an \href{ftp://ftp.ams.org/ams/doc/amsmath/short-math-guide.pdf}{AMSmath}\DUfootnotemark{footnote-reference-14}{footnote-8}{7}
+\texttt{align} environment:
+%
+\begin{align*}
+s_{\mathrm{out}}(x) & = s_{\mathrm{in}}(x') * s_\delta (x-x') \\
+ & = \int s_{\mathrm{in}}(x')s_\delta (x-x')\mathrm{d}x'
+\end{align*}
+Cases (“manually”, with \texttt{matrix} environment):
+%
+\begin{equation*}
+\mathrm{sgn}(x) = \left\{\begin{matrix}
+ -1 & x<0\\
+ 1 & x>0
+ \end{matrix}\right.
+\end{equation*}
+Cases with the \href{ftp://ftp.ams.org/ams/doc/amsmath/short-math-guide.pdf}{AMSmath}\DUfootnotemark{footnote-reference-15}{footnote-8}{7} \texttt{cases} environment (not (yet) supported by
+HTML writers with \texttt{-{}-math-output=MathML}):
+%
+\begin{equation*}
+\mathrm{sgn}(x) = \begin{cases}
+ -1 & x<0\\
+ 1 & x>0
+ \end{cases}
+\end{equation*}
+
+\section{3 Tests for the LaTeX writer%
+ \label{tests-for-the-latex-writer}%
+}
+
+Test syntax elements which may cause trouble for the LaTeX writer but might
+not need to be tested with other writers (e.g. the HTML writer).
+
+
+\subsection{3.1 Custom Roles in LaTeX%
+ \label{custom-roles-in-latex}%
+}
+
+\begin{itemize}
+\item Role names and class arguments are converted to conform to the
+regular expression \texttt{{[}a-z{]}{[}-a-z0-9{]}*} (letters are downcased,
+accents and similar decoration is stripped, non-conforming
+characters are replaced by a hyphen).
+
+Class arguments may contain numbers and hyphens, which need special
+treatment in LaTeX command names.
+
+\DUrole{large}{\DUrole{custom4}{\DUrole{small-caps}{\DUrole{custom-role}{\DUrole{custom-role}{Text with role “custom4”}}}}} (but without styling by \texttt{DUrole*}
+macros).
+
+\item With LaTeX, roles can be styled within the document using the \DUroletitlereference{raw}
+directive.
+
+\newcommand{\DUrolelarge}[1]{{\large #1}}
+\makeatletter
+\@namedef{DUrolesmall-caps}{\textsc}
+\@namedef{DUrolecustom4}{\textbf}
+\makeatother
+
+\DUrole{large}{\DUrole{custom4}{\DUrole{small-caps}{\DUrole{custom-role}{\DUrole{custom-role}{inline text}}}}} in large, bold, small-caps.
+
+\item Custom roles can be based on standard roles:
+
+This is a \emph{\DUrole{custom-emphasis}{customized emphasis text role}}
+
+This is a \texttt{\DUrole{custom-literal}{customized literal text role}}
+
+This is a \textbf{\DUrole{custom-strong}{customized strong text role}}
+
+This is a \textsubscript{\DUrole{custom-subscript}{customized subscript text role}}
+
+This is a \textsuperscript{\DUrole{custom-superscript}{customized superscript text role}}
+
+This is a \DUroletitlereference{\DUrole{custom-title-reference}{customized title-reference text role}}
+\end{itemize}
+
+
+\subsection{3.2 class handling%
+ \label{class-handling}%
+}
+
+This section tests class handling for block level elements by the LaTeX
+writer. See the input file \texttt{classes\_latex.txt} for the raw LaTeX code used
+to style the examples.
+
+An “epigraph” directive is exported as “quote” wrapped in a “DUclass”
+environment. Here, it is styled by a “DUCLASSepigraph” environment
+redefining the “quote” environment as “minipage”:
+
+\newcommand*{\DUCLASSepigraph}{%
+ \renewenvironment{quote}{\vspace{1em}
+ \footnotesize\hfill{}%
+ \begin{minipage}{0.4\columnwidth}}%
+ {\end{minipage}\vskip\baselineskip}}
+
+\begin{DUclass}{epigraph}
+\begin{quote}
+Do not play this piece fast. It is never right to play \emph{Ragtime} fast.
+\nopagebreak
+
+\raggedleft —Scott Joplin
+\end{quote}
+\end{DUclass}
+
+Raw latex is also used to style the following lists: “DUCLASSenumerateitems”
+redefines “itemize” as “enumerate”, “DUCLASSrules” draws horizontal lines
+above and below.
+
+\newcommand*{\DUCLASSenumerateitems}{%
+ \renewenvironment{itemize}{\begin{enumerate}}%
+ {\end{enumerate}}%
+}
+
+\newenvironment{DUCLASSrules}%
+ {\noindent\rule[0.5ex]{1\columnwidth}{1pt}}%
+ {\noindent\rule[0.5ex]{1\columnwidth}{1pt}}
+
+An “enumerated” bullet list:
+
+\begin{DUclass}{enumerateitems}
+\begin{itemize}
+\item item
+
+\item next item
+
+\item third item
+\end{itemize}
+\end{DUclass}
+
+A list with lines above and below:
+
+\begin{DUclass}{rules}
+\begin{itemize}
+\item item
+
+\item next item
+\end{itemize}
+\end{DUclass}
+
+A normal bullet list is kept unchanged by the above redefinitions:
+
+\begin{itemize}
+\item item
+
+\item next item
+
+\item third item
+\end{itemize}
+
+A container wraps several elements in a common “class wrapper”. Here, we use
+it to set 2 paragraphs and a list in small caps:
+
+\newcommand*{\DUCLASSscshape}{\scshape}
+
+\begin{DUclass}{scshape}
+
+paragraph 1
+
+paragraph 2
+
+\begin{itemize}
+\item bullet list
+
+\item still bullet list
+\end{itemize}
+\end{DUclass}
+
+A right-aligned line-block. Alignment handling is built into the latex
+writer for image, table, and line block elements.
+
+\begin{DUlineblock}{0em}
+\raggedleft
+\item[] Max Mustermann
+\item[] Waldstr. 22
+\item[] D 01234 Testdorf
+\item[] Tel.: 0123/456789
+\end{DUlineblock}
+
+
+\subsection{3.3 More Tables%
+ \label{more-tables}%
+}
+
+A table with multi-paragraph multicolumn cells:
+
+\setlength{\DUtablewidth}{\linewidth}
+\begin{longtable*}[c]{|p{0.133\DUtablewidth}|p{0.179\DUtablewidth}|p{0.179\DUtablewidth}|p{0.110\DUtablewidth}|p{0.121\DUtablewidth}|p{0.145\DUtablewidth}|}
+\hline
+
+test
+ &
+\textbf{bold hd}
+ & \multicolumn{3}{p{0.41\DUtablewidth}|}{%
+multicolumn 1
+
+With a second paragraph
+} &
+\emph{emph hd}
+ \\
+\hline
+\multicolumn{2}{|p{0.31\DUtablewidth}|}{%
+multicolumn 2
+
+With a second paragraph
+} &
+cell
+ &
+cell
+ &
+cell
+ &
+cell
+ \\
+\hline
+
+cell
+ & \multicolumn{2}{p{0.36\DUtablewidth}|}{%
+multicolumn 3 (one line,
+but very very very very
+very looooong)
+} &
+cell
+ &
+cell
+ &
+cell
+ \\
+\hline
+
+cell
+ &
+cell
+ &
+cell
+ & \multicolumn{3}{p{0.38\DUtablewidth}|}{%
+Short multicolumn 4
+} \\
+\hline
+\end{longtable*}
+
+Tables with multi-paragraph multirow cells currently fail due to a LaTeX
+limitation (see \url{https://sourceforge.net/p/docutils/bugs/225/}).
+
+A table with multirow header and column-widths set by LaTeX:
+
+\begin{longtable*}[c]{|l|l|}
+\hline
+\multirow{2}{*}{\textbf{XXX}} & \textbf{Variable Summary} \\
+\cline{2-2}
+ & \textbf{Description} \\
+\hline
+\endfirsthead
+\hline
+\multirow{2}{*}{\textbf{XXX}} & \textbf{Variable Summary} \\
+\cline{2-2}
+ & \textbf{Description} \\
+\hline
+\endhead
+\multicolumn{2}{c}{\hfill ... continued on next page} \\
+\endfoot
+\endlastfoot
+\multicolumn{2}{|l|}{multicollumn cell} \\
+\hline
+\end{longtable*}
+
+In a table with column-widths set by LaTeX, each cell has just one line.
+Paragraphs are merged (a warning is given).
+
+\begin{longtable*}[c]{|l|l|}
+\hline
+11 & first paragraph
+second paragraph
+third paragraph \\
+\hline
+21 & 22 \\
+\hline
+\end{longtable*}
+
+% This file is used by the standalone_rst_latex test.
+
+
+\subsection{3.4 Option lists%
+ \label{option-lists-1}%
+}
+
+The LaTeX-2e description environment is used for definition lists.
+The definition is continued on the same line as the term, this should
+not happen if a option-list is at the top of the definition.
+
+If the option list is not at the first element in the definition, it
+is contained in a quote
+
+\begin{quote}
+\begin{DUoptionlist}
+\item[-{}-help] show help
+
+\item[-v] verbose
+\end{DUoptionlist}
+\end{quote}
+
+\begin{description}
+\item[{In a definition list:}] \leavevmode
+\begin{DUoptionlist}
+\item[-{}-help] show help
+
+\item[-v] verbose
+\end{DUoptionlist}
+
+\end{description}
+
+
+\subsection{3.5 Monospaced non-alphanumeric characters%
+ \label{monospaced-non-alphanumeric-characters}%
+}
+
+These are all ASCII characters except a-zA-Z0-9 and space:
+
+\texttt{!!!\textquotedbl{}\textquotedbl{}\textquotedbl{}\#\#\#\$\$\$\%\%\%\&\&\&'{}'{}'((()))***+++,{},{},-{}-{}-...///:::}
+
+\texttt{;;;<{}<{}<===>{}>{}>???@@@{[}{[}{[}\textbackslash{}\textbackslash{}\textbackslash{}{]}{]}{]}\textasciicircum{}\textasciicircum{}\textasciicircum{}\_\_\_`{}`{}`\{\{\{|||\}\}\}\textasciitilde{}\textasciitilde{}\textasciitilde{}}
+
+\texttt{xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx}
+
+The two lines of non-alphanumeric characters should both have the same
+width as the third line.
+
+
+\subsection{3.6 Non-ASCII characters%
+ \label{non-ascii-characters}%
+}
+
+Punctuation and footnote symbols
+
+\setlength{\DUtablewidth}{\linewidth}
+\begin{longtable*}[c]{|p{0.028\DUtablewidth}|p{0.424\DUtablewidth}|}
+\hline
+
+–
+ &
+en-dash
+ \\
+\hline
+
+—
+ &
+em-dash
+ \\
+\hline
+
+‘
+ &
+single turned comma quotation mark
+ \\
+\hline
+
+’
+ &
+single comma quotation mark
+ \\
+\hline
+
+‚
+ &
+low single comma quotation mark
+ \\
+\hline
+
+“
+ &
+double turned comma quotation mark
+ \\
+\hline
+
+”
+ &
+double comma quotation mark
+ \\
+\hline
+
+„
+ &
+low double comma quotation mark
+ \\
+\hline
+
+†
+ &
+dagger
+ \\
+\hline
+
+‡
+ &
+double dagger
+ \\
+\hline
+
+\ding{169}
+ &
+black diamond suit
+ \\
+\hline
+
+\ding{170}
+ &
+black heart suit
+ \\
+\hline
+
+♠
+ &
+black spade suit
+ \\
+\hline
+
+♣
+ &
+black club suit
+ \\
+\hline
+
+…
+ &
+ellipsis
+ \\
+\hline
+
+™
+ &
+trade mark sign
+ \\
+\hline
+
+⇔
+ &
+left-right double arrow
+ \\
+\hline
+\end{longtable*}
+
+The \DUroletitlereference{Latin-1 extended} Unicode block
+
+\setlength{\DUtablewidth}{\linewidth}
+\begin{longtable*}[c]{|p{0.051\DUtablewidth}|p{0.028\DUtablewidth}|p{0.028\DUtablewidth}|p{0.028\DUtablewidth}|p{0.028\DUtablewidth}|p{0.028\DUtablewidth}|p{0.028\DUtablewidth}|p{0.028\DUtablewidth}|p{0.028\DUtablewidth}|p{0.028\DUtablewidth}|p{0.028\DUtablewidth}|}
+\hline
+
+%
+ &
+0
+ &
+1
+ &
+2
+ &
+3
+ &
+4
+ &
+5
+ &
+6
+ &
+7
+ &
+8
+ &
+9
+ \\
+\hline
+
+160
+ & &
+¡
+ &
+¢
+ &
+£
+ & &
+¥
+ &
+¦
+ &
+§
+ &
+¨
+ &
+©
+ \\
+\hline
+
+170
+ &
+ª
+ &
+«
+ &
+¬
+ &
+\-
+ &
+®
+ &
+¯
+ &
+°
+ &
+±
+ &
+²
+ &
+³
+ \\
+\hline
+
+180
+ &
+´
+ &
+µ
+ &
+¶
+ &
+·
+ &
+¸
+ &
+¹
+ &
+º
+ &
+»
+ &
+¼
+ &
+½
+ \\
+\hline
+
+190
+ &
+¾
+ &
+¿
+ &
+À
+ &
+Á
+ &
+Â
+ &
+Ã
+ &
+Ä
+ &
+Å
+ &
+Æ
+ &
+Ç
+ \\
+\hline
+
+200
+ &
+È
+ &
+É
+ &
+Ê
+ &
+Ë
+ &
+Ì
+ &
+Í
+ &
+Î
+ &
+Ï
+ &
+Ð
+ &
+Ñ
+ \\
+\hline
+
+210
+ &
+Ò
+ &
+Ó
+ &
+Ô
+ &
+Õ
+ &
+Ö
+ &
+×
+ &
+Ø
+ &
+Ù
+ &
+Ú
+ &
+Û
+ \\
+\hline
+
+220
+ &
+Ü
+ &
+Ý
+ &
+Þ
+ &
+ß
+ &
+à
+ &
+á
+ &
+â
+ &
+ã
+ &
+ä
+ &
+å
+ \\
+\hline
+
+230
+ &
+æ
+ &
+ç
+ &
+è
+ &
+é
+ &
+ê
+ &
+ë
+ &
+ì
+ &
+í
+ &
+î
+ &
+ï
+ \\
+\hline
+
+240
+ &
+ð
+ &
+ñ
+ &
+ò
+ &
+ó
+ &
+ô
+ &
+õ
+ &
+ö
+ &
+÷
+ &
+ø
+ &
+ù
+ \\
+\hline
+
+250
+ &
+ú
+ &
+û
+ &
+ü
+ &
+ý
+ &
+þ
+ &
+ÿ
+ & & & & \\
+\hline
+\end{longtable*}
+
+\begin{itemize}
+\item The following line should not be wrapped, because it uses
+no-break spaces (\textbackslash{}u00a0):
+
+X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X
+
+\item Line wrapping with/without breakpoints marked by soft hyphens
+(\textbackslash{}u00ad):
+
+pdn\-derd\-mdtd\-ri\-schpdn\-derd\-mdtd\-ri\-schpdn\-derd\-mdtd\-ri\-schpdn\-derd\-mdtd\-ri\-schpdn\-derd\-mdtd\-ri\-sch
+
+pdnderdmdtdrischpdnderdmdtdrischpdnderdmdtdrischpdnderdmdtdrischpdnderdmdtdrisch
+\end{itemize}
+
+
+\subsection{3.7 Encoding special chars%
+ \label{encoding-special-chars}%
+}
+
+The LaTeX Info pages lists under “2.18 Special Characters”
+
+\begin{quote}
+The following characters play a special role in LaTeX and are called
+“special printing characters”, or simply “special characters”.
+
+\begin{quote}
+\# \$ \% \& \textasciitilde{} \_ \textasciicircum{} \textbackslash{} \{ \}
+\end{quote}
+\end{quote}
+
+The special chars verbatim:
+
+\begin{quote}
+\begin{alltt}
+# $ % & ~ _ ^ \textbackslash{} \{ \}
+\end{alltt}
+\end{quote}
+
+However also \emph{square brackets} {[}{]} need special care.
+
+\begin{quote}
+Commands with optional arguments (e.g. \texttt{\textbackslash{}item}) check
+if the token right after the macro name is an opening bracket.
+In that case the contents between that bracket and the following
+closing bracket on the same grouping level are taken as the
+optional argument. What makes this unintuitive is the fact that
+the square brackets aren’t grouping characters themselves, so in
+your last example \texttt{\textbackslash{}item{[}{[}...{]}{]}} the optional argument consists of
+{[}… (without the closing bracket).
+\end{quote}
+
+Compare the items in the following lists:
+
+\begin{itemize}
+\item simple item
+
+\item {[}bracketed{]} item
+\end{itemize}
+
+\begin{description}
+\item[{simple}] \leavevmode
+description term
+
+\item[{{[}bracketed{]}}] \leavevmode
+description term
+
+\end{description}
+
+The OT1 font-encoding has different characters for the less-than,
+greater-than and bar, < | >, except for typewriter font \DUroletitlereference{cmtt}:
+
+\begin{quote}
+\begin{alltt}
+< | >
+\end{alltt}
+\end{quote}
+
+
+\subsection{3.8 Hyperlinks and -targets%
+ \label{hyperlinks-and-targets}%
+}
+
+In LaTeX, we must set an explicit anchor (\texttt{\textbackslash{}phantomsection}) for a
+%
+\phantomsection\label{hypertarget-in-plain-text}hypertarget in plain text or in a figure but not in a longtable or
+caption:
+
+\setlength{\DUtablewidth}{\linewidth}
+\begin{longtable}[c]{|p{0.075\DUtablewidth}|p{0.075\DUtablewidth}|p{0.075\DUtablewidth}|}
+\caption{Table with %
+\label{hypertarget-in-table-title}hypertarget in table title.}\\
+\hline
+
+False
+ &
+True
+ &
+None
+ \\
+\hline
+\end{longtable}
+\label{table-label}
+
+\begin{figure}
+\phantomsection\label{figure-label}
+\noindent\makebox[\linewidth][c]{\includegraphics{../../../docs/user/rst/images/biohazard.png}}
+\caption{Figure with %
+\label{hypertarget-in-figure-caption}hypertarget in figure caption.}
+\begin{DUlegend}
+Legend with %
+\phantomsection\label{hypertarget-in-figure-legend}hypertarget in figure legend.
+\end{DUlegend}
+\end{figure}
+
+\includegraphics{../../../docs/user/rst/images/biohazard.png}
+\phantomsection\label{image-label}
+
+See \hyperref[hypertarget-in-plain-text]{hypertarget in plain text},
+\hyperref[table-label]{table label}, \hyperref[hypertarget-in-table-title]{hypertarget in table title},
+\hyperref[figure-label]{figure label}, \hyperref[hypertarget-in-figure-caption]{hypertarget in figure caption},
+\hyperref[hypertarget-in-figure-legend]{hypertarget in figure legend}, and
+\hyperref[image-label]{image label}.
+
+
+\subsection{3.9 External references%
+ \label{external-references}%
+}
+
+Long URLs should be wrapped in the PDF. This can be achieved with the
+\texttt{\textbackslash{}url} command which is used by the LaTeX writer whenever the content
+(name) of a reference node equals the link URL.
+
+\begin{description}
+\item[{Example:}] \leavevmode
+a long URL that should wrap in the output
+\url{http://docutils.sourceforge.net/docs/user/latex.html\#id79}
+
+\end{description}
+
+If the argument contains any “\%”, “\#”, or “\textasciicircum{}\textasciicircum{}”, or ends with \texttt{\textbackslash{}}, it can’t
+be used in the argument to another command. The argument must not contain
+unbalanced braces.
+
+The characters \textasciicircum{}, \{, \}, and \texttt{\textbackslash{}} are invalid in a “http:” or “ftp:” URL
+and not recognized as part of it:
+
+\begin{DUlineblock}{0em}
+\item[] \url{http://www.example.org}/strange\textasciicircum{}\textasciicircum{}name
+\item[] \url{http://www.example.org}\textbackslash{}using\textbackslash{}DOS\textbackslash{}paths\textbackslash{}
+\item[] \url{http://www.example.org/XML}/strange\{n\}ame
+\end{DUlineblock}
+
+They can, however be used in paths and/or filenames.
+
+Handling by the LaTeX writer:
+
+\begin{itemize}
+\item \texttt{\#}, \texttt{\textbackslash{}} and \texttt{\%} are escaped:
+
+\begin{DUlineblock}{0em}
+\item[] \href{http://www.w3.org/XML/Schema\#dev}{URL with \#}
+\url{http://www.w3.org/XML/Schema\#dev}
+\item[] \href{http://www.w3.org/XML/Schema\%dev}{URL with \%}
+\url{http://example.org/Schema\%dev}
+\item[] \href{A:DOS\\path\\}{file with DOS path}\DUfootnotemark{footnote-reference-18}{footnote-10}{9} \url{A:DOS\\path\\}\DUfootnotemark{footnote-reference-19}{footnote-10}{9}
+\end{DUlineblock}
+
+\DUadmonition[note]{
+\DUtitle[note]{Note}
+
+These URLs are typeset inside a LaTeX command without error.
+
+\begin{DUlineblock}{0em}
+\item[] \url{http://www.w3.org/XML/Schema\#dev}
+\item[] \url{http://example.org/Schema\%dev}
+\item[] \url{A:DOS\\path\\}\DUfootnotemark{footnote-reference-20}{footnote-10}{9}
+\end{DUlineblock}
+}
+\end{itemize}
+
+\begin{itemize}
+\item \texttt{\textasciicircum{}\textasciicircum{}} LaTeX’s special syntax for characters results in “strange” replacements
+(both with \texttt{\textbackslash{}href} and \texttt{\textbackslash{}url}). A warning is given.
+
+\href{../strange^^name}{file with \textasciicircum{}\textasciicircum{}}:
+\url{../strange^^name}
+
+\item Unbalanced braces, \{ or \}, will fail (both with \texttt{\textbackslash{}href} and \texttt{\textbackslash{}url}):
+
+\begin{quote}
+\begin{alltt}
+`file with \{ <../strange\{name>`__
+`<../strange\{name>`__
+\end{alltt}
+\end{quote}
+
+while balanced braces are suported:
+
+\begin{DUlineblock}{0em}
+\item[] \url{../strange{n}ame}
+\item[] \url{../st{r}ange{n}ame}
+\item[] \url{../{st{r}ange{n}ame}}
+\end{DUlineblock}
+\end{itemize}
+
+
+\subsection{3.10 Section titles with \hyperref[inline-markup]{inline markup}%
+ \label{section-titles-with-inline-markup}%
+}
+
+
+\subsubsection{3.10.1 \emph{emphasized}, H\textsubscript{2}O and $x^2$%
+ \label{emphasized-h2o-and-x-2}%
+}
+
+
+\subsubsection{3.10.2 Substitutions work%
+ \label{substitutions-fail}%
+}
+
+
+\subsection{3.11 Deeply nested sections%
+ \label{deeply-nested-sections}%
+}
+
+In LaTeX and HTML,
+
+
+\subsubsection{3.11.1 Level 3%
+ \label{level-3}%
+}
+
+nested sections
+
+
+\paragraph{3.11.1.1 level 4%
+ \label{level-4}%
+}
+
+reach at some level
+
+
+\subparagraph{3.11.1.1.1 level 5%
+ \label{level-5}%
+}
+
+(depending on the document class)
+
+
+\DUtitle[sectionVI]{3.11.1.1.1.1 level 6%
+ \label{level-6}%
+}
+
+an unsupported level.
+
+% unusual combinations (currently separately tested)
+% .. include:: data/latex_cornercases.txt
+
+% Preface for System Messages:
+
+
+\section{4 Error Handling%
+ \label{error-handling}%
+}
+
+Any errors caught during processing will generate system messages.
+
+There should be five messages in the following, auto-generated
+section, “Docutils System Messages”:
+
+% section should be added by Docutils automatically
+
+
+\section[Docutils System Messages]{\color{red}Docutils System Messages%
+}
+
+\DUadmonition[system-message]{
+\DUtitle[system-message]{system-message}
+\raisebox{1em}{\hypertarget{system-message-1}{}}
+
+{\color{red}ERROR/3} in \texttt{functional/input/data/standard.txt}, line~104
+
+\hyperlink{problematic-1}{
+Undefined substitution referenced: \textquotedbl{}problematic\textquotedbl{}.
+}}
+
+\DUadmonition[system-message]{
+\DUtitle[system-message]{system-message}
+\raisebox{1em}{\hypertarget{system-message-2}{}}
+
+{\color{red}ERROR/3} in \texttt{functional/input/data/standard.txt}, line~392
+
+\hyperlink{footnote-reference-8}{
+Unknown target name: \textquotedbl{}5\textquotedbl{}.
+}}
+
+\DUadmonition[system-message]{
+\DUtitle[system-message]{system-message}
+\raisebox{1em}{\hypertarget{system-message-3}{}}
+
+{\color{red}ERROR/3} in \texttt{functional/input/data/standard.txt}, line~401
+
+\hyperlink{citation-reference-3}{
+Unknown target name: \textquotedbl{}nonexistent\textquotedbl{}.
+}}
+
+\DUadmonition[system-message]{
+\DUtitle[system-message]{system-message}
+\raisebox{1em}{\hypertarget{system-message-4}{}}
+
+{\color{red}ERROR/3} in \texttt{functional/input/data/standard.txt}, line~428
+
+\hyperlink{problematic-2}{
+Unknown target name: \textquotedbl{}hyperlink reference without a target\textquotedbl{}.
+}}
+
+\DUadmonition[system-message]{
+\DUtitle[system-message]{system-message}
+\raisebox{1em}{\hypertarget{system-message-5}{}}
+
+{\color{red}ERROR/3} in \texttt{functional/input/data/standard.txt}, line~441
+
+\hyperlink{problematic-3}{
+Duplicate target name, cannot be used as a unique reference: \textquotedbl{}duplicate target names\textquotedbl{}.
+}}
+
+\end{document}
--- /dev/null
+.\" Man page generated from reStructuredText.
+.
+.TH RST2MAN 1 "2006-10-22" "0.1" "text processing"
+.SH NAME
+rst2man \- generate unix manpages from reStructured text
+.
+.nr rst2man-indent-level 0
+.
+.de1 rstReportMargin
+\\$1 \\n[an-margin]
+level \\n[rst2man-indent-level]
+level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
+-
+\\n[rst2man-indent0]
+\\n[rst2man-indent1]
+\\n[rst2man-indent2]
+..
+.de1 INDENT
+.\" .rstReportMargin pre:
+. RS \\$1
+. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin]
+. nr rst2man-indent-level +1
+.\" .rstReportMargin post:
+..
+.de UNINDENT
+. RE
+.\" indent \\n[an-margin]
+.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.nr rst2man-indent-level -1
+.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
+..
+.\" TODO: authors and author with name <email>
+.
+.SH SYNOPSIS
+.INDENT 0.0
+.INDENT 3.5
+rst2man.py inputfile outputfile
+.UNINDENT
+.UNINDENT
+.SH DESCRIPTION
+.sp
+rst2man transforms a reStructured text document into a unix man page.
+.sp
+In theory any valid reStructured text document should be processable,
+in reality this is
+.INDENT 0.0
+.IP \(bu 2
+a goal, that is not met yet
+.IP \(bu 2
+a goal that might never be met, because only few constructs are
+used in man pages \fIand\fP because the common text file does not adhere
+to man page requirements.
+.sp
+For example a unix man page belongs into a numbered section, 1 is
+user commands, 8 contains administrator commands and the headlines
+of all manpages are collected into a database, queryable with the
+programm \fBapropos\fP, therefore the headline should contain a short
+text describing into which group this command belongs.
+.sp
+These informations are collected from title, subtitle and the
+docinfo, see this document as an example.
+.UNINDENT
+.SH OPTIONS
+.INDENT 0.0
+.TP
+.BI \-\-config\fB= <file>
+Read configuration settings from <file>, if it exists.
+.TP
+.B \-\-version\fP,\fB \-V
+Show this program\(aqs version number and exit.
+.TP
+.B \-\-help\fP,\fB \-h
+Show this help message and exit.
+.UNINDENT
+.sp
+And a lot more standard docutils options.
+.SH FILES
+.sp
+None yet.
+.SH SEE ALSO
+.sp
+\fI\%docutils\fP
+\fI\%linux man page howto\fP
+.sp
+and \fBman man\fP also \fBman 7 man\fP
+.SH BUGS
+.INDENT 0.0
+.IP 1. 3
+Format options are included as they are required.
+.IP 2. 3
+bullet lists
+.IP 3. 3
+number lists
+.IP 4. 3
+math: The LaTeX source is shown, e.g. \fBn! + \esin(x_n^2)\fP\&.
+.UNINDENT
+.sp
+Discussion is still open.
+.SH AUTHOR
+grubert@users.sourceforge.net
+.SH COPYRIGHT
+public domain
+.\" Generated by docutils manpage writer.
+.
--- /dev/null
+<document ids="restructuredtext-test-document doctitle" names="restructuredtext\ test\ document doctitle" source="functional/input/standalone_rst_pseudoxml.txt" title="reStructuredText Test Document">
+ <title>
+ reStructuredText Test Document
+ <subtitle ids="examples-of-syntax-constructs subtitle" names="examples\ of\ syntax\ constructs subtitle">
+ Examples of Syntax Constructs
+ <decoration>
+ <header>
+ <paragraph>
+ Document header
+ <footer>
+ <paragraph>
+ Document footer
+ <docinfo>
+ <author>
+ David Goodger
+ <address xml:space="preserve">
+ 123 Example Street
+ Example, EX Canada
+ A1B 2C3
+ <contact>
+ <reference refuri="mailto:goodger@python.org">
+ goodger@python.org
+ <authors>
+ <author>
+ Me
+ <author>
+ Myself
+ <author>
+ I
+ <organization>
+ humankind
+ <date>
+ Now, or yesterday. Or maybe even
+ <emphasis>
+ before
+ yesterday.
+ <status>
+ This is a "work in progress"
+ <revision>
+ is managed by a version control system.
+ <version>
+ 1
+ <copyright>
+ This document has been placed in the public domain. You
+ may do with it as you wish. You may copy, modify,
+ redistribute, reattribute, sell, buy, rent, lease,
+ destroy, or improve it, quote it at length, excerpt,
+ incorporate, collate, fold, staple, or mutilate it, or do
+ anything else to it that your or anyone else's heart
+ desires.
+ <field classes="field-name">
+ <field_name>
+ field name
+ <field_body>
+ <paragraph>
+ This is a "generic bibliographic field".
+ <field classes="field-name-2">
+ <field_name>
+ field name "2"
+ <field_body>
+ <paragraph>
+ Generic bibliographic fields may contain multiple body elements.
+ <paragraph>
+ Like this.
+ <topic classes="dedication">
+ <title>
+ Dedication
+ <paragraph>
+ For Docutils users & co-developers.
+ <topic classes="abstract">
+ <title>
+ Abstract
+ <paragraph>
+ This is a test document, containing at least one example of each
+ reStructuredText construct.
+ <comment xml:space="preserve">
+ This is a comment. Note how any initial comments are moved by
+ transforms to after the document title, subtitle, and docinfo.
+ <target refid="doctitle">
+ <comment xml:space="preserve">
+ Above is the document title, and below is the subtitle.
+ They are transformed from section titles after parsing.
+ <target refid="subtitle">
+ <comment xml:space="preserve">
+ bibliographic fields (which also require a transform):
+ <meta content="reStructuredText, test, parser" name="keywords">
+ <meta content="A test document, containing at least one example of each reStructuredText construct." lang="en" name="description">
+ <raw format="latex" xml:space="preserve">
+ \pagebreak[4] % start ToC on new page
+ <topic classes="contents" ids="table-of-contents" names="table\ of\ contents">
+ <title>
+ Table of Contents
+ <bullet_list classes="auto-toc">
+ <list_item>
+ <paragraph>
+ <reference ids="toc-entry-1" refid="structural-elements">
+ <generated classes="sectnum">
+ 1
+ Structural Elements
+ <bullet_list classes="auto-toc">
+ <list_item>
+ <paragraph>
+ <reference ids="toc-entry-2" refid="section-title">
+ <generated classes="sectnum">
+ 1.1
+ Section Title
+ <list_item>
+ <paragraph>
+ <reference ids="toc-entry-3" refid="empty-section">
+ <generated classes="sectnum">
+ 1.2
+ Empty Section
+ <list_item>
+ <paragraph>
+ <reference ids="toc-entry-4" refid="transitions">
+ <generated classes="sectnum">
+ 1.3
+ Transitions
+ <list_item>
+ <paragraph>
+ <reference ids="toc-entry-5" refid="body-elements">
+ <generated classes="sectnum">
+ 2
+ Body Elements
+ <bullet_list classes="auto-toc">
+ <list_item>
+ <paragraph>
+ <reference ids="toc-entry-6" refid="paragraphs">
+ <generated classes="sectnum">
+ 2.1
+ Paragraphs
+ <bullet_list classes="auto-toc">
+ <list_item>
+ <paragraph>
+ <reference ids="toc-entry-7" refid="inline-markup">
+ <generated classes="sectnum">
+ 2.1.1
+ Inline Markup
+ <list_item>
+ <paragraph>
+ <reference ids="toc-entry-8" refid="bullet-lists">
+ <generated classes="sectnum">
+ 2.2
+ Bullet Lists
+ <list_item>
+ <paragraph>
+ <reference ids="toc-entry-9" refid="enumerated-lists">
+ <generated classes="sectnum">
+ 2.3
+ Enumerated Lists
+ <list_item>
+ <paragraph>
+ <reference ids="toc-entry-10" refid="definition-lists">
+ <generated classes="sectnum">
+ 2.4
+ Definition Lists
+ <list_item>
+ <paragraph>
+ <reference ids="toc-entry-11" refid="field-lists">
+ <generated classes="sectnum">
+ 2.5
+ Field Lists
+ <list_item>
+ <paragraph>
+ <reference ids="toc-entry-12" refid="option-lists">
+ <generated classes="sectnum">
+ 2.6
+ Option Lists
+ <list_item>
+ <paragraph>
+ <reference ids="toc-entry-13" refid="literal-blocks">
+ <generated classes="sectnum">
+ 2.7
+ Literal Blocks
+ <list_item>
+ <paragraph>
+ <reference ids="toc-entry-14" refid="line-blocks">
+ <generated classes="sectnum">
+ 2.8
+ Line Blocks
+ <list_item>
+ <paragraph>
+ <reference ids="toc-entry-15" refid="block-quotes">
+ <generated classes="sectnum">
+ 2.9
+ Block Quotes
+ <list_item>
+ <paragraph>
+ <reference ids="toc-entry-16" refid="doctest-blocks">
+ <generated classes="sectnum">
+ 2.10
+ Doctest Blocks
+ <list_item>
+ <paragraph>
+ <reference ids="toc-entry-17" refid="footnotes">
+ <generated classes="sectnum">
+ 2.11
+ Footnotes
+ <list_item>
+ <paragraph>
+ <reference ids="toc-entry-18" refid="citations">
+ <generated classes="sectnum">
+ 2.12
+ Citations
+ <list_item>
+ <paragraph>
+ <reference ids="toc-entry-19" refid="targets">
+ <generated classes="sectnum">
+ 2.13
+ Targets
+ <bullet_list classes="auto-toc">
+ <list_item>
+ <paragraph>
+ <reference ids="toc-entry-20" refid="duplicate-target-names">
+ <generated classes="sectnum">
+ 2.13.1
+ Duplicate Target Names
+ <list_item>
+ <paragraph>
+ <reference ids="toc-entry-21" refid="duplicate-target-names-1">
+ <generated classes="sectnum">
+ 2.13.2
+ Duplicate Target Names
+ <list_item>
+ <paragraph>
+ <reference ids="toc-entry-22" refid="directives">
+ <generated classes="sectnum">
+ 2.14
+ Directives
+ <bullet_list classes="auto-toc">
+ <list_item>
+ <paragraph>
+ <reference ids="toc-entry-23" refid="document-parts">
+ <generated classes="sectnum">
+ 2.14.1
+ Document Parts
+ <list_item>
+ <paragraph>
+ <reference ids="toc-entry-24" refid="images-and-figures">
+ <generated classes="sectnum">
+ 2.14.2
+ Images and Figures
+ <list_item>
+ <paragraph>
+ <reference ids="toc-entry-25" refid="admonitions">
+ <generated classes="sectnum">
+ 2.14.3
+ Admonitions
+ <list_item>
+ <paragraph>
+ <reference ids="toc-entry-26" refid="topics-sidebars-and-rubrics">
+ <generated classes="sectnum">
+ 2.14.4
+ Topics, Sidebars, and Rubrics
+ <list_item>
+ <paragraph>
+ <reference ids="toc-entry-27" refid="target-footnotes">
+ <generated classes="sectnum">
+ 2.14.5
+ Target Footnotes
+ <list_item>
+ <paragraph>
+ <reference ids="toc-entry-28" refid="replacement-text">
+ <generated classes="sectnum">
+ 2.14.6
+ Replacement Text
+ <list_item>
+ <paragraph>
+ <reference ids="toc-entry-29" refid="compound-paragraph">
+ <generated classes="sectnum">
+ 2.14.7
+ Compound Paragraph
+ <list_item>
+ <paragraph>
+ <reference ids="toc-entry-30" refid="parsed-literal-blocks">
+ <generated classes="sectnum">
+ 2.14.8
+ Parsed Literal Blocks
+ <list_item>
+ <paragraph>
+ <reference ids="toc-entry-31" refid="code">
+ <generated classes="sectnum">
+ 2.14.9
+ Code
+ <list_item>
+ <paragraph>
+ <reference ids="toc-entry-32" refid="substitution-definitions">
+ <generated classes="sectnum">
+ 2.15
+ Substitution Definitions
+ <list_item>
+ <paragraph>
+ <reference ids="toc-entry-33" refid="comments">
+ <generated classes="sectnum">
+ 2.16
+ Comments
+ <list_item>
+ <paragraph>
+ <reference ids="toc-entry-34" refid="raw-text">
+ <generated classes="sectnum">
+ 2.17
+ Raw text
+ <list_item>
+ <paragraph>
+ <reference ids="toc-entry-35" refid="container">
+ <generated classes="sectnum">
+ 2.18
+ Container
+ <list_item>
+ <paragraph>
+ <reference ids="toc-entry-36" refid="colspanning-tables">
+ <generated classes="sectnum">
+ 2.19
+ Colspanning tables
+ <list_item>
+ <paragraph>
+ <reference ids="toc-entry-37" refid="rowspanning-tables">
+ <generated classes="sectnum">
+ 2.20
+ Rowspanning tables
+ <list_item>
+ <paragraph>
+ <reference ids="toc-entry-38" refid="complex-tables">
+ <generated classes="sectnum">
+ 2.21
+ Complex tables
+ <list_item>
+ <paragraph>
+ <reference ids="toc-entry-39" refid="list-tables">
+ <generated classes="sectnum">
+ 2.22
+ List Tables
+ <list_item>
+ <paragraph>
+ <reference ids="toc-entry-40" refid="error-handling">
+ <generated classes="sectnum">
+ 3
+ Error Handling
+ <section ids="structural-elements" names="structural\ elements">
+ <title auto="1" refid="toc-entry-1">
+ <generated classes="sectnum">
+ 1
+ Structural Elements
+ <section ids="section-title" names="section\ title">
+ <title auto="1" refid="toc-entry-2">
+ <generated classes="sectnum">
+ 1.1
+ Section Title
+ <subtitle ids="section-subtitle" names="section\ subtitle">
+ Section Subtitle
+ <paragraph>
+ Lone subsections are converted to a section subtitle by a transform
+ activated with the
+ <literal>
+ --section-subtitles
+ command line option or the
+ <literal>
+ sectsubtitle-xform
+ configuration value.
+ <section ids="empty-section" names="empty\ section">
+ <title auto="1" refid="toc-entry-3">
+ <generated classes="sectnum">
+ 1.2
+ Empty Section
+ <section ids="transitions" names="transitions">
+ <title auto="1" refid="toc-entry-4">
+ <generated classes="sectnum">
+ 1.3
+ Transitions
+ <paragraph>
+ Here's a transition:
+ <transition>
+ <paragraph>
+ It divides the section. Transitions may also occur between sections:
+ <transition>
+ <section ids="body-elements" names="body\ elements">
+ <title auto="1" refid="toc-entry-5">
+ <generated classes="sectnum">
+ 2
+ Body Elements
+ <section ids="paragraphs" names="paragraphs">
+ <title auto="1" refid="toc-entry-6">
+ <generated classes="sectnum">
+ 2.1
+ Paragraphs
+ <paragraph>
+ A paragraph.
+ <section ids="inline-markup" names="inline\ markup">
+ <title auto="1" refid="toc-entry-7">
+ <generated classes="sectnum">
+ 2.1.1
+ Inline Markup
+ <paragraph>
+ Paragraphs contain text and may contain inline markup:
+ <emphasis>
+ emphasis
+ ,
+ <strong>
+ strong emphasis
+ ,
+ <literal>
+ inline literals
+ , standalone hyperlinks
+ (
+ <reference refuri="http://www.python.org">
+ http://www.python.org
+ ), external hyperlinks (
+ <reference name="Python" refuri="http://www.python.org/">
+ Python
+
+ <footnote_reference auto="1" ids="footnote-reference-10" refid="footnote-6">
+ 5
+ ), internal
+ cross-references (
+ <reference name="example" refid="example">
+ example
+ ), external hyperlinks with embedded URIs
+ (
+ <reference name="Python web site" refuri="http://www.python.org">
+ Python web site
+ ),
+ <reference anonymous="1" name="anonymous hyperlink references" refuri="http://www.python.org/">
+ anonymous hyperlink
+ references
+
+ <footnote_reference auto="1" ids="footnote-reference-14" refid="footnote-6">
+ 5
+ (
+ <reference anonymous="1" name="a second reference" refuri="http://docutils.sourceforge.net/">
+ a second reference
+
+ <footnote_reference auto="1" ids="footnote-reference-15" refid="footnote-8">
+ 7
+ ), footnote references (manually
+ numbered
+ <footnote_reference ids="footnote-reference-1" refid="footnote-1">
+ 1
+ , anonymous auto-numbered
+ <footnote_reference auto="1" ids="footnote-reference-2" refid="footnote-2">
+ 3
+ , labeled auto-numbered
+ <footnote_reference auto="1" ids="footnote-reference-3" refid="label">
+ 2
+ , or symbolic
+ <footnote_reference auto="*" ids="footnote-reference-4" refid="footnote-3">
+ *
+ ), citation references (
+ <citation_reference ids="citation-reference-1" refid="cit2002">
+ CIT2002
+ ),
+ substitution references (
+ <image alt="EXAMPLE" uri="../../../docs/user/rst/images/biohazard.png">
+ &
+ a
+ <emphasis>
+ trimmed heart
+
+ <literal>
+ (U+2665):
+ ♥
+ ), and
+ <target ids="inline-hyperlink-targets" names="inline\ hyperlink\ targets">
+ inline hyperlink targets
+
+ (see
+ <reference name="Targets" refid="targets">
+ Targets
+ below for a reference back to here). Character-level
+ inline markup is also possible (although exceedingly ugly!) in
+ <emphasis>
+ re
+ <literal>
+ Structured
+ <emphasis>
+ Text
+ . Problems are indicated by
+ <problematic ids="problematic-1" refid="system-message-1">
+ |problematic|
+ text
+ (generated by processing errors; this one is intentional). Here is a
+ reference to the
+ <reference name="doctitle" refid="doctitle">
+ doctitle
+ and the
+ <reference name="subtitle" refid="subtitle">
+ subtitle
+ .
+ <target anonymous="1" ids="target-1" refuri="http://www.python.org/">
+ <target anonymous="1" ids="target-2" refuri="http://docutils.sourceforge.net/">
+ <paragraph>
+ The default role for interpreted text is
+ <title_reference>
+ Title Reference
+ . Here are
+ some explicit interpreted text roles: a PEP reference (
+ <reference refuri="http://www.python.org/dev/peps/pep-0287">
+ PEP 287
+ ); an
+ RFC reference (
+ <reference refuri="http://tools.ietf.org/html/rfc2822.html">
+ RFC 2822
+ ); an abbreviation (
+ <abbreviation>
+ abb.
+ ), an acronym
+ (
+ <acronym>
+ reST
+ ), code (
+ <literal classes="code">
+ print "hello world"
+ ); a
+ <subscript>
+ subscript
+ ;
+ a
+ <superscript>
+ superscript
+ and explicit roles for
+ <title_reference>
+ Docutils
+ '
+ <emphasis>
+ standard
+
+ <strong>
+ inline
+
+ <literal>
+ markup
+ .
+ <comment xml:space="preserve">
+ DO NOT RE-WRAP THE FOLLOWING PARAGRAPH!
+ <paragraph>
+ Let's test wrapping and whitespace significance in inline literals:
+ <literal>
+ This is an example of --inline-literal --text, --including some--
+ strangely--hyphenated-words. Adjust-the-width-of-your-browser-window
+ to see how the text is wrapped. -- ---- -------- Now note the
+ spacing between the words of this sentence (words
+ should be grouped in pairs).
+ <paragraph>
+ If the
+ <literal>
+ --pep-references
+ option was supplied, there should be a
+ live link to PEP 258 here.
+ <section ids="bullet-lists" names="bullet\ lists">
+ <title auto="1" refid="toc-entry-8">
+ <generated classes="sectnum">
+ 2.2
+ Bullet Lists
+ <bullet_list bullet="-">
+ <list_item>
+ <paragraph>
+ A bullet list
+ <bullet_list bullet="+">
+ <list_item>
+ <paragraph>
+ Nested bullet list.
+ <list_item>
+ <paragraph>
+ Nested item 2.
+ <list_item>
+ <paragraph>
+ Item 2.
+ <paragraph>
+ Paragraph 2 of item 2.
+ <bullet_list bullet="*">
+ <list_item>
+ <paragraph>
+ Nested bullet list.
+ <list_item>
+ <paragraph>
+ Nested item 2.
+ <bullet_list bullet="-">
+ <list_item>
+ <paragraph>
+ Third level.
+ <list_item>
+ <paragraph>
+ Item 2.
+ <list_item>
+ <paragraph>
+ Nested item 3.
+ <list_item>
+ <paragraph>
+ This nested list should be compacted by the HTML writer.
+ <target ids="target" names="target">
+ <comment xml:space="preserve">
+ Even if this item contains a target and a comment.
+ <section ids="enumerated-lists" names="enumerated\ lists">
+ <title auto="1" refid="toc-entry-9">
+ <generated classes="sectnum">
+ 2.3
+ Enumerated Lists
+ <enumerated_list enumtype="arabic" prefix="" suffix=".">
+ <list_item>
+ <paragraph>
+ Arabic numerals.
+ <enumerated_list enumtype="loweralpha" prefix="" suffix=")">
+ <list_item>
+ <paragraph>
+ lower alpha)
+ <enumerated_list enumtype="lowerroman" prefix="(" suffix=")">
+ <list_item>
+ <paragraph>
+ (lower roman)
+ <enumerated_list enumtype="upperalpha" prefix="" suffix=".">
+ <list_item>
+ <paragraph>
+ upper alpha.
+ <enumerated_list enumtype="upperroman" prefix="" suffix=")">
+ <list_item>
+ <paragraph>
+ upper roman)
+ <list_item>
+ <paragraph>
+ Lists that don't start at 1:
+ <enumerated_list enumtype="arabic" prefix="" start="3" suffix=".">
+ <list_item>
+ <paragraph>
+ Three
+ <list_item>
+ <paragraph>
+ Four
+ <system_message level="1" line="8" source="functional/input/data/standard.txt" type="INFO">
+ <paragraph>
+ Enumerated list start value not ordinal-1: "3" (ordinal 3)
+ <enumerated_list enumtype="upperalpha" prefix="" start="3" suffix=".">
+ <list_item>
+ <paragraph>
+ C
+ <list_item>
+ <paragraph>
+ D
+ <system_message level="1" line="8" source="functional/input/data/standard.txt" type="INFO">
+ <paragraph>
+ Enumerated list start value not ordinal-1: "C" (ordinal 3)
+ <enumerated_list enumtype="lowerroman" prefix="" start="3" suffix=".">
+ <list_item>
+ <paragraph>
+ iii
+ <list_item>
+ <paragraph>
+ iv
+ <system_message level="1" line="8" source="functional/input/data/standard.txt" type="INFO">
+ <paragraph>
+ Enumerated list start value not ordinal-1: "iii" (ordinal 3)
+ <section ids="definition-lists" names="definition\ lists">
+ <title auto="1" refid="toc-entry-10">
+ <generated classes="sectnum">
+ 2.4
+ Definition Lists
+ <definition_list>
+ <definition_list_item>
+ <term>
+ Term
+ <definition>
+ <paragraph>
+ Definition
+ <definition_list_item>
+ <term>
+ Term
+ <classifier>
+ classifier
+ <definition>
+ <paragraph>
+ Definition paragraph 1.
+ <paragraph>
+ Definition paragraph 2.
+ <definition_list_item>
+ <term>
+ Term
+ <definition>
+ <paragraph>
+ Definition
+ <definition_list_item>
+ <term>
+ Term
+ <classifier>
+ classifier one
+ <classifier>
+ classifier two
+ <definition>
+ <paragraph>
+ Definition
+ <section ids="field-lists" names="field\ lists">
+ <title auto="1" refid="toc-entry-11">
+ <generated classes="sectnum">
+ 2.5
+ Field Lists
+ <field_list>
+ <field>
+ <field_name>
+ what
+ <field_body>
+ <paragraph>
+ Field lists map field names to field bodies, like database
+ records. They are often part of an extension syntax. They are
+ an unambiguous variant of RFC 2822 fields.
+ <field>
+ <field_name>
+ how arg1 arg2
+ <field_body>
+ <paragraph>
+ The field marker is a colon, the field name, and a colon.
+ <paragraph>
+ The field body may contain one or more body elements, indented
+ relative to the field marker.
+ <field>
+ <field_name>
+ credits
+ <field_body>
+ <paragraph classes="credits">
+ This paragraph has the
+ <title_reference>
+ credits
+ class set. (This is actually not
+ about credits but just for ensuring that the class attribute
+ doesn't get stripped away.)
+ <section ids="option-lists" names="option\ lists">
+ <title auto="1" refid="toc-entry-12">
+ <generated classes="sectnum">
+ 2.6
+ Option Lists
+ <paragraph>
+ For listing command-line options:
+ <option_list>
+ <option_list_item>
+ <option_group>
+ <option>
+ <option_string>
+ -a
+ <description>
+ <paragraph>
+ command-line option "a"
+ <option_list_item>
+ <option_group>
+ <option>
+ <option_string>
+ -b
+ <option_argument delimiter=" ">
+ file
+ <description>
+ <paragraph>
+ options can have arguments
+ and long descriptions
+ <option_list_item>
+ <option_group>
+ <option>
+ <option_string>
+ --long
+ <description>
+ <paragraph>
+ options can be long also
+ <option_list_item>
+ <option_group>
+ <option>
+ <option_string>
+ --input
+ <option_argument delimiter="=">
+ file
+ <description>
+ <paragraph>
+ long options can also have
+ arguments
+ <option_list_item>
+ <option_group>
+ <option>
+ <option_string>
+ --very-long-option
+ <description>
+ <paragraph>
+ The description can also start on the next line.
+ <paragraph>
+ The description may contain multiple body elements,
+ regardless of where it starts.
+ <option_list_item>
+ <option_group>
+ <option>
+ <option_string>
+ -x
+ <option>
+ <option_string>
+ -y
+ <option>
+ <option_string>
+ -z
+ <description>
+ <paragraph>
+ Multiple options are an "option group".
+ <option_list_item>
+ <option_group>
+ <option>
+ <option_string>
+ -v
+ <option>
+ <option_string>
+ --verbose
+ <description>
+ <paragraph>
+ Commonly-seen: short & long options.
+ <option_list_item>
+ <option_group>
+ <option>
+ <option_string>
+ -1
+ <option_argument delimiter=" ">
+ file
+ <option>
+ <option_string>
+ --one
+ <option_argument delimiter="=">
+ file
+ <option>
+ <option_string>
+ --two
+ <option_argument delimiter=" ">
+ file
+ <description>
+ <paragraph>
+ Multiple options with arguments.
+ <option_list_item>
+ <option_group>
+ <option>
+ <option_string>
+ /V
+ <description>
+ <paragraph>
+ DOS/VMS-style options too
+ <paragraph>
+ There must be at least two spaces between the option and the
+ description.
+ <section ids="literal-blocks" names="literal\ blocks">
+ <title auto="1" refid="toc-entry-13">
+ <generated classes="sectnum">
+ 2.7
+ Literal Blocks
+ <paragraph>
+ Literal blocks are indicated with a double-colon ("::") at the end of
+ the preceding paragraph (over there
+ <literal>
+ -->
+ ). They can be indented:
+ <literal_block xml:space="preserve">
+ if literal_block:
+ text = 'is left as-is'
+ spaces_and_linebreaks = 'are preserved'
+ markup_processing = None
+ <paragraph>
+ Or they can be quoted without indentation:
+ <literal_block xml:space="preserve">
+ >> Great idea!
+ >
+ > Why didn't I think of that?
+ <section ids="line-blocks" names="line\ blocks">
+ <title auto="1" refid="toc-entry-14">
+ <generated classes="sectnum">
+ 2.8
+ Line Blocks
+ <paragraph>
+ This section tests line blocks. Line blocks are body elements which
+ consist of lines and other line blocks. Nested line blocks cause
+ indentation.
+ <line_block>
+ <line>
+ This is a line block. It ends with a blank line.
+ <line_block>
+ <line>
+ New lines begin with a vertical bar ("|").
+ <line>
+ Line breaks and initial indent are significant, and preserved.
+ <line_block>
+ <line>
+ Continuation lines are also possible. A long line that is intended
+ to wrap should begin with a space in place of the vertical bar.
+ <line>
+ The left edge of a continuation line need not be aligned with
+ the left edge of the text above it.
+ <line_block>
+ <line>
+ This is a second line block.
+ <line>
+ <line>
+ Blank lines are permitted internally, but they must begin with a "|".
+ <paragraph>
+ Another line block, surrounded by paragraphs:
+ <line_block>
+ <line>
+ And it's no good waiting by the window
+ <line>
+ It's no good waiting for the sun
+ <line>
+ Please believe me, the things you dream of
+ <line>
+ They don't fall in the lap of no-one
+ <paragraph>
+ Take it away, Eric the Orchestra Leader!
+ <block_quote>
+ <line_block>
+ <line>
+ A one, two, a one two three four
+ <line>
+ <line>
+ Half a bee, philosophically,
+ <line_block>
+ <line>
+ must,
+ <emphasis>
+ ipso facto
+ , half not be.
+ <line>
+ But half the bee has got to be,
+ <line_block>
+ <line>
+ <emphasis>
+ vis a vis
+ its entity. D'you see?
+ <line>
+ <line>
+ But can a bee be said to be
+ <line_block>
+ <line>
+ or not to be an entire bee,
+ <line_block>
+ <line>
+ when half the bee is not a bee,
+ <line_block>
+ <line>
+ due to some ancient injury?
+ <line>
+ <line>
+ Singing...
+ <paragraph>
+ A line block, like the following poem by Christian Morgenstern, can
+ also be centre-aligned:
+ <line_block classes="language-de align-center">
+ <line>
+ <strong>
+ Die Trichter
+ <line>
+ <line>
+ Zwei Trichter wandeln durch die Nacht.
+ <line>
+ Durch ihres Rumpfs verengten Schacht
+ <line>
+ fließt weißes Mondlicht
+ <line>
+ still und heiter
+ <line>
+ auf ihren
+ <line>
+ Waldweg
+ <line>
+ u. s.
+ <line>
+ w.
+ <line>
+ <section ids="block-quotes" names="block\ quotes">
+ <title auto="1" refid="toc-entry-15">
+ <generated classes="sectnum">
+ 2.9
+ Block Quotes
+ <paragraph>
+ Block quotes consist of indented body elements:
+ <block_quote>
+ <paragraph>
+ My theory by A. Elk. Brackets Miss, brackets. This theory goes
+ as follows and begins now. All brontosauruses are thin at one
+ end, much much thicker in the middle and then thin again at the
+ far end. That is my theory, it is mine, and belongs to me and I
+ own it, and what it is too.
+ <attribution>
+ Anne Elk (Miss)
+ <paragraph>
+ The language of a quote (like any other object) can be specified by
+ a class attribute:
+ <comment xml:space="preserve">
+ <block_quote classes="language-fr">
+ <paragraph>
+ ReStructuredText est un langage de balisage léger utilisé
+ notamment dans la documentation du langage Python.
+ <section ids="doctest-blocks" names="doctest\ blocks">
+ <title auto="1" refid="toc-entry-16">
+ <generated classes="sectnum">
+ 2.10
+ Doctest Blocks
+ <doctest_block xml:space="preserve">
+ >>> print 'Python-specific usage examples; begun with ">>>"'
+ Python-specific usage examples; begun with ">>>"
+ >>> print '(cut and pasted from interactive Python sessions)'
+ (cut and pasted from interactive Python sessions)
+ <section ids="footnotes" names="footnotes">
+ <title auto="1" refid="toc-entry-17">
+ <generated classes="sectnum">
+ 2.11
+ Footnotes
+ <footnote backrefs="footnote-reference-1 footnote-reference-5 footnote-reference-9" ids="footnote-1" names="1">
+ <label>
+ 1
+ <paragraph>
+ A footnote contains body elements, consistently indented by at
+ least 3 spaces.
+ <paragraph>
+ This is the footnote's second paragraph.
+ <footnote auto="1" backrefs="footnote-reference-3 footnote-reference-6" ids="label" names="label">
+ <label>
+ 2
+ <paragraph>
+ Footnotes may be numbered, either manually (as in
+ <footnote_reference ids="footnote-reference-5" refid="footnote-1">
+ 1
+ ) or
+ automatically using a "#"-prefixed label. This footnote has a
+ label so it can be referred to from multiple places, both as a
+ footnote reference (
+ <footnote_reference auto="1" ids="footnote-reference-6" refid="label">
+ 2
+ ) and as a
+ <reference anonymous="1" name="hyperlink reference" refid="label">
+ hyperlink reference
+ .
+ <target anonymous="1" ids="target-3" refid="label">
+ <footnote auto="1" backrefs="footnote-reference-2" ids="footnote-2" names="3">
+ <label>
+ 3
+ <paragraph>
+ This footnote is numbered automatically and anonymously using a
+ label of "#" only.
+ <paragraph>
+ This is the second paragraph.
+ <paragraph>
+ And this is the third paragraph.
+ <footnote auto="*" backrefs="footnote-reference-4" ids="footnote-3">
+ <label>
+ *
+ <paragraph>
+ Footnotes may also use symbols, specified with a "*" label.
+ Here's a reference to the next footnote:
+ <footnote_reference auto="*" ids="footnote-reference-7" refid="footnote-4">
+ †
+ .
+ <footnote auto="*" backrefs="footnote-reference-7" ids="footnote-4">
+ <label>
+ †
+ <paragraph>
+ This footnote shows the next symbol in the sequence.
+ <footnote ids="footnote-5" names="4">
+ <label>
+ 4
+ <paragraph>
+ Here's an unreferenced footnote, with a reference to a
+ nonexistent footnote:
+ <problematic ids="footnote-reference-8" refid="system-message-2">
+ [5]_
+ .
+ <section ids="citations" names="citations">
+ <title auto="1" refid="toc-entry-18">
+ <generated classes="sectnum">
+ 2.12
+ Citations
+ <citation backrefs="citation-reference-1 citation-reference-2" ids="cit2002" names="cit2002">
+ <label>
+ CIT2002
+ <paragraph>
+ Citations are text-labeled footnotes. They may be
+ rendered separately and differently from footnotes.
+ <paragraph>
+ Here's a reference to the above,
+ <citation_reference ids="citation-reference-2" refid="cit2002">
+ CIT2002
+ , and a
+ <problematic ids="citation-reference-3" refid="system-message-3">
+ [nonexistent]_
+
+ citation.
+ <target refid="another-target">
+ <section ids="targets another-target" names="targets another\ target">
+ <title auto="1" refid="toc-entry-19">
+ <generated classes="sectnum">
+ 2.13
+ Targets
+ <target refid="example">
+ <paragraph ids="example" names="example">
+ This paragraph is pointed to by the explicit "example" target. A
+ reference can be found under
+ <reference name="Inline Markup" refid="inline-markup">
+ Inline Markup
+ , above.
+ <reference name="Inline hyperlink targets" refid="inline-hyperlink-targets">
+ Inline
+ hyperlink targets
+ are also possible.
+ <paragraph>
+ Section headers are implicit targets, referred to by name. See
+ <reference name="Targets" refid="targets">
+ Targets
+ , which is a subsection of
+ <reference name="Body Elements" refid="body-elements">
+ Body Elements
+ .
+ <paragraph>
+ Explicit external targets are interpolated into references such as
+ "
+ <reference name="Python" refuri="http://www.python.org/">
+ Python
+
+ <footnote_reference auto="1" ids="footnote-reference-11" refid="footnote-6">
+ 5
+ ".
+ <target ids="python" names="python" refuri="http://www.python.org/">
+ <paragraph>
+ Targets may be indirect and anonymous. Thus
+ <reference anonymous="1" name="this phrase" refid="targets">
+ this phrase
+ may also
+ refer to the
+ <reference name="Targets" refid="targets">
+ Targets
+ section.
+ <target anonymous="1" ids="target-4" refid="targets">
+ <paragraph>
+ Here's a
+ <problematic ids="problematic-2" refid="system-message-4">
+ `hyperlink reference without a target`_
+ , which generates an
+ error.
+ <section dupnames="duplicate\ target\ names" ids="duplicate-target-names">
+ <title auto="1" refid="toc-entry-20">
+ <generated classes="sectnum">
+ 2.13.1
+ Duplicate Target Names
+ <paragraph>
+ Duplicate names in section headers or other implicit targets will
+ generate "info" (level-1) system messages. Duplicate names in
+ explicit targets will generate "warning" (level-2) system messages.
+ <section dupnames="duplicate\ target\ names" ids="duplicate-target-names-1">
+ <title auto="1" refid="toc-entry-21">
+ <generated classes="sectnum">
+ 2.13.2
+ Duplicate Target Names
+ <system_message backrefs="duplicate-target-names-1" level="1" line="439" source="functional/input/data/standard.txt" type="INFO">
+ <paragraph>
+ Duplicate implicit target name: "duplicate target names".
+ <paragraph>
+ Since there are two "Duplicate Target Names" section headers, we
+ cannot uniquely refer to either of them by name. If we try to (like
+ this:
+ <problematic ids="problematic-3" refid="system-message-5">
+ `Duplicate Target Names`_
+ ), an error is generated.
+ <section ids="directives" names="directives">
+ <title auto="1" refid="toc-entry-22">
+ <generated classes="sectnum">
+ 2.14
+ Directives
+ <topic classes="contents local" ids="contents" names="contents">
+ <bullet_list classes="auto-toc">
+ <list_item>
+ <paragraph>
+ <reference ids="toc-entry-41" refid="document-parts">
+ <generated classes="sectnum">
+ 2.14.1
+ Document Parts
+ <list_item>
+ <paragraph>
+ <reference ids="toc-entry-42" refid="images-and-figures">
+ <generated classes="sectnum">
+ 2.14.2
+ Images and Figures
+ <list_item>
+ <paragraph>
+ <reference ids="toc-entry-43" refid="admonitions">
+ <generated classes="sectnum">
+ 2.14.3
+ Admonitions
+ <list_item>
+ <paragraph>
+ <reference ids="toc-entry-44" refid="topics-sidebars-and-rubrics">
+ <generated classes="sectnum">
+ 2.14.4
+ Topics, Sidebars, and Rubrics
+ <list_item>
+ <paragraph>
+ <reference ids="toc-entry-45" refid="target-footnotes">
+ <generated classes="sectnum">
+ 2.14.5
+ Target Footnotes
+ <list_item>
+ <paragraph>
+ <reference ids="toc-entry-46" refid="replacement-text">
+ <generated classes="sectnum">
+ 2.14.6
+ Replacement Text
+ <list_item>
+ <paragraph>
+ <reference ids="toc-entry-47" refid="compound-paragraph">
+ <generated classes="sectnum">
+ 2.14.7
+ Compound Paragraph
+ <list_item>
+ <paragraph>
+ <reference ids="toc-entry-48" refid="parsed-literal-blocks">
+ <generated classes="sectnum">
+ 2.14.8
+ Parsed Literal Blocks
+ <list_item>
+ <paragraph>
+ <reference ids="toc-entry-49" refid="code">
+ <generated classes="sectnum">
+ 2.14.9
+ Code
+ <paragraph>
+ These are just a sample of the many reStructuredText Directives. For
+ others, please see
+ <reference refuri="http://docutils.sourceforge.net/docs/ref/rst/directives.html">
+ http://docutils.sourceforge.net/docs/ref/rst/directives.html
+ .
+ <section ids="document-parts" names="document\ parts">
+ <title auto="1" refid="toc-entry-41">
+ <generated classes="sectnum">
+ 2.14.1
+ Document Parts
+ <paragraph>
+ An example of the "contents" directive can be seen above this section
+ (a local, untitled table of
+ <reference name="contents" refid="contents">
+ contents
+ ) and at the beginning of the
+ document (a document-wide
+ <reference name="table of contents" refid="table-of-contents">
+ table of contents
+ ).
+ <section ids="images-and-figures" names="images\ and\ figures">
+ <title auto="1" refid="toc-entry-42">
+ <generated classes="sectnum">
+ 2.14.2
+ Images and Figures
+ <paragraph>
+ An image directive (also clickable -- a hyperlink reference):
+ <reference name="directives" refid="directives">
+ <image classes="class1 class2" uri="../../../docs/user/rst/images/title.png">
+ <paragraph>
+ Image with multiple IDs:
+ <target refid="image-target-1">
+ <target refid="image-target-2">
+ <target refid="image-target-3">
+ <image ids="image-target-3 image-target-2 image-target-1" names="image\ target\ 3 image\ target\ 2 image\ target\ 1" uri="../../../docs/user/rst/images/title.png">
+ <paragraph>
+ A centered image:
+ <image align="center" uri="../../../docs/user/rst/images/biohazard.png">
+ <paragraph>
+ A left-aligned image:
+ <image align="left" uri="../../../docs/user/rst/images/biohazard.png">
+ <paragraph>
+ This paragraph might flow around the image.
+ The specific behavior depends upon the style sheet and
+ the browser or rendering software used.
+ <paragraph>
+ A right-aligned image:
+ <image align="right" uri="../../../docs/user/rst/images/biohazard.png">
+ <paragraph>
+ This paragraph might flow around the image.
+ The specific behavior depends upon the style sheet and
+ the browser or rendering software used.
+ <paragraph>
+ For inline images see
+ <reference name="Substitution Definitions" refid="substitution-definitions">
+ Substitution Definitions
+ .
+ <paragraph>
+ Image size:
+ <paragraph>
+ An image 2 em wide:
+ <image uri="../../../docs/user/rst/images/biohazard.png" width="2em">
+ <paragraph>
+ An image 2 em wide and 15 pixel high:
+ <image height="15px" uri="../../../docs/user/rst/images/biohazard.png" width="2em">
+ <paragraph>
+ An image occupying 50% of the line width:
+ <image uri="../../../docs/user/rst/images/title.png" width="50%">
+ <paragraph>
+ An image 2 cm high:
+ <image height="2cm" uri="../../../docs/user/rst/images/biohazard.png">
+ <paragraph>
+ A
+ <emphasis>
+ figure
+ is an image with a caption and/or a legend. With page-based output
+ media, figures might float to a different position if this helps the page
+ layout.
+ <figure classes="figclass1 figclass2">
+ <image alt="reStructuredText, the markup syntax" classes="class1 class2" uri="../../../docs/user/rst/images/title.png" width="258">
+ <caption>
+ Plaintext markup syntax and parser system.
+ <legend>
+ <table>
+ <tgroup cols="2">
+ <colspec colwidth="12">
+ <colspec colwidth="47">
+ <tbody>
+ <row>
+ <entry>
+ <paragraph>
+ re
+ <entry>
+ <paragraph>
+ Revised, revisited, based on 're' module.
+ <row>
+ <entry>
+ <paragraph>
+ Structured
+ <entry>
+ <paragraph>
+ Structure-enhanced text, structuredtext.
+ <row>
+ <entry>
+ <paragraph>
+ Text
+ <entry>
+ <paragraph>
+ Well it is, isn't it?
+ <paragraph>
+ This paragraph is also part of the legend.
+ <paragraph>
+ A left-aligned figure:
+ <figure align="left" classes="figclass1 figclass2" width="70%">
+ <image alt="reStructuredText, the markup syntax" classes="class1 class2" uri="../../../docs/user/rst/images/biohazard.png" width="40px">
+ <caption>
+ This is the caption.
+ <legend>
+ <paragraph>
+ This is the legend.
+ <paragraph>
+ The legend may consist of several paragraphs.
+ <paragraph>
+ This paragraph might flow around the figure.
+ <paragraph>
+ The specific behavior depends upon the style sheet and the browser or
+ rendering software used.
+ <paragraph>
+ A centered figure:
+ <figure align="center">
+ <image uri="../../../docs/user/rst/images/biohazard.png" width="40px">
+ <caption>
+ This is the caption.
+ <legend>
+ <paragraph>
+ This is the legend.
+ <paragraph>
+ The legend may consist of several paragraphs.
+ <paragraph>
+ This paragraph might flow around the figure.
+ <paragraph>
+ The specific behavior depends upon the style sheet and the browser or
+ rendering software used.
+ <paragraph>
+ A right-aligned figure:
+ <figure align="right">
+ <image uri="../../../docs/user/rst/images/biohazard.png" width="40px">
+ <caption>
+ This is the caption.
+ <legend>
+ <paragraph>
+ This is the legend.
+ <paragraph>
+ The legend may consist of several paragraphs.
+ <paragraph>
+ This paragraph might flow around the figure. The specific behavior depends
+ upon the style sheet and the browser or rendering software used.
+ <paragraph>
+ Tables may be given titles and additional arguments with the
+ <emphasis>
+ table
+
+ directive:
+ <table align="left">
+ <title>
+ left-aligned table
+ <tgroup cols="2">
+ <colspec colwidth="5">
+ <colspec colwidth="5">
+ <thead>
+ <row>
+ <entry>
+ <paragraph>
+ A
+ <entry>
+ <paragraph>
+ not A
+ <tbody>
+ <row>
+ <entry>
+ <paragraph>
+ False
+ <entry>
+ <paragraph>
+ True
+ <row>
+ <entry>
+ <paragraph>
+ True
+ <entry>
+ <paragraph>
+ False
+ <table align="center">
+ <title>
+ center-aligned table
+ <tgroup cols="2">
+ <colspec colwidth="5">
+ <colspec colwidth="5">
+ <thead>
+ <row>
+ <entry>
+ <paragraph>
+ A
+ <entry>
+ <paragraph>
+ not A
+ <tbody>
+ <row>
+ <entry>
+ <paragraph>
+ False
+ <entry>
+ <paragraph>
+ True
+ <row>
+ <entry>
+ <paragraph>
+ True
+ <entry>
+ <paragraph>
+ False
+ <table align="right">
+ <title>
+ right-aligned table
+ <tgroup cols="2">
+ <colspec colwidth="5">
+ <colspec colwidth="5">
+ <thead>
+ <row>
+ <entry>
+ <paragraph>
+ A
+ <entry>
+ <paragraph>
+ not A
+ <tbody>
+ <row>
+ <entry>
+ <paragraph>
+ False
+ <entry>
+ <paragraph>
+ True
+ <row>
+ <entry>
+ <paragraph>
+ True
+ <entry>
+ <paragraph>
+ False
+ <paragraph>
+ With the "widths" argument "auto" (or "class" value "colwidths-auto"),
+ column widths are determined by the backend (if supported by the
+ writer/backend).
+ <target refid="target1">
+ <target refid="target2">
+ <table classes="colwidths-auto" ids="target2 target1" names="target2 target1">
+ <tgroup cols="3">
+ <colspec colwidth="7">
+ <colspec colwidth="7">
+ <colspec colwidth="10">
+ <thead>
+ <row>
+ <entry>
+ <paragraph>
+ A
+ <entry>
+ <paragraph>
+ B
+ <entry>
+ <paragraph>
+ A or B
+ <tbody>
+ <row>
+ <entry>
+ <paragraph>
+ False
+ <entry>
+ <paragraph>
+ False
+ <entry>
+ <paragraph>
+ False
+ <row>
+ <entry>
+ <paragraph>
+ True
+ <entry>
+ <paragraph>
+ False
+ <entry>
+ <paragraph>
+ True
+ <row>
+ <entry>
+ <paragraph>
+ False
+ <entry>
+ <paragraph>
+ True
+ <entry>
+ <paragraph>
+ True
+ <row>
+ <entry>
+ <paragraph>
+ True
+ <entry>
+ <paragraph>
+ True
+ <entry>
+ <paragraph>
+ True
+ <section ids="admonitions" names="admonitions">
+ <title auto="1" refid="toc-entry-43">
+ <generated classes="sectnum">
+ 2.14.3
+ Admonitions
+ <attention>
+ <paragraph>
+ Directives at large.
+ <caution>
+ <paragraph>
+ Don't take any wooden nickels.
+ <danger>
+ <paragraph>
+ Mad scientist at work!
+ <error>
+ <paragraph>
+ Does not compute.
+ <hint>
+ <paragraph>
+ It's bigger than a bread box.
+ <important>
+ <bullet_list bullet="-">
+ <list_item>
+ <paragraph>
+ Wash behind your ears.
+ <list_item>
+ <paragraph>
+ Clean up your room.
+ <list_item>
+ <paragraph>
+ Call your mother.
+ <list_item>
+ <paragraph>
+ Back up your data.
+ <note>
+ <paragraph>
+ This is a note.
+ <tip>
+ <paragraph>
+ 15% if the service is good.
+ <warning>
+ <paragraph>
+ Strong prose may provoke extreme mental exertion.
+ Reader discretion is strongly advised.
+ <admonition classes="admonition-and-by-the-way">
+ <title>
+ And, by the way...
+ <paragraph>
+ You can make up your own admonition too.
+ <target ids="docutils" names="docutils" refuri="http://docutils.sourceforge.net/">
+ <section ids="topics-sidebars-and-rubrics" names="topics,\ sidebars,\ and\ rubrics">
+ <title auto="1" refid="toc-entry-44">
+ <generated classes="sectnum">
+ 2.14.4
+ Topics, Sidebars, and Rubrics
+ <paragraph>
+ <emphasis>
+ Sidebars
+ are like miniature, parallel documents.
+ <sidebar>
+ <title>
+ Sidebar Title
+ <subtitle>
+ Optional Subtitle
+ <paragraph>
+ This is a sidebar. It is for text outside the flow of the main
+ text.
+ <rubric>
+ This is a rubric inside a sidebar
+ <paragraph>
+ Sidebars often appear beside the main text with a border and a different
+ background or font color.
+ <paragraph>
+ A
+ <emphasis>
+ topic
+ is like a block quote with a title, or a self-contained section
+ with no subsections.
+ <topic>
+ <title>
+ Topic Title
+ <paragraph>
+ This is a topic.
+ <paragraph>
+ A
+ <emphasis>
+ rubric
+ is like an informal heading that doesn't correspond to the
+ document's structure. It is typically highlighted in red (hence the name).
+ <rubric>
+ This is a rubric
+ <paragraph>
+ Topics and rubrics can be used at places where a
+ <reference name="section title" refid="section-title">
+ section title
+ is not
+ allowed (e.g. inside a directive).
+ <section ids="target-footnotes" names="target\ footnotes">
+ <title auto="1" refid="toc-entry-45">
+ <generated classes="sectnum">
+ 2.14.5
+ Target Footnotes
+ <footnote auto="1" backrefs="footnote-reference-10 footnote-reference-11 footnote-reference-12 footnote-reference-14" ids="footnote-6" names="TARGET_NOTE:\ footnote-6">
+ <label>
+ 5
+ <paragraph>
+ <reference refuri="http://www.python.org/">
+ http://www.python.org/
+ <footnote auto="1" backrefs="footnote-reference-13" ids="footnote-7" names="TARGET_NOTE:\ footnote-7">
+ <label>
+ 6
+ <paragraph>
+ <reference refuri="http://pygments.org/">
+ http://pygments.org/
+ <footnote auto="1" backrefs="footnote-reference-15" ids="footnote-8" names="TARGET_NOTE:\ footnote-8">
+ <label>
+ 7
+ <paragraph>
+ <reference refuri="http://docutils.sourceforge.net/">
+ http://docutils.sourceforge.net/
+ <section ids="replacement-text" names="replacement\ text">
+ <title auto="1" refid="toc-entry-46">
+ <generated classes="sectnum">
+ 2.14.6
+ Replacement Text
+ <paragraph>
+ I recommend you try
+ <reference refuri="http://www.python.org/">
+ Python,
+ <emphasis>
+ the
+ best language around
+
+ <footnote_reference auto="1" ids="footnote-reference-12" refid="footnote-6">
+ 5
+ .
+ <substitution_definition names="Python">
+ Python,
+ <emphasis>
+ the
+ best language around
+ <section ids="compound-paragraph" names="compound\ paragraph">
+ <title auto="1" refid="toc-entry-47">
+ <generated classes="sectnum">
+ 2.14.7
+ Compound Paragraph
+ <paragraph>
+ The
+ <emphasis>
+ compound
+ directive is used to create a "compound paragraph", which
+ is a single logical paragraph containing multiple physical body
+ elements. For example:
+ <compound>
+ <paragraph>
+ The 'rm' command is very dangerous. If you are logged
+ in as root and enter
+ <literal_block xml:space="preserve">
+ cd /
+ rm -rf *
+ <paragraph>
+ you will erase the entire contents of your file system.
+ <paragraph>
+ Test the handling and display of compound paragraphs:
+ <compound classes="some-class">
+ <paragraph>
+ Compound 2, paragraph 1,
+ <paragraph>
+ compound 2, paragraph 2,
+ <bullet_list bullet="*">
+ <list_item>
+ <paragraph>
+ list item 1,
+ <list_item>
+ <paragraph>
+ list item 2,
+ <paragraph>
+ compound 2, paragraph 3.
+ <compound>
+ <paragraph>
+ Compound 3, only consisting of one paragraph.
+ <compound>
+ <literal_block xml:space="preserve">
+ Compound 4.
+ This one starts with a literal block.
+ <paragraph>
+ Compound 4, paragraph following the literal block.
+ <paragraph>
+ Now something
+ <emphasis>
+ really
+ perverted -- a nested compound block. This is
+ just to test that it works at all; the results don't have to be
+ meaningful.
+ <compound>
+ <paragraph>
+ Compound 5, block 1 (a paragraph).
+ <compound>
+ <paragraph>
+ Compound 6 is block 2 in compound 5.
+ <paragraph>
+ Compound 6, another paragraph.
+ <paragraph>
+ Compound 5, block 3 (a paragraph).
+ <compound>
+ <paragraph>
+ Compound 7, tests the inclusion of various block-level
+ elements in one logical paragraph. First a table,
+ <table>
+ <tgroup cols="3">
+ <colspec colwidth="20">
+ <colspec colwidth="20">
+ <colspec colwidth="20">
+ <tbody>
+ <row>
+ <entry>
+ <paragraph>
+ Left cell, first
+ paragraph.
+ <paragraph>
+ Left cell, second
+ paragraph.
+ <entry>
+ <paragraph>
+ Middle cell,
+ consisting of
+ exactly one
+ paragraph.
+ <entry>
+ <paragraph>
+ Right cell.
+ <paragraph>
+ Paragraph 2.
+ <paragraph>
+ Paragraph 3.
+ <paragraph>
+ followed by a paragraph. This physical paragraph is
+ actually a continuation of the paragraph before the table. It is followed
+ by
+ <block_quote>
+ <paragraph>
+ a quote and
+ <enumerated_list enumtype="arabic" prefix="" suffix=".">
+ <list_item>
+ <paragraph>
+ an enumerated list,
+ <paragraph>
+ a paragraph,
+ <option_list>
+ <option_list_item>
+ <option_group>
+ <option>
+ <option_string>
+ --an
+ <description>
+ <paragraph>
+ option list,
+ <paragraph>
+ a paragraph,
+ <field_list>
+ <field>
+ <field_name>
+ a field
+ <field_body>
+ <paragraph>
+ list,
+ <paragraph>
+ a paragraph,
+ <definition_list>
+ <definition_list_item>
+ <term>
+ a definition
+ <definition>
+ <paragraph>
+ list,
+ <paragraph>
+ a paragraph, an image:
+ <image uri="../../../docs/user/rst/images/biohazard.png">
+ <paragraph>
+ a paragraph,
+ <line_block>
+ <line>
+ a line
+ <line>
+ block,
+ <paragraph>
+ a paragraph followed by a comment,
+ <comment xml:space="preserve">
+ this is a comment
+ <paragraph>
+ a paragraph, a
+ <note>
+ <paragraph>
+ with content
+ <paragraph>
+ and the final paragraph of the compound 7.
+ <section ids="parsed-literal-blocks" names="parsed\ literal\ blocks">
+ <title auto="1" refid="toc-entry-48">
+ <generated classes="sectnum">
+ 2.14.8
+ Parsed Literal Blocks
+ <literal_block xml:space="preserve">
+ This is a parsed literal block.
+ This line is indented. The next line is blank.
+
+ Inline markup is supported, e.g.
+ <emphasis>
+ emphasis
+ ,
+ <strong>
+ strong
+ ,
+ <literal>
+ literal
+ text
+ ,
+ <subscript>
+ sub-
+ and
+ <superscript>
+ super
+ scripts,
+ inline formulas:
+ <math>
+ A = 2 \pi r^2
+ ,
+ footnotes
+ <footnote_reference ids="footnote-reference-9" refid="footnote-1">
+ 1
+ ,
+ <target ids="hyperlink-targets" names="hyperlink\ targets">
+ hyperlink targets
+ , and
+ <reference name="references" refuri="http://www.python.org/">
+ references
+ <target ids="references" names="references" refuri="http://www.python.org/">
+ .
+ <section ids="code" names="code">
+ <title auto="1" refid="toc-entry-49">
+ <generated classes="sectnum">
+ 2.14.9
+ Code
+ <paragraph>
+ Blocks of source code can be set with the
+ <title_reference>
+ code
+ directive. If the code
+ language is specified, the content is parsed and tagged by the
+ <reference name="Pygments" refuri="http://pygments.org/">
+ Pygments
+
+ <footnote_reference auto="1" ids="footnote-reference-13" refid="footnote-7">
+ 6
+
+ syntax highlighter and can be formatted with a style sheet. (Code parsing
+ is turned off using the
+ <literal>
+ syntax-highlight
+ config setting in the test
+ conversions in order to get identical results with/without installed
+ Pygments highlighter.)
+ <literal_block classes="code python" xml:space="preserve">
+ print 'This is Python code.'
+ <paragraph>
+ The
+ <literal>
+ :number-lines:
+ option (with optional start value) generates line
+ numbers:
+ <literal_block classes="code python" xml:space="preserve">
+ <inline classes="ln">
+ 8
+ # print integers from 0 to 9:
+ <inline classes="ln">
+ 9
+ for i in range(10):
+ <inline classes="ln">
+ 10
+ print i
+ <paragraph>
+ For inline code snippets, there is the
+ <title_reference>
+ code
+ role, which can be used
+ directly (the code will not be parsed/tagged, as the language is not known)
+ or as base for special code roles, e.g. the LaTeX code in the next
+ paragraph.
+ <paragraph>
+ Docutils uses LaTeX syntax for math directives and roles:
+ <literal classes="code tex">
+ \alpha = f(x)
+ prints
+ <math>
+ \alpha = f(x)
+ .
+ <paragraph>
+ The
+ <literal>
+ :code:
+ option of the
+ <title_reference>
+ include
+ directive sets the included content
+ as a code block, here the rst file
+ <literal>
+ header_footer.txt
+ with line numbers:
+ <literal_block classes="code rst" source="functional/input/data/header_footer.txt" xml:space="preserve">
+ <inline classes="ln">
+ 1
+ .. header:: Document header
+ <inline classes="ln">
+ 2
+ .. footer:: Document footer
+ <target ids="pygments" names="pygments" refuri="http://pygments.org/">
+ <section ids="substitution-definitions" names="substitution\ definitions">
+ <title auto="1" refid="toc-entry-32">
+ <generated classes="sectnum">
+ 2.15
+ Substitution Definitions
+ <paragraph>
+ An inline image (
+ <image alt="EXAMPLE" uri="../../../docs/user/rst/images/biohazard.png">
+ ) example:
+ <substitution_definition names="EXAMPLE">
+ <image alt="EXAMPLE" uri="../../../docs/user/rst/images/biohazard.png">
+ <paragraph>
+ A Unicode example:
+ <substitution_definition ltrim="1" names="heart" rtrim="1">
+ ♥
+ <paragraph>
+ (Substitution definitions are not visible in the HTML source.)
+ <section ids="comments" names="comments">
+ <title auto="1" refid="toc-entry-33">
+ <generated classes="sectnum">
+ 2.16
+ Comments
+ <paragraph>
+ Here's one:
+ <comment xml:space="preserve">
+ Comments begin with two dots and a space. Anything may
+ follow, except for the syntax of footnotes, hyperlink
+ targets, directives, or substitution definitions.
+
+ Double-dashes -- "--" -- must be escaped somehow in HTML output.
+
+ Comments may contain non-ASCII characters: ä ö ü æ ø å
+ <paragraph>
+ (View the HTML source to see the comment.)
+ <section ids="raw-text" names="raw\ text">
+ <title auto="1" refid="toc-entry-34">
+ <generated classes="sectnum">
+ 2.17
+ Raw text
+ <paragraph>
+ This does not necessarily look nice, because there may be missing white space.
+ <paragraph>
+ It's just there to freeze the behavior.
+ <raw format="html latex" xml:space="preserve">
+ A test.
+ <raw format="html latex" xml:space="preserve">
+ Second test.
+ <raw classes="myclass" format="html latex" xml:space="preserve">
+ Another test with myclass set.
+ <paragraph>
+ This is the
+ <raw classes="myrawroleclass" format="html latex" xml:space="preserve">
+ fourth test
+ with myrawroleclass set.
+ <raw format="html" xml:space="preserve">
+ Fifth test in HTML.<br />Line two.
+ <raw format="latex" xml:space="preserve">
+ Fifth test in LaTeX.\\Line two.
+ <section ids="container" names="container">
+ <title auto="1" refid="toc-entry-35">
+ <generated classes="sectnum">
+ 2.18
+ Container
+ <container classes="custom">
+ <paragraph>
+ paragraph 1
+ <paragraph>
+ paragraph 2
+ <section ids="colspanning-tables" names="colspanning\ tables">
+ <title auto="1" refid="toc-entry-36">
+ <generated classes="sectnum">
+ 2.19
+ Colspanning tables
+ <paragraph>
+ This table has a cell spanning two columns:
+ <table>
+ <tgroup cols="3">
+ <colspec colwidth="5">
+ <colspec colwidth="5">
+ <colspec colwidth="6">
+ <thead>
+ <row>
+ <entry morecols="1">
+ <paragraph>
+ Inputs
+ <entry>
+ <paragraph>
+ Output
+ <row>
+ <entry>
+ <paragraph>
+ A
+ <entry>
+ <paragraph>
+ B
+ <entry>
+ <paragraph>
+ A or B
+ <tbody>
+ <row>
+ <entry>
+ <paragraph>
+ False
+ <entry>
+ <paragraph>
+ False
+ <entry>
+ <paragraph>
+ False
+ <row>
+ <entry>
+ <paragraph>
+ True
+ <entry>
+ <paragraph>
+ False
+ <entry>
+ <paragraph>
+ True
+ <row>
+ <entry>
+ <paragraph>
+ False
+ <entry>
+ <paragraph>
+ True
+ <entry>
+ <paragraph>
+ True
+ <row>
+ <entry>
+ <paragraph>
+ True
+ <entry>
+ <paragraph>
+ True
+ <entry>
+ <paragraph>
+ True
+ <section ids="rowspanning-tables" names="rowspanning\ tables">
+ <title auto="1" refid="toc-entry-37">
+ <generated classes="sectnum">
+ 2.20
+ Rowspanning tables
+ <paragraph>
+ Here's a table with cells spanning several rows:
+ <table>
+ <tgroup cols="3">
+ <colspec colwidth="24">
+ <colspec colwidth="12">
+ <colspec colwidth="18">
+ <thead>
+ <row>
+ <entry>
+ <paragraph>
+ Header row, column 1
+ (header rows optional)
+ <entry>
+ <paragraph>
+ Header 2
+ <entry>
+ <paragraph>
+ Header 3
+ <tbody>
+ <row>
+ <entry>
+ <paragraph>
+ body row 1, column 1
+ <entry>
+ <paragraph>
+ column 2
+ <entry>
+ <paragraph>
+ column 3
+ <row>
+ <entry>
+ <paragraph>
+ body row 2
+ <entry morerows="1">
+ <paragraph>
+ Cells may
+ span rows.
+ <entry morerows="1">
+ <paragraph>
+ Another
+ rowspanning
+ cell.
+ <row>
+ <entry>
+ <paragraph>
+ body row 3
+ <section ids="complex-tables" names="complex\ tables">
+ <title auto="1" refid="toc-entry-38">
+ <generated classes="sectnum">
+ 2.21
+ Complex tables
+ <paragraph>
+ Here's a complex table, which should test all features.
+ <table>
+ <tgroup cols="4">
+ <colspec colwidth="24">
+ <colspec colwidth="12">
+ <colspec colwidth="10">
+ <colspec colwidth="10">
+ <thead>
+ <row>
+ <entry>
+ <paragraph>
+ Header row, column 1
+ (header rows optional)
+ <entry>
+ <paragraph>
+ Header 2
+ <entry>
+ <paragraph>
+ Header 3
+ <entry>
+ <paragraph>
+ Header 4
+ <tbody>
+ <row>
+ <entry>
+ <paragraph>
+ body row 1, column 1
+ <entry>
+ <paragraph>
+ column 2
+ <entry>
+ <paragraph>
+ column 3
+ <entry>
+ <paragraph>
+ column 4
+ <row>
+ <entry>
+ <paragraph>
+ body row 2
+ <entry morecols="2">
+ <paragraph>
+ Cells may span columns.
+ <row>
+ <entry>
+ <paragraph>
+ body row 3
+ <entry morerows="1">
+ <paragraph>
+ Cells may
+ span rows.
+ <paragraph>
+ Paragraph.
+ <entry morecols="1" morerows="1">
+ <bullet_list bullet="-">
+ <list_item>
+ <paragraph>
+ Table cells
+ <list_item>
+ <paragraph>
+ contain
+ <list_item>
+ <paragraph>
+ body elements.
+ <row>
+ <entry>
+ <paragraph>
+ body row 4
+ <row>
+ <entry>
+ <paragraph>
+ body row 5
+ <entry morecols="1">
+ <paragraph>
+ Cells may also be
+ empty:
+ <literal>
+ -->
+ <entry>
+ <section ids="list-tables" names="list\ tables">
+ <title auto="1" refid="toc-entry-39">
+ <generated classes="sectnum">
+ 2.22
+ List Tables
+ <paragraph>
+ Here's a list table exercising all features:
+ <table classes="colwidths-given test" width="40em">
+ <title>
+ list table with integral header
+ <tgroup cols="3">
+ <colspec colwidth="10" stub="1">
+ <colspec colwidth="20">
+ <colspec colwidth="30">
+ <thead>
+ <row>
+ <entry>
+ <paragraph>
+ Treat
+ <entry>
+ <paragraph>
+ Quantity
+ <entry>
+ <paragraph>
+ Description
+ <tbody>
+ <row>
+ <entry>
+ <paragraph>
+ Albatross
+ <entry>
+ <paragraph>
+ 2.99
+ <entry>
+ <paragraph>
+ On a stick!
+ <row>
+ <entry>
+ <paragraph>
+ Crunchy Frog
+ <entry>
+ <paragraph>
+ 1.49
+ <entry>
+ <paragraph>
+ If we took the bones out, it wouldn't be
+ crunchy, now would it?
+ <row>
+ <entry>
+ <paragraph>
+ Gannet Ripple
+ <entry>
+ <paragraph>
+ 1.99
+ <entry>
+ <paragraph>
+ On a stick!
+ <table align="center" classes="colwidths-auto">
+ <title>
+ center aligned list table
+ <tgroup cols="2">
+ <colspec colwidth="50">
+ <colspec colwidth="50">
+ <tbody>
+ <row>
+ <entry>
+ <paragraph>
+ Albatross
+ <entry>
+ <paragraph>
+ 2.99
+ <row>
+ <entry>
+ <paragraph>
+ Crunchy Frog
+ <entry>
+ <paragraph>
+ 1.49
+ <row>
+ <entry>
+ <paragraph>
+ Gannet Ripple
+ <entry>
+ <paragraph>
+ 1.99
+ <section ids="error-handling" names="error\ handling">
+ <title auto="1" refid="toc-entry-40">
+ <generated classes="sectnum">
+ 3
+ Error Handling
+ <paragraph>
+ Any errors caught during processing will generate system messages.
+ <paragraph>
+ There should be five messages in the following, auto-generated
+ section, "Docutils System Messages":
+ <comment xml:space="preserve">
+ section should be added by Docutils automatically
+ <section classes="system-messages">
+ <title>
+ Docutils System Messages
+ <system_message backrefs="problematic-1" ids="system-message-1" level="3" line="104" source="functional/input/data/standard.txt" type="ERROR">
+ <paragraph>
+ Undefined substitution referenced: "problematic".
+ <system_message backrefs="footnote-reference-8" ids="system-message-2" level="3" line="392" source="functional/input/data/standard.txt" type="ERROR">
+ <paragraph>
+ Unknown target name: "5".
+ <system_message backrefs="citation-reference-3" ids="system-message-3" level="3" line="401" source="functional/input/data/standard.txt" type="ERROR">
+ <paragraph>
+ Unknown target name: "nonexistent".
+ <system_message backrefs="problematic-2" ids="system-message-4" level="3" line="428" source="functional/input/data/standard.txt" type="ERROR">
+ <paragraph>
+ Unknown target name: "hyperlink reference without a target".
+ <system_message backrefs="problematic-3" ids="system-message-5" level="3" line="441" source="functional/input/data/standard.txt" type="ERROR">
+ <paragraph>
+ Duplicate target name, cannot be used as a unique reference: "duplicate target names".
+ <system_message level="1" line="164" source="functional/input/data/standard.txt" type="INFO">
+ <paragraph>
+ Hyperlink target "target" is not referenced.
+ <system_message level="1" line="406" source="functional/input/data/standard.txt" type="INFO">
+ <paragraph>
+ Hyperlink target "another-target" is not referenced.
+ <system_message level="1" line="474" source="functional/input/data/standard.txt" type="INFO">
+ <paragraph>
+ Hyperlink target "image-target-1" is not referenced.
+ <system_message level="1" line="475" source="functional/input/data/standard.txt" type="INFO">
+ <paragraph>
+ Hyperlink target "image-target-2" is not referenced.
+ <system_message level="1" line="476" source="functional/input/data/standard.txt" type="INFO">
+ <paragraph>
+ Hyperlink target "image-target-3" is not referenced.
+ <system_message level="1" line="640" source="functional/input/data/standard.txt" type="INFO">
+ <paragraph>
+ Hyperlink target "target1" is not referenced.
+ <system_message level="1" line="641" source="functional/input/data/standard.txt" type="INFO">
+ <paragraph>
+ Hyperlink target "target2" is not referenced.
+ <system_message level="1" line="686" source="functional/input/data/standard.txt" type="INFO">
+ <paragraph>
+ Hyperlink target "docutils" is not referenced.
+ <system_message level="1" line="852" source="functional/input/data/standard.txt" type="INFO">
+ <paragraph>
+ Hyperlink target "hyperlink targets" is not referenced.
--- /dev/null
+<?xml version="1.0" encoding="utf-8" ?>
+<!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">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<meta name="generator" content="Docutils 0.16: http://docutils.sourceforge.net/" />
+<meta name="version" content="S5 1.1" />
+<title>Slide Shows</title>
+<meta name="author" content="David Goodger" />
+<meta name="date" content="2005-11-28" />
+<link rel="stylesheet" href="../input/data/html4css1.css" type="text/css" />
+<!-- configuration parameters -->
+<meta name="defaultView" content="slideshow" />
+<meta name="controlVis" content="hidden" />
+<!-- style sheet links -->
+<script src="ui/small-black/slides.js" type="text/javascript"></script>
+<link rel="stylesheet" href="ui/small-black/slides.css"
+ type="text/css" media="projection" id="slideProj" />
+<link rel="stylesheet" href="ui/small-black/outline.css"
+ type="text/css" media="screen" id="outlineStyle" />
+<link rel="stylesheet" href="ui/small-black/print.css"
+ type="text/css" media="print" id="slidePrint" />
+<link rel="stylesheet" href="ui/small-black/opera.css"
+ type="text/css" media="projection" id="operaFix" />
+
+<style type="text/css">
+#currentSlide {display: none;}
+</style>
+</head>
+<body>
+<div class="layout">
+<div id="controls"></div>
+<div id="currentSlide"></div>
+<div id="header">
+
+</div>
+<div id="footer">
+<h1>Slide Shows</h1>
+<h2>Location • Date</h2>
+</div>
+</div>
+<div class="presentation">
+<div class="slide" id="slide0">
+<h1 class="title">Slide Shows</h1>
+<table class="docinfo" frame="void" rules="none">
+<col class="docinfo-name" />
+<col class="docinfo-content" />
+<tbody valign="top">
+<tr><th class="docinfo-name">Author:</th>
+<td>David Goodger</td></tr>
+<tr><th class="docinfo-name">Date:</th>
+<td>2005-11-28</td></tr>
+</tbody>
+</table>
+<!-- Definitions of interpreted text roles (classes) for S5/HTML data. -->
+<!-- This data file has been placed in the public domain. -->
+<!-- Colours
+======= -->
+<!-- Text Sizes
+========== -->
+<!-- Display in Slides (Presentation Mode) Only
+========================================== -->
+<!-- Display in Outline Mode Only
+============================ -->
+<!-- Display in Print Only
+===================== -->
+<!-- Display in Handout Mode Only
+============================ -->
+<!-- Incremental Display
+=================== -->
+<div class="contents handout topic" id="contents">
+<p class="topic-title">Contents</p>
+<ul class="simple">
+<li><a class="reference internal" href="#introduction" id="toc-entry-1">Introduction</a></li>
+<li><a class="reference internal" href="#features-1" id="toc-entry-2">Features (1)</a></li>
+<li><a class="reference internal" href="#features-2" id="toc-entry-3">Features (2)</a></li>
+<li><a class="reference internal" href="#checklist" id="toc-entry-4">Checklist</a></li>
+</ul>
+</div>
+<p class="handout">This is a test. This is only a test. If this were a real slide
+show, there would be a projector handy.</p>
+<p>Let's test the S5/HTML writer!</p>
+<ul class="small simple">
+<li>Use the arrow keys to navigate.</li>
+<li>Click the "Ø" button to switch between presentation &
+handout/outline modes.</li>
+</ul>
+<div class="handout docutils container">
+In presentation mode, mouse over to the lower right-hand corner to
+display the controls.</div>
+
+</div>
+<div class="slide" id="introduction">
+<h1>Introduction</h1>
+<ul class="compact simple">
+<li>reStructuredText<p class="handout">Uses normal reStructuredText as input.</p>
+</li>
+<li>One section per slide<p class="handout">Each first-level section is converted into a single slide.</p>
+</li>
+<li>(X)HTML output<p class="handout">Presentations can be viewed using any modern graphical web browser.
+The browser must support CSS, JavaScript, and XHTML. S5 even works
+with IE!</p>
+</li>
+<li>Themes<p class="handout">A variety of themes are available.</p>
+</li>
+<li><tt class="docutils literal">rst2s5.py</tt><p class="handout">The front-end tool to generate S5 slide shows.</p>
+</li>
+</ul>
+</div>
+<div class="slide" id="features-1">
+<h1>Features (1)</h1>
+<p class="left">A flush-left paragraph</p>
+<p class="center">A centered paragraph</p>
+<p class="right">A flush-right paragraph</p>
+<p>Some colours: <span class="black">black</span> [black], <span class="gray">gray</span>, <span class="silver">silver</span>,
+<span class="white">white</span> [white], <span class="maroon">maroon</span>, <span class="red">red</span>,
+<span class="magenta">magenta</span>, <span class="fuchsia">fuchsia</span>, <span class="pink">pink</span>,
+<span class="orange">orange</span>, <span class="yellow">yellow</span>, <span class="lime">lime</span>, <span class="green">green</span>,
+<span class="olive">olive</span>, <span class="teal">teal</span>, <span class="cyan">cyan</span>, <span class="aqua">aqua</span>,
+<span class="blue">blue</span>, <span class="navy">navy</span>, <span class="purple">purple</span></p>
+</div>
+<div class="slide" id="features-2">
+<h1>Features (2)</h1>
+<p><span class="incremental">Some</span> <span class="incremental">incremental</span> <span class="incremental">text.</span></p>
+<ul class="incremental open">
+<li><p class="first"><span class="tiny">tiny</span> (class & role name: "tiny", e.g. "<tt class="docutils literal"><span class="pre">:tiny:`text`</span></tt>")</p>
+</li>
+<li><p class="first"><span class="small">small</span> ("small")</p>
+</li>
+<li><p class="first">normal (unstyled)</p>
+</li>
+<li><p class="first"><span class="big">big</span> ("big")</p>
+</li>
+<li><p class="first"><span class="huge">huge</span> ("huge")</p>
+</li>
+</ul>
+</div>
+<div class="slide" id="checklist">
+<h1>Checklist</h1>
+<ul class="simple">
+<li>The document title should be duplicated on each slide in the footer
+(except for the first slide, <tt class="docutils literal">slide0</tt>, where the entire footer is
+disabled).</li>
+<li>The footer also contains a second line, "Location • Date"</li>
+<li>There's no table of contents on the first slide, although it does
+appear in the handout/outline.</li>
+<li>Handout material is not displayed in presentation mode.</li>
+<li>The theme directories should be created, and the theme files copied
+over.</li>
+</ul>
+</div>
+</div>
+</body>
+</html>
--- /dev/null
+<?xml version="1.0" encoding="utf-8" ?>
+<!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">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<meta name="generator" content="Docutils 0.16: http://docutils.sourceforge.net/" />
+<meta name="version" content="S5 1.1" />
+<title>Slide Shows</title>
+<meta name="author" content="David Goodger" />
+<meta name="date" content="2005-11-28" />
+<link rel="stylesheet" href="../input/data/html4css1.css" type="text/css" />
+<!-- configuration parameters -->
+<meta name="defaultView" content="slideshow" />
+<meta name="controlVis" content="hidden" />
+<!-- style sheet links -->
+<script src="ui/default/slides.js" type="text/javascript"></script>
+<link rel="stylesheet" href="ui/default/slides.css"
+ type="text/css" media="projection" id="slideProj" />
+<link rel="stylesheet" href="ui/default/outline.css"
+ type="text/css" media="screen" id="outlineStyle" />
+<link rel="stylesheet" href="ui/default/print.css"
+ type="text/css" media="print" id="slidePrint" />
+<link rel="stylesheet" href="ui/default/opera.css"
+ type="text/css" media="projection" id="operaFix" />
+</head>
+<body>
+<div class="layout">
+<div id="controls"></div>
+<div id="currentSlide"></div>
+<div id="header">
+
+</div>
+<div id="footer">
+<h1>Slide Shows</h1>
+<h2>Location • Date</h2>
+</div>
+</div>
+<div class="presentation">
+<div class="slide" id="slide0">
+<h1 class="title">Slide Shows</h1>
+<table class="docinfo" frame="void" rules="none">
+<col class="docinfo-name" />
+<col class="docinfo-content" />
+<tbody valign="top">
+<tr><th class="docinfo-name">Author:</th>
+<td>David Goodger</td></tr>
+<tr><th class="docinfo-name">Date:</th>
+<td>2005-11-28</td></tr>
+</tbody>
+</table>
+<!-- Definitions of interpreted text roles (classes) for S5/HTML data. -->
+<!-- This data file has been placed in the public domain. -->
+<!-- Colours
+======= -->
+<!-- Text Sizes
+========== -->
+<!-- Display in Slides (Presentation Mode) Only
+========================================== -->
+<!-- Display in Outline Mode Only
+============================ -->
+<!-- Display in Print Only
+===================== -->
+<!-- Display in Handout Mode Only
+============================ -->
+<!-- Incremental Display
+=================== -->
+<div class="contents handout topic" id="contents">
+<p class="topic-title">Contents</p>
+<ul class="simple">
+<li><a class="reference internal" href="#introduction" id="toc-entry-1">Introduction</a></li>
+<li><a class="reference internal" href="#features-1" id="toc-entry-2">Features (1)</a></li>
+<li><a class="reference internal" href="#features-2" id="toc-entry-3">Features (2)</a></li>
+<li><a class="reference internal" href="#checklist" id="toc-entry-4">Checklist</a></li>
+</ul>
+</div>
+<p class="handout">This is a test. This is only a test. If this were a real slide
+show, there would be a projector handy.</p>
+<p>Let's test the S5/HTML writer!</p>
+<ul class="small simple">
+<li>Use the arrow keys to navigate.</li>
+<li>Click the "Ø" button to switch between presentation &
+handout/outline modes.</li>
+</ul>
+<div class="handout docutils container">
+In presentation mode, mouse over to the lower right-hand corner to
+display the controls.</div>
+
+</div>
+<div class="slide" id="introduction">
+<h1>Introduction</h1>
+<ul class="compact simple">
+<li>reStructuredText<p class="handout">Uses normal reStructuredText as input.</p>
+</li>
+<li>One section per slide<p class="handout">Each first-level section is converted into a single slide.</p>
+</li>
+<li>(X)HTML output<p class="handout">Presentations can be viewed using any modern graphical web browser.
+The browser must support CSS, JavaScript, and XHTML. S5 even works
+with IE!</p>
+</li>
+<li>Themes<p class="handout">A variety of themes are available.</p>
+</li>
+<li><tt class="docutils literal">rst2s5.py</tt><p class="handout">The front-end tool to generate S5 slide shows.</p>
+</li>
+</ul>
+</div>
+<div class="slide" id="features-1">
+<h1>Features (1)</h1>
+<p class="left">A flush-left paragraph</p>
+<p class="center">A centered paragraph</p>
+<p class="right">A flush-right paragraph</p>
+<p>Some colours: <span class="black">black</span> [black], <span class="gray">gray</span>, <span class="silver">silver</span>,
+<span class="white">white</span> [white], <span class="maroon">maroon</span>, <span class="red">red</span>,
+<span class="magenta">magenta</span>, <span class="fuchsia">fuchsia</span>, <span class="pink">pink</span>,
+<span class="orange">orange</span>, <span class="yellow">yellow</span>, <span class="lime">lime</span>, <span class="green">green</span>,
+<span class="olive">olive</span>, <span class="teal">teal</span>, <span class="cyan">cyan</span>, <span class="aqua">aqua</span>,
+<span class="blue">blue</span>, <span class="navy">navy</span>, <span class="purple">purple</span></p>
+</div>
+<div class="slide" id="features-2">
+<h1>Features (2)</h1>
+<p><span class="incremental">Some</span> <span class="incremental">incremental</span> <span class="incremental">text.</span></p>
+<ul class="incremental open">
+<li><p class="first"><span class="tiny">tiny</span> (class & role name: "tiny", e.g. "<tt class="docutils literal"><span class="pre">:tiny:`text`</span></tt>")</p>
+</li>
+<li><p class="first"><span class="small">small</span> ("small")</p>
+</li>
+<li><p class="first">normal (unstyled)</p>
+</li>
+<li><p class="first"><span class="big">big</span> ("big")</p>
+</li>
+<li><p class="first"><span class="huge">huge</span> ("huge")</p>
+</li>
+</ul>
+</div>
+<div class="slide" id="checklist">
+<h1>Checklist</h1>
+<ul class="simple">
+<li>The document title should be duplicated on each slide in the footer
+(except for the first slide, <tt class="docutils literal">slide0</tt>, where the entire footer is
+disabled).</li>
+<li>The footer also contains a second line, "Location • Date"</li>
+<li>There's no table of contents on the first slide, although it does
+appear in the handout/outline.</li>
+<li>Handout material is not displayed in presentation mode.</li>
+<li>The theme directories should be created, and the theme files copied
+over.</li>
+</ul>
+</div>
+</div>
+</body>
+</html>
--- /dev/null
+\documentclass[a4paper]{article}
+% generated by Docutils <http://docutils.sourceforge.net/>
+% 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
+\usepackage{ifthen}
+\usepackage{alltt}
+\usepackage{amsmath}
+\usepackage{polyglossia}
+\setdefaultlanguage{english}
+\setotherlanguages{english,french,german}
+\usepackage{color}
+\usepackage{float} % float configuration
+\floatplacement{figure}{H} % place figures here definitely
+\usepackage{graphicx}
+\usepackage{multirow}
+\setcounter{secnumdepth}{0}
+\usepackage{longtable,ltcaption,array}
+\setlength{\extrarowheight}{2pt}
+\newlength{\DUtablewidth} % internal use in tables
+\usepackage{tabularx}
+
+%%% Custom LaTeX 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}
+
+%%% User specified packages and stylesheets
+
+%%% Fallback definitions for Docutils-specific commands
+
+% 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]%
+ {\def\DocutilsClassFunctionName{DUCLASS#1}% arg cannot be used in end-part of environment.
+ \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}}{}
+}
+
+% abstract title
+\providecommand*{\DUtitleabstract}[1]{\centerline{\textbf{#1}}}
+
+% admonition (specially marked topic)
+\providecommand{\DUadmonition}[2][class-arg]{%
+ % try \DUadmonition#1{#2}:
+ \ifcsname DUadmonition#1\endcsname%
+ \csname DUadmonition#1\endcsname{#2}%
+ \else
+ \begin{center}
+ \fbox{\parbox{0.9\linewidth}{#2}}
+ \end{center}
+ \fi
+}
+
+% dedication topic
+\providecommand*{\DUCLASSdedication}{%
+ \renewenvironment{quote}{\begin{center}}{\end{center}}%
+}
+
+% docinfo (width of docinfo table)
+\DUprovidelength{\DUdocinfowidth}{0.9\linewidth}
+
+% subtitle (in document title)
+\providecommand*{\DUdocumentsubtitle}[1]{{\large #1}}
+\newcounter{enumv}
+
+% error admonition title
+\providecommand*{\DUtitleerror}[1]{\DUtitle{\color{red}#1}}
+
+% fieldlist environment
+\ifthenelse{\isundefined{\DUfieldlist}}{
+ \newenvironment{DUfieldlist}%
+ {\quote\description}
+ {\enddescription\endquote}
+}{}
+% numeric or symbol footnotes with hyperlinks
+\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 markup (custom roles)
+% \DUrole{#1}{#2} tries \DUrole#1{#2}
+\providecommand*{\DUrole}[2]{%
+ \ifcsname DUrole#1\endcsname%
+ \csname DUrole#1\endcsname{#2}%
+ \else
+ % backwards compatibility: try \docutilsrole#1{#2}
+ \ifcsname docutilsrole#1\endcsname%
+ \PackageWarningNoLine{docutils}{Command prefix "docutilsrole" is
+ deprecated, \MessageBreak use `\protect\DUrole #1`}
+ \csname docutilsrole#1\endcsname{#2}%
+ \else%
+ #2%
+ \fi%
+ \fi%
+}
+
+% legend environment
+\ifthenelse{\isundefined{\DUlegend}}{
+ \newenvironment{DUlegend}{\small}{}
+}{}
+
+% lineblock 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 environment
+\providecommand*{\DUoptionlistlabel}[1]{\bf #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}
+}{}
+
+\DUprovidelength{\pdfpxdimen}{1bp}
+
+
+% 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}
+}
+
+% subtitle (for sidebar)
+\providecommand*{\DUsubtitle}[1]{\par\emph{#1}\smallskip}
+
+% text mode subscript
+\ifx\textsubscript\undefined
+ \usepackage{fixltx2e} % since 2015 loaded by default
+\fi
+
+% title for topics, admonitions, unsupported section levels, and sidebar
+\providecommand*{\DUtitle}[2][class-arg]{%
+ % call \DUtitle#1{#2} if it exists:
+ \ifcsname DUtitle#1\endcsname%
+ \csname DUtitle#1\endcsname{#2}%
+ \else
+ \smallskip\noindent\textbf{#2}\smallskip%
+ \fi
+}
+
+% titlereference role
+\providecommand*{\DUroletitlereference}[1]{\textsl{#1}}
+
+% transition (break, fancybreak, anonymous section)
+\providecommand*{\DUtransition}{%
+ \hspace*{\fill}\hrulefill\hspace*{\fill}
+ \vskip 0.5\baselineskip
+}
+% hyperlinks:
+\ifthenelse{\isundefined{\hypersetup}}{
+ \usepackage[colorlinks=true,linkcolor=blue,urlcolor=blue]{hyperref}
+ \usepackage{bookmark}
+ \urlstyle{same} % normal text font (alternatives: tt, rm, sf)
+}{}
+\hypersetup{
+ pdftitle={reStructuredText Test Document},
+ pdfauthor={David Goodger;Me;Myself;I}
+}
+
+\title{reStructuredText Test Document%
+ \label{restructuredtext-test-document}%
+ \label{doctitle}%
+ \\%
+ \DUdocumentsubtitle{Examples of Syntax Constructs}%
+ \label{examples-of-syntax-constructs}%
+ \label{subtitle}}
+\author{}
+\date{}
+
+%%% Body
+\begin{document}
+\maketitle
+
+% Docinfo
+\begin{center}
+\begin{tabularx}{\DUdocinfowidth}{lX}
+\textbf{Author}: &
+ David Goodger \\
+\textbf{Address}: &
+ {\raggedright
+123 Example Street\\
+Example, EX Canada\\
+A1B 2C3 } \\
+\textbf{Contact}: &
+ \href{mailto:goodger@python.org}{goodger@python.org} \\
+\textbf{Author}: &
+ Me \\
+\textbf{Author}: &
+ Myself \\
+\textbf{Author}: &
+ I \\
+\textbf{Organization}: &
+ humankind \\
+\textbf{Date}: &
+ Now, or yesterday. Or maybe even \emph{before} yesterday. \\
+\textbf{Status}: &
+ This is a “work in progress” \\
+\textbf{Revision}: &
+ is managed by a version control system. \\
+\textbf{Version}: &
+ 1 \\
+\textbf{Copyright}: &
+ This document has been placed in the public domain. You
+may do with it as you wish. You may copy, modify,
+redistribute, reattribute, sell, buy, rent, lease,
+destroy, or improve it, quote it at length, excerpt,
+incorporate, collate, fold, staple, or mutilate it, or do
+anything else to it that your or anyone else’s heart
+desires. \\
+\textbf{field name}: &
+This is a “generic bibliographic field”.
+\\
+\textbf{field name “2”}: &
+Generic bibliographic fields may contain multiple body elements.
+
+Like this.
+\\
+\end{tabularx}
+\end{center}
+
+\begin{DUclass}{dedication}
+\begin{quote}
+\DUtitle[dedication]{Dedication}
+
+For Docutils users \& co-developers.
+\end{quote}
+\end{DUclass}
+
+\begin{DUclass}{abstract}
+\begin{quote}
+\DUtitle[abstract]{Abstract}
+
+This is a test document, containing at least one example of each
+reStructuredText construct.
+\end{quote}
+\end{DUclass}
+
+% This is a comment. Note how any initial comments are moved by
+% transforms to after the document title, subtitle, and docinfo.
+
+% Above is the document title, and below is the subtitle.
+% They are transformed from section titles after parsing.
+
+% bibliographic fields (which also require a transform):
+
+\pagebreak[4] % start ToC on new page
+
+\phantomsection\label{table-of-contents}
+\pdfbookmark[1]{Table of Contents}{table-of-contents}
+\renewcommand{\contentsname}{Table of Contents}
+\tableofcontents
+
+
+\section{1 Structural Elements%
+ \label{structural-elements}%
+}
+
+
+\subsection{1.1 Section Title%
+ \label{section-title}%
+}
+\subsubsection*{Section Subtitle}
+
+Lone subsections are converted to a section subtitle by a transform
+activated with the \texttt{--section-subtitles} command line option or the
+\texttt{sectsubtitle-xform} configuration value.
+
+
+\subsection{1.2 Empty Section%
+ \label{empty-section}%
+}
+
+
+\subsection{1.3 Transitions%
+ \label{transitions}%
+}
+
+Here’s a transition:
+
+%___________________________________________________________________________
+\DUtransition
+
+It divides the section. Transitions may also occur between sections:
+
+%___________________________________________________________________________
+\DUtransition
+
+
+\section{2 Body Elements%
+ \label{body-elements}%
+}
+
+
+\subsection{2.1 Paragraphs%
+ \label{paragraphs}%
+}
+
+A paragraph.
+
+
+\subsubsection{2.1.1 Inline Markup%
+ \label{inline-markup}%
+}
+
+Paragraphs contain text and may contain inline markup: \emph{emphasis},
+\textbf{strong emphasis}, \texttt{inline literals}, standalone hyperlinks
+(\url{http://www.python.org}), external hyperlinks (\href{http://www.python.org/}{Python}\DUfootnotemark{footnote-reference-10}{footnote-6}{5}), internal
+cross-references (\hyperref[example]{example}), external hyperlinks with embedded URIs
+(\href{http://www.python.org}{Python web site}), \href{http://www.python.org/}{anonymous hyperlink
+references}\DUfootnotemark{footnote-reference-17}{footnote-6}{5} (\href{http://docutils.sourceforge.net/}{a second reference}\DUfootnotemark{footnote-reference-18}{footnote-10}{9}), footnote references (manually
+numbered\DUfootnotemark{footnote-reference-1}{footnote-1}{1}, anonymous auto-numbered\DUfootnotemark{footnote-reference-2}{footnote-2}{3}, labeled auto-numbered\DUfootnotemark{footnote-reference-3}{label}{2}, or symbolic\DUfootnotemark{footnote-reference-4}{footnote-3}{*}), citation references (\hyperlink{cit2002}{[CIT2002]}),
+substitution references (\includegraphics{../../../docs/user/rst/images/biohazard.png} \&
+a \emph{trimmed heart} \texttt{(U+2665):}♥), and %
+\phantomsection\label{inline-hyperlink-targets}inline hyperlink targets
+(see \hyperref[targets]{Targets} below for a reference back to here). Character-level
+inline markup is also possible (although exceedingly ugly!) in \emph{re}\texttt{Structured}\emph{Text}. Problems are indicated by %
+\raisebox{1em}{\hypertarget{problematic-1}{}}\hyperlink{system-message-1}{\textbf{\color{red}|problematic|}} text
+(generated by processing errors; this one is intentional). Here is a
+reference to the \hyperref[doctitle]{doctitle} and the \hyperref[subtitle]{subtitle}.
+
+The default role for interpreted text is \DUroletitlereference{Title Reference}. Here are
+some explicit interpreted text roles: a PEP reference (\href{http://www.python.org/dev/peps/pep-0287}{PEP 287}); an
+RFC reference (\href{http://tools.ietf.org/html/rfc2822.html}{RFC 2822}); an abbreviation (\DUrole{abbreviation}{abb.}), an acronym
+(\DUrole{acronym}{reST}), code (\texttt{\DUrole{code}{print \textquotedbl{}hello world\textquotedbl{}}}); a \textsubscript{subscript};
+a \textsuperscript{superscript} and explicit roles for \DUroletitlereference{Docutils}’
+\emph{standard} \textbf{inline} \texttt{markup}.
+
+% DO NOT RE-WRAP THE FOLLOWING PARAGRAPH!
+
+Let’s test wrapping and whitespace significance in inline literals:
+\texttt{This is an example of --inline-literal --text, --including some--
+strangely--hyphenated-words. ~Adjust-the-width-of-your-browser-window
+to see how the text is wrapped. ~-- ---- -------- ~Now note ~ ~the
+spacing ~ ~between the ~ ~words of ~ ~this sentence ~ ~(words
+should ~ ~be grouped ~ ~in pairs).}
+
+If the \texttt{--pep-references} option was supplied, there should be a
+live link to PEP 258 here.
+
+
+\subsection{2.2 Bullet Lists%
+ \label{bullet-lists}%
+}
+
+\begin{itemize}
+\item A bullet list
+
+\begin{itemize}
+\item Nested bullet list.
+
+\item Nested item 2.
+\end{itemize}
+
+\item Item 2.
+
+Paragraph 2 of item 2.
+
+\begin{itemize}
+\item Nested bullet list.
+
+\item Nested item 2.
+
+\begin{itemize}
+\item Third level.
+
+\item Item 2.
+\end{itemize}
+
+\item Nested item 3.
+
+\item This nested list should be compacted by the HTML writer.
+%
+\phantomsection\label{target}
+% Even if this item contains a target and a comment.
+\end{itemize}
+\end{itemize}
+
+
+\subsection{2.3 Enumerated Lists%
+ \label{enumerated-lists}%
+}
+
+\begin{enumerate}
+\item Arabic numerals.
+
+\begin{enumerate}
+\renewcommand{\labelenumii}{\alph{enumii})}
+\item lower alpha)
+
+\begin{enumerate}
+\renewcommand{\labelenumiii}{(\roman{enumiii})}
+\item (lower roman)
+
+\begin{enumerate}
+\item upper alpha.
+
+\begin{list}{\Roman{enumv})}{\usecounter{enumv}}
+\item upper roman)
+\end{list}
+\end{enumerate}
+\end{enumerate}
+\end{enumerate}
+
+\item Lists that don’t start at 1:
+
+\begin{enumerate}
+\renewcommand{\labelenumii}{\arabic{enumii}.}
+\setcounter{enumii}{2}
+\item Three
+
+\item Four
+\end{enumerate}
+
+\begin{enumerate}
+\renewcommand{\labelenumii}{\Alph{enumii}.}
+\setcounter{enumii}{2}
+\item C
+
+\item D
+\end{enumerate}
+
+\begin{enumerate}
+\renewcommand{\labelenumii}{\roman{enumii}.}
+\setcounter{enumii}{2}
+\item iii
+
+\item iv
+\end{enumerate}
+\end{enumerate}
+
+
+\subsection{2.4 Definition Lists%
+ \label{definition-lists}%
+}
+
+\begin{description}
+\item[{Term}] \leavevmode
+Definition
+
+\item[{Term}] \leavevmode (\textbf{classifier})
+Definition paragraph 1.
+
+Definition paragraph 2.
+
+\item[{Term}] \leavevmode
+Definition
+
+\item[{Term}] \leavevmode (\textbf{classifier one})(\textbf{classifier two})
+Definition
+
+\end{description}
+
+
+\subsection{2.5 Field Lists%
+ \label{field-lists}%
+}
+
+\begin{DUfieldlist}
+\item[{what:}]
+Field lists map field names to field bodies, like database
+records. They are often part of an extension syntax. They are
+an unambiguous variant of RFC 2822 fields.
+
+\item[{how arg1 arg2:}]
+The field marker is a colon, the field name, and a colon.
+
+The field body may contain one or more body elements, indented
+relative to the field marker.
+
+\item[{credits:}]
+\DUrole{credits}{This paragraph has the \DUroletitlereference{credits} class set. (This is actually not
+about credits but just for ensuring that the class attribute
+doesn’t get stripped away.)}
+\end{DUfieldlist}
+
+
+\subsection{2.6 Option Lists%
+ \label{option-lists}%
+}
+
+For listing command-line options:
+
+\begin{DUoptionlist}
+\item[-a] command-line option “a”
+
+\item[-b file] options can have arguments
+and long descriptions
+
+\item[--long] options can be long also
+
+\item[--input=file] long options can also have
+arguments
+
+\item[--very-long-option] The description can also start on the next line.
+
+The description may contain multiple body elements,
+regardless of where it starts.
+
+\item[-x, -y, -z] Multiple options are an “option group”.
+
+\item[-v, --verbose] Commonly-seen: short \& long options.
+
+\item[-1 file, --one=file, --two file] Multiple options with arguments.
+
+\item[/V] DOS/VMS-style options too
+\end{DUoptionlist}
+
+There must be at least two spaces between the option and the
+description.
+
+
+\subsection{2.7 Literal Blocks%
+ \label{literal-blocks}%
+}
+
+Literal blocks are indicated with a double-colon (“::”) at the end of
+the preceding paragraph (over there \texttt{-->}). They can be indented:
+
+\begin{quote}
+\begin{alltt}
+if literal_block:
+ text = 'is left as-is'
+ spaces_and_linebreaks = 'are preserved'
+ markup_processing = None
+\end{alltt}
+\end{quote}
+
+Or they can be quoted without indentation:
+
+\begin{quote}
+\begin{alltt}
+>> Great idea!
+>
+> Why didn't I think of that?
+\end{alltt}
+\end{quote}
+
+
+\subsection{2.8 Line Blocks%
+ \label{line-blocks}%
+}
+
+This section tests line blocks. Line blocks are body elements which
+consist of lines and other line blocks. Nested line blocks cause
+indentation.
+
+\begin{DUlineblock}{0em}
+\item[] This is a line block. It ends with a blank line.
+\item[]
+\begin{DUlineblock}{\DUlineblockindent}
+\item[] New lines begin with a vertical bar (“|”).
+\item[] Line breaks and initial indent are significant, and preserved.
+\item[]
+\begin{DUlineblock}{\DUlineblockindent}
+\item[] Continuation lines are also possible. A long line that is intended
+to wrap should begin with a space in place of the vertical bar.
+\end{DUlineblock}
+\item[] The left edge of a continuation line need not be aligned with
+the left edge of the text above it.
+\end{DUlineblock}
+\end{DUlineblock}
+
+\begin{DUlineblock}{0em}
+\item[] This is a second line block.
+\item[]
+\item[] Blank lines are permitted internally, but they must begin with a “|”.
+\end{DUlineblock}
+
+Another line block, surrounded by paragraphs:
+
+\begin{DUlineblock}{0em}
+\item[] And it’s no good waiting by the window
+\item[] It’s no good waiting for the sun
+\item[] Please believe me, the things you dream of
+\item[] They don’t fall in the lap of no-one
+\end{DUlineblock}
+
+Take it away, Eric the Orchestra Leader!
+
+\begin{quote}
+\begin{DUlineblock}{0em}
+\item[] A one, two, a one two three four
+\item[]
+\item[] Half a bee, philosophically,
+\item[]
+\begin{DUlineblock}{\DUlineblockindent}
+\item[] must, \emph{ipso facto}, half not be.
+\end{DUlineblock}
+\item[] But half the bee has got to be,
+\item[]
+\begin{DUlineblock}{\DUlineblockindent}
+\item[] \emph{vis a vis} its entity. D’you see?
+\item[]
+\end{DUlineblock}
+\item[] But can a bee be said to be
+\item[]
+\begin{DUlineblock}{\DUlineblockindent}
+\item[] or not to be an entire bee,
+\item[]
+\begin{DUlineblock}{\DUlineblockindent}
+\item[] when half the bee is not a bee,
+\item[]
+\begin{DUlineblock}{\DUlineblockindent}
+\item[] due to some ancient injury?
+\item[]
+\end{DUlineblock}
+\end{DUlineblock}
+\end{DUlineblock}
+\item[] Singing…
+\end{DUlineblock}
+\end{quote}
+
+A line block, like the following poem by Christian Morgenstern, can
+also be centre-aligned:
+
+\begin{selectlanguage}{german}
+\begin{DUlineblock}{0em}
+\centering
+\item[] \textbf{Die Trichter}
+\item[]
+\item[] Zwei Trichter wandeln durch die Nacht.
+\item[] Durch ihres Rumpfs verengten Schacht
+\item[] fließt weißes Mondlicht
+\item[] still und heiter
+\item[] auf ihren
+\item[] Waldweg
+\item[] u. s.
+\item[] w.
+\item[]
+\end{DUlineblock}
+\end{selectlanguage}
+
+
+\subsection{2.9 Block Quotes%
+ \label{block-quotes}%
+}
+
+Block quotes consist of indented body elements:
+
+\begin{quote}
+My theory by A. Elk. Brackets Miss, brackets. This theory goes
+as follows and begins now. All brontosauruses are thin at one
+end, much much thicker in the middle and then thin again at the
+far end. That is my theory, it is mine, and belongs to me and I
+own it, and what it is too.
+\nopagebreak
+
+\raggedleft —Anne Elk (Miss)
+\end{quote}
+
+The language of a quote (like any other object) can be specified by
+a class attribute:
+
+%
+
+\begin{selectlanguage}{french}
+\begin{quote}
+ReStructuredText est un langage de balisage léger utilisé
+notamment dans la documentation du langage Python.
+\end{quote}
+\end{selectlanguage}
+
+
+\subsection{2.10 Doctest Blocks%
+ \label{doctest-blocks}%
+}
+
+\begin{quote}
+\begin{alltt}
+>>> print 'Python-specific usage examples; begun with ">>>"'
+Python-specific usage examples; begun with ">>>"
+>>> print '(cut and pasted from interactive Python sessions)'
+(cut and pasted from interactive Python sessions)
+\end{alltt}
+\end{quote}
+
+
+\subsection{2.11 Footnotes%
+ \label{footnotes}%
+}
+%
+\DUfootnotetext{footnote-1}{footnote-reference-1}{1}{%
+A footnote contains body elements, consistently indented by at
+least 3 spaces.
+
+This is the footnote’s second paragraph.
+}
+%
+\DUfootnotetext{label}{footnote-reference-3}{2}{\phantomsection\label{label}%
+Footnotes may be numbered, either manually (as in\DUfootnotemark{footnote-reference-5}{footnote-1}{1}) or
+automatically using a “\#”-prefixed label. This footnote has a
+label so it can be referred to from multiple places, both as a
+footnote reference (\DUfootnotemark{footnote-reference-6}{label}{2}) and as a \hyperref[label]{hyperlink reference}.
+}
+%
+\DUfootnotetext{footnote-2}{footnote-reference-2}{3}{%
+This footnote is numbered automatically and anonymously using a
+label of “\#” only.
+
+This is the second paragraph.
+
+And this is the third paragraph.
+}
+%
+\DUfootnotetext{footnote-3}{footnote-reference-4}{*}{%
+Footnotes may also use symbols, specified with a “*” label.
+Here’s a reference to the next footnote:\DUfootnotemark{footnote-reference-7}{footnote-4}{†}.
+}
+%
+\DUfootnotetext{footnote-4}{footnote-reference-7}{†}{%
+This footnote shows the next symbol in the sequence.
+}
+%
+\DUfootnotetext{footnote-5}{footnote-5}{4}{%
+Here’s an unreferenced footnote, with a reference to a
+nonexistent footnote:%
+\raisebox{1em}{\hypertarget{footnote-reference-8}{}}\hyperlink{system-message-2}{\textbf{\color{red}{[}5{]}\_}}.
+}
+
+
+\subsection{2.12 Citations%
+ \label{citations}%
+}
+\begin{figure}[b]\raisebox{1em}{\hypertarget{cit2002}{}}[CIT2002]
+Citations are text-labeled footnotes. They may be
+rendered separately and differently from footnotes.
+\end{figure}
+
+Here’s a reference to the above, \hyperlink{cit2002}{[CIT2002]}, and a %
+\raisebox{1em}{\hypertarget{citation-reference-3}{}}\hyperlink{system-message-3}{\textbf{\color{red}{[}nonexistent{]}\_}}
+citation.
+
+
+\subsection{2.13 Targets%
+ \label{targets}%
+ \label{another-target}%
+}
+
+\phantomsection\label{example}
+This paragraph is pointed to by the explicit “example” target. A
+reference can be found under \hyperref[inline-markup]{Inline Markup}, above. \hyperref[inline-hyperlink-targets]{Inline
+hyperlink targets} are also possible.
+
+Section headers are implicit targets, referred to by name. See
+\hyperref[targets]{Targets}, which is a subsection of \hyperref[body-elements]{Body Elements}.
+
+Explicit external targets are interpolated into references such as
+“\href{http://www.python.org/}{Python}\DUfootnotemark{footnote-reference-11}{footnote-6}{5}”.
+
+Targets may be indirect and anonymous. Thus \hyperref[targets]{this phrase} may also
+refer to the \hyperref[targets]{Targets} section.
+
+Here’s a %
+\raisebox{1em}{\hypertarget{problematic-2}{}}\hyperlink{system-message-4}{\textbf{\color{red}`hyperlink reference without a target`\_}}, which generates an
+error.
+
+
+\subsubsection{2.13.1 Duplicate Target Names%
+ \label{duplicate-target-names}%
+}
+
+Duplicate names in section headers or other implicit targets will
+generate “info” (level-1) system messages. Duplicate names in
+explicit targets will generate “warning” (level-2) system messages.
+
+
+\subsubsection{2.13.2 Duplicate Target Names%
+ \label{duplicate-target-names-1}%
+}
+
+Since there are two “Duplicate Target Names” section headers, we
+cannot uniquely refer to either of them by name. If we try to (like
+this: %
+\raisebox{1em}{\hypertarget{problematic-3}{}}\hyperlink{system-message-5}{\textbf{\color{red}`Duplicate Target Names`\_}}), an error is generated.
+
+
+\subsection{2.14 Directives%
+ \label{directives}%
+}
+
+\phantomsection\label{contents}
+These are just a sample of the many reStructuredText Directives. For
+others, please see
+\url{http://docutils.sourceforge.net/docs/ref/rst/directives.html}.
+
+
+\subsubsection{2.14.1 Document Parts%
+ \label{document-parts}%
+}
+
+An example of the “contents” directive can be seen above this section
+(a local, untitled table of \hyperref[contents]{contents}) and at the beginning of the
+document (a document-wide \hyperref[table-of-contents]{table of contents}).
+
+
+\subsubsection{2.14.2 Images and Figures%
+ \label{images-and-figures}%
+}
+
+An image directive (also clickable – a hyperlink reference):
+
+\hyperref[directives]{\includegraphics{../../../docs/user/rst/images/title.png}}
+
+Image with multiple IDs:
+
+\includegraphics{../../../docs/user/rst/images/title.png}
+\phantomsection\label{image-target-3}\label{image-target-2}\label{image-target-1}
+
+A centered image:
+
+\noindent\makebox[\linewidth][c]{\includegraphics{../../../docs/user/rst/images/biohazard.png}}
+
+A left-aligned image:
+
+\noindent{\includegraphics{../../../docs/user/rst/images/biohazard.png}\hfill}
+
+This paragraph might flow around the image.
+The specific behavior depends upon the style sheet and
+the browser or rendering software used.
+
+A right-aligned image:
+
+\noindent{\hfill\includegraphics{../../../docs/user/rst/images/biohazard.png}}
+
+This paragraph might flow around the image.
+The specific behavior depends upon the style sheet and
+the browser or rendering software used.
+
+For inline images see \hyperref[substitution-definitions]{Substitution Definitions}.
+
+Image size:
+
+An image 2 em wide:
+
+\includegraphics[width=2em]{../../../docs/user/rst/images/biohazard.png}
+
+An image 2 em wide and 15 pixel high:
+
+\includegraphics[height=15\pdfpxdimen,width=2em]{../../../docs/user/rst/images/biohazard.png}
+
+An image occupying 50\% of the line width:
+
+\includegraphics[width=0.500\linewidth]{../../../docs/user/rst/images/title.png}
+
+An image 2 cm high:
+
+\includegraphics[height=2cm]{../../../docs/user/rst/images/biohazard.png}
+
+A \emph{figure} is an image with a caption and/or a legend. With page-based output
+media, figures might float to a different position if this helps the page
+layout.
+
+\begin{DUclass}{figclass1}
+\begin{DUclass}{figclass2}
+\begin{figure}
+\noindent\makebox[\linewidth][c]{\includegraphics[width=258bp]{../../../docs/user/rst/images/title.png}}
+\caption{Plaintext markup syntax and parser system.}
+\begin{DUlegend}
+\setlength{\DUtablewidth}{\linewidth}
+\begin{longtable*}[c]{|p{0.156\DUtablewidth}|p{0.563\DUtablewidth}|}
+\hline
+
+re
+ &
+Revised, revisited, based on ‘re’ module.
+ \\
+\hline
+
+Structured
+ &
+Structure-enhanced text, structuredtext.
+ \\
+\hline
+
+Text
+ &
+Well it is, isn’t it?
+ \\
+\hline
+\end{longtable*}
+
+This paragraph is also part of the legend.
+\end{DUlegend}
+\end{figure}
+\end{DUclass}
+\end{DUclass}
+
+A left-aligned figure:
+
+\begin{DUclass}{figclass1}
+\begin{DUclass}{figclass2}
+\begin{figure} % align = "left"
+\noindent\makebox[\linewidth][c]{\includegraphics[width=40\pdfpxdimen]{../../../docs/user/rst/images/biohazard.png}}
+\caption{This is the caption.}
+\begin{DUlegend}
+This is the legend.
+
+The legend may consist of several paragraphs.
+\end{DUlegend}
+\end{figure}
+\end{DUclass}
+\end{DUclass}
+
+This paragraph might flow around the figure.
+
+The specific behavior depends upon the style sheet and the browser or
+rendering software used.
+
+A centered figure:
+
+\begin{figure}
+\noindent\makebox[\linewidth][c]{\includegraphics[width=40\pdfpxdimen]{../../../docs/user/rst/images/biohazard.png}}
+\caption{This is the caption.}
+\begin{DUlegend}
+This is the legend.
+
+The legend may consist of several paragraphs.
+\end{DUlegend}
+\end{figure}
+
+This paragraph might flow around the figure.
+
+The specific behavior depends upon the style sheet and the browser or
+rendering software used.
+
+A right-aligned figure:
+
+\begin{figure} % align = "right"
+\noindent\makebox[\linewidth][c]{\includegraphics[width=40\pdfpxdimen]{../../../docs/user/rst/images/biohazard.png}}
+\caption{This is the caption.}
+\begin{DUlegend}
+This is the legend.
+
+The legend may consist of several paragraphs.
+\end{DUlegend}
+\end{figure}
+
+This paragraph might flow around the figure. The specific behavior depends
+upon the style sheet and the browser or rendering software used.
+
+Tables may be given titles and additional arguments with the \emph{table}
+directive:
+
+\setlength{\DUtablewidth}{\linewidth}
+\begin{longtable}[l]{|p{0.075\DUtablewidth}|p{0.075\DUtablewidth}|}
+\caption{left-aligned table}\\
+\hline
+\textbf{%
+A
+} & \textbf{%
+not A
+} \\
+\hline
+\endfirsthead
+\caption[]{left-aligned table (... continued)}\\
+\hline
+\textbf{%
+A
+} & \textbf{%
+not A
+} \\
+\hline
+\endhead
+\multicolumn{2}{c}{\hfill ... continued on next page} \\
+\endfoot
+\endlastfoot
+
+False
+ &
+True
+ \\
+\hline
+
+True
+ &
+False
+ \\
+\hline
+\end{longtable}
+
+\setlength{\DUtablewidth}{\linewidth}
+\begin{longtable}[c]{|p{0.075\DUtablewidth}|p{0.075\DUtablewidth}|}
+\caption{center-aligned table}\\
+\hline
+\textbf{%
+A
+} & \textbf{%
+not A
+} \\
+\hline
+\endfirsthead
+\caption[]{center-aligned table (... continued)}\\
+\hline
+\textbf{%
+A
+} & \textbf{%
+not A
+} \\
+\hline
+\endhead
+\multicolumn{2}{c}{\hfill ... continued on next page} \\
+\endfoot
+\endlastfoot
+
+False
+ &
+True
+ \\
+\hline
+
+True
+ &
+False
+ \\
+\hline
+\end{longtable}
+
+\setlength{\DUtablewidth}{\linewidth}
+\begin{longtable}[r]{|p{0.075\DUtablewidth}|p{0.075\DUtablewidth}|}
+\caption{right-aligned table}\\
+\hline
+\textbf{%
+A
+} & \textbf{%
+not A
+} \\
+\hline
+\endfirsthead
+\caption[]{right-aligned table (... continued)}\\
+\hline
+\textbf{%
+A
+} & \textbf{%
+not A
+} \\
+\hline
+\endhead
+\multicolumn{2}{c}{\hfill ... continued on next page} \\
+\endfoot
+\endlastfoot
+
+False
+ &
+True
+ \\
+\hline
+
+True
+ &
+False
+ \\
+\hline
+\end{longtable}
+
+With the “widths” argument “auto” (or “class” value “colwidths-auto”),
+column widths are determined by the backend (if supported by the
+writer/backend).
+
+\begin{longtable*}[c]{|l|l|l|}
+\hline
+\textbf{A} & \textbf{B} & \textbf{A or B} \\
+\hline
+\endfirsthead
+\hline
+\textbf{A} & \textbf{B} & \textbf{A or B} \\
+\hline
+\endhead
+\multicolumn{3}{c}{\hfill ... continued on next page} \\
+\endfoot
+\endlastfoot
+False & False & False \\
+\hline
+True & False & True \\
+\hline
+False & True & True \\
+\hline
+True & True & True \\
+\hline
+\end{longtable*}
+\label{target2}\label{target1}
+
+
+\subsubsection{2.14.3 Admonitions%
+ \label{admonitions}%
+}
+
+\DUadmonition[attention]{
+\DUtitle[attention]{Attention!}
+
+Directives at large.
+}
+
+\DUadmonition[caution]{
+\DUtitle[caution]{Caution!}
+
+Don’t take any wooden nickels.
+}
+
+\DUadmonition[danger]{
+\DUtitle[danger]{!DANGER!}
+
+Mad scientist at work!
+}
+
+\DUadmonition[error]{
+\DUtitle[error]{Error}
+
+Does not compute.
+}
+
+\DUadmonition[hint]{
+\DUtitle[hint]{Hint}
+
+It’s bigger than a bread box.
+}
+
+\DUadmonition[important]{
+\DUtitle[important]{Important}
+
+\begin{itemize}
+\item Wash behind your ears.
+
+\item Clean up your room.
+
+\item Call your mother.
+
+\item Back up your data.
+\end{itemize}
+}
+
+\DUadmonition[note]{
+\DUtitle[note]{Note}
+
+This is a note.
+}
+
+\DUadmonition[tip]{
+\DUtitle[tip]{Tip}
+
+15\% if the service is good.
+}
+
+\DUadmonition[warning]{
+\DUtitle[warning]{Warning}
+
+Strong prose may provoke extreme mental exertion.
+Reader discretion is strongly advised.
+}
+
+\DUadmonition[admonition-and-by-the-way]{
+\DUtitle[admonition-and-by-the-way]{And, by the way…}
+
+You can make up your own admonition too.
+}
+
+
+\subsubsection{2.14.4 Topics, Sidebars, and Rubrics%
+ \label{topics-sidebars-and-rubrics}%
+}
+
+\emph{Sidebars} are like miniature, parallel documents.
+
+\DUsidebar{
+\DUtitle[sidebar]{Sidebar Title}
+
+\DUsubtitle{Optional Subtitle}
+
+This is a sidebar. It is for text outside the flow of the main
+text.
+
+\DUrubric{This is a rubric inside a sidebar}
+
+Sidebars often appear beside the main text with a border and a different
+background or font color.
+}
+
+A \emph{topic} is like a block quote with a title, or a self-contained section
+with no subsections.
+
+\begin{DUclass}{topic}
+\begin{quote}
+\DUtitle[topic]{Topic Title}
+
+This is a topic.
+\end{quote}
+\end{DUclass}
+
+A \emph{rubric} is like an informal heading that doesn’t correspond to the
+document’s structure. It is typically highlighted in red (hence the name).
+
+\DUrubric{This is a rubric}
+
+Topics and rubrics can be used at places where a \hyperref[section-title]{section title} is not
+allowed (e.g. inside a directive).
+
+
+\subsubsection{2.14.5 Target Footnotes%
+ \label{target-footnotes}%
+}
+%
+\DUfootnotetext{footnote-6}{footnote-reference-10}{5}{%
+\url{http://www.python.org/}
+}
+%
+\DUfootnotetext{footnote-7}{footnote-reference-13}{6}{%
+\url{http://pygments.org/}
+}
+%
+\DUfootnotetext{footnote-8}{footnote-reference-14}{7}{%
+\url{ftp://ftp.ams.org/ams/doc/amsmath/short-math-guide.pdf}
+}
+%
+\DUfootnotetext{footnote-9}{footnote-reference-16}{8}{%
+\url{http://ctan.org/pkg/polyglossia}
+}
+%
+\DUfootnotetext{footnote-10}{footnote-reference-18}{9}{%
+\url{http://docutils.sourceforge.net/}
+}
+%
+\DUfootnotetext{footnote-11}{footnote-reference-19}{10}{%
+\url{A:DOS\\path\\}
+}
+
+
+\subsubsection{2.14.6 Replacement Text%
+ \label{replacement-text}%
+}
+
+I recommend you try \href{http://www.python.org/}{Python, \emph{the} best language around}\DUfootnotemark{footnote-reference-12}{footnote-6}{5}.
+
+
+\subsubsection{2.14.7 Compound Paragraph%
+ \label{compound-paragraph}%
+}
+
+The \emph{compound} directive is used to create a “compound paragraph”, which
+is a single logical paragraph containing multiple physical body
+elements. For example:
+
+\begin{DUclass}{compound}
+The ‘rm’ command is very dangerous. If you are logged
+in as root and enter
+\begin{quote}
+\begin{alltt}
+cd /
+rm -rf *
+\end{alltt}
+\end{quote}
+you will erase the entire contents of your file system.
+\end{DUclass}
+
+Test the handling and display of compound paragraphs:
+
+\begin{DUclass}{compound}
+\begin{DUclass}{some-class}
+Compound 2, paragraph 1,
+
+compound 2, paragraph 2,
+\begin{itemize}
+\item list item 1,
+
+\item list item 2,
+\end{itemize}
+compound 2, paragraph 3.
+\end{DUclass}
+\end{DUclass}
+
+\begin{DUclass}{compound}
+Compound 3, only consisting of one paragraph.
+\end{DUclass}
+
+\begin{DUclass}{compound}
+\begin{quote}
+\begin{alltt}
+Compound 4.
+This one starts with a literal block.
+\end{alltt}
+\end{quote}
+Compound 4, paragraph following the literal block.
+\end{DUclass}
+
+Now something \emph{really} perverted – a nested compound block. This is
+just to test that it works at all; the results don’t have to be
+meaningful.
+
+\begin{DUclass}{compound}
+Compound 5, block 1 (a paragraph).
+
+\begin{DUclass}{compound}
+Compound 6 is block 2 in compound 5.
+
+Compound 6, another paragraph.
+\end{DUclass}
+
+Compound 5, block 3 (a paragraph).
+\end{DUclass}
+
+\begin{DUclass}{compound}
+Compound 7, tests the inclusion of various block-level
+elements in one logical paragraph. First a table,
+
+\setlength{\DUtablewidth}{\linewidth}
+\begin{longtable*}[c]{|p{0.249\DUtablewidth}|p{0.249\DUtablewidth}|p{0.249\DUtablewidth}|}
+\hline
+
+Left cell, first
+paragraph.
+
+Left cell, second
+paragraph.
+ &
+Middle cell,
+consisting of
+exactly one
+paragraph.
+ &
+Right cell.
+
+Paragraph 2.
+
+Paragraph 3.
+ \\
+\hline
+\end{longtable*}
+followed by a paragraph. This physical paragraph is
+actually a continuation of the paragraph before the table. It is followed
+by
+\begin{quote}
+a quote and
+\end{quote}
+\begin{enumerate}
+\item an enumerated list,
+\end{enumerate}
+a paragraph,
+\begin{DUoptionlist}
+\item[--an] option list,
+\end{DUoptionlist}
+a paragraph,
+\begin{DUfieldlist}
+\item[{a field:}]
+list,
+\end{DUfieldlist}
+a paragraph,
+\begin{description}
+\item[{a definition}] \leavevmode
+list,
+
+\end{description}
+a paragraph, an image:
+\includegraphics{../../../docs/user/rst/images/biohazard.png}
+a paragraph,
+\begin{DUlineblock}{0em}
+\item[] a line
+\item[] block,
+\end{DUlineblock}
+a paragraph followed by a comment,
+% this is a comment
+a paragraph, a
+
+\DUadmonition[note]{
+\DUtitle[note]{Note}
+
+with content
+}
+and the final paragraph of the compound 7.
+\end{DUclass}
+
+
+\subsubsection{2.14.8 Parsed Literal Blocks%
+ \label{parsed-literal-blocks}%
+}
+
+\begin{quote}
+\ttfamily\raggedright
+This~is~a~parsed~literal~block.\\
+~~~~This~line~is~indented.~~The~next~line~is~blank.\\
+~\\
+Inline~markup~is~supported,~e.g.~\emph{emphasis},~\textbf{strong},~\texttt{literal\\
+text},~\textsubscript{sub-}~and~\textsuperscript{super}scripts,\\
+inline~formulas:~$A = 2 \pi r^2$,\\
+footnotes\DUfootnotemark{footnote-reference-9}{footnote-1}{1},~%
+\phantomsection\label{hyperlink-targets}hyperlink~targets,~and~\href{http://www.python.org/}{references}.
+\end{quote}
+
+
+\subsubsection{2.14.9 Code%
+ \label{code}%
+}
+
+Blocks of source code can be set with the \DUroletitlereference{code} directive. If the code
+language is specified, the content is parsed and tagged by the \href{http://pygments.org/}{Pygments}\DUfootnotemark{footnote-reference-13}{footnote-7}{6}
+syntax highlighter and can be formatted with a style sheet. (Code parsing
+is turned off using the \texttt{syntax-highlight} config setting in the test
+conversions in order to get identical results with/without installed
+Pygments highlighter.)
+
+\begin{DUclass}{code}
+\begin{DUclass}{python}
+\begin{quote}
+\begin{alltt}
+print 'This is Python code.'
+\end{alltt}
+\end{quote}
+\end{DUclass}
+\end{DUclass}
+
+The \texttt{:number-lines:} option (with optional start value) generates line
+numbers:
+
+\begin{DUclass}{code}
+\begin{DUclass}{python}
+\begin{quote}
+\ttfamily\raggedright
+\DUrole{ln}{~8~}\#~print~integers~from~0~to~9:\\
+\DUrole{ln}{~9~}for~i~in~range(10):\\
+\DUrole{ln}{10~}~~~~print~i
+\end{quote}
+\end{DUclass}
+\end{DUclass}
+
+For inline code snippets, there is the \DUroletitlereference{code} role, which can be used
+directly (the code will not be parsed/tagged, as the language is not known)
+or as base for special code roles, e.g. the LaTeX code in the next
+paragraph.
+
+Docutils uses LaTeX syntax for math directives and roles:
+\texttt{\DUrole{code}{\DUrole{tex}{\textbackslash{}alpha = f(x)}}} prints $\alpha = f(x)$.
+
+The \texttt{:code:} option of the \DUroletitlereference{include} directive sets the included content
+as a code block, here the rst file \texttt{header\_footer.txt} with line numbers:
+
+\begin{DUclass}{code}
+\begin{DUclass}{rst}
+\begin{quote}
+\ttfamily\raggedright
+\DUrole{ln}{1~}..~header::~Document~header\\
+\DUrole{ln}{2~}..~footer::~Document~footer
+\end{quote}
+\end{DUclass}
+\end{DUclass}
+
+
+\subsection{2.15 Substitution Definitions%
+ \label{substitution-definitions}%
+}
+
+An inline image (\includegraphics{../../../docs/user/rst/images/biohazard.png}) example:
+
+A Unicode example:
+
+(Substitution definitions are not visible in the HTML source.)
+
+
+\subsection{2.16 Comments%
+ \label{comments}%
+}
+
+Here’s one:
+
+% Comments begin with two dots and a space. Anything may
+% follow, except for the syntax of footnotes, hyperlink
+% targets, directives, or substitution definitions.
+%
+% Double-dashes -- "--" -- must be escaped somehow in HTML output.
+%
+% Comments may contain non-ASCII characters: ä ö ü æ ø å
+
+(View the HTML source to see the comment.)
+
+
+\subsection{2.17 Raw text%
+ \label{raw-text}%
+}
+
+This does not necessarily look nice, because there may be missing white space.
+
+It’s just there to freeze the behavior.
+
+A test.
+
+Second test.
+
+\DUrole{myclass}{Another test with myclass set.}
+
+This is the \DUrole{myrawroleclass}{fourth test} with myrawroleclass set.
+
+Fifth test in LaTeX.\\Line two.
+
+
+\subsection{2.18 Container%
+ \label{container}%
+}
+
+\begin{DUclass}{custom}
+
+paragraph 1
+
+paragraph 2
+\end{DUclass}
+
+% currently not implemented in LaTeX:
+% .. include:: data/header_footer.txt
+
+
+\subsection{2.19 Colspanning tables%
+ \label{colspanning-tables}%
+}
+
+This table has a cell spanning two columns:
+
+\setlength{\DUtablewidth}{\linewidth}
+\begin{longtable*}[c]{|p{0.075\DUtablewidth}|p{0.075\DUtablewidth}|p{0.086\DUtablewidth}|}
+\hline
+\multicolumn{2}{|p{0.15\DUtablewidth}|}{\textbf{%
+Inputs
+}} & \textbf{%
+Output
+} \\
+\hline
+\textbf{%
+A
+} & \textbf{%
+B
+} & \textbf{%
+A or B
+} \\
+\hline
+\endfirsthead
+\hline
+\multicolumn{2}{|p{0.15\DUtablewidth}|}{\textbf{%
+Inputs
+}} & \textbf{%
+Output
+} \\
+\hline
+\textbf{%
+A
+} & \textbf{%
+B
+} & \textbf{%
+A or B
+} \\
+\hline
+\endhead
+\multicolumn{3}{c}{\hfill ... continued on next page} \\
+\endfoot
+\endlastfoot
+
+False
+ &
+False
+ &
+False
+ \\
+\hline
+
+True
+ &
+False
+ &
+True
+ \\
+\hline
+
+False
+ &
+True
+ &
+True
+ \\
+\hline
+
+True
+ &
+True
+ &
+True
+ \\
+\hline
+\end{longtable*}
+
+
+\subsection{2.20 Rowspanning tables%
+ \label{rowspanning-tables}%
+}
+
+Here’s a table with cells spanning several rows:
+
+\setlength{\DUtablewidth}{\linewidth}
+\begin{longtable*}[c]{|p{0.296\DUtablewidth}|p{0.156\DUtablewidth}|p{0.226\DUtablewidth}|}
+\hline
+\textbf{%
+Header row, column 1
+(header rows optional)
+} & \textbf{%
+Header 2
+} & \textbf{%
+Header 3
+} \\
+\hline
+\endfirsthead
+\hline
+\textbf{%
+Header row, column 1
+(header rows optional)
+} & \textbf{%
+Header 2
+} & \textbf{%
+Header 3
+} \\
+\hline
+\endhead
+\multicolumn{3}{c}{\hfill ... continued on next page} \\
+\endfoot
+\endlastfoot
+
+body row 1, column 1
+ &
+column 2
+ &
+column 3
+ \\
+\hline
+
+body row 2
+ & \multirow{2}{0.16\DUtablewidth}{%
+Cells may
+span rows.
+} & \multirow{2}{0.23\DUtablewidth}{%
+Another
+rowspanning
+cell.
+} \\
+\cline{1-1}
+
+body row 3
+ & & \\
+\hline
+\end{longtable*}
+
+
+\subsection{2.21 List Tables%
+ \label{list-tables}%
+}
+
+Here’s a list table exercising all features:
+
+\setlength{\DUtablewidth}{40em}
+\begin{longtable}[c]{|p{0.133\DUtablewidth}|p{0.249\DUtablewidth}|p{0.365\DUtablewidth}|}
+\caption{list table with integral header}\\
+\hline
+\textbf{%
+Treat
+} & \textbf{%
+Quantity
+} & \textbf{%
+Description
+} \\
+\hline
+\endfirsthead
+\caption[]{list table with integral header (... continued)}\\
+\hline
+\textbf{%
+Treat
+} & \textbf{%
+Quantity
+} & \textbf{%
+Description
+} \\
+\hline
+\endhead
+\multicolumn{3}{c}{\hfill ... continued on next page} \\
+\endfoot
+\endlastfoot
+\textbf{%
+Albatross
+} &
+2.99
+ &
+On a stick!
+ \\
+\hline
+\textbf{%
+Crunchy Frog
+} &
+1.49
+ &
+If we took the bones out, it wouldn’t be
+crunchy, now would it?
+ \\
+\hline
+\textbf{%
+Gannet Ripple
+} &
+1.99
+ &
+On a stick!
+ \\
+\hline
+\end{longtable}
+
+\begin{longtable}[c]{|l|l|}
+\caption{center aligned list table}\\
+\hline
+Albatross & 2.99 \\
+\hline
+Crunchy Frog & 1.49 \\
+\hline
+Gannet Ripple & 1.99 \\
+\hline
+\end{longtable}
+
+
+\subsection{2.22 Custom Roles%
+ \label{custom-roles}%
+}
+
+\begin{itemize}
+\item A role based on an existing role.
+
+\texttt{\DUrole{custom}{one}} \texttt{\DUrole{custom}{two}} \texttt{\DUrole{custom}{three}}
+
+\item A new role.
+
+\DUrole{customnew}{one two three}
+
+\item A role with class attribute.
+
+\DUrole{special}{interpreted text}
+
+\item A language-switching role:
+
+Let’s count in German \foreignlanguage{german}{eins zwei drei}.
+
+\item A role with multiple class attributes, styled with raw directives:
+
+\newcommand{\DUrolegreen}[1]{\textcolor{green}{#1}}
+\newcommand{\DUrolesc}[1]{\textsc{#1}}
+
+The following works in most browsers but does not validate
+(\texttt{<style>} is only allowed in the document head):
+
+\begin{quote}
+\begin{alltt}
+.. raw:: html
+
+ <style type="text/css"><!--
+ .green \{color: green;\}
+ .sc \{font-variant: small-caps;\}
+ --></style>
+\end{alltt}
+\end{quote}
+
+\DUrole{green}{\DUrole{sc}{\foreignlanguage{english}{British colourful text in small-caps}}}.
+\end{itemize}
+
+
+\subsection{2.23 Mathematics%
+ \label{mathematics}%
+}
+
+Docutils supports inline math with the prefix or postfix \texttt{:math:}
+role specificator, $n! + \sin(x_n^2)$ and $A_\text{c} =
+\frac{\pi}{4} d^2$, as well as displayed math via the
+\DUroletitlereference{math} directive:
+%
+\begin{equation*}
+f(\epsilon) = \frac{1}{1 + \exp\left(\frac{\varepsilon}{k_\text{B}T}\right)}
+\end{equation*}
+Content may start on the first line of the directive, e.g.
+%
+\begin{equation*}
+N = \frac{\text{number of apples}}{7}
+\end{equation*}
+Equations can be labeled with a reference name using the \texttt{:name:} option.
+See \hyperref[eq-m]{eq:M} and \hyperref[eq-schrodinger]{eq:schrödinger} below.
+
+The determinant of the matrix
+%
+\begin{equation*}
+\mathbf{M} = \left(\begin{matrix}a&b\\c&d\end{matrix}\right)
+\phantomsection
+\label{eq-m}
+\end{equation*}
+is $|\mathbf{M}| = ad - bc$.
+
+More than one display math block can be put in one math directive.
+For example, the following sum and integral with limits:
+%
+\begin{equation*}
+\int_0^1 x^n dx = \frac{1}{n + 1}
+\end{equation*}%
+\begin{equation*}
+\sum_{n=1}^m n = \frac{m(m+1)}{2}
+\end{equation*}
+LaTeX-supported Unicode math symbols can be used in math roles and
+directives:
+
+The Schrödinger equation
+%
+\begin{equation*}
+i\hbar \frac{\partial }{\partial t}\Psi = \hat{H}\Psi ,
+\phantomsection
+\label{eq-schrodinger}
+\end{equation*}
+with the \emph{wave function} $\Psi $, describes how the quantum state of a
+physical system changes in time.
+
+\begin{description}
+\item[{Math-Accents:}] \leavevmode
+\setlength{\DUtablewidth}{\linewidth}
+\begin{longtable*}[c]{p{0.315\DUtablewidth}p{0.315\DUtablewidth}p{0.315\DUtablewidth}}
+
+$\acute{a}$ \texttt{\textbackslash{}acute\{a\}}
+ &
+$\dot{t}$ \texttt{\textbackslash{}dot\{t\}}
+ &
+$\hat{\gamma}$ \texttt{\textbackslash{}hat\{\textbackslash{}gamma\}}
+ \\
+
+$\grave{a}$ \texttt{\textbackslash{}grave\{a\}}
+ &
+$\ddot{t}$ \texttt{\textbackslash{}ddot\{t\}}
+ &
+$\tilde{\alpha}$ \texttt{\textbackslash{}tilde\{\textbackslash{}alpha\}}
+ \\
+
+$\breve{x}$ \texttt{\textbackslash{}breve\{x\}}
+ &
+$\dddot{t}$ \texttt{\textbackslash{}dddot\{t\}}
+ &
+$\vec{\imath}$ \texttt{\textbackslash{}vec\{\textbackslash{}imath\}}
+ \\
+
+$\check{a}$ \texttt{\textbackslash{}check\{a\}}
+ &
+$\bar{a}$ \texttt{\textbackslash{}bar\{a\}}
+ &
+$\vec{R}$ \texttt{\textbackslash{}vec\{R\}}
+ \\
+\end{longtable*}
+
+\end{description}
+
+% \widetilde{xxx}
+% \widehat{xxx}
+
+Modulation Transfer Function:
+%
+\begin{equation*}
+\text{MTF} = \left|\frac{\mathcal{F}\{s(x)\}}
+ {\mathcal{F}\{ s(x)\} |_{\omega _{x}=0}}\right|
+ = \mathrm{abs}\left(\frac
+ {\int _{-\infty }^{\infty }s(x) \mathrm{e}^{\mathrm{i}\omega _{x}x}\mathrm{d}{x}}
+ {\int _{-\infty }^{\infty }s(x)\mathrm{d}{x}}
+ \right).
+\end{equation*}
+Math split over two lines: If a double backslash is detected outside a
+\texttt{\textbackslash{}begin\{...\} \textbackslash{}end\{...\}} pair, the math code is wrapped in an \href{ftp://ftp.ams.org/ams/doc/amsmath/short-math-guide.pdf}{AMSmath}\DUfootnotemark{footnote-reference-14}{footnote-8}{7}
+\texttt{align} environment:
+%
+\begin{align*}
+s_{\mathrm{out}}(x) & = s_{\mathrm{in}}(x') * s_\delta (x-x') \\
+ & = \int s_{\mathrm{in}}(x')s_\delta (x-x')\mathrm{d}x'
+\end{align*}
+Cases (“manually”, with \texttt{matrix} environment):
+%
+\begin{equation*}
+\mathrm{sgn}(x) = \left\{\begin{matrix}
+ -1 & x<0\\
+ 1 & x>0
+ \end{matrix}\right.
+\end{equation*}
+Cases with the \href{ftp://ftp.ams.org/ams/doc/amsmath/short-math-guide.pdf}{AMSmath}\DUfootnotemark{footnote-reference-15}{footnote-8}{7} \texttt{cases} environment (not (yet) supported by
+HTML writers with \texttt{--math-output=MathML}):
+%
+\begin{equation*}
+\mathrm{sgn}(x) = \begin{cases}
+ -1 & x<0\\
+ 1 & x>0
+ \end{cases}
+\end{equation*}
+
+\section{3 Tests for the LaTeX writer%
+ \label{tests-for-the-latex-writer}%
+}
+
+Test syntax elements which may cause trouble for the LaTeX writer but might
+not need to be tested with other writers (e.g. the HTML writer).
+
+
+\subsection{3.1 Custom Roles in LaTeX%
+ \label{custom-roles-in-latex}%
+}
+
+\begin{itemize}
+\item Role names and class arguments are converted to conform to the
+regular expression \texttt{{[}a-z{]}{[}-a-z0-9{]}*} (letters are downcased,
+accents and similar decoration is stripped, non-conforming
+characters are replaced by a hyphen).
+
+Class arguments may contain numbers and hyphens, which need special
+treatment in LaTeX command names.
+
+\DUrole{large}{\DUrole{custom4}{\DUrole{small-caps}{\DUrole{custom-role}{\DUrole{custom-role}{Text with role “custom4”}}}}} (but without styling by \texttt{DUrole*}
+macros).
+
+\item With LaTeX, roles can be styled within the document using the \DUroletitlereference{raw}
+directive.
+
+\newcommand{\DUrolelarge}[1]{{\large #1}}
+\makeatletter
+\@namedef{DUrolesmall-caps}{\textsc}
+\@namedef{DUrolecustom4}{\textbf}
+\makeatother
+
+\DUrole{large}{\DUrole{custom4}{\DUrole{small-caps}{\DUrole{custom-role}{\DUrole{custom-role}{inline text}}}}} in large, bold, small-caps.
+
+\item Custom roles can be based on standard roles:
+
+This is a \emph{\DUrole{custom-emphasis}{customized emphasis text role}}
+
+This is a \texttt{\DUrole{custom-literal}{customized literal text role}}
+
+This is a \textbf{\DUrole{custom-strong}{customized strong text role}}
+
+This is a \textsubscript{\DUrole{custom-subscript}{customized subscript text role}}
+
+This is a \textsuperscript{\DUrole{custom-superscript}{customized superscript text role}}
+
+This is a \DUroletitlereference{\DUrole{custom-title-reference}{customized title-reference text role}}
+\end{itemize}
+
+
+\subsection{3.2 class handling%
+ \label{class-handling}%
+}
+
+This section tests class handling for block level elements by the LaTeX
+writer. See the input file \texttt{classes\_latex.txt} for the raw LaTeX code used
+to style the examples.
+
+An “epigraph” directive is exported as “quote” wrapped in a “DUclass”
+environment. Here, it is styled by a “DUCLASSepigraph” environment
+redefining the “quote” environment as “minipage”:
+
+\newcommand*{\DUCLASSepigraph}{%
+ \renewenvironment{quote}{\vspace{1em}
+ \footnotesize\hfill{}%
+ \begin{minipage}{0.4\columnwidth}}%
+ {\end{minipage}\vskip\baselineskip}}
+
+\begin{DUclass}{epigraph}
+\begin{quote}
+Do not play this piece fast. It is never right to play \emph{Ragtime} fast.
+\nopagebreak
+
+\raggedleft —Scott Joplin
+\end{quote}
+\end{DUclass}
+
+Raw latex is also used to style the following lists: “DUCLASSenumerateitems”
+redefines “itemize” as “enumerate”, “DUCLASSrules” draws horizontal lines
+above and below.
+
+\newcommand*{\DUCLASSenumerateitems}{%
+ \renewenvironment{itemize}{\begin{enumerate}}%
+ {\end{enumerate}}%
+}
+
+\newenvironment{DUCLASSrules}%
+ {\noindent\rule[0.5ex]{1\columnwidth}{1pt}}%
+ {\noindent\rule[0.5ex]{1\columnwidth}{1pt}}
+
+An “enumerated” bullet list:
+
+\begin{DUclass}{enumerateitems}
+\begin{itemize}
+\item item
+
+\item next item
+
+\item third item
+\end{itemize}
+\end{DUclass}
+
+A list with lines above and below:
+
+\begin{DUclass}{rules}
+\begin{itemize}
+\item item
+
+\item next item
+\end{itemize}
+\end{DUclass}
+
+A normal bullet list is kept unchanged by the above redefinitions:
+
+\begin{itemize}
+\item item
+
+\item next item
+
+\item third item
+\end{itemize}
+
+A container wraps several elements in a common “class wrapper”. Here, we use
+it to set 2 paragraphs and a list in small caps:
+
+\newcommand*{\DUCLASSscshape}{\scshape}
+
+\begin{DUclass}{scshape}
+
+paragraph 1
+
+paragraph 2
+
+\begin{itemize}
+\item bullet list
+
+\item still bullet list
+\end{itemize}
+\end{DUclass}
+
+A right-aligned line-block. Alignment handling is built into the latex
+writer for image, table, and line block elements.
+
+\begin{DUlineblock}{0em}
+\raggedleft
+\item[] Max Mustermann
+\item[] Waldstr. 22
+\item[] D 01234 Testdorf
+\item[] Tel.: 0123/456789
+\end{DUlineblock}
+
+
+\subsection{3.3 More Tables%
+ \label{more-tables}%
+}
+
+A table with multi-paragraph multicolumn cells:
+
+\setlength{\DUtablewidth}{\linewidth}
+\begin{longtable*}[c]{|p{0.133\DUtablewidth}|p{0.179\DUtablewidth}|p{0.179\DUtablewidth}|p{0.110\DUtablewidth}|p{0.121\DUtablewidth}|p{0.145\DUtablewidth}|}
+\hline
+
+test
+ &
+\textbf{bold hd}
+ & \multicolumn{3}{p{0.41\DUtablewidth}|}{%
+multicolumn 1
+
+With a second paragraph
+} &
+\emph{emph hd}
+ \\
+\hline
+\multicolumn{2}{|p{0.31\DUtablewidth}|}{%
+multicolumn 2
+
+With a second paragraph
+} &
+cell
+ &
+cell
+ &
+cell
+ &
+cell
+ \\
+\hline
+
+cell
+ & \multicolumn{2}{p{0.36\DUtablewidth}|}{%
+multicolumn 3 (one line,
+but very very very very
+very looooong)
+} &
+cell
+ &
+cell
+ &
+cell
+ \\
+\hline
+
+cell
+ &
+cell
+ &
+cell
+ & \multicolumn{3}{p{0.38\DUtablewidth}|}{%
+Short multicolumn 4
+} \\
+\hline
+\end{longtable*}
+
+Tables with multi-paragraph multirow cells currently fail due to a LaTeX
+limitation (see \url{https://sourceforge.net/p/docutils/bugs/225/}).
+
+A table with multirow header and column-widths set by LaTeX:
+
+\begin{longtable*}[c]{|l|l|}
+\hline
+\multirow{2}{*}{\textbf{XXX}} & \textbf{Variable Summary} \\
+\cline{2-2}
+ & \textbf{Description} \\
+\hline
+\endfirsthead
+\hline
+\multirow{2}{*}{\textbf{XXX}} & \textbf{Variable Summary} \\
+\cline{2-2}
+ & \textbf{Description} \\
+\hline
+\endhead
+\multicolumn{2}{c}{\hfill ... continued on next page} \\
+\endfoot
+\endlastfoot
+\multicolumn{2}{|l|}{multicollumn cell} \\
+\hline
+\end{longtable*}
+
+In a table with column-widths set by LaTeX, each cell has just one line.
+Paragraphs are merged (a warning is given).
+
+\begin{longtable*}[c]{|l|l|}
+\hline
+11 & first paragraph
+second paragraph
+third paragraph \\
+\hline
+21 & 22 \\
+\hline
+\end{longtable*}
+
+% This file is used by the standalone_rst_latex test.
+
+
+\subsection{3.4 Option lists%
+ \label{option-lists-1}%
+}
+
+The LaTeX-2e description environment is used for definition lists.
+The definition is continued on the same line as the term, this should
+not happen if a option-list is at the top of the definition.
+
+If the option list is not at the first element in the definition, it
+is contained in a quote
+
+\begin{quote}
+\begin{DUoptionlist}
+\item[--help] show help
+
+\item[-v] verbose
+\end{DUoptionlist}
+\end{quote}
+
+\begin{description}
+\item[{In a definition list:}] \leavevmode
+\begin{DUoptionlist}
+\item[--help] show help
+
+\item[-v] verbose
+\end{DUoptionlist}
+
+\end{description}
+
+
+\subsection{3.5 Monospaced non-alphanumeric characters%
+ \label{monospaced-non-alphanumeric-characters}%
+}
+
+These are all ASCII characters except a-zA-Z0-9 and space:
+
+\texttt{!!!\textquotedbl{}\textquotedbl{}\textquotedbl{}\#\#\#\$\$\$\%\%\%\&\&\&'''((()))***+++,,,---...///:::}
+
+\texttt{;;;<<<===>>>???@@@{[}{[}{[}\textbackslash{}\textbackslash{}\textbackslash{}{]}{]}{]}\textasciicircum{}\textasciicircum{}\textasciicircum{}\_\_\_```\{\{\{|||\}\}\}\textasciitilde{}\textasciitilde{}\textasciitilde{}}
+
+\texttt{xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx}
+
+The two lines of non-alphanumeric characters should both have the same
+width as the third line.
+
+
+\subsection{3.6 Non-ASCII characters%
+ \label{non-ascii-characters}%
+}
+
+Punctuation and footnote symbols
+
+\setlength{\DUtablewidth}{\linewidth}
+\begin{longtable*}[c]{|p{0.028\DUtablewidth}|p{0.424\DUtablewidth}|}
+\hline
+
+–
+ &
+en-dash
+ \\
+\hline
+
+—
+ &
+em-dash
+ \\
+\hline
+
+‘
+ &
+single turned comma quotation mark
+ \\
+\hline
+
+’
+ &
+single comma quotation mark
+ \\
+\hline
+
+‚
+ &
+low single comma quotation mark
+ \\
+\hline
+
+“
+ &
+double turned comma quotation mark
+ \\
+\hline
+
+”
+ &
+double comma quotation mark
+ \\
+\hline
+
+„
+ &
+low double comma quotation mark
+ \\
+\hline
+
+†
+ &
+dagger
+ \\
+\hline
+
+‡
+ &
+double dagger
+ \\
+\hline
+
+♦
+ &
+black diamond suit
+ \\
+\hline
+
+♥
+ &
+black heart suit
+ \\
+\hline
+
+♠
+ &
+black spade suit
+ \\
+\hline
+
+♣
+ &
+black club suit
+ \\
+\hline
+
+…
+ &
+ellipsis
+ \\
+\hline
+
+™
+ &
+trade mark sign
+ \\
+\hline
+
+⇔
+ &
+left-right double arrow
+ \\
+\hline
+\end{longtable*}
+
+The \DUroletitlereference{Latin-1 extended} Unicode block
+
+\setlength{\DUtablewidth}{\linewidth}
+\begin{longtable*}[c]{|p{0.051\DUtablewidth}|p{0.028\DUtablewidth}|p{0.028\DUtablewidth}|p{0.028\DUtablewidth}|p{0.028\DUtablewidth}|p{0.028\DUtablewidth}|p{0.028\DUtablewidth}|p{0.028\DUtablewidth}|p{0.028\DUtablewidth}|p{0.028\DUtablewidth}|p{0.028\DUtablewidth}|}
+\hline
+
+%
+ &
+0
+ &
+1
+ &
+2
+ &
+3
+ &
+4
+ &
+5
+ &
+6
+ &
+7
+ &
+8
+ &
+9
+ \\
+\hline
+
+160
+ & &
+¡
+ &
+¢
+ &
+£
+ & &
+¥
+ &
+¦
+ &
+§
+ &
+¨
+ &
+©
+ \\
+\hline
+
+170
+ &
+ª
+ &
+«
+ &
+¬
+ &
+\-
+ &
+®
+ &
+¯
+ &
+°
+ &
+±
+ &
+²
+ &
+³
+ \\
+\hline
+
+180
+ &
+´
+ &
+µ
+ &
+¶
+ &
+·
+ &
+¸
+ &
+¹
+ &
+º
+ &
+»
+ &
+¼
+ &
+½
+ \\
+\hline
+
+190
+ &
+¾
+ &
+¿
+ &
+À
+ &
+Á
+ &
+Â
+ &
+Ã
+ &
+Ä
+ &
+Å
+ &
+Æ
+ &
+Ç
+ \\
+\hline
+
+200
+ &
+È
+ &
+É
+ &
+Ê
+ &
+Ë
+ &
+Ì
+ &
+Í
+ &
+Î
+ &
+Ï
+ &
+Ð
+ &
+Ñ
+ \\
+\hline
+
+210
+ &
+Ò
+ &
+Ó
+ &
+Ô
+ &
+Õ
+ &
+Ö
+ &
+×
+ &
+Ø
+ &
+Ù
+ &
+Ú
+ &
+Û
+ \\
+\hline
+
+220
+ &
+Ü
+ &
+Ý
+ &
+Þ
+ &
+ß
+ &
+à
+ &
+á
+ &
+â
+ &
+ã
+ &
+ä
+ &
+å
+ \\
+\hline
+
+230
+ &
+æ
+ &
+ç
+ &
+è
+ &
+é
+ &
+ê
+ &
+ë
+ &
+ì
+ &
+í
+ &
+î
+ &
+ï
+ \\
+\hline
+
+240
+ &
+ð
+ &
+ñ
+ &
+ò
+ &
+ó
+ &
+ô
+ &
+õ
+ &
+ö
+ &
+÷
+ &
+ø
+ &
+ù
+ \\
+\hline
+
+250
+ &
+ú
+ &
+û
+ &
+ü
+ &
+ý
+ &
+þ
+ &
+ÿ
+ & & & & \\
+\hline
+\end{longtable*}
+
+\begin{itemize}
+\item The following line should not be wrapped, because it uses
+no-break spaces (\textbackslash{}u00a0):
+
+X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X
+
+\item Line wrapping with/without breakpoints marked by soft hyphens
+(\textbackslash{}u00ad):
+
+pdn\-derd\-mdtd\-ri\-schpdn\-derd\-mdtd\-ri\-schpdn\-derd\-mdtd\-ri\-schpdn\-derd\-mdtd\-ri\-schpdn\-derd\-mdtd\-ri\-sch
+
+pdnderdmdtdrischpdnderdmdtdrischpdnderdmdtdrischpdnderdmdtdrischpdnderdmdtdrisch
+\end{itemize}
+
+
+\subsection{3.7 Encoding special chars%
+ \label{encoding-special-chars}%
+}
+
+The LaTeX Info pages lists under “2.18 Special Characters”
+
+\begin{quote}
+The following characters play a special role in LaTeX and are called
+“special printing characters”, or simply “special characters”.
+
+\begin{quote}
+\# \$ \% \& \textasciitilde{} \_ \textasciicircum{} \textbackslash{} \{ \}
+\end{quote}
+\end{quote}
+
+The special chars verbatim:
+
+\begin{quote}
+\begin{alltt}
+# $ % & ~ _ ^ \textbackslash{} \{ \}
+\end{alltt}
+\end{quote}
+
+However also \emph{square brackets} {[}{]} need special care.
+
+\begin{quote}
+Commands with optional arguments (e.g. \texttt{\textbackslash{}item}) check
+if the token right after the macro name is an opening bracket.
+In that case the contents between that bracket and the following
+closing bracket on the same grouping level are taken as the
+optional argument. What makes this unintuitive is the fact that
+the square brackets aren’t grouping characters themselves, so in
+your last example \texttt{\textbackslash{}item{[}{[}...{]}{]}} the optional argument consists of
+{[}… (without the closing bracket).
+\end{quote}
+
+Compare the items in the following lists:
+
+\begin{itemize}
+\item simple item
+
+\item {[}bracketed{]} item
+\end{itemize}
+
+\begin{description}
+\item[{simple}] \leavevmode
+description term
+
+\item[{{[}bracketed{]}}] \leavevmode
+description term
+
+\end{description}
+
+The OT1 font-encoding has different characters for the less-than,
+greater-than and bar, < | >, except for typewriter font \DUroletitlereference{cmtt}:
+
+\begin{quote}
+\begin{alltt}
+< | >
+\end{alltt}
+\end{quote}
+
+
+\subsection{3.8 Hyperlinks and -targets%
+ \label{hyperlinks-and-targets}%
+}
+
+In LaTeX, we must set an explicit anchor (\texttt{\textbackslash{}phantomsection}) for a
+%
+\phantomsection\label{hypertarget-in-plain-text}hypertarget in plain text or in a figure but not in a longtable or
+caption:
+
+\setlength{\DUtablewidth}{\linewidth}
+\begin{longtable}[c]{|p{0.075\DUtablewidth}|p{0.075\DUtablewidth}|p{0.075\DUtablewidth}|}
+\caption{Table with %
+\label{hypertarget-in-table-title}hypertarget in table title.}\\
+\hline
+
+False
+ &
+True
+ &
+None
+ \\
+\hline
+\end{longtable}
+\label{table-label}
+
+\begin{figure}
+\phantomsection\label{figure-label}
+\noindent\makebox[\linewidth][c]{\includegraphics{../../../docs/user/rst/images/biohazard.png}}
+\caption{Figure with %
+\label{hypertarget-in-figure-caption}hypertarget in figure caption.}
+\begin{DUlegend}
+Legend with %
+\phantomsection\label{hypertarget-in-figure-legend}hypertarget in figure legend.
+\end{DUlegend}
+\end{figure}
+
+\includegraphics{../../../docs/user/rst/images/biohazard.png}
+\phantomsection\label{image-label}
+
+See \hyperref[hypertarget-in-plain-text]{hypertarget in plain text},
+\hyperref[table-label]{table label}, \hyperref[hypertarget-in-table-title]{hypertarget in table title},
+\hyperref[figure-label]{figure label}, \hyperref[hypertarget-in-figure-caption]{hypertarget in figure caption},
+\hyperref[hypertarget-in-figure-legend]{hypertarget in figure legend}, and
+\hyperref[image-label]{image label}.
+
+
+\subsection{3.9 External references%
+ \label{external-references}%
+}
+
+Long URLs should be wrapped in the PDF. This can be achieved with the
+\texttt{\textbackslash{}url} command which is used by the LaTeX writer whenever the content
+(name) of a reference node equals the link URL.
+
+\begin{description}
+\item[{Example:}] \leavevmode
+a long URL that should wrap in the output
+\url{http://docutils.sourceforge.net/docs/user/latex.html\#id79}
+
+\end{description}
+
+If the argument contains any “\%”, “\#”, or “\textasciicircum{}\textasciicircum{}”, or ends with \texttt{\textbackslash{}}, it can’t
+be used in the argument to another command. The argument must not contain
+unbalanced braces.
+
+The characters \textasciicircum{}, \{, \}, and \texttt{\textbackslash{}} are invalid in a “http:” or “ftp:” URL
+and not recognized as part of it:
+
+\begin{DUlineblock}{0em}
+\item[] \url{http://www.example.org}/strange\textasciicircum{}\textasciicircum{}name
+\item[] \url{http://www.example.org}\textbackslash{}using\textbackslash{}DOS\textbackslash{}paths\textbackslash{}
+\item[] \url{http://www.example.org/XML}/strange\{n\}ame
+\end{DUlineblock}
+
+They can, however be used in paths and/or filenames.
+
+Handling by the LaTeX writer:
+
+\begin{itemize}
+\item \texttt{\#}, \texttt{\textbackslash{}} and \texttt{\%} are escaped:
+
+\begin{DUlineblock}{0em}
+\item[] \href{http://www.w3.org/XML/Schema\#dev}{URL with \#}
+\url{http://www.w3.org/XML/Schema\#dev}
+\item[] \href{http://www.w3.org/XML/Schema\%dev}{URL with \%}
+\url{http://example.org/Schema\%dev}
+\item[] \href{A:DOS\\path\\}{file with DOS path}\DUfootnotemark{footnote-reference-19}{footnote-11}{10} \url{A:DOS\\path\\}\DUfootnotemark{footnote-reference-20}{footnote-11}{10}
+\end{DUlineblock}
+
+\DUadmonition[note]{
+\DUtitle[note]{Note}
+
+These URLs are typeset inside a LaTeX command without error.
+
+\begin{DUlineblock}{0em}
+\item[] \url{http://www.w3.org/XML/Schema\#dev}
+\item[] \url{http://example.org/Schema\%dev}
+\item[] \url{A:DOS\\path\\}\DUfootnotemark{footnote-reference-21}{footnote-11}{10}
+\end{DUlineblock}
+}
+\end{itemize}
+
+\begin{itemize}
+\item \texttt{\textasciicircum{}\textasciicircum{}} LaTeX’s special syntax for characters results in “strange” replacements
+(both with \texttt{\textbackslash{}href} and \texttt{\textbackslash{}url}). A warning is given.
+
+\href{../strange^^name}{file with \textasciicircum{}\textasciicircum{}}:
+\url{../strange^^name}
+
+\item Unbalanced braces, \{ or \}, will fail (both with \texttt{\textbackslash{}href} and \texttt{\textbackslash{}url}):
+
+\begin{quote}
+\begin{alltt}
+`file with \{ <../strange\{name>`__
+`<../strange\{name>`__
+\end{alltt}
+\end{quote}
+
+while balanced braces are suported:
+
+\begin{DUlineblock}{0em}
+\item[] \url{../strange{n}ame}
+\item[] \url{../st{r}ange{n}ame}
+\item[] \url{../{st{r}ange{n}ame}}
+\end{DUlineblock}
+\end{itemize}
+
+
+\subsection{3.10 Section titles with \hyperref[inline-markup]{inline markup}%
+ \label{section-titles-with-inline-markup}%
+}
+
+
+\subsubsection{3.10.1 \emph{emphasized}, H\textsubscript{2}O and $x^2$%
+ \label{emphasized-h2o-and-x-2}%
+}
+
+
+\subsubsection{3.10.2 Substitutions work%
+ \label{substitutions-fail}%
+}
+
+
+\subsection{3.11 Deeply nested sections%
+ \label{deeply-nested-sections}%
+}
+
+In LaTeX and HTML,
+
+
+\subsubsection{3.11.1 Level 3%
+ \label{level-3}%
+}
+
+nested sections
+
+
+\paragraph{3.11.1.1 level 4%
+ \label{level-4}%
+}
+
+reach at some level
+
+
+\subparagraph{3.11.1.1.1 level 5%
+ \label{level-5}%
+}
+
+(depending on the document class)
+
+
+\DUtitle[sectionVI]{3.11.1.1.1.1 level 6%
+ \label{level-6}%
+}
+
+an unsupported level.
+
+
+\section{4 Tests for the XeTeX writer%
+ \label{tests-for-the-xetex-writer}%
+}
+
+With XeTeX, you can typeset text in any language/script supported by
+Unicode and the selected font, e.g. Azərbaycanca, Bân-lâm-gú, Башҡорт
+Беларуская, Български, Català, Чӑвашла, Česky, Ελληνικά, Español,
+Français, Føroyskt, Хальмг, Íslenska, עברית , Қазақша, Kurdî,
+Latviešu, Lietuvių, Македонски, Монгол, Nāhuatl, Português, Română,
+Русский, Slovenščina, Српски, Türkçe, Українська, Tiếng Việt, Volapük,
+Võro, ייִדיש , Žemaitėška.
+Currently, there is extended support for 28 languages in the
+\href{http://ctan.org/pkg/polyglossia}{polyglossia}\DUfootnotemark{footnote-reference-16}{footnote-9}{8} package.
+
+% System Messages:
+
+
+\section{5 Error Handling%
+ \label{error-handling}%
+}
+
+Any errors caught during processing will generate system messages.
+
+There should be five messages in the following, auto-generated
+section, “Docutils System Messages”:
+
+% section should be added by Docutils automatically
+
+
+\section[Docutils System Messages]{\color{red}Docutils System Messages%
+}
+
+\DUadmonition[system-message]{
+\DUtitle[system-message]{system-message}
+\raisebox{1em}{\hypertarget{system-message-1}{}}
+
+{\color{red}ERROR/3} in \texttt{functional/input/data/standard.txt}, line~104
+
+\hyperlink{problematic-1}{
+Undefined substitution referenced: \textquotedbl{}problematic\textquotedbl{}.
+}}
+
+\DUadmonition[system-message]{
+\DUtitle[system-message]{system-message}
+\raisebox{1em}{\hypertarget{system-message-2}{}}
+
+{\color{red}ERROR/3} in \texttt{functional/input/data/standard.txt}, line~392
+
+\hyperlink{footnote-reference-8}{
+Unknown target name: \textquotedbl{}5\textquotedbl{}.
+}}
+
+\DUadmonition[system-message]{
+\DUtitle[system-message]{system-message}
+\raisebox{1em}{\hypertarget{system-message-3}{}}
+
+{\color{red}ERROR/3} in \texttt{functional/input/data/standard.txt}, line~401
+
+\hyperlink{citation-reference-3}{
+Unknown target name: \textquotedbl{}nonexistent\textquotedbl{}.
+}}
+
+\DUadmonition[system-message]{
+\DUtitle[system-message]{system-message}
+\raisebox{1em}{\hypertarget{system-message-4}{}}
+
+{\color{red}ERROR/3} in \texttt{functional/input/data/standard.txt}, line~428
+
+\hyperlink{problematic-2}{
+Unknown target name: \textquotedbl{}hyperlink reference without a target\textquotedbl{}.
+}}
+
+\DUadmonition[system-message]{
+\DUtitle[system-message]{system-message}
+\raisebox{1em}{\hypertarget{system-message-5}{}}
+
+{\color{red}ERROR/3} in \texttt{functional/input/data/standard.txt}, line~441
+
+\hyperlink{problematic-3}{
+Duplicate target name, cannot be used as a unique reference: \textquotedbl{}duplicate target names\textquotedbl{}.
+}}
+
+\end{document}
--- /dev/null
+/* 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;}
+*/
--- /dev/null
+<public:component>
+<public:attach event="onpropertychange" onevent="doFix()" />
+
+<script>
+
+// IE5.5+ PNG Alpha Fix v1.0 by Angus Turnbull http://www.twinhelix.com
+// Free usage permitted as long as this notice remains intact.
+
+// This must be a path to a blank image. That's all the configuration you need here.
+var blankImg = 'ui/default/blank.gif';
+
+var f = 'DXImageTransform.Microsoft.AlphaImageLoader';
+
+function filt(s, m) {
+ if (filters[f]) {
+ filters[f].enabled = s ? true : false;
+ if (s) with (filters[f]) { src = s; sizingMethod = m }
+ } else if (s) style.filter = 'progid:'+f+'(src="'+s+'",sizingMethod="'+m+'")';
+}
+
+function doFix() {
+ if ((parseFloat(navigator.userAgent.match(/MSIE (\S+)/)[1]) < 5.5) ||
+ (event && !/(background|src)/.test(event.propertyName))) return;
+
+ if (tagName == 'IMG') {
+ if ((/\.png$/i).test(src)) {
+ filt(src, 'image'); // was 'scale'
+ src = blankImg;
+ } else if (src.indexOf(blankImg) < 0) filt();
+ } else if (style.backgroundImage) {
+ if (style.backgroundImage.match(/^url[("']+(.*\.png)[)"']+$/i)) {
+ var s = RegExp.$1;
+ style.backgroundImage = '';
+ filt(s, 'crop');
+ } else filt();
+ }
+}
+
+doFix();
+
+</script>
+</public:component>
\ No newline at end of file
--- /dev/null
+/* 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;}
--- /dev/null
+/* 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;}
--- /dev/null
+/* 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;}
+*/
--- /dev/null
+/* 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;}
--- /dev/null
+/* 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;}
--- /dev/null
+/* 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);
--- /dev/null
+// S5 v1.1 slides.js -- released into the Public Domain
+// Modified for Docutils (http://docutils.sf.net) 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();">Ø<\/a>' +
+ '<a accesskey="z" id="prev" href="javascript:go(-1);">«<\/a>' +
+ '<a accesskey="x" id="next" href="javascript:go(1);">»<\/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);}
--- /dev/null
+/* 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;}
+*/
--- /dev/null
+<public:component>
+<public:attach event="onpropertychange" onevent="doFix()" />
+
+<script>
+
+// IE5.5+ PNG Alpha Fix v1.0 by Angus Turnbull http://www.twinhelix.com
+// Free usage permitted as long as this notice remains intact.
+
+// This must be a path to a blank image. That's all the configuration you need here.
+var blankImg = 'ui/small-black/blank.gif';
+
+var f = 'DXImageTransform.Microsoft.AlphaImageLoader';
+
+function filt(s, m) {
+ if (filters[f]) {
+ filters[f].enabled = s ? true : false;
+ if (s) with (filters[f]) { src = s; sizingMethod = m }
+ } else if (s) style.filter = 'progid:'+f+'(src="'+s+'",sizingMethod="'+m+'")';
+}
+
+function doFix() {
+ if ((parseFloat(navigator.userAgent.match(/MSIE (\S+)/)[1]) < 5.5) ||
+ (event && !/(background|src)/.test(event.propertyName))) return;
+
+ if (tagName == 'IMG') {
+ if ((/\.png$/i).test(src)) {
+ filt(src, 'image'); // was 'scale'
+ src = blankImg;
+ } else if (src.indexOf(blankImg) < 0) filt();
+ } else if (style.backgroundImage) {
+ if (style.backgroundImage.match(/^url[("']+(.*\.png)[)"']+$/i)) {
+ var s = RegExp.$1;
+ style.backgroundImage = '';
+ filt(s, 'crop');
+ } else filt();
+ }
+}
+
+doFix();
+
+</script>
+</public:component>
\ No newline at end of file
--- /dev/null
+/* 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;}
--- /dev/null
+/* 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;}
--- /dev/null
+/* 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;}
+*/
--- /dev/null
+/* 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;}
--- /dev/null
+/* 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;}
--- /dev/null
+/* 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);
--- /dev/null
+// S5 v1.1 slides.js -- released into the Public Domain
+// Modified for Docutils (http://docutils.sf.net) 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();">Ø<\/a>' +
+ '<a accesskey="z" id="prev" href="javascript:go(-1);">«<\/a>' +
+ '<a accesskey="x" id="next" href="javascript:go(1);">»<\/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/small-black/iepngfix.htc)');
+ document.styleSheets[0].addRule('div', 'behavior: url(ui/small-black/iepngfix.htc)');
+ document.styleSheets[0].addRule('.slide', 'behavior: url(ui/small-black/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);}
--- /dev/null
+\documentclass[a4paper,russian]{article}
+% generated by Docutils <http://docutils.sourceforge.net/>
+% 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
+\usepackage{ifthen}
+\usepackage{polyglossia}
+\setdefaultlanguage{russian}
+\setotherlanguages{english}
+\setcounter{secnumdepth}{0}
+
+%%% Custom LaTeX 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}
+
+%%% User specified packages and stylesheets
+
+%%% Fallback definitions for Docutils-specific commands
+
+% titlereference role
+\providecommand*{\DUroletitlereference}[1]{\textsl{#1}}
+% hyperlinks:
+\ifthenelse{\isundefined{\hypersetup}}{
+ \usepackage[colorlinks=true,linkcolor=blue,urlcolor=blue,unicode=false]{hyperref}
+ \usepackage{bookmark}
+ \urlstyle{same} % normal text font (alternatives: tt, rm, sf)
+}{}
+
+
+%%% Body
+\begin{document}
+
+
+\section{Заголовок%
+ \label{section-1}%
+}
+
+первый пример: «Здравствуй, мир!»
+
+
+\section{Title%
+ \label{title}%
+}
+
+\foreignlanguage{english}{first example: “Hello world”.}
+
+
+\section{Notes%
+ \label{notes}%
+}
+
+\foreignlanguage{english}{This example tests rendering of Latin and Cyrillic characters by the LaTeX
+and XeTeX writers. Check the compiled PDF for garbage characters in text and
+bookmarks.}
+
+\foreignlanguage{english}{To work around a problem with Cyrillic in PDF-bookmarks in \DUroletitlereference{hyperref}
+versions older than v6.79g 2009/11/20, the test caller \texttt{latex\_cyrillic.py}
+sets \texttt{hyperref\_options} to \texttt{'unicode=true'} while \texttt{xetex\_cyrillic.py}
+sets it to \texttt{'unicode=false'}. The recommended option for current
+(2011-08-24) hyperref versions is \texttt{'pdfencoding=auto'}.}
+
+\end{document}
--- /dev/null
+# Default settings for all tests.
+
+settings_overrides['report_level'] = 2
+settings_overrides['halt_level'] = 5
+settings_overrides['warning_stream'] = ''
+settings_overrides['input_encoding'] = 'utf-8'
+settings_overrides['embed_stylesheet'] = False
+settings_overrides['auto_id_prefix'] = '%'
--- /dev/null
+# Keyword parameters passed to publish_file.
+reader_name = "standalone"
+parser_name = "rst"
+
+# Settings.
+settings_overrides['sectsubtitle_xform'] = 1
+settings_overrides['syntax_highlight'] = 'none'
--- /dev/null
+# Source and destination file names.
+test_source = "compact_lists.txt"
+test_destination = "compact_lists.html"
+
+# Keyword parameters passed to publish_file.
+reader_name = "standalone"
+parser_name = "rst"
+writer_name = "html"
+
+# Settings
+# local copy of default stylesheet:
+settings_overrides['stylesheet_path'] = (
+ 'functional/input/data/html4css1.css')
--- /dev/null
+# Source and destination file names.
+test_source = "dangerous.txt"
+test_destination = "dangerous.html"
+
+# Keyword parameters passed to publish_file.
+reader_name = "standalone"
+parser_name = "rst"
+writer_name = "html"
+
+# Settings
+settings_overrides['file_insertion_enabled'] = False
+settings_overrides['raw_enabled'] = False
+# local copy of default stylesheet:
+settings_overrides['stylesheet_path'] = (
+ 'functional/input/data/html4css1.css')
--- /dev/null
+# Source and destination file names.
+test_source = "field_list.txt"
+test_destination = "field_name_limit.html"
+
+# Keyword parameters passed to publish_file.
+reader_name = "standalone"
+parser_name = "rst"
+writer_name = "html"
+
+# Settings
+settings_overrides['field_name_limit'] = 0 # no limit
+settings_overrides['docinfo_xform'] = False
+# local copy of default stylesheet:
+settings_overrides['stylesheet_path'] = (
+ 'functional/input/data/html4css1.css')
--- /dev/null
+with open('functional/tests/_standalone_rst_defaults.py') as _f:
+ exec(_f.read())
+
+# Source and destination file names.
+test_source = "footnotes.txt"
+test_destination = "footnotes_html5.html"
+
+# Keyword parameters passed to publish_file.
+writer_name = "html5"
+
+# Settings:
+settings_overrides['footnote_references']='superscript'
+# local copy of stylesheets:
+# (Test runs in ``docutils/test/``, we need relative path from there.)
+settings_overrides['stylesheet_dirs'] = ('.', 'functional/input/data')
--- /dev/null
+# Source and destination file names.
+test_source = "latex_babel.txt"
+test_destination = "latex_babel.tex"
+
+# Keyword parameters passed to publish_file.
+reader_name = "standalone"
+parser_name = "rst"
+writer_name = "latex"
+
+# Extra setting we need
--- /dev/null
+# Source and destination file names.
+test_source = "latex_cornercases.txt"
+test_destination = "latex_cornercases.tex"
+
+# Keyword parameters passed to publish_file.
+reader_name = "standalone"
+parser_name = "rst"
+writer_name = "latex"
+
+# Extra setting we need
--- /dev/null
+# Source and destination file names.
+test_source = "cyrillic.txt"
+test_destination = "cyrillic.tex"
+
+# Keyword parameters passed to publish_file.
+reader_name = "standalone"
+parser_name = "rst"
+writer_name = "latex"
+
+# Extra setting we need
+
+settings_overrides['hyperref_options'] = 'unicode=true'
+settings_overrides['font_encoding'] = 'T1,T2A'
+settings_overrides['stylesheet'] = 'cmlgc'
+settings_overrides['language_code'] = 'ru'
+
+# use "smartquotes" transition:
+settings_overrides['smart_quotes'] = True
--- /dev/null
+# Source and destination file names.
+test_source = "latex_docinfo.txt"
+test_destination = "latex_docinfo.tex"
+
+# Keyword parameters passed to publish_file.
+reader_name = "standalone"
+parser_name = "rst"
+writer_name = "latex"
+
+# Extra setting we need
+
+settings_overrides['use_latex_docinfo'] = 1
--- /dev/null
+# Source and destination file names.
+test_source = "latex_literal_block.txt"
+test_destination = "latex_literal_block.tex"
+
+# Keyword parameters passed to publish_file.
+reader_name = "standalone"
+parser_name = "rst"
+writer_name = "latex"
+
+# Extra setting we need
+# settings_overrides['literal_block_env'] = 'verbatim'
+settings_overrides['syntax_highlight'] = 'none'
--- /dev/null
+# Source and destination file names.
+test_source = "latex_literal_block.txt"
+test_destination = "latex_literal_block_fancyvrb.tex"
+
+# Keyword parameters passed to publish_file.
+reader_name = "standalone"
+parser_name = "rst"
+writer_name = "latex"
+
+# Extra setting we need
+settings_overrides['literal_block_env'] = 'Verbatim'
+settings_overrides['syntax_highlight'] = 'none'
--- /dev/null
+# Source and destination file names.
+test_source = "latex_literal_block.txt"
+test_destination = "latex_literal_block_listings.tex"
+
+# Keyword parameters passed to publish_file.
+reader_name = "standalone"
+parser_name = "rst"
+writer_name = "latex"
+
+# Extra setting we need
+settings_overrides['literal_block_env'] = 'lstlisting'
+settings_overrides['syntax_highlight'] = 'none'
+settings_overrides['latex_preamble'] = r"""
+% PDF Standard Fonts
+\usepackage{mathptmx} % Times
+\usepackage[scaled=.90]{helvet}
+\usepackage{courier}
+% LaTeX syntax highlight with "listings":
+\lstloadlanguages{[LaTeX]TeX} % comma separated list of languages
+\newcommand{\DUCLASSlatex}{\lstset{language=[LaTeX]TeX}}
+"""
--- /dev/null
+# Source and destination file names.
+test_source = "latex_literal_block.txt"
+test_destination = "latex_literal_block_verbatim.tex"
+
+# Keyword parameters passed to publish_file.
+reader_name = "standalone"
+parser_name = "rst"
+writer_name = "latex"
+
+# Extra setting we need
+settings_overrides['literal_block_env'] = 'verbatim'
+settings_overrides['syntax_highlight'] = 'none'
--- /dev/null
+# Source and destination file names.
+test_source = "latex_literal_block.txt"
+test_destination = "latex_literal_block_verbatimtab.tex"
+
+# Keyword parameters passed to publish_file.
+reader_name = "standalone"
+parser_name = "rst"
+writer_name = "latex"
+
+# Extra setting we need
+settings_overrides['literal_block_env'] = 'verbatimtab'
+settings_overrides['syntax_highlight'] = 'none'
--- /dev/null
+# Source and destination file names.
+test_source = "data/math.txt"
+test_destination = "math_output_html.html"
+
+# Keyword parameters passed to publish_file.
+reader_name = "standalone"
+parser_name = "rst"
+writer_name = "html"
+
+# Extra settings
+settings_overrides['math_output'] = 'HTML'
+# stylesheets:
+settings_overrides['stylesheet_path'] = (
+ 'functional/input/data/html4css1.css,'
+ 'functional/input/data/math.css')
+
+
--- /dev/null
+# Source and destination file names.
+test_source = "data/math.txt"
+test_destination = "math_output_latex.html"
+
+# Keyword parameters passed to publish_file.
+reader_name = "standalone"
+parser_name = "rst"
+writer_name = "html"
+
+# Settings
+settings_overrides['math_output'] = 'latex'
+# local copy of default stylesheet:
+settings_overrides['stylesheet_path'] = (
+ 'functional/input/data/html4css1.css')
+
+
--- /dev/null
+# Source and destination file names.
+test_source = "data/math.txt"
+test_destination = "math_output_mathjax.html"
+
+# Keyword parameters passed to publish_file.
+reader_name = "standalone"
+parser_name = "rst"
+writer_name = "html"
+
+# Settings
+settings_overrides['math_output'] = 'MathJax /usr/share/javascript/mathjax/MathJax.js'
+# local copy of default stylesheet:
+settings_overrides['stylesheet_path'] = (
+ 'functional/input/data/html4css1.css')
--- /dev/null
+# Source and destination file names.
+test_source = "data/math.txt"
+test_destination = "math_output_mathml.xhtml"
+
+# Keyword parameters passed to publish_file.
+reader_name = "standalone"
+parser_name = "rst"
+writer_name = "html5"
+
+# Settings
+settings_overrides['math_output'] = 'MathML'
+# local copy of default stylesheet:
+# (test runs in ``docutils/test/``, we need relative path from there.)
+settings_overrides['stylesheet_dirs'] = ('.', 'functional/input/data')
--- /dev/null
+# Source and destination file names.
+test_source = "link_in_substitution.txt"
+test_destination = "misc_rst_html4css1.html"
+
+# Keyword parameters passed to publish_file.
+reader_name = "standalone"
+parser_name = "rst"
+writer_name = "html4css1"
+
+# Settings
+# test for encoded attribute value:
+settings_overrides['stylesheet'] = 'foo&bar.css'
+settings_overrides['stylesheet_path'] = ''
+settings_overrides['embed_stylesheet'] = False
--- /dev/null
+# Source and destination file names.
+test_source = "pep_html.txt"
+test_destination = "pep_html.html"
+
+# Keyword parameters passed to publish_file.
+reader_name = "pep"
+parser_name = "rst"
+writer_name = "pep_html"
+
+# Settings
+settings_overrides['python_home'] = "http://www.python.org"
+settings_overrides['pep_home'] = "http://www.python.org/peps"
+settings_overrides['no_random'] = 1
+settings_overrides['cloak_email_addresses'] = 1
+# local copy of default stylesheet:
+settings_overrides['stylesheet_path'] = (
+ 'functional/input/data/html4css1.css')
--- /dev/null
+with open('functional/tests/_standalone_rst_defaults.py') as _f:
+ exec(_f.read())
+
+# Source and destination file names.
+test_source = "standalone_rst_docutils_xml.txt"
+test_destination = "standalone_rst_docutils_xml.xml"
+
+# Keyword parameters passed to publish_file.
+writer_name = "docutils_xml"
+
+# Settings
+# enable INFO-level system messages in this test:
+settings_overrides['report_level'] = 1
+
+# format output with indents and newlines
+settings_overrides['indents'] = True
--- /dev/null
+with open('functional/tests/_standalone_rst_defaults.py') as _f:
+ exec(_f.read())
+
+# Source and destination file names.
+test_source = "standalone_rst_html4css1.txt"
+test_destination = "standalone_rst_html4css1.html"
+
+# Keyword parameters passed to publish_file.
+writer_name = "html4css1"
+
+# Settings:
+# local copy of stylesheets:
+# (Test runs in ``docutils/test/``, we need relative path from there.)
+settings_overrides['stylesheet_dirs'] = ('.', 'functional/input/data')
--- /dev/null
+with open('functional/tests/_standalone_rst_defaults.py') as _f:
+ exec(_f.read())
+
+# Source and destination file names.
+test_source = "standalone_rst_html5.txt"
+test_destination = "standalone_rst_html5.html"
+
+# Keyword parameters passed to publish_file.
+writer_name = "html5"
+
+# Settings:
+# "smart" quotes:
+# settings_overrides['smart_quotes']='yes'
+# local copy of stylesheets:
+# (Test runs in ``docutils/test/``, we need relative path from there.)
+settings_overrides['stylesheet_dirs'] = ('.', 'functional/input/data')
--- /dev/null
+with open('functional/tests/_standalone_rst_defaults.py') as _f:
+ exec(_f.read())
+
+# Source and destination file names.
+test_source = "standalone_rst_latex.txt"
+test_destination = "standalone_rst_latex.tex"
+
+# Keyword parameters passed to publish_file.
+writer_name = "latex"
+
+# Settings
+# use "smartquotes" transition:
+settings_overrides['smart_quotes'] = True
--- /dev/null
+with open('functional/tests/_standalone_rst_defaults.py') as _f:
+ exec(_f.read())
+
+# Source and destination file names.
+test_source = "standalone_rst_manpage.txt"
+test_destination = "standalone_rst_manpage.man"
+
+# Keyword parameters passed to publish_file.
+writer_name = "manpage"
--- /dev/null
+with open('functional/tests/_standalone_rst_defaults.py') as _f:
+ exec(_f.read())
+
+# Source and destination file names.
+test_source = "standalone_rst_pseudoxml.txt"
+test_destination = "standalone_rst_pseudoxml.txt"
+
+# Keyword parameters passed to publish_file.
+writer_name = "pseudoxml"
+
+# Settings
+# enable INFO-level system messages in this test:
+settings_overrides['report_level'] = 1
--- /dev/null
+with open('functional/tests/_standalone_rst_defaults.py') as _f:
+ exec(_f.read())
+
+# Source and destination file names:
+test_source = 'standalone_rst_s5_html.txt'
+test_destination = 'standalone_rst_s5_html_1.html'
+
+# Keyword parameters passed to publish_file:
+writer_name = 's5_html'
+
+# Settings:
+settings_overrides['theme'] = 'small-black'
+# local copy of default stylesheet:
+settings_overrides['stylesheet_path'] = (
+ 'functional/input/data/html4css1.css')
+
+
+# Extra functional tests.
+# Prefix all names with '_' to avoid confusing `docutils.core.publish_file`.
+
+import filecmp as _filecmp
+
+def _test_more(expected_dir, output_dir, test_case, parameters):
+ """Compare ``ui/<theme>`` directories."""
+ theme = settings_overrides.get('theme', 'default')
+ expected = '%s/%s/%s' % (expected_dir, 'ui', theme)
+ output = '%s/%s/%s' % (output_dir, 'ui', theme)
+ differences, uniques = _compare_directories(expected, output)
+ parts = []
+ if differences:
+ parts.append('The following files differ from the expected output:')
+ parts.extend(differences)
+ expected = [path.replace('functional/output/', 'functional/expected/')
+ for path in differences]
+ parts.append('Please compare the expected and actual output files:')
+ parts.extend([' diff %s %s' % tup
+ for tup in zip(expected, differences)])
+ parts.append('If the actual output is correct, please replace the '
+ 'expected output files:')
+ parts.extend([' mv %s %s' % tup
+ for tup in zip(differences, expected)])
+ parts.append('and check them in to Subversion:')
+ parts.extend([' svn commit -m "<comment>" %s' % path
+ for path in expected])
+ if uniques:
+ parts.append('The following paths are unique:')
+ parts.extend(uniques)
+ test_case.assertTrue(not parts, '\n'.join(parts))
+
+def _compare_directories(expected, output):
+ dircmp = _filecmp.dircmp(expected, output, ['.svn', 'CVS'])
+ differences = ['%s/%s' % (output, name) for name in dircmp.diff_files]
+ uniques = (['%s/%s' % (expected, name) for name in dircmp.left_only]
+ + ['%s/%s' % (output, name) for name in dircmp.right_only])
+ for subdir in dircmp.common_dirs:
+ diffs, uniqs = _compare_directories('%s/%s' % (expected, subdir),
+ '%s/%s' % (output, subdir))
+ differences.extend(diffs)
+ uniques.extend(uniqs)
+ return differences, uniques
--- /dev/null
+# initialize with the settings & definitions from test 1:
+with open('functional/tests/standalone_rst_s5_html_1.py') as _f:
+ exec(_f.read())
+
+# overrides specific to this test:
+test_destination = 'standalone_rst_s5_html_2.html'
+del settings_overrides['theme'] # use the default
+settings_overrides['current_slide'] = 1
--- /dev/null
+with open('functional/tests/_standalone_rst_defaults.py') as _f:
+ exec(_f.read())
+
+# Source and destination file names.
+test_source = "standalone_rst_xetex.txt"
+test_destination = "standalone_rst_xetex.tex"
+
+# Keyword parameters passed to publish_file.
+writer_name = "xetex"
+
+# Settings
+# use "smartquotes" transition:
+settings_overrides['smart_quotes'] = True
--- /dev/null
+# Source and destination file names.
+test_source = "cyrillic.txt"
+test_destination = "xetex-cyrillic.tex"
+
+# Keyword parameters passed to publish_file.
+writer_name = "xetex"
+
+# Settings
+settings_overrides['language_code'] = 'ru'
+# Override the automatic addition of "unicode" option for "russian"
+# language to work around a problem with cyrillic in PDF-bookmarks in
+# hyperref versions < v6.79g 2009/11/20
+settings_overrides['hyperref_options'] = 'unicode=false'
+# use "smartquotes" transition:
+settings_overrides['smart_quotes'] = True
--- /dev/null
+# -*- coding: utf-8 -*-
+# $Id: local-parser.py 7504 2012-08-27 07:55:20Z grubert $
+# Authors: Engelbert Gruber <grubert@users.sourceforge.net>
+# Toshio Kuratomi <toshio@fedoraproject.org>
+# Copyright: This module is put into the public domain.
+
+"""
+mini-reader to test get_reader_class with local reader
+"""
+
+from docutils import parsers
+
+class Parser(parsers.Parser):
+
+ supported = ('dummy',)
+ """Formats this reader supports."""
+
+ def parser(self, inputstring, document):
+ self.setup_parse(inputstring, document)
+ document = dict()
+ self.finish_parse()
--- /dev/null
+# -*- coding: utf-8 -*-
+# $Id: local-reader.py 7504 2012-08-27 07:55:20Z grubert $
+# Authors: Engelbert Gruber <grubert@users.sourceforge.net>
+# Toshio Kuratomi <toshio@fedoraproject.org>
+# Copyright: This module is put into the public domain.
+
+"""
+mini-reader to test get_reader_class with local reader
+"""
+
+import docutils
+from docutils import readers
+
+class Reader(readers.Reader):
+
+ supported = ('dummy',)
+ """Formats this reader supports."""
+
+ document = None
+ """A document tree."""
--- /dev/null
+# -*- coding: utf-8 -*-
+# $Id: local-writer.py 7500 2012-08-22 19:38:14Z grubert $
+# Author: Engelbert Gruber <grubert@users.sourceforge.net>
+# Copyright: This module is put into the public domain.
+
+"""
+mini-writer to test get_writer_class with local writer
+"""
+
+import docutils
+from docutils import nodes, writers, languages
+try:
+ import roman
+except ImportError:
+ import docutils.utils.roman as roman
+
+class Writer(writers.Writer):
+
+ supported = ('dummy',)
+ """Formats this writer supports."""
+
+ output = None
+ """Final translated form of `document`."""
+
+ def __init__(self):
+ writers.Writer.__init__(self)
+ self.translator_class = Translator
+
+ def translate(self):
+ visitor = self.translator_class(self.document)
+ self.document.walkabout(visitor)
+ self.output = visitor.astext()
+
+class Translator(nodes.NodeVisitor):
+ def __init__(self, document):
+ nodes.NodeVisitor.__init__(self, document)
+
+
--- /dev/null
+# $Id: local_dummy_lang.py 8452 2020-01-09 10:50:44Z milde $
+# Author: David Goodger <goodger@python.org>
+# Copyright: This module has been placed in the public domain.
+
+# New language mappings are welcome. Before doing a new translation, please
+# read <http://docutils.sf.net/docs/howto/i18n.html>. Two files must be
+# translated for each language: one in docutils/languages, the other in
+# docutils/parsers/rst/languages.
+
+"""
+English-language mappings for language-dependent features of Docutils.
+"""
+
+__docformat__ = 'reStructuredText'
+
+labels = {
+ # fixed: language-dependent
+ 'author': 'dummy Author',
+ 'authors': 'dummy Authors',
+ 'organization': 'dummy Organization',
+ 'address': 'dummy Address',
+ 'contact': 'dummy Contact',
+ 'version': 'dummy Version',
+ 'revision': 'dummy Revision',
+ 'status': 'dummy Status',
+ 'date': 'dummy Date',
+ 'copyright': 'dummy Copyright',
+ 'dedication': 'dummy Dedication',
+ 'abstract': 'dummy Abstract',
+ 'attention': 'dummy Attention!',
+ 'caution': 'dummy Caution!',
+ 'danger': 'dummy !DANGER!',
+ 'error': 'dummy Error',
+ 'hint': 'dummy Hint',
+ 'important': 'dummy Important',
+ 'note': 'dummy Note',
+ 'tip': 'dummy Tip',
+ 'warning': 'dummy Warning',
+ 'contents': 'dummy Contents'}
+"""Mapping of node class name to label text."""
+
+bibliographic_fields = {
+ # language-dependent: fixed
+ 'dummy author': 'author',
+ 'dummy authors': 'authors',
+ 'dummy organization': 'organization',
+ 'dummy address': 'address',
+ 'dummy contact': 'contact',
+ 'dummy version': 'version',
+ 'dummy revision': 'revision',
+ 'dummy status': 'status',
+ 'dummy date': 'date',
+ 'dummy copyright': 'copyright',
+ 'dummy dedication': 'dedication',
+ 'dummy abstract': 'abstract'}
+"""English (lowcased) to canonical name mapping for bibliographic fields."""
+
+author_separators = [';', ',']
+"""List of separator strings for the 'Authors' bibliographic field. Tried in
+order."""
+
+directives = {
+ # language-dependent: fixed
+ 'dummy-attention': 'attention',
+ 'dummy-caution': 'caution',
+ 'dummy-code': 'code',
+ 'dummy-code-block': 'code',
+ 'dummy-sourcecode': 'code',
+ 'dummy-danger': 'danger',
+ 'dummy-error': 'error',
+ 'dummy-hint': 'hint',
+ 'dummy-important': 'important',
+ 'dummy-note': 'note',
+ 'dummy-tip': 'tip',
+ 'dummy-warning': 'warning',
+ 'dummy-admonition': 'admonition',
+ 'dummy-sidebar': 'sidebar',
+ 'dummy-topic': 'topic',
+ 'dummy-line-block': 'line-block',
+ 'dummy-parsed-literal': 'parsed-literal',
+ 'dummy-rubric': 'rubric',
+ 'dummy-epigraph': 'epigraph',
+ 'dummy-highlights': 'highlights',
+ 'dummy-pull-quote': 'pull-quote',
+ 'dummy-compound': 'compound',
+ 'dummy-container': 'container',
+ #'dummy-questions': 'questions',
+ 'dummy-table': 'table',
+ 'dummy-csv-table': 'csv-table',
+ 'dummy-list-table': 'list-table',
+ #'dummy-qa': 'questions',
+ #'dummy-faq': 'questions',
+ 'dummy-meta': 'meta',
+ 'dummy-math': 'math',
+ #'dummy-imagemap': 'imagemap',
+ 'dummy-image': 'image',
+ 'dummy-figure': 'figure',
+ 'dummy-include': 'include',
+ 'dummy-raw': 'raw',
+ 'dummy-replace': 'replace',
+ 'dummy-unicode': 'unicode',
+ 'dummy-date': 'date',
+ 'dummy-class': 'class',
+ 'dummy-role': 'role',
+ 'dummy-default-role': 'default-role',
+ 'dummy-title': 'title',
+ 'dummy-contents': 'contents',
+ 'dummy-sectnum': 'sectnum',
+ 'dummy-section-numbering': 'sectnum',
+ 'dummy-header': 'header',
+ 'dummy-footer': 'footer',
+ #'dummy-footnotes': 'footnotes',
+ #'dummy-citations': 'citations',
+ 'dummy-target-notes': 'target-notes',
+ 'dummy-restructuredtext-test-directive': 'restructuredtext-test-directive'}
+"""English name to registered (in directives/__init__.py) directive name
+mapping."""
+
+roles = {
+ # language-dependent: fixed
+ 'dummy abbreviation': 'abbreviation',
+ 'dummy ab': 'abbreviation',
+ 'dummy acronym': 'acronym',
+ 'dummy ac': 'acronym',
+ 'dummy code': 'code',
+ 'dummy index': 'index',
+ 'dummy i': 'index',
+ 'dummy subscript': 'subscript',
+ 'dummy sub': 'subscript',
+ 'dummy superscript': 'superscript',
+ 'dummy sup': 'superscript',
+ 'dummy title-reference': 'title-reference',
+ 'dummy title': 'title-reference',
+ 'dummy t': 'title-reference',
+ 'dummy pep-reference': 'pep-reference',
+ 'dummy pep': 'pep-reference',
+ 'dummy rfc-reference': 'rfc-reference',
+ 'dummy rfc': 'rfc-reference',
+ 'dummy emphasis': 'emphasis',
+ 'dummy strong': 'strong',
+ 'dummy literal': 'literal',
+ 'dummy math': 'math',
+ 'dummy named-reference': 'named-reference',
+ 'dummy anonymous-reference': 'anonymous-reference',
+ 'dummy footnote-reference': 'footnote-reference',
+ 'dummy citation-reference': 'citation-reference',
+ 'dummy substitution-reference': 'substitution-reference',
+ 'dummy target': 'target',
+ 'dummy uri-reference': 'uri-reference',
+ 'dummy uri': 'uri-reference',
+ 'dummy url': 'uri-reference',
+ 'dummy raw': 'raw',}
+"""Mapping of English role names to canonical role names for interpreted text.
+"""
--- /dev/null
+#! /usr/bin/env python
+
+# $Id: package_unittest.py 8359 2019-08-26 16:45:33Z milde $
+# Author: Garth Kidd <garth@deadlybloodyserious.com>
+# Copyright: This module has been placed in the public domain.
+
+"""
+This module extends unittest.py with `loadTestModules()`, by loading multiple
+test modules from a directory. Optionally, test packages are also loaded,
+recursively.
+"""
+from __future__ import print_function
+
+import sys
+import os
+import getopt
+import types
+import unittest
+import re
+
+
+# So that individual test modules can share a bit of state,
+# `package_unittest` acts as an intermediary for the following
+# variables:
+debug = False
+verbosity = 1
+
+USAGE = """\
+Usage: test_whatever [options]
+
+Options:
+ -h, --help Show this message
+ -v, --verbose Verbose output
+ -q, --quiet Minimal output
+ -d, --debug Debug mode
+"""
+
+def usageExit(msg=None):
+ """Print usage and exit."""
+ if msg:
+ print(msg)
+ print(USAGE)
+ sys.exit(2)
+
+def parseArgs(argv=sys.argv):
+ """Parse command line arguments and set TestFramework state.
+
+ State is to be acquired by test_* modules by a grotty hack:
+ ``from TestFramework import *``. For this stylistic
+ transgression, I expect to be first up against the wall
+ when the revolution comes. --Garth"""
+ global verbosity, debug
+ try:
+ options, args = getopt.getopt(argv[1:], 'hHvqd',
+ ['help', 'verbose', 'quiet', 'debug'])
+ for opt, value in options:
+ if opt in ('-h', '-H', '--help'):
+ usageExit()
+ if opt in ('-q', '--quiet'):
+ verbosity = 0
+ if opt in ('-v', '--verbose'):
+ verbosity = 2
+ if opt in ('-d', '--debug'):
+ debug =1
+ if len(args) != 0:
+ usageExit("No command-line arguments supported yet.")
+ except getopt.error as msg:
+ usageExit(msg)
+
+def loadTestModules(path, name='', packages=None):
+ """
+ Return a test suite composed of all the tests from modules in a directory.
+
+ Search for modules in directory `path`, beginning with `name`. If
+ `packages` is true, search subdirectories (also beginning with `name`)
+ recursively. Subdirectories must be Python packages; they must contain an
+ '__init__.py' module.
+ """
+ testLoader = unittest.defaultTestLoader
+ testSuite = unittest.TestSuite()
+ testModules = []
+ path = os.path.abspath(path) # current working dir if `path` empty
+ paths = [path]
+ while paths:
+ p = paths.pop(0)
+ files = os.listdir(p)
+ for filename in files:
+ if filename.startswith(name):
+ fullpath = os.path.join(p, filename)
+ if filename.endswith('.py'):
+ fullpath = fullpath[len(path)+1:]
+ testModules.append(path2mod(fullpath))
+ elif packages and os.path.isdir(fullpath) and \
+ os.path.isfile(os.path.join(fullpath, '__init__.py')):
+ paths.append(fullpath)
+ # Import modules and add their tests to the suite.
+ sys.path.insert(0, path)
+ for mod in testModules:
+ if debug:
+ print("importing %s" % mod, file=sys.stderr)
+ try:
+ module = import_module(mod)
+ except ImportError:
+ print("ERROR: Can't import %s, skipping its tests:" % mod, file=sys.stderr)
+ sys.excepthook(*sys.exc_info())
+ else:
+ # if there's a suite defined, incorporate its contents
+ try:
+ suite = getattr(module, 'suite')
+ except AttributeError:
+ # Look for individual tests
+ moduleTests = testLoader.loadTestsFromModule(module)
+ # unittest.TestSuite.addTests() doesn't work as advertised,
+ # as it can't load tests from another TestSuite, so we have
+ # to cheat:
+ testSuite.addTest(moduleTests)
+ continue
+ if isinstance(suite, types.FunctionType):
+ testSuite.addTest(suite())
+ elif isinstance(suite, unittest.TestSuite):
+ testSuite.addTest(suite)
+ else:
+ raise AssertionError("don't understand suite (%s)" % mod)
+ sys.path.pop(0)
+ return testSuite
+
+def path2mod(path):
+ """Convert a file path to a dotted module name."""
+ return path[:-3].replace(os.sep, '.')
+
+def import_module(name):
+ """Import a dotted-path module name, and return the final component."""
+ mod = __import__(name)
+ components = name.split('.')
+ for comp in components[1:]:
+ mod = getattr(mod, comp)
+ return mod
+
+def main(suite=None):
+ """
+ Shared `main` for any individual test_* file.
+
+ suite -- TestSuite to run. If not specified, look for any globally defined
+ tests and run them.
+ """
+ parseArgs()
+ if suite is None:
+ # Load any globally defined tests.
+ suite = unittest.defaultTestLoader.loadTestsFromModule(
+ __import__('__main__'))
+ if debug:
+ print("Debug: Suite=%s" % suite, file=sys.stderr)
+ testRunner = unittest.TextTestRunner(verbosity=verbosity)
+ # run suites (if we were called from test_all) or suite...
+ if isinstance(suite, type([])):
+ for s in suite:
+ testRunner.run(s)
+ else:
+ return testRunner.run(suite)
--- /dev/null
+data/include.txt
+data/raw.txt
+data/stylesheet.txt
--- /dev/null
+#! /usr/bin/env python
+# -*- coding: utf-8 -*-
+# $Id: test__init__.py 8367 2019-08-27 12:09:56Z milde $
+# Authors: Günter Milde <milde@users.sourceforge.net>,
+# David Goodger <goodger@python.org>
+# Copyright: This module has been placed in the public domain.
+
+"""
+Test module for the docutils' __init__.py.
+"""
+
+import unittest
+import sys
+import DocutilsTestSupport # must be imported before docutils
+import docutils
+import docutils.utils
+
+
+if sys.version_info >= (3, 0):
+ unicode = str # noqa
+
+
+class ApplicationErrorTests(unittest.TestCase):
+
+ def test_message(self):
+ err = docutils.ApplicationError('the message')
+ self.assertEqual(unicode(err), u'the message')
+
+ def test_non_ASCII_message(self):
+ err = docutils.ApplicationError(u'\u0169')
+ self.assertEqual(unicode(err), u'\u0169')
+
+
+class VersionInfoTests(unittest.TestCase):
+
+ def test__version_info__(self):
+ self.assertEqual(len(docutils.__version_info__), 6)
+ self.assertEqual(type(docutils.__version_info__.major), int)
+ self.assertEqual(type(docutils.__version_info__.minor), int)
+ self.assertEqual(type(docutils.__version_info__.micro), int)
+ self.assertEqual(type(docutils.__version_info__.releaselevel), str)
+ self.assertEqual(type(docutils.__version_info__.serial), int)
+ self.assertEqual(type(docutils.__version_info__.release), bool)
+
+ releaselevels = ('alpha', 'beta', 'candidate', 'final')
+ self.assertTrue(
+ docutils.__version_info__.releaselevel in releaselevels)
+
+ if (docutils.__version_info__.releaselevel == 'final'):
+ # releaselevel 'final' must not be used with development versions
+ # (leads to wrong version ordering of the related __version__):
+ #
+ # Within a numeric release (1.0, 2.7.3), the following suffixes
+ # are permitted and MUST be ordered as shown:
+ #
+ # .devN, aN, bN, rcN, <no suffix>, .postN
+ #
+ # https://www.python.org/dev/peps/pep-0440/#summary-of-permitted-suffixes-and-relative-ordering
+ self.assertTrue(docutils.__version_info__.release)
+ # pre-release serial number must be 0 for final releases:
+ self.assertEqual(docutils.__version_info__.serial, 0)
+
+ def test__version__(self):
+ """Test that __version__ is equivalent to __version_info__."""
+ self.assertEqual(
+ docutils.utils.version_identifier(docutils.__version_info__),
+ docutils.__version__)
+
+
+if __name__ == '__main__':
+ unittest.main()
--- /dev/null
+#! /usr/bin/env python
+# .. coding: utf-8
+# $Id: test_command_line.py 8367 2019-08-27 12:09:56Z milde $
+# Author: Günter Milde <milde@users.sourceforge.net>
+# Copyright: This module has been placed in the public domain.
+
+"""
+Test module for the command line.
+"""
+
+import unittest
+import sys, codecs
+import DocutilsTestSupport # must be imported before docutils
+import docutils.core
+
+# determine/guess the encoding of the standard input:
+try:
+ import locale # module missing in Jython
+ locale_encoding = locale.getlocale()[1] or locale.getdefaultlocale()[1]
+except ImportError:
+ locale_encoding = None
+
+argv_encoding = locale_encoding or 'ascii'
+try:
+ codecs.lookup(argv_encoding)
+except LookupError:
+ argv_encoding = 'ascii'
+
+
+class CommandLineEncodingTests(unittest.TestCase):
+
+ def test_sys_argv_decoding(self):
+ if argv_encoding == 'ascii': # cannot test
+ return
+ sys.argv.append('--source-url=test.txt') # pure ASCII argument
+ if sys.version_info < (3, 0):
+ sys.argv.append(u'--title=Dornröschen'.encode(argv_encoding))
+ else:
+ sys.argv.append(u'--title=Dornröschen')
+ publisher = docutils.core.Publisher()
+ publisher.process_command_line()
+ self.assertEqual(publisher.settings.source_url, 'test.txt')
+ self.assertEqual(publisher.settings.title, u'Dornröschen')
+ sys.argv.pop() # --title
+ sys.argv.pop() # --source-url
+
+
+if __name__ == '__main__':
+ unittest.main()
--- /dev/null
+#! /usr/bin/env python
+
+# $Id: test_dependencies.py 8357 2019-08-26 16:44:51Z milde $
+# Author: Lea Wiemann <LeWiemann@gmail.com>
+# Copyright: This module has been placed in the public domain.
+
+"""
+Test module for the --record-dependencies option.
+"""
+
+import csv
+import os.path
+import unittest
+import DocutilsTestSupport # must be imported before docutils
+import docutils.core
+import docutils.utils
+import docutils.io
+from docutils.parsers.rst.directives.images import PIL
+
+# docutils.utils.DependencyList records POSIX paths,
+# i.e. "/" as a path separator even on Windows (not os.path.join).
+paths = {'include': u'data/include.txt', # included rst file
+ 'raw': u'data/raw.txt', # included raw "HTML file"
+ 'scaled-image': u'../docs/user/rst/images/biohazard.png',
+ 'figure-image': u'../docs/user/rst/images/title.png',
+ 'stylesheet': u'data/stylesheet.txt',
+ }
+
+
+class RecordDependenciesTests(unittest.TestCase):
+
+ def get_record(self, **settings):
+ recordfile = 'record.txt'
+ recorder = docutils.utils.DependencyList(recordfile)
+ # (Re) create the record file by running a conversion:
+ settings.setdefault('source_path',
+ os.path.join('data', 'dependencies.txt'))
+ settings.setdefault('settings_overrides', {})
+ settings['settings_overrides'].update(_disable_config=True,
+ record_dependencies=recorder)
+ docutils.core.publish_file(destination=DocutilsTestSupport.DevNull(),
+ **settings)
+ recorder.close()
+ # Read the record file:
+ record = docutils.io.FileInput(source_path=recordfile,
+ encoding='utf8')
+ return record.read().splitlines()
+
+ def test_dependencies(self):
+ # Note: currently, raw input files are read (and hence recorded) while
+ # parsing even if not used in the chosen output format.
+ # This should change (see parsers/rst/directives/misc.py).
+ keys = ['include', 'raw']
+ if PIL:
+ keys += ['figure-image']
+ expected = [paths[key] for key in keys]
+ record = sorted(self.get_record(writer_name='xml'))
+ # the order of the files is arbitrary
+ expected.sort()
+ self.assertEqual(record, expected)
+
+ def test_dependencies_html(self):
+ keys = ['include', 'raw']
+ if PIL:
+ keys += ['figure-image', 'scaled-image']
+ expected = [paths[key] for key in keys]
+ # stylesheets are tested separately in test_stylesheet_dependencies():
+ so = {'stylesheet_path': None, 'stylesheet': None}
+ record = sorted(self.get_record(writer_name='html', settings_overrides=so))
+ # the order of the files is arbitrary
+ expected.sort()
+ self.assertEqual(record, expected)
+
+ def test_dependencies_latex(self):
+ # since 0.9, the latex writer records only really accessed files, too.
+ # Note: currently, raw input files are read (and hence recorded) while
+ # parsing even if not used in the chosen output format.
+ # This should change (see parsers/rst/directives/misc.py).
+ keys = ['include', 'raw']
+ if PIL:
+ keys += ['figure-image']
+ expected = [paths[key] for key in keys]
+ record = sorted(self.get_record(writer_name='latex'))
+ # the order of the files is arbitrary
+ expected.sort()
+ self.assertEqual(record, expected)
+
+ def test_csv_dependencies(self):
+ csvsource = os.path.join('data', 'csv_dep.txt')
+ self.assertEqual(self.get_record(source_path=csvsource),
+ ['data/csv_data.txt'])
+
+ def test_stylesheet_dependencies(self):
+ stylesheet = paths['stylesheet']
+ so = {'stylesheet_path': paths['stylesheet'],
+ 'stylesheet': None}
+
+ so['embed_stylesheet'] = False
+ record = self.get_record(writer_name='html', settings_overrides=so)
+ self.assertTrue(stylesheet not in record,
+ '%r should not be in %r' % (stylesheet, record))
+ record = self.get_record(writer_name='latex', settings_overrides=so)
+ self.assertTrue(stylesheet not in record,
+ '%r should not be in %r' % (stylesheet, record))
+
+ so['embed_stylesheet'] = True
+ record = self.get_record(writer_name='html', settings_overrides=so)
+ self.assertTrue(stylesheet in record,
+ '%r should be in %r' % (stylesheet, record))
+ record = self.get_record(writer_name='latex', settings_overrides=so)
+ self.assertTrue(stylesheet in record,
+ '%r should be in %r' % (stylesheet, record))
+
+
+if __name__ == '__main__':
+ unittest.main()
--- /dev/null
+#! /usr/bin/env python
+# .. coding: utf-8
+# $Id: test_error_reporting.py 8367 2019-08-27 12:09:56Z milde $
+# Author: Günter Milde <milde@users.sourceforge.net>
+# Copyright: This module has been placed in the public domain.
+
+"""
+Test `EnvironmentError` reporting.
+
+In some locales, the `errstr` argument of IOError and OSError contains
+non-ASCII chars.
+
+In Python 2, converting an exception instance to `str` or `unicode`
+might fail, with non-ASCII chars in arguments and the default encoding
+and errors ('ascii', 'strict').
+
+Therefore, Docutils must not use string interpolation with exception
+instances like, e.g., ::
+
+ try:
+ something
+ except IOError as error:
+ print('Found %s' % error)
+
+unless the minimal required Python version has this problem fixed.
+"""
+from __future__ import print_function
+
+import os
+import sys
+import unittest
+from io import StringIO, BytesIO
+
+import DocutilsTestSupport # must be imported before docutils
+from docutils import core, parsers, frontend, utils
+from docutils.utils.error_reporting import SafeString, ErrorString, ErrorOutput
+
+
+oldlocale = None
+if sys.version_info < (3, 0): # problems solved in py3k
+ try:
+ import locale # module missing in Jython
+ oldlocale = locale.getlocale()
+ except ImportError:
+ print('cannot test error reporting with problematic locales,\n'
+ '`import locale` failed.')
+
+if sys.version_info >= (3, 0):
+ unicode = str # noqa
+
+
+# locales confirmed to use non-ASCII chars in the IOError message
+# for a missing file (https://bugs.gentoo.org/show_bug.cgi?id=349101)
+# TODO: add more confirmed problematic locales
+problematic_locales = ['cs_CZ', 'cs_CZ.UTF8',
+ 'el_GR', 'el_GR.UTF-8',
+ # 'fr_FR.UTF-8', # only OSError
+ 'ja_JP.UTF-8',
+ 'ru_RU', 'ru_RU.KOI8-R',
+ 'ru_RU.UTF-8',
+ '', # default locale: might be non-problematic
+ ]
+
+if oldlocale is not None:
+ # find a supported problematic locale:
+ for testlocale in problematic_locales:
+ try:
+ locale.setlocale(locale.LC_ALL, testlocale)
+ except locale.Error:
+ testlocale = None
+ else:
+ break
+ locale.setlocale(locale.LC_ALL, oldlocale) # reset
+else:
+ testlocale = None
+
+class SafeStringTests(unittest.TestCase):
+ # the error message in EnvironmentError instances comes from the OS
+ # and in some locales (e.g. ru_RU), contains high bit chars.
+ # -> see the test in test_error_reporting.py
+
+ # test data:
+ bs = b'\xfc' # unicode(bs) fails, str(bs) in Python 3 return repr()
+ us = u'\xfc' # bytes(us) fails; str(us) fails in Python 2
+ be = Exception(bs) # unicode(be) fails
+ ue = Exception(us) # bytes(ue) fails, str(ue) fails in Python 2;
+ # wrapped test data:
+ wbs = SafeString(bs)
+ wus = SafeString(us)
+ wbe = SafeString(be)
+ wue = SafeString(ue)
+
+ def test_7bit(self):
+ # wrapping (not required with 7-bit chars) must not change the
+ # result of conversions:
+ bs7 = b'foo'
+ us7 = u'foo'
+ be7 = Exception(bs7)
+ ue7 = Exception(us7)
+ self.assertEqual(str(42), str(SafeString(42)))
+ self.assertEqual(str(bs7), str(SafeString(bs7)))
+ self.assertEqual(str(us7), str(SafeString(us7)))
+ self.assertEqual(str(be7), str(SafeString(be7)))
+ self.assertEqual(str(ue7), str(SafeString(ue7)))
+ self.assertEqual(unicode(7), unicode(SafeString(7)))
+ self.assertEqual(unicode(bs7), unicode(SafeString(bs7)))
+ self.assertEqual(unicode(us7), unicode(SafeString(us7)))
+ self.assertEqual(unicode(be7), unicode(SafeString(be7)))
+ self.assertEqual(unicode(ue7), unicode(SafeString(ue7)))
+
+ def test_ustr(self):
+ """Test conversion to a unicode-string."""
+ # unicode(self.bs) fails
+ self.assertEqual(unicode, type(unicode(self.wbs)))
+ self.assertEqual(unicode(self.us), unicode(self.wus))
+ # unicode(self.be) fails
+ self.assertEqual(unicode, type(unicode(self.wbe)))
+ self.assertEqual(unicode, type(unicode(self.ue)))
+ self.assertEqual(unicode, type(unicode(self.wue)))
+ self.assertEqual(self.us, unicode(self.wue))
+
+ def test_str(self):
+ """Test conversion to a string (bytes in Python 2, unicode in Python 3)."""
+ self.assertEqual(str(self.bs), str(self.wbs))
+ self.assertEqual(str(self.be), str(self.be))
+ # str(us) fails in Python 2
+ self.assertEqual(str, type(str(self.wus)))
+ # str(ue) fails in Python 2
+ self.assertEqual(str, type(str(self.wue)))
+
+
+class ErrorStringTests(unittest.TestCase):
+ bs = b'\xfc' # unicode(bs) fails, str(bs) in Python 3 return repr()
+ us = u'\xfc' # bytes(us) fails; str(us) fails in Python 2
+
+ def test_str(self):
+ self.assertEqual('Exception: spam',
+ str(ErrorString(Exception('spam'))))
+ self.assertEqual('IndexError: '+str(self.bs),
+ str(ErrorString(IndexError(self.bs))))
+ self.assertEqual('ImportError: %s' % SafeString(self.us),
+ str(ErrorString(ImportError(self.us))))
+
+ def test_unicode(self):
+ self.assertEqual(u'Exception: spam',
+ unicode(ErrorString(Exception(u'spam'))))
+ self.assertEqual(u'IndexError: '+self.us,
+ unicode(ErrorString(IndexError(self.us))))
+ self.assertEqual(u'ImportError: %s' % SafeString(self.bs),
+ unicode(ErrorString(ImportError(self.bs))))
+
+
+# ErrorOutput tests
+# -----------------
+
+# Stub: Buffer with 'strict' auto-conversion of input to byte string:
+class BBuf(BytesIO):
+ def write(self, data):
+ if isinstance(data, unicode):
+ data.encode('ascii', 'strict')
+ super(BBuf, self).write(data)
+
+# Stub: Buffer expecting unicode string:
+class UBuf(StringIO):
+ def write(self, data):
+ # emulate Python 3 handling of stdout, stderr
+ if isinstance(data, bytes):
+ raise TypeError('must be unicode, not bytes')
+ super(UBuf, self).write(data)
+
+class ErrorOutputTests(unittest.TestCase):
+ def test_defaults(self):
+ e = ErrorOutput()
+ self.assertEqual(e.stream, sys.stderr)
+
+ def test_bbuf(self):
+ buf = BBuf() # buffer storing byte string
+ e = ErrorOutput(buf, encoding='ascii')
+ # write byte-string as-is
+ e.write(b'b\xfc')
+ self.assertEqual(buf.getvalue(), b'b\xfc')
+ # encode unicode data with backslashescape fallback replacement:
+ e.write(u' u\xfc')
+ self.assertEqual(buf.getvalue(), b'b\xfc u\\xfc')
+ # handle Exceptions with Unicode string args
+ # unicode(Exception(u'e\xfc')) # fails in Python < 2.6
+ e.write(AttributeError(u' e\xfc'))
+ self.assertEqual(buf.getvalue(), b'b\xfc u\\xfc e\\xfc')
+ # encode with `encoding` attribute
+ e.encoding = 'utf8'
+ e.write(u' u\xfc')
+ self.assertEqual(buf.getvalue(), b'b\xfc u\\xfc e\\xfc u\xc3\xbc')
+
+ def test_ubuf(self):
+ buf = UBuf() # buffer only accepting unicode string
+ # decode of binary strings
+ e = ErrorOutput(buf, encoding='ascii')
+ e.write(b'b\xfc')
+ self.assertEqual(buf.getvalue(), u'b\ufffd') # use REPLACEMENT CHARACTER
+ # write Unicode string and Exceptions with Unicode args
+ e.write(u' u\xfc')
+ self.assertEqual(buf.getvalue(), u'b\ufffd u\xfc')
+ e.write(AttributeError(u' e\xfc'))
+ self.assertEqual(buf.getvalue(), u'b\ufffd u\xfc e\xfc')
+ # decode with `encoding` attribute
+ e.encoding = 'latin1'
+ e.write(b' b\xfc')
+ self.assertEqual(buf.getvalue(), u'b\ufffd u\xfc e\xfc b\xfc')
+
+
+
+class SafeStringTests_locale(unittest.TestCase):
+ """
+ Test docutils.SafeString with 'problematic' locales.
+
+ The error message in `EnvironmentError` instances comes from the OS
+ and in some locales (e.g. ru_RU), contains high bit chars.
+ """
+ if testlocale:
+ locale.setlocale(locale.LC_ALL, testlocale)
+ # test data:
+ bs = b'\xfc'
+ us = u'\xfc'
+ try:
+ open(b'\xfc')
+ except IOError as e: # in Python 3 the name for the exception instance
+ bioe = e # is local to the except clause
+ try:
+ open(u'\xfc')
+ except IOError as e:
+ uioe = e
+ except UnicodeEncodeError:
+ try:
+ open(u'\xfc'.encode(sys.getfilesystemencoding(), 'replace'))
+ except IOError as e:
+ uioe = e
+ try:
+ os.chdir(b'\xfc')
+ except OSError as e:
+ bose = e
+ try:
+ os.chdir(u'\xfc')
+ except OSError as e:
+ uose = e
+ except UnicodeEncodeError:
+ try:
+ os.chdir(u'\xfc'.encode(sys.getfilesystemencoding(), 'replace'))
+ except OSError as e:
+ uose = e
+ # wrapped test data:
+ wbioe = SafeString(bioe)
+ wuioe = SafeString(uioe)
+ wbose = SafeString(bose)
+ wuose = SafeString(uose)
+ # reset locale
+ if testlocale:
+ locale.setlocale(locale.LC_ALL, oldlocale)
+
+ def test_ustr(self):
+ """Test conversion to a unicode-string."""
+ # unicode(bioe) fails with e.g. 'ru_RU.utf8' locale
+ self.assertEqual(unicode, type(unicode(self.wbioe)))
+ self.assertEqual(unicode, type(unicode(self.wuioe)))
+ self.assertEqual(unicode, type(unicode(self.wbose)))
+ self.assertEqual(unicode, type(unicode(self.wuose)))
+
+ def test_str(self):
+ """Test conversion to a string (bytes in Python 2, unicode in Python 3)."""
+ self.assertEqual(str(self.bioe), str(self.wbioe))
+ self.assertEqual(str(self.uioe), str(self.wuioe))
+ self.assertEqual(str(self.bose), str(self.wbose))
+ self.assertEqual(str(self.uose), str(self.wuose))
+
+
+
+class ErrorReportingTests(unittest.TestCase):
+ """
+ Test cases where error reporting can go wrong.
+
+ Do not test the exact output (as this varies with the locale), just
+ ensure that the correct exception is thrown.
+ """
+
+ # These tests fail with a 'problematic locale',
+ # Docutils revision < 7035, and Python 2:
+
+ parser = parsers.rst.Parser()
+ """Parser shared by all ParserTestCases."""
+
+ option_parser = frontend.OptionParser(components=(parsers.rst.Parser,))
+ settings = option_parser.get_default_values()
+ settings.report_level = 1
+ settings.halt_level = 1
+ settings.warning_stream = ''
+ document = utils.new_document('test data', settings)
+
+ def setUp(self):
+ if testlocale:
+ locale.setlocale(locale.LC_ALL, testlocale)
+
+ def tearDown(self):
+ if testlocale:
+ locale.setlocale(locale.LC_ALL, oldlocale)
+
+ def test_include(self):
+ source = ('.. include:: bogus.txt')
+ self.assertRaises(utils.SystemMessage,
+ self.parser.parse, source, self.document)
+
+ def test_raw_file(self):
+ source = ('.. raw:: html\n'
+ ' :file: bogus.html\n')
+ self.assertRaises(utils.SystemMessage,
+ self.parser.parse, source, self.document)
+
+ def test_csv_table(self):
+ source = ('.. csv-table:: external file\n'
+ ' :file: bogus.csv\n')
+ self.assertRaises(utils.SystemMessage,
+ self.parser.parse, source, self.document)
+
+if __name__ == '__main__':
+ unittest.main()
--- /dev/null
+#!/usr/bin/env python
+
+# $Id: test_functional.py 8372 2019-08-27 12:11:15Z milde $
+# Author: Lea Wiemann <LeWiemann@gmail.com>
+# Copyright: This module has been placed in the public domain.
+
+"""
+Perform tests with the data in the functional/ directory.
+
+Read README.txt for details on how this is done.
+"""
+from __future__ import print_function
+
+import sys
+import os
+import os.path
+import shutil
+import unittest
+import difflib
+import DocutilsTestSupport # must be imported before docutils
+import docutils
+import docutils.core
+
+
+datadir = 'functional'
+"""The directory to store the data needed for the functional tests."""
+
+
+def join_path(*args):
+ return '/'.join(args) or '.'
+
+
+class FunctionalTestSuite(DocutilsTestSupport.CustomTestSuite):
+
+ """Test suite containing test cases for all config files."""
+
+ def __init__(self):
+ """Process all config files in functional/tests/."""
+ DocutilsTestSupport.CustomTestSuite.__init__(self)
+ os.chdir(DocutilsTestSupport.testroot)
+ self.clear_output_directory()
+ self.added = 0
+ try:
+ for root, dirs, files in os.walk(join_path(datadir, 'tests')):
+ # Process all config files among `names` in `dirname`. A config
+ # file is a Python file (*.py) which sets several variables.
+ for name in files:
+ if name.endswith('.py') and not name.startswith('_'):
+ config_file_full_path = join_path(root, name)
+ self.addTestCase(FunctionalTestCase, 'test', None, None,
+ id=config_file_full_path,
+ configfile=config_file_full_path)
+ self.added += 1
+ except (AttributeError): # python2.2 does not have os.walk
+ os.path.walk(join_path(datadir, 'tests'), self.walker, None)
+ assert self.added, 'No functional tests found.'
+
+ def clear_output_directory(self):
+ files = os.listdir(os.path.join('functional', 'output'))
+ for f in files:
+ if f in ('README.txt', '.svn', 'CVS'):
+ continue # don't touch the infrastructure
+ path = os.path.join('functional', 'output', f)
+ if os.path.isdir(path):
+ shutil.rmtree(path)
+ else:
+ os.remove(path)
+
+ def walker(self, dummy, dirname, names):
+ """
+ Process all config files among `names` in `dirname`.
+
+ This is a helper function for os.path.walk. A config file is
+ a Python file (*.py) which sets several variables.
+ """
+ for name in names:
+ if name.endswith('.py') and not name.startswith('_'):
+ config_file_full_path = join_path(dirname, name)
+ self.addTestCase(FunctionalTestCase, 'test', None, None,
+ id=config_file_full_path,
+ configfile=config_file_full_path)
+ self.added += 1
+
+
+class FunctionalTestCase(DocutilsTestSupport.CustomTestCase):
+
+ """Test case for one config file."""
+
+ no_expected_template = """\
+Cannot find expected output at %(exp)s
+If the output in %(out)s
+is correct, move it to the expected/ dir and check it in:
+
+ mv %(out)s %(exp)s
+ svn add %(exp)s
+ svn commit -m "<comment>" %(exp)s"""
+
+ expected_output_differs_template = """\
+The expected and actual output differs.
+Please compare the expected and actual output files:
+
+ diff %(exp)s %(out)s\n'
+
+If the actual output is correct, please replace the
+expected output and check it in:
+
+ mv %(out)s %(exp)s
+ svn add %(exp)s
+ svn commit -m "<comment>" %(exp)s"""
+
+ def __init__(self, *args, **kwargs):
+ """Set self.configfile, pass arguments to parent __init__."""
+ self.configfile = kwargs['configfile']
+ del kwargs['configfile']
+ DocutilsTestSupport.CustomTestCase.__init__(self, *args, **kwargs)
+
+ def shortDescription(self):
+ return 'test_functional.py: ' + self.configfile
+
+ def test(self):
+ """Process self.configfile."""
+ os.chdir(DocutilsTestSupport.testroot)
+ # Keyword parameters for publish_file:
+ namespace = {}
+ # Initialize 'settings_overrides' for test settings scripts,
+ # and disable configuration files:
+ namespace['settings_overrides'] = {'_disable_config': True}
+ # Read the variables set in the default config file and in
+ # the current config file into namespace:
+ with open(join_path(datadir, 'tests', '_default.py')) as f:
+ defaultpy = f.read()
+ exec(defaultpy, namespace)
+ with open(self.configfile) as f:
+ exec(f.read(), namespace)
+ # Check for required settings:
+ assert 'test_source' in namespace,\
+ "No 'test_source' supplied in " + self.configfile
+ assert 'test_destination' in namespace,\
+ "No 'test_destination' supplied in " + self.configfile
+ # Set source_path and destination_path if not given:
+ namespace.setdefault('source_path',
+ join_path(datadir, 'input',
+ namespace['test_source']))
+ # Path for actual output:
+ namespace.setdefault('destination_path',
+ join_path(datadir, 'output',
+ namespace['test_destination']))
+ # Path for expected output:
+ expected_path = join_path(datadir, 'expected',
+ namespace['test_destination'])
+ # shallow copy of namespace to minimize:
+ params = namespace.copy()
+ # remove unneeded parameters:
+ del params['test_source']
+ del params['test_destination']
+ # Delete private stuff like params['__builtins__']:
+ for key in list(params.keys()):
+ if key.startswith('_'):
+ del params[key]
+ # Get output (automatically written to the output/ directory
+ # by publish_file):
+ output = docutils.core.publish_file(**params)
+ # ensure output is unicode
+ output_encoding = params.get('output_encoding', 'utf-8')
+ if sys.version_info < (3, 0):
+ try:
+ output = output.decode(output_encoding)
+ except UnicodeDecodeError:
+ # failsafe
+ output = output.decode('latin1', 'replace')
+ # Normalize line endings:
+ output = '\n'.join(output.splitlines())
+ # Get the expected output *after* writing the actual output.
+ no_expected = self.no_expected_template % {
+ 'exp': expected_path, 'out': params['destination_path']}
+ self.assertTrue(os.access(expected_path, os.R_OK), no_expected)
+ if sys.version_info < (3, 0):
+ f = open(expected_path, 'r')
+ else: # samples are UTF8 encoded. 'rb' leads to errors with Python 3!
+ f = open(expected_path, 'r', encoding='utf-8')
+ # Normalize line endings:
+ expected = '\n'.join(f.read().splitlines())
+ f.close()
+ if sys.version_info < (3, 0):
+ try:
+ expected = expected.decode(output_encoding)
+ except UnicodeDecodeError:
+ expected = expected.decode('latin1', 'replace')
+
+ diff = self.expected_output_differs_template % {
+ 'exp': expected_path, 'out': params['destination_path']}
+ try:
+ self.assertEqual(output, expected, diff)
+ except AssertionError:
+ diff = ''.join(difflib.unified_diff(
+ expected.splitlines(True), output.splitlines(True),
+ expected_path, params['destination_path']))
+ if sys.version_info < (3, 0):
+ diff = diff.encode(sys.stderr.encoding or 'ascii', 'replace')
+ print('\n%s:' % (self,), file=sys.stderr)
+ print(diff, file=sys.stderr)
+ raise
+ # Execute optional function containing extra tests:
+ if '_test_more' in namespace:
+ namespace['_test_more'](join_path(datadir, 'expected'),
+ join_path(datadir, 'output'),
+ self, namespace)
+
+
+def suite():
+ return FunctionalTestSuite()
+
+
+if __name__ == '__main__':
+ unittest.main(defaultTest='suite')
--- /dev/null
+#! /usr/bin/env python
+
+# $Id: test_io.py 8367 2019-08-27 12:09:56Z milde $
+# Author: Lea Wiemann <LeWiemann@gmail.com>
+# Copyright: This module has been placed in the public domain.
+
+"""
+Test module for io.py.
+"""
+
+import unittest, sys
+import DocutilsTestSupport # must be imported before docutils
+from docutils import io
+from docutils.utils.error_reporting import locale_encoding
+from test_error_reporting import BBuf, UBuf
+
+class mock_stdout(UBuf):
+ encoding = 'utf8'
+
+ def __init__(self):
+ self.buffer = BBuf()
+ UBuf.__init__(self)
+
+class HelperTests(unittest.TestCase):
+
+ def test_check_encoding_true(self):
+ """Return `True` if lookup returns the same codec"""
+ self.assertEqual(io.check_encoding(mock_stdout, 'utf8'), True)
+ self.assertEqual(io.check_encoding(mock_stdout, 'utf-8'), True)
+ self.assertEqual(io.check_encoding(mock_stdout, 'UTF-8'), True)
+
+ def test_check_encoding_false(self):
+ """Return `False` if lookup returns different codecs"""
+ self.assertEqual(io.check_encoding(mock_stdout, 'ascii'), False)
+ self.assertEqual(io.check_encoding(mock_stdout, 'latin-1'), False)
+
+ def test_check_encoding_none(self):
+ """Cases where the comparison fails."""
+ # stream.encoding is None:
+ self.assertEqual(io.check_encoding(io.FileInput(), 'ascii'), None)
+ # stream.encoding does not exist:
+ self.assertEqual(io.check_encoding(BBuf, 'ascii'), None)
+ # encoding is None:
+ self.assertEqual(io.check_encoding(mock_stdout, None), None)
+ # encoding is invalid
+ self.assertEqual(io.check_encoding(mock_stdout, 'UTF-9'), None)
+
+
+class InputTests(unittest.TestCase):
+
+ def test_bom(self):
+ input = io.StringInput(source=b'\xef\xbb\xbf foo \xef\xbb\xbf bar',
+ encoding='utf8')
+ # Assert BOMs are gone.
+ self.assertEqual(input.read(), u' foo bar')
+ # With unicode input:
+ input = io.StringInput(source=u'\ufeff foo \ufeff bar')
+ # Assert BOMs are still there.
+ self.assertEqual(input.read(), u'\ufeff foo \ufeff bar')
+
+ def test_coding_slug(self):
+ input = io.StringInput(source=b"""\
+.. -*- coding: ascii -*-
+data
+blah
+""")
+ data = input.read()
+ self.assertEqual(input.successful_encoding, 'ascii')
+ input = io.StringInput(source=b"""\
+#! python
+# -*- coding: ascii -*-
+print("hello world")
+""")
+ data = input.read()
+ self.assertEqual(input.successful_encoding, 'ascii')
+ input = io.StringInput(source=b"""\
+#! python
+# extraneous comment; prevents coding slug from being read
+# -*- coding: ascii -*-
+print("hello world")
+""")
+ data = input.read()
+ self.assertNotEqual(input.successful_encoding, 'ascii')
+
+ def test_bom_detection(self):
+ source = u'\ufeffdata\nblah\n'
+ input = io.StringInput(source=source.encode('utf-16-be'))
+ data = input.read()
+ self.assertEqual(input.successful_encoding, 'utf-16-be')
+ input = io.StringInput(source=source.encode('utf-16-le'))
+ data = input.read()
+ self.assertEqual(input.successful_encoding, 'utf-16-le')
+ input = io.StringInput(source=source.encode('utf-8'))
+ data = input.read()
+ self.assertEqual(input.successful_encoding, 'utf-8')
+
+ def test_readlines(self):
+ input = io.FileInput(source_path='data/include.txt')
+ data = input.readlines()
+ self.assertEqual(data, [u'Some include text.\n'])
+
+ def test_heuristics_utf8(self):
+ # if no encoding is given, try decoding with utf8:
+ input = io.FileInput(source_path='functional/input/cyrillic.txt')
+ data = input.read()
+ if sys.version_info < (3, 0):
+ # in Py3k, the locale encoding is used without --input-encoding
+ # skipping the heuristic
+ self.assertEqual(input.successful_encoding, 'utf-8')
+
+ def test_heuristics_no_utf8(self):
+ # if no encoding is given and decoding with utf8 fails,
+ # use either the locale encoding (if specified) or latin-1:
+ if sys.version_info >= (3, 0) and locale_encoding != "utf8":
+ # in Py3k, the locale encoding is used without --input-encoding
+ # skipping the heuristic unless decoding fails.
+ return
+ probed_encodings = (locale_encoding, 'latin-1')
+ input = io.FileInput(source_path='data/latin1.txt')
+ data = input.read()
+ if input.successful_encoding not in probed_encodings:
+ raise AssertionError(
+ "guessed encoding '%s' differs from probed encodings %r"
+ % (input.successful_encoding, probed_encodings))
+ if input.successful_encoding == 'latin-1':
+ self.assertEqual(data, u'Gr\xfc\xdfe\n')
+
+ def test_decode_unicode(self):
+ # With the special value "unicode" or "Unicode":
+ uniinput = io.Input(encoding='unicode')
+ # keep unicode instances as-is
+ self.assertEqual(uniinput.decode(u'ja'), u'ja')
+ # raise AssertionError if data is not an unicode string
+ self.assertRaises(AssertionError, uniinput.decode, b'ja')
+
+ def test_deprecation_warning(self):
+ # Test deprecation warning of 'U' universal newlines mode.
+ # TODO remove with 3.4 support end
+
+ # Arrange
+ import warnings
+ with warnings.catch_warnings(record=True) as w:
+ # Cause all warnings to always be triggered
+ warnings.simplefilter("always", DeprecationWarning)
+
+ # Act
+ # Trigger a warning?
+ io.FileInput(source_path='data/include.txt').close()
+
+ # Assert
+ self.assertEqual(len(w), 0, "Expected no warnings, got %s" %
+ list(v.category for v in w))
+
+
+class OutputTests(unittest.TestCase):
+
+ bdata = b'\xfc'
+ udata = u'\xfc'
+
+ def setUp(self):
+ self.bdrain = BBuf()
+ """Buffer accepting binary strings (bytes)"""
+ self.udrain = UBuf()
+ """Buffer accepting unicode strings"""
+ self.mock_stdout = mock_stdout()
+ """Stub of sys.stdout under Python 3"""
+
+ def test_write_unicode(self):
+ fo = io.FileOutput(destination=self.udrain, encoding='unicode',
+ autoclose=False)
+ fo.write(self.udata)
+ self.assertEqual(self.udrain.getvalue(), self.udata)
+
+ def test_write_utf8(self):
+ if sys.version_info >= (3, 0):
+ fo = io.FileOutput(destination=self.udrain, encoding='utf8',
+ autoclose=False)
+ fo.write(self.udata)
+ self.assertEqual(self.udrain.getvalue(), self.udata)
+ else:
+ fo = io.FileOutput(destination=self.bdrain, encoding='utf8',
+ autoclose=False)
+ fo.write(self.udata)
+ self.assertEqual(self.bdrain.getvalue(), self.udata.encode('utf8'))
+
+ # With destination in binary mode, data must be binary string
+ # and is written as-is:
+ def test_write_bytes(self):
+ fo = io.FileOutput(destination=self.bdrain, encoding='utf8',
+ mode='wb', autoclose=False)
+ fo.write(self.bdata)
+ self.assertEqual(self.bdrain.getvalue(), self.bdata)
+
+ # Test for Python 3 features:
+ if sys.version_info >= (3, 0):
+ def test_write_bytes_to_stdout(self):
+ # try writing data to `destination.buffer`, if data is
+ # instance of `bytes` and writing to `destination` fails:
+ fo = io.FileOutput(destination=self.mock_stdout)
+ fo.write(self.bdata)
+ self.assertEqual(self.mock_stdout.buffer.getvalue(),
+ self.bdata)
+
+ def test_encoding_clash_resolved(self):
+ fo = io.FileOutput(destination=self.mock_stdout,
+ encoding='latin1', autoclose=False)
+ fo.write(self.udata)
+ self.assertEqual(self.mock_stdout.buffer.getvalue(),
+ self.udata.encode('latin1'))
+
+ def test_encoding_clash_nonresolvable(self):
+ del(self.mock_stdout.buffer)
+ fo = io.FileOutput(destination=self.mock_stdout,
+ encoding='latin1', autoclose=False)
+ self.assertRaises(ValueError, fo.write, self.udata)
+
+
+if __name__ == '__main__':
+ unittest.main()
--- /dev/null
+#!/usr/bin/env python
+
+# $Id: test_language.py 8372 2019-08-27 12:11:15Z milde $
+# Authors: Engelbert Gruber <grubert@users.sourceforge.net>;
+# David Goodger <goodger@python.org>
+# Copyright: This module has been placed in the public domain.
+
+"""
+Tests for language module completeness.
+
+Specify a language code (e.g. "de") as a command-line parameter to test only
+that language.
+"""
+
+import sys
+import os
+import re
+import DocutilsTestSupport # must be imported before docutils
+import docutils.languages
+import docutils.parsers.rst.languages
+from docutils.parsers.rst import states, directives, roles
+import docutils.utils, docutils.frontend
+
+_settings = docutils.frontend.OptionParser().get_default_values()
+_reporter = docutils.utils.new_reporter('', _settings)
+
+reference_language = 'en'
+
+if sys.version_info >= (3, 0):
+ unicode = str # noqa
+
+
+class LanguageTestSuite(DocutilsTestSupport.CustomTestSuite):
+
+ language_module_pattern = re.compile(r'^([a-z]{2,3}(_[a-z]{2,8})*)\.py$')
+
+ def __init__(self, languages=None):
+ DocutilsTestSupport.CustomTestSuite.__init__(self)
+ if languages:
+ self.languages = languages
+ else:
+ self.get_languages()
+
+ def get_languages(self):
+ """
+ Get installed language translations from docutils.languages and from
+ docutils.parsers.rst.languages.
+ """
+ languages = {}
+ for mod in (os.listdir(docutils.languages.__path__[0])
+ + os.listdir(docutils.parsers.rst.languages.__path__[0])):
+ match = self.language_module_pattern.match(mod)
+ if match:
+ languages[match.group(1)] = 1
+ self.languages = list(languages.keys())
+ # test language tag normalization:
+ self.languages += ['en_gb', 'en_US', 'en-CA', 'de-DE', 'de-AT-1901',
+ 'pt-BR', 'pt-foo-BR']
+ # test that locally created language files are also loaded.
+ # requires local_dummy_lang.py in test directory (testroot)
+ # The local_dummy_lang.py contains all the fields from both
+ # the docutils language tags and the parser.rst language tags
+ self.languages += ['local_dummy_lang']
+
+ def generateTests(self):
+ for language in self.languages:
+ for method in LanguageTestCase.test_methods:
+ self.addTestCase(LanguageTestCase, method, None, None,
+ id=language+'.py', language=language)
+
+
+class LanguageTestCase(DocutilsTestSupport.CustomTestCase):
+
+ test_methods = ['test_labels', 'test_bibliographic_fields',
+ 'test_directives', 'test_roles']
+ """Names of methods used to test each language."""
+
+ def __init__(self, *args, **kwargs):
+ self.ref = docutils.languages.get_language(reference_language,
+ _reporter)
+ self.language = kwargs['language']
+ del kwargs['language'] # only wanted here
+ DocutilsTestSupport.CustomTestCase.__init__(self, *args, **kwargs)
+
+ def _xor(self, ref_dict, l_dict):
+ """
+ Returns entries that are only in one dictionary.
+ (missing_in_lang, more_than_in_ref).
+ """
+ missing = [] # in ref but not in l.
+ too_much = [] # in l but not in ref.
+ for label in ref_dict.keys():
+ if label not in l_dict:
+ missing.append(label)
+ for label in l_dict.keys():
+ if label not in ref_dict:
+ too_much.append(label)
+ return (missing, too_much)
+
+ def _invert(self, adict):
+ """Return an inverted (keys & values swapped) dictionary."""
+ inverted = {}
+ for key, value in adict.items():
+ inverted[value] = key
+ return inverted
+
+ def test_labels(self):
+ try:
+ module = docutils.languages.get_language(self.language, _reporter)
+ if not module:
+ raise ImportError
+ except ImportError:
+ self.fail('No docutils.languages.%s module.' % self.language)
+ missed, unknown = self._xor(self.ref.labels, module.labels)
+ if missed or unknown:
+ self.fail('Module docutils.languages.%s.labels:\n'
+ ' Missed: %s; Unknown: %s'
+ % (self.language, str(missed), str(unknown)))
+
+ def test_bibliographic_fields(self):
+ try:
+ module = docutils.languages.get_language(self.language, _reporter)
+ if not module:
+ raise ImportError
+ except ImportError:
+ self.fail('No docutils.languages.%s module.' % self.language)
+ missed, unknown = self._xor(
+ self._invert(self.ref.bibliographic_fields),
+ self._invert(module.bibliographic_fields))
+ if missed or unknown:
+ self.fail('Module docutils.languages.%s.bibliographic_fields:\n'
+ ' Missed: %s; Unknown: %s'
+ % (self.language, str(missed), str(unknown)))
+
+ def test_directives(self):
+ try:
+ module = docutils.parsers.rst.languages.get_language(
+ self.language)
+ if not module:
+ raise ImportError
+ except ImportError:
+ self.fail('No docutils.parsers.rst.languages.%s module.'
+ % self.language)
+ failures = []
+ for d in module.directives.keys():
+ try:
+ func, msg = directives.directive(d, module, None)
+ if not func:
+ failures.append('"%s": unknown directive' % d)
+ except Exception as error:
+ failures.append('"%s": %s' % (d, error))
+ inverted = self._invert(module.directives)
+ canonical = sorted(directives._directive_registry.keys())
+ canonical.remove('restructuredtext-test-directive')
+ for name in canonical:
+ if name not in inverted:
+ failures.append('"%s": translation missing' % name)
+ if failures:
+ text = ('Module docutils.parsers.rst.languages.%s:\n %s'
+ % (self.language, '\n '.join(failures)))
+ if isinstance(text, unicode):
+ text = text.encode('raw_unicode_escape')
+ self.fail(text)
+
+ def test_roles(self):
+ try:
+ module = docutils.parsers.rst.languages.get_language(
+ self.language)
+ if not module:
+ raise ImportError
+ module.roles
+ except ImportError:
+ self.fail('No docutils.parsers.rst.languages.%s module.'
+ % self.language)
+ except AttributeError:
+ self.fail('No "roles" mapping in docutils.parsers.rst.languages.'
+ '%s module.' % self.language)
+ failures = []
+ for d in module.roles.values():
+ try:
+ method = roles._role_registry[d]
+ #if not method:
+ # failures.append('"%s": unknown role' % d)
+ except KeyError as error:
+ failures.append('"%s": %s' % (d, error))
+ inverted = self._invert(module.roles)
+ canonical = sorted(roles._role_registry.keys())
+ canonical.remove('restructuredtext-unimplemented-role')
+ for name in canonical:
+ if name not in inverted:
+ failures.append('"%s": translation missing' % name)
+ if failures:
+ text = ('Module docutils.parsers.rst.languages.%s:\n %s'
+ % (self.language, '\n '.join(failures)))
+ if isinstance(text, unicode):
+ text = text.encode('raw_unicode_escape')
+ self.fail(text)
+
+languages_to_test = []
+
+def suite():
+ s = LanguageTestSuite(languages_to_test)
+ s.generateTests()
+ return s
+
+def get_language_arguments():
+ while len(sys.argv) > 1:
+ last = sys.argv[-1]
+ if last.startswith('-'):
+ break
+ languages_to_test.append(last)
+ sys.argv.pop()
+ languages_to_test.reverse()
+
+
+if __name__ == '__main__':
+ get_language_arguments()
+ import unittest
+ unittest.main(defaultTest='suite')
+
+# vim: set et ts=4 ai :
--- /dev/null
+#! /usr/bin/env python
+# -*- coding: utf-8 -*-
+
+# $Id: test_nodes.py 8430 2019-12-02 21:14:28Z grubert $
+# Author: David Goodger <goodger@python.org>
+# Copyright: This module has been placed in the public domain.
+
+"""
+Test module for nodes.py.
+"""
+
+import sys
+import unittest
+
+import DocutilsTestSupport # must be imported before docutils
+from DocutilsTestSupport import nodes, utils
+
+debug = False
+
+if sys.version_info >= (3, 0):
+ unicode = str # noqa
+
+
+class TextTests(unittest.TestCase):
+
+ def setUp(self):
+ self.text = nodes.Text('Line 1.\nLine 2.')
+ self.unicode_text = nodes.Text(u'Möhren')
+ self.longtext = nodes.Text('Mary had a little lamb whose '
+ 'fleece was white as snow and '
+ 'everwhere that Mary went the '
+ 'lamb was sure to go.')
+
+ def test_repr(self):
+ self.assertEqual(repr(self.text), r"<#text: 'Line 1.\nLine 2.'>")
+ self.assertEqual(self.text.shortrepr(),
+ r"<#text: 'Line 1.\nLine 2.'>")
+ self.assertEqual(nodes.reprunicode('foo'), u'foo')
+ if sys.version_info < (3, 0):
+ self.assertEqual(repr(self.unicode_text), r"<#text: 'M\xf6hren'>")
+ else:
+ self.assertEqual(repr(self.unicode_text), u"<#text: 'Möhren'>")
+
+ def test_str(self):
+ self.assertEqual(str(self.text), 'Line 1.\nLine 2.')
+
+ def test_unicode(self):
+ self.assertEqual(unicode(self.unicode_text), u'Möhren')
+ self.assertEqual(str(self.unicode_text), 'M\xf6hren')
+
+ def test_astext(self):
+ self.assertTrue(isinstance(self.text.astext(), unicode))
+ self.assertEqual(self.text.astext(), u'Line 1.\nLine 2.')
+ self.assertEqual(self.unicode_text.astext(), u'Möhren')
+
+ def test_pformat(self):
+ self.assertTrue(isinstance(self.text.pformat(), unicode))
+ self.assertEqual(self.text.pformat(), u'Line 1.\nLine 2.\n')
+
+ def test_strip(self):
+ text = nodes.Text(' was noch ', r' \was\ noch \\ ')
+ stripped = text.lstrip().rstrip()
+ stripped2 = text.lstrip(' wahn').rstrip(' wahn')
+ self.assertEqual(stripped, u'was noch')
+ self.assertEqual(stripped2, u's noc')
+
+ def test_asciirestriction(self):
+ if sys.version_info < (3, 0):
+ self.assertRaises(UnicodeDecodeError, nodes.Text,
+ b'hol%s' % chr(224))
+ else:
+ # no bytes at all allowed
+ self.assertRaises(TypeError, nodes.Text, b'hol')
+
+ def test_longrepr(self):
+ self.assertEqual(repr(self.longtext), r"<#text: 'Mary had a "
+ r"little lamb whose fleece was white as snow "
+ r"and everwh ...'>")
+ self.assertEqual(self.longtext.shortrepr(),
+ r"<#text: 'Mary had a lit ...'>")
+
+class ElementTests(unittest.TestCase):
+
+ def test_empty(self):
+ element = nodes.Element()
+ self.assertEqual(repr(element), '<Element: >')
+ self.assertEqual(str(element), '<Element/>')
+ dom = element.asdom()
+ self.assertEqual(dom.toxml(), '<Element/>')
+ dom.unlink()
+ element['attr'] = '1'
+ self.assertEqual(repr(element), '<Element: >')
+ self.assertEqual(str(element), '<Element attr="1"/>')
+ dom = element.asdom()
+ self.assertEqual(dom.toxml(), '<Element attr="1"/>')
+ dom.unlink()
+ self.assertEqual(element.pformat(), '<Element attr="1">\n')
+ del element['attr']
+ element['mark'] = u'\u2022'
+ self.assertEqual(repr(element), '<Element: >')
+ if sys.version_info < (3, 0):
+ self.assertEqual(str(element), '<Element mark="\\u2022"/>')
+ else:
+ self.assertEqual(str(element), u'<Element mark="\u2022"/>')
+ dom = element.asdom()
+ self.assertEqual(dom.toxml(), u'<Element mark="\u2022"/>')
+ dom.unlink()
+ element['names'] = ['nobody', u'имя', u'näs']
+ if sys.version_info < (3, 0):
+ self.assertEqual(repr(element),
+ '<Element "nobody; \\u0438\\u043c\\u044f; n\\xe4s": >')
+ else:
+ self.assertEqual(repr(element), u'<Element "nobody; имя; näs": >')
+ self.assertTrue(isinstance(repr(element), str))
+
+ def test_withtext(self):
+ element = nodes.Element('text\nmore', nodes.Text('text\nmore'))
+ uelement = nodes.Element(u'grün', nodes.Text(u'grün'))
+ self.assertEqual(repr(element), r"<Element: <#text: 'text\nmore'>>")
+ if sys.version_info < (3, 0):
+ self.assertEqual(repr(uelement), "<Element: <#text: 'gr\\xfcn'>>")
+ else:
+ self.assertEqual(repr(uelement), u"<Element: <#text: 'grün'>>")
+ self.assertTrue(isinstance(repr(uelement), str))
+ self.assertEqual(str(element), '<Element>text\nmore</Element>')
+ self.assertEqual(str(uelement), '<Element>gr\xfcn</Element>')
+ dom = element.asdom()
+ self.assertEqual(dom.toxml(), '<Element>text\nmore</Element>')
+ dom.unlink()
+ element['attr'] = '1'
+ self.assertEqual(repr(element), r"<Element: <#text: 'text\nmore'>>")
+ self.assertEqual(str(element),
+ '<Element attr="1">text\nmore</Element>')
+ dom = element.asdom()
+ self.assertEqual(dom.toxml(),
+ '<Element attr="1">text\nmore</Element>')
+ dom.unlink()
+ self.assertEqual(element.pformat(),
+ '<Element attr="1">\n text\n more\n')
+
+ def test_clear(self):
+ element = nodes.Element()
+ element += nodes.Element()
+ self.assertTrue(len(element))
+ element.clear()
+ self.assertTrue(not len(element))
+
+ def test_normal_attributes(self):
+ element = nodes.Element()
+ self.assertTrue('foo' not in element)
+ self.assertRaises(KeyError, element.__getitem__, 'foo')
+ element['foo'] = 'sometext'
+ self.assertEqual(element['foo'], 'sometext')
+ del element['foo']
+ self.assertRaises(KeyError, element.__getitem__, 'foo')
+
+ def test_default_attributes(self):
+ element = nodes.Element()
+ self.assertEqual(element['ids'], [])
+ self.assertEqual(element.non_default_attributes(), {})
+ self.assertTrue(not element.is_not_default('ids'))
+ self.assertTrue(element['ids'] is not nodes.Element()['ids'])
+ element['ids'].append('someid')
+ self.assertEqual(element['ids'], ['someid'])
+ self.assertEqual(element.non_default_attributes(),
+ {'ids': ['someid']})
+ self.assertTrue(element.is_not_default('ids'))
+
+ def test_update_basic_atts(self):
+ element1 = nodes.Element(ids=['foo', 'bar'], test=['test1'])
+ element2 = nodes.Element(ids=['baz', 'qux'], test=['test2'])
+ element1.update_basic_atts(element2)
+ # 'ids' are appended because 'ids' is a basic attribute.
+ self.assertEqual(element1['ids'], ['foo', 'bar', 'baz', 'qux'])
+ # 'test' is not overwritten because it is not a basic attribute.
+ self.assertEqual(element1['test'], ['test1'])
+
+ def test_update_all_atts(self):
+ # Note: Also tests is_not_list_attribute and is_not_known_attribute
+ # and various helpers
+ ## Test for full attribute replacement
+ element1 = nodes.Element(ids=['foo', 'bar'], parent_only='parent',
+ all_nodes='mom')
+ element2 = nodes.Element(ids=['baz', 'qux'], child_only='child',
+ all_nodes='dad', source='source')
+
+ # Test for when same fields are replaced as well as source...
+ element1.update_all_atts_consistantly(element2, True, True)
+ # 'ids' are appended because 'ids' is a basic attribute.
+ self.assertEqual(element1['ids'], ['foo', 'bar', 'baz', 'qux'])
+ # 'parent_only' should remain unaffected.
+ self.assertEqual(element1['parent_only'], 'parent')
+ # 'all_nodes' is overwritten due to the second parameter == True.
+ self.assertEqual(element1['all_nodes'], 'dad')
+ # 'child_only' should have been added.
+ self.assertEqual(element1['child_only'], 'child')
+ # 'source' is also overwritten due to the third parameter == True.
+ self.assertEqual(element1['source'], 'source')
+
+ # Test for when same fields are replaced but not source...
+ element1 = nodes.Element(ids=['foo', 'bar'], parent_only='parent',
+ all_nodes='mom')
+ element1.update_all_atts_consistantly(element2)
+ # 'ids' are appended because 'ids' is a basic attribute.
+ self.assertEqual(element1['ids'], ['foo', 'bar', 'baz', 'qux'])
+ # 'parent_only' should remain unaffected.
+ self.assertEqual(element1['parent_only'], 'parent')
+ # 'all_nodes' is overwritten due to the second parameter default of True.
+ self.assertEqual(element1['all_nodes'], 'dad')
+ # 'child_only' should have been added.
+ self.assertEqual(element1['child_only'], 'child')
+ # 'source' remains unset due to the third parameter default of False.
+ self.assertEqual(element1.get('source'), None)
+
+ # Test for when fields are NOT replaced but source is...
+ element1 = nodes.Element(ids=['foo', 'bar'], parent_only='parent',
+ all_nodes='mom')
+ element1.update_all_atts_consistantly(element2, False, True)
+ # 'ids' are appended because 'ids' is a basic attribute.
+ self.assertEqual(element1['ids'], ['foo', 'bar', 'baz', 'qux'])
+ # 'parent_only' should remain unaffected.
+ self.assertEqual(element1['parent_only'], 'parent')
+ # 'all_nodes' is preserved due to the second parameter == False.
+ self.assertEqual(element1['all_nodes'], 'mom')
+ # 'child_only' should have been added.
+ self.assertEqual(element1['child_only'], 'child')
+ # 'source' is added due to the third parameter == True.
+ self.assertEqual(element1['source'], 'source')
+ element1 = nodes.Element(source='destination')
+ element1.update_all_atts_consistantly(element2, False, True)
+ # 'source' remains unchanged due to the second parameter == False.
+ self.assertEqual(element1['source'], 'destination')
+
+ # Test for when same fields are replaced but not source...
+ element1 = nodes.Element(ids=['foo', 'bar'], parent_only='parent',
+ all_nodes='mom')
+ element1.update_all_atts_consistantly(element2, False)
+ # 'ids' are appended because 'ids' is a basic attribute.
+ self.assertEqual(element1['ids'], ['foo', 'bar', 'baz', 'qux'])
+ # 'parent_only' should remain unaffected.
+ self.assertEqual(element1['parent_only'], 'parent')
+ # 'all_nodes' is preserved due to the second parameter == False.
+ self.assertEqual(element1['all_nodes'], 'mom')
+ # 'child_only' should have been added.
+ self.assertEqual(element1['child_only'], 'child')
+ # 'source' remains unset due to the third parameter default of False.
+ self.assertEqual(element1.get('source'), None)
+
+ ## Test for List attribute merging
+ # Attribute Concatination
+ element1 = nodes.Element(ss='a', sl='1', ls=['I'], ll=['A'])
+ element2 = nodes.Element(ss='b', sl=['2'], ls='II', ll=['B'])
+ element1.update_all_atts_concatenating(element2)
+ # 'ss' is replaced because non-list
+ self.assertEqual(element1['ss'], 'b')
+ # 'sl' is replaced because they are both not lists
+ self.assertEqual(element1['sl'], ['2'])
+ # 'ls' is replaced because they are both not lists
+ self.assertEqual(element1['ls'], 'II')
+ # 'll' is extended because they are both lists
+ self.assertEqual(element1['ll'], ['A', 'B'])
+
+ # Attribute Coercion
+ element1 = nodes.Element(ss='a', sl='1', ls=['I'], ll=['A'])
+ element2 = nodes.Element(ss='b', sl=['2'], ls='II', ll=['B'])
+ element1.update_all_atts_coercion(element2)
+ # 'ss' is replaced because non-list
+ self.assertEqual(element1['ss'], 'b')
+ # 'sl' is converted to a list and appended because element2 has a list
+ self.assertEqual(element1['sl'], ['1', '2'])
+ # 'ls' has element2's value appended to the list
+ self.assertEqual(element1['ls'], ['I', 'II'])
+ # 'll' is extended because they are both lists
+ self.assertEqual(element1['ll'], ['A', 'B'])
+
+ # Attribute Conversion
+ element1 = nodes.Element(ss='a', sl='1', ls=['I'], ll=['A'])
+ element2 = nodes.Element(ss='b', sl=['2'], ls='II', ll=['B'])
+ element1.update_all_atts_convert(element2)
+ # 'ss' is converted to a list with the values from each element
+ self.assertEqual(element1['ss'], ['a', 'b'])
+ # 'sl' is converted to a list and appended
+ self.assertEqual(element1['sl'], ['1', '2'])
+ # 'ls' has element2's value appended to the list
+ self.assertEqual(element1['ls'], ['I', 'II'])
+ # 'll' is extended
+ self.assertEqual(element1['ll'], ['A', 'B'])
+
+ def test_replace_self(self):
+ parent = nodes.Element(ids=['parent'])
+ child1 = nodes.Element(ids=['child1'])
+ grandchild = nodes.Element(ids=['grandchild'])
+ child1 += grandchild
+ child2 = nodes.Element(ids=['child2'])
+ twins = [nodes.Element(ids=['twin%s' % i]) for i in (1, 2)]
+ child2 += twins
+ child3 = nodes.Element(ids=['child3'])
+ child4 = nodes.Element(ids=['child4'])
+ parent += [child1, child2, child3, child4]
+ self.assertEqual(parent.pformat(), """\
+<Element ids="parent">
+ <Element ids="child1">
+ <Element ids="grandchild">
+ <Element ids="child2">
+ <Element ids="twin1">
+ <Element ids="twin2">
+ <Element ids="child3">
+ <Element ids="child4">
+""")
+ # Replace child1 with the grandchild.
+ child1.replace_self(child1[0])
+ self.assertEqual(parent[0], grandchild)
+ # Assert that 'ids' have been updated.
+ self.assertEqual(grandchild['ids'], ['grandchild', 'child1'])
+ # Replace child2 with its children.
+ child2.replace_self(child2[:])
+ self.assertEqual(parent[1:3], twins)
+ # Assert that 'ids' have been propagated to first child.
+ self.assertEqual(twins[0]['ids'], ['twin1', 'child2'])
+ self.assertEqual(twins[1]['ids'], ['twin2'])
+ # Replace child3 with new child.
+ newchild = nodes.Element(ids=['newchild'])
+ child3.replace_self(newchild)
+ self.assertEqual(parent[3], newchild)
+ self.assertEqual(newchild['ids'], ['newchild', 'child3'])
+ # Crazy but possible case: Substitute child4 for itself.
+ child4.replace_self(child4)
+ # Make sure the 'child4' ID hasn't been duplicated.
+ self.assertEqual(child4['ids'], ['child4'])
+ self.assertEqual(len(parent), 5)
+
+ def test_unicode(self):
+ node = nodes.Element(u'Möhren', nodes.Text(u'Möhren', u'Möhren'))
+ self.assertEqual(unicode(node), u'<Element>Möhren</Element>')
+
+
+class MiscTests(unittest.TestCase):
+
+ def test_reprunicode(self):
+ # return `unicode` instance
+ self.assertTrue(isinstance(nodes.reprunicode('foo'), unicode))
+ self.assertEqual(nodes.reprunicode('foo'), u'foo')
+ self.assertEqual(nodes.reprunicode(u'Möhre'), u'Möhre')
+ if sys.version_info < (3, 0): # strip leading "u" from representation
+ self.assertEqual(repr(nodes.reprunicode(u'Möhre')),
+ repr(u'Möhre')[1:])
+ else: # no change to `unicode` under Python 3k
+ self.assertEqual(repr(nodes.reprunicode(u'Möhre')), repr(u'Möhre'))
+
+ def test_ensure_str(self):
+ self.assertTrue(isinstance(nodes.ensure_str(u'über'), str))
+ self.assertEqual(nodes.ensure_str('over'), 'over')
+ if sys.version_info < (3, 0): # strip leading "u" from representation
+ self.assertEqual(nodes.ensure_str(u'über'), r'\xfcber')
+ else:
+ self.assertEqual(nodes.ensure_str(u'über'), r'über')
+
+ def test_node_class_names(self):
+ node_class_names = []
+ for x in dir(nodes):
+ c = getattr(nodes, x)
+ if isinstance(c, type) and \
+ issubclass(c, nodes.Node) and len(c.__bases__) > 1:
+ node_class_names.append(x)
+ node_class_names.sort()
+ nodes.node_class_names.sort()
+ self.assertEqual(node_class_names, nodes.node_class_names)
+
+ ids = [(u'a', 'a'), ('A', 'a'), ('', ''), ('a b \n c', 'a-b-c'),
+ ('a.b.c', 'a-b-c'), (' - a - b - c - ', 'a-b-c'), (' - ', ''),
+ (u'\u2020\u2066', ''), (u'a \xa7 b \u2020 c', 'a-b-c'),
+ ('1', ''), ('1abc', 'abc'),
+ ]
+ ids_unicode_all = [
+ (u'\u00f8 o with stroke', 'o-o-with-stroke'),
+ (u'\u0111 d with stroke', 'd-d-with-stroke'),
+ (u'\u0127 h with stroke', 'h-h-with-stroke'),
+ (u'\u0131 dotless i', 'i-dotless-i'),
+ (u'\u0142 l with stroke', 'l-l-with-stroke'),
+ (u'\u0167 t with stroke', 't-t-with-stroke'),
+ # From Latin Extended-B
+ (u'\u0180 b with stroke', 'b-b-with-stroke'),
+ (u'\u0183 b with topbar', 'b-b-with-topbar'),
+ (u'\u0188 c with hook', 'c-c-with-hook'),
+ (u'\u018c d with topbar', 'd-d-with-topbar'),
+ (u'\u0192 f with hook', 'f-f-with-hook'),
+ (u'\u0199 k with hook', 'k-k-with-hook'),
+ (u'\u019a l with bar', 'l-l-with-bar'),
+ (u'\u019e n with long right leg', 'n-n-with-long-right-leg'),
+ (u'\u01a5 p with hook', 'p-p-with-hook'),
+ (u'\u01ab t with palatal hook', 't-t-with-palatal-hook'),
+ (u'\u01ad t with hook', 't-t-with-hook'),
+ (u'\u01b4 y with hook', 'y-y-with-hook'),
+ (u'\u01b6 z with stroke', 'z-z-with-stroke'),
+ (u'\u01e5 g with stroke', 'g-g-with-stroke'),
+ (u'\u0225 z with hook', 'z-z-with-hook'),
+ (u'\u0234 l with curl', 'l-l-with-curl'),
+ (u'\u0235 n with curl', 'n-n-with-curl'),
+ (u'\u0236 t with curl', 't-t-with-curl'),
+ (u'\u0237 dotless j', 'j-dotless-j'),
+ (u'\u023c c with stroke', 'c-c-with-stroke'),
+ (u'\u023f s with swash tail', 's-s-with-swash-tail'),
+ (u'\u0240 z with swash tail', 'z-z-with-swash-tail'),
+ (u'\u0247 e with stroke', 'e-e-with-stroke'),
+ (u'\u0249 j with stroke', 'j-j-with-stroke'),
+ (u'\u024b q with hook tail', 'q-q-with-hook-tail'),
+ (u'\u024d r with stroke', 'r-r-with-stroke'),
+ (u'\u024f y with stroke', 'y-y-with-stroke'),
+ # From Latin-1 Supplements
+ (u'\u00e0: a with grave', 'a-a-with-grave'),
+ (u'\u00e1 a with acute', 'a-a-with-acute'),
+ (u'\u00e2 a with circumflex', 'a-a-with-circumflex'),
+ (u'\u00e3 a with tilde', 'a-a-with-tilde'),
+ (u'\u00e4 a with diaeresis', 'a-a-with-diaeresis'),
+ (u'\u00e5 a with ring above', 'a-a-with-ring-above'),
+ (u'\u00e7 c with cedilla', 'c-c-with-cedilla'),
+ (u'\u00e8 e with grave', 'e-e-with-grave'),
+ (u'\u00e9 e with acute', 'e-e-with-acute'),
+ (u'\u00ea e with circumflex', 'e-e-with-circumflex'),
+ (u'\u00eb e with diaeresis', 'e-e-with-diaeresis'),
+ (u'\u00ec i with grave', 'i-i-with-grave'),
+ (u'\u00ed i with acute', 'i-i-with-acute'),
+ (u'\u00ee i with circumflex', 'i-i-with-circumflex'),
+ (u'\u00ef i with diaeresis', 'i-i-with-diaeresis'),
+ (u'\u00f1 n with tilde', 'n-n-with-tilde'),
+ (u'\u00f2 o with grave', 'o-o-with-grave'),
+ (u'\u00f3 o with acute', 'o-o-with-acute'),
+ (u'\u00f4 o with circumflex', 'o-o-with-circumflex'),
+ (u'\u00f5 o with tilde', 'o-o-with-tilde'),
+ (u'\u00f6 o with diaeresis', 'o-o-with-diaeresis'),
+ (u'\u00f9 u with grave', 'u-u-with-grave'),
+ (u'\u00fa u with acute', 'u-u-with-acute'),
+ (u'\u00fb u with circumflex', 'u-u-with-circumflex'),
+ (u'\u00fc u with diaeresis', 'u-u-with-diaeresis'),
+ (u'\u00fd y with acute', 'y-y-with-acute'),
+ (u'\u00ff y with diaeresis', 'y-y-with-diaeresis'),
+ # From Latin Extended-A
+ (u'\u0101 a with macron', 'a-a-with-macron'),
+ (u'\u0103 a with breve', 'a-a-with-breve'),
+ (u'\u0105 a with ogonek', 'a-a-with-ogonek'),
+ (u'\u0107 c with acute', 'c-c-with-acute'),
+ (u'\u0109 c with circumflex', 'c-c-with-circumflex'),
+ (u'\u010b c with dot above', 'c-c-with-dot-above'),
+ (u'\u010d c with caron', 'c-c-with-caron'),
+ (u'\u010f d with caron', 'd-d-with-caron'),
+ (u'\u0113 e with macron', 'e-e-with-macron'),
+ (u'\u0115 e with breve', 'e-e-with-breve'),
+ (u'\u0117 e with dot above', 'e-e-with-dot-above'),
+ (u'\u0119 e with ogonek', 'e-e-with-ogonek'),
+ (u'\u011b e with caron', 'e-e-with-caron'),
+ (u'\u011d g with circumflex', 'g-g-with-circumflex'),
+ (u'\u011f g with breve', 'g-g-with-breve'),
+ (u'\u0121 g with dot above', 'g-g-with-dot-above'),
+ (u'\u0123 g with cedilla', 'g-g-with-cedilla'),
+ (u'\u0125 h with circumflex', 'h-h-with-circumflex'),
+ (u'\u0129 i with tilde', 'i-i-with-tilde'),
+ (u'\u012b i with macron', 'i-i-with-macron'),
+ (u'\u012d i with breve', 'i-i-with-breve'),
+ (u'\u012f i with ogonek', 'i-i-with-ogonek'),
+ (u'\u0133 ligature ij', 'ij-ligature-ij'),
+ (u'\u0135 j with circumflex', 'j-j-with-circumflex'),
+ (u'\u0137 k with cedilla', 'k-k-with-cedilla'),
+ (u'\u013a l with acute', 'l-l-with-acute'),
+ (u'\u013c l with cedilla', 'l-l-with-cedilla'),
+ (u'\u013e l with caron', 'l-l-with-caron'),
+ (u'\u0140 l with middle dot', 'l-l-with-middle-dot'),
+ (u'\u0144 n with acute', 'n-n-with-acute'),
+ (u'\u0146 n with cedilla', 'n-n-with-cedilla'),
+ (u'\u0148 n with caron', 'n-n-with-caron'),
+ (u'\u014d o with macron', 'o-o-with-macron'),
+ (u'\u014f o with breve', 'o-o-with-breve'),
+ (u'\u0151 o with double acute', 'o-o-with-double-acute'),
+ (u'\u0155 r with acute', 'r-r-with-acute'),
+ (u'\u0157 r with cedilla', 'r-r-with-cedilla'),
+ (u'\u0159 r with caron', 'r-r-with-caron'),
+ (u'\u015b s with acute', 's-s-with-acute'),
+ (u'\u015d s with circumflex', 's-s-with-circumflex'),
+ (u'\u015f s with cedilla', 's-s-with-cedilla'),
+ (u'\u0161 s with caron', 's-s-with-caron'),
+ (u'\u0163 t with cedilla', 't-t-with-cedilla'),
+ (u'\u0165 t with caron', 't-t-with-caron'),
+ (u'\u0169 u with tilde', 'u-u-with-tilde'),
+ (u'\u016b u with macron', 'u-u-with-macron'),
+ (u'\u016d u with breve', 'u-u-with-breve'),
+ (u'\u016f u with ring above', 'u-u-with-ring-above'),
+ (u'\u0171 u with double acute', 'u-u-with-double-acute'),
+ (u'\u0173 u with ogonek', 'u-u-with-ogonek'),
+ (u'\u0175 w with circumflex', 'w-w-with-circumflex'),
+ (u'\u0177 y with circumflex', 'y-y-with-circumflex'),
+ (u'\u017a z with acute', 'z-z-with-acute'),
+ (u'\u017c z with dot above', 'z-z-with-dot-above'),
+ (u'\u017e z with caron', 'z-z-with-caron'),
+ # From Latin Extended-B
+ (u'\u01a1 o with horn', 'o-o-with-horn'),
+ (u'\u01b0 u with horn', 'u-u-with-horn'),
+ (u'\u01c6 dz with caron', 'dz-dz-with-caron'),
+ (u'\u01c9 lj', 'lj-lj'),
+ (u'\u01cc nj', 'nj-nj'),
+ (u'\u01ce a with caron', 'a-a-with-caron'),
+ (u'\u01d0 i with caron', 'i-i-with-caron'),
+ (u'\u01d2 o with caron', 'o-o-with-caron'),
+ (u'\u01d4 u with caron', 'u-u-with-caron'),
+ (u'\u01e7 g with caron', 'g-g-with-caron'),
+ (u'\u01e9 k with caron', 'k-k-with-caron'),
+ (u'\u01eb o with ogonek', 'o-o-with-ogonek'),
+ (u'\u01ed o with ogonek and macron', 'o-o-with-ogonek-and-macron'),
+ (u'\u01f0 j with caron', 'j-j-with-caron'),
+ (u'\u01f3 dz', 'dz-dz'),
+ (u'\u01f5 g with acute', 'g-g-with-acute'),
+ (u'\u01f9 n with grave', 'n-n-with-grave'),
+ (u'\u0201 a with double grave', 'a-a-with-double-grave'),
+ (u'\u0203 a with inverted breve', 'a-a-with-inverted-breve'),
+ (u'\u0205 e with double grave', 'e-e-with-double-grave'),
+ (u'\u0207 e with inverted breve', 'e-e-with-inverted-breve'),
+ (u'\u0209 i with double grave', 'i-i-with-double-grave'),
+ (u'\u020b i with inverted breve', 'i-i-with-inverted-breve'),
+ (u'\u020d o with double grave', 'o-o-with-double-grave'),
+ (u'\u020f o with inverted breve', 'o-o-with-inverted-breve'),
+ (u'\u0211 r with double grave', 'r-r-with-double-grave'),
+ (u'\u0213 r with inverted breve', 'r-r-with-inverted-breve'),
+ (u'\u0215 u with double grave', 'u-u-with-double-grave'),
+ (u'\u0217 u with inverted breve', 'u-u-with-inverted-breve'),
+ (u'\u0219 s with comma below', 's-s-with-comma-below'),
+ (u'\u021b t with comma below', 't-t-with-comma-below'),
+ (u'\u021f h with caron', 'h-h-with-caron'),
+ (u'\u0227 a with dot above', 'a-a-with-dot-above'),
+ (u'\u0229 e with cedilla', 'e-e-with-cedilla'),
+ (u'\u022f o with dot above', 'o-o-with-dot-above'),
+ (u'\u0233 y with macron', 'y-y-with-macron'),
+ # digraphs From Latin-1 Supplements
+ (u'\u00df: ligature sz', 'sz-ligature-sz'),
+ (u'\u00e6 ae', 'ae-ae'),
+ (u'\u0153 ligature oe', 'oe-ligature-oe'),
+ (u'\u0238 db digraph', 'db-db-digraph'),
+ (u'\u0239 qp digraph', 'qp-qp-digraph'),
+ ]
+
+ def test_make_id(self):
+ failures = []
+ tests = self.ids + self.ids_unicode_all
+ for input, expect in tests:
+ output = nodes.make_id(input)
+ if expect != output:
+ failures.append("'%s' != '%s'" % (expect, output))
+ if failures:
+ self.fail("%d failures in %d\n%s" % (len(failures), len(self.ids), "\n".join(failures)))
+
+ def test_traverse(self):
+ e = nodes.Element()
+ e += nodes.Element()
+ e[0] += nodes.Element()
+ e[0] += nodes.TextElement()
+ e[0][1] += nodes.Text('some text')
+ e += nodes.Element()
+ e += nodes.Element()
+ self.assertEqual(list(e.traverse()),
+ [e, e[0], e[0][0], e[0][1], e[0][1][0], e[1], e[2]])
+ self.assertEqual(list(e.traverse(include_self=False)),
+ [e[0], e[0][0], e[0][1], e[0][1][0], e[1], e[2]])
+ self.assertEqual(list(e.traverse(descend=False)),
+ [e])
+ self.assertEqual(list(e[0].traverse(descend=False, ascend=True)),
+ [e[0], e[1], e[2]])
+ self.assertEqual(list(e[0][0].traverse(descend=False, ascend=True)),
+ [e[0][0], e[0][1], e[1], e[2]])
+ self.assertEqual(list(e[0][0].traverse(descend=False, siblings=True)),
+ [e[0][0], e[0][1]])
+ self.testlist = e[0:2]
+ self.assertEqual(list(e.traverse(condition=self.not_in_testlist)),
+ [e, e[0][0], e[0][1], e[0][1][0], e[2]])
+ # Return siblings despite siblings=False because ascend is true.
+ self.assertEqual(list(e[1].traverse(ascend=True, siblings=False)),
+ [e[1], e[2]])
+ self.assertEqual(list(e[0].traverse()),
+ [e[0], e[0][0], e[0][1], e[0][1][0]])
+ self.testlist = [e[0][0], e[0][1]]
+ self.assertEqual(list(e[0].traverse(condition=self.not_in_testlist)),
+ [e[0], e[0][1][0]])
+ self.testlist.append(e[0][1][0])
+ self.assertEqual(list(e[0].traverse(condition=self.not_in_testlist)),
+ [e[0]])
+ self.assertEqual(list(e.traverse(nodes.TextElement)), [e[0][1]])
+
+ def test_next_node(self):
+ e = nodes.Element()
+ e += nodes.Element()
+ e[0] += nodes.Element()
+ e[0] += nodes.TextElement()
+ e[0][1] += nodes.Text('some text')
+ e += nodes.Element()
+ e += nodes.Element()
+ self.testlist = [e[0], e[0][1], e[1]]
+ compare = [(e, e[0][0]),
+ (e[0], e[0][0]),
+ (e[0][0], e[0][1][0]),
+ (e[0][1], e[0][1][0]),
+ (e[0][1][0], e[2]),
+ (e[1], e[2]),
+ (e[2], None)]
+ for node, next_node in compare:
+ self.assertEqual(node.next_node(self.not_in_testlist, ascend=True),
+ next_node)
+ self.assertEqual(e[0][0].next_node(ascend=True), e[0][1])
+ self.assertEqual(e[2].next_node(), None)
+
+ def not_in_testlist(self, x):
+ return x not in self.testlist
+
+ def test_copy(self):
+ grandchild = nodes.Text('mytext')
+ child = nodes.emphasis('mytext', grandchild, att='child')
+ e = nodes.Element('mytext', child, att='e')
+ # Shallow copy:
+ e_copy = e.copy()
+ self.assertTrue(e is not e_copy)
+ # Internal attributes (like `rawsource`) are also copied.
+ self.assertEqual(e.rawsource, 'mytext')
+ self.assertEqual(e_copy.rawsource, e.rawsource)
+ self.assertEqual(e_copy['att'], 'e')
+ self.assertEqual(e_copy.document, e.document)
+ self.assertEqual(e_copy.source, e.source)
+ self.assertEqual(e_copy.line, e.line)
+ # Children are not copied.
+ self.assertEqual(len(e_copy), 0)
+ # Deep copy:
+ e_deepcopy = e.deepcopy()
+ self.assertEqual(e_deepcopy.rawsource, e.rawsource)
+ self.assertEqual(e_deepcopy['att'], 'e')
+ # Children are copied recursively.
+ self.assertEqual(e_deepcopy[0][0], grandchild)
+ self.assertTrue(e_deepcopy[0][0] is not grandchild)
+ self.assertEqual(e_deepcopy[0]['att'], 'child')
+
+
+class TreeCopyVisitorTests(unittest.TestCase):
+
+ def setUp(self):
+ document = utils.new_document('test data')
+ document += nodes.paragraph('', 'Paragraph 1.')
+ blist = nodes.bullet_list()
+ for i in range(1, 6):
+ item = nodes.list_item()
+ for j in range(1, 4):
+ item += nodes.paragraph('', 'Item %s, paragraph %s.' % (i, j))
+ blist += item
+ document += blist
+ self.document = document
+
+ def compare_trees(self, one, two):
+ self.assertEqual(one.__class__, two.__class__)
+ self.assertNotEqual(id(one), id(two))
+ self.assertEqual(len(one.children), len(two.children))
+ for i in range(len(one.children)):
+ self.compare_trees(one.children[i], two.children[i])
+
+ def test_copy_whole(self):
+ visitor = nodes.TreeCopyVisitor(self.document)
+ self.document.walkabout(visitor)
+ newtree = visitor.get_tree_copy()
+ self.assertEqual(self.document.pformat(), newtree.pformat())
+ self.compare_trees(self.document, newtree)
+
+
+class SetIdTests(unittest.TestCase):
+
+ def setUp(self):
+ self.document = utils.new_document('test')
+ self.elements = [nodes.Element(names=['test']),
+ nodes.section(), # Name empty
+ nodes.section(names=['Test']), # duplicate id
+ nodes.footnote(names=['2019-10-30']), # id empty
+ ]
+
+ def test_set_id_default(self):
+ # Default prefixes.
+ for element in self.elements:
+ self.document.set_id(element)
+ ids = [element['ids'] for element in self.elements]
+ self.assertEqual(ids, [['test'], ['id1'], ['id2'], ['id3']])
+
+ def test_set_id_custom(self):
+ # Custom prefixes.
+
+ # Change settings.
+ self.document.settings.id_prefix = 'P-'
+ self.document.settings.auto_id_prefix = 'auto'
+
+ for element in self.elements:
+ self.document.set_id(element)
+ ids = [element['ids'] for element in self.elements]
+ self.assertEqual(ids, [['P-test'],
+ ['P-auto1'],
+ ['P-auto2'],
+ ['P-auto3']])
+
+ def test_set_id_descriptive_auto_id(self):
+ # Use name or tag-name for auto-id.
+
+ # Change setting.
+ self.document.settings.auto_id_prefix = '%'
+
+ for element in self.elements:
+ self.document.set_id(element)
+ ids = [element['ids'] for element in self.elements]
+ self.assertEqual(ids, [['test'],
+ ['section-1'],
+ ['test-1'],
+ ['footnote-1']])
+
+ def test_set_id_custom_descriptive_auto_id(self):
+ # Custom prefixes and name or tag-name for auto-id.
+
+ # Change settings.
+ self.document.settings.id_prefix = 'P:'
+ self.document.settings.auto_id_prefix = 'a-%'
+
+ for element in self.elements:
+ self.document.set_id(element)
+ ids = [element['ids'] for element in self.elements]
+ self.assertEqual(ids, [['P:test'],
+ ['P:a-section-1'],
+ ['P:test-1'],
+ ['P:a-footnote-1']])
+
+
+class MiscFunctionTests(unittest.TestCase):
+
+ names = [('a', 'a'), ('A', 'a'), ('A a A', 'a a a'),
+ ('A a A a', 'a a a a'),
+ (' AaA\n\r\naAa\tAaA\t\t', 'aaa aaa aaa')]
+
+ def test_normalize_name(self):
+ for input, output in self.names:
+ normed = nodes.fully_normalize_name(input)
+ self.assertEqual(normed, output)
+
+
+if __name__ == '__main__':
+ unittest.main()
--- /dev/null
+import os
+import os.path
+import sys
+
+sys.path.insert(0, os.path.abspath(os.path.dirname(__file__)))
+prev = ''
+while sys.path[0] != prev:
+ try:
+ import DocutilsTestSupport
+ break
+ except ImportError:
+ prev = sys.path[0]
+ sys.path[0] = os.path.dirname(prev)
+sys.path.pop(0)
--- /dev/null
+#! /usr/bin/env python
+
+# $Id: test_get_parser_class.py 8356 2019-08-26 16:44:19Z milde $
+# Author: grubert abadger1999
+# Maintainer: docutils-develop@lists.sourceforge.net
+# Copyright: This module has been placed in the public domain.
+
+"""
+test get_parser_class
+"""
+from __future__ import absolute_import
+
+from . import DocutilsTestSupport
+from docutils.parsers import get_parser_class
+
+class GetParserClassTestCase(DocutilsTestSupport.StandardTestCase):
+
+ def test_registered_parser(self):
+ rdr = get_parser_class('rst')
+ # raises ImportError on failure
+
+ def test_bogus_parser(self):
+ self.assertRaises(ImportError,
+ get_parser_class, 'nope')
+
+ def test_local_parser(self):
+ # requires local-parser.py in test directory (testroot)
+ wr = get_parser_class('local-parser')
+
+if __name__ == '__main__':
+ import unittest
+ unittest.main()
+
--- /dev/null
+#! /usr/bin/env python
+
+# $Id: test_parser.py 8367 2019-08-27 12:09:56Z milde $
+# Author: Stefan Rank <strank(AT)strank(DOT)info>
+# Copyright: This module has been placed in the public domain.
+
+"""
+Tests for basic functionality of parser classes.
+"""
+
+import sys
+import unittest
+import DocutilsTestSupport # must be imported before docutils
+import docutils
+from docutils import parsers, utils, frontend
+
+
+class RstParserTests(unittest.TestCase):
+
+ def test_inputrestrictions(self):
+ parser_class = parsers.get_parser_class('rst')
+ parser = parser_class()
+ document = utils.new_document('test data', frontend.OptionParser(
+ components=(parser, )).get_default_values())
+
+ if sys.version_info < (3, 0):
+ # supplying string input is supported, but only if ascii-decodable
+ self.assertRaises(UnicodeDecodeError,
+ parser.parse, b'hol%s' % chr(224), document)
+ else:
+ # input must be unicode at all times
+ self.assertRaises(TypeError, parser.parse, b'hol', document)
+
+
+if __name__ == '__main__':
+ unittest.main()
--- /dev/null
+import os
+import os.path
+import sys
+
+sys.path.insert(0, os.path.abspath(os.path.dirname(__file__)))
+prev = ''
+while sys.path[0] != prev:
+ try:
+ import DocutilsTestSupport
+ break
+ except ImportError:
+ prev = sys.path[0]
+ sys.path[0] = os.path.dirname(prev)
+sys.path.pop(0)
--- /dev/null
+In ../includes/include9.txt.
+
+.. include:: ../test_directives/include2.txt
--- /dev/null
+#! /usr/bin/env python
+# .. coding: utf-8
+
+# $Id: test_SimpleTableParser.py 8356 2019-08-26 16:44:19Z milde $
+# Author: David Goodger <goodger@python.org>
+# Copyright: This module has been placed in the public domain.
+
+"""
+Tests for states.py.
+"""
+from __future__ import absolute_import
+
+from . import DocutilsTestSupport
+
+def suite():
+ s = DocutilsTestSupport.SimpleTableParserTestSuite()
+ s.generateTests(totest)
+ return s
+
+totest = {}
+
+totest['simple_tables'] = [
+["""\
+============ ============
+A table with two columns.
+============ ============
+""",
+([12, 12],
+ [],
+ [[[0, 0, 1, ['A table with']],
+ [0, 0, 1, ['two columns.']]]])],
+[u"""\
+============ ===============
+A tāble w̅ith comb̲ining chars
+============ ===============
+""",
+([12, 15],
+ [],
+ [[[0, 0, 1, [u'A ta\u0304ble w\u0305ith']],
+ [0, 0, 1, [u'comb\u0332ining chars']]]])],
+["""\
+============ ============
+A table with two columns
+and two rows.
+============ ============
+""",
+([12, 12],
+ [],
+ [[[0, 0, 1, ['A table with']],
+ [0, 0, 1, ['two columns']]],
+ [[0, 0, 2, ['and']],
+ [0, 0, 2, ['two rows.']]]])],
+["""\
+======================================
+The last row might stick into the margin
+second row.
+======================================
+""",
+([40],
+ [],
+ [[[0, 0, 1, ['The last row might stick into the margin']]],
+ [[0, 0, 2, ['second row.']]]])],
+["""\
+========== ===========
+A table with four rows,
+-----------------------
+and two columns.
+First and last rows
+contain column spans.
+=======================
+""",
+([10, 11],
+ [],
+ [[[0, 1, 1, ['A table with four rows,']]],
+ [[0, 0, 3, ['and two']],
+ [0, 0, 3, ['columns.']]],
+ [[0, 0, 4, ['First and']],
+ [0, 0, 4, ['last rows']]],
+ [[0, 1, 5, ['contain column spans.']]]])],
+["""\
+======= ===== ======
+A bad table cell 2
+cell 3 cell 4
+============ ======
+""",
+'TableMarkupError: Text in column margin in table line 2.'],
+["""\
+====== ===== ======
+row one
+Another bad table
+====== ===== ======
+""",
+'TableMarkupError: Text in column margin in table line 3.'],
+["""\
+=========== ================
+A table with two header rows,
+-----------------------------
+the first with a span.
+=========== ================
+Two body rows,
+the second with a span.
+=============================
+""",
+([11, 16],
+ [[[0, 1, 1, ['A table with two header rows,']]],
+ [[0, 0, 3, ['the first']],
+ [0, 0, 3, ['with a span.']]]],
+ [[[0, 0, 5, ['Two body']],
+ [0, 0, 5, ['rows,']]],
+ [[0, 1, 6, ['the second with a span.']]]])],
+["""\
+============ =============
+A table with two head/body
+============ =============
+row separators.
+============ =============
+That's bad.
+============ =============
+""",
+'TableMarkupError: Multiple head/body row separators '
+'(table lines 3 and 5); only one allowed.'],
+["""\
+============ ============
+============ ============
+""",
+([12, 12],
+ [],
+ [[[0, 0, 1, []],
+ [0, 0, 1, []]]])],
+# ["""\
+# ============== ==========
+# Table with row separators
+# ============== ==========
+# and blank
+# -------------- ----------
+# entries
+# -------------- ----------
+# in first
+# -------------- ----------
+# columns.
+# ============== ==========
+# """,
+# '']
+]
+
+
+if __name__ == '__main__':
+ import unittest
+ unittest.main(defaultTest='suite')
--- /dev/null
+#! /usr/bin/env python
+# coding: utf-8
+
+# $Id: test_TableParser.py 8356 2019-08-26 16:44:19Z milde $
+# Author: David Goodger <goodger@python.org>
+# Copyright: This module has been placed in the public domain.
+
+"""
+Tests for states.py.
+"""
+from __future__ import absolute_import
+
+from . import DocutilsTestSupport
+
+def suite():
+ s = DocutilsTestSupport.GridTableParserTestSuite()
+ s.generateTests(totest)
+ return s
+
+totest = {}
+
+totest['grid_tables'] = [
+["""\
++-------------------------------------+
+| A table with one cell and one line. |
++-------------------------------------+
+""",
+[(0, 0, 2, 38, ['A table with one cell and one line.'])],
+([37],
+ [],
+ [[(0, 0, 1, ['A table with one cell and one line.'])]])],
+["""\
++--------------+--------------+
+| A table with | two columns. |
++--------------+--------------+
+""",
+[(0, 0, 2, 15, ['A table with']),
+ (0, 15, 2, 30, ['two columns.'])],
+([14, 14],
+ [],
+ [[(0, 0, 1, ['A table with']),
+ (0, 0, 1, ['two columns.'])]])],
+# Combining chars in grid tables still fail
+# [u"""\
+# +--------------+------------------+
+# | A tāble w̅ith | comb̲ining chars. |
+# +--------------+------------------+
+# """,
+# [(0, 0, 2, 15, [u'A table with']),
+# (0, 15, 2, 30, [u'combining chars.'])],
+# ([14, 14],
+# [],
+# [[(0, 0, 1, [u'A table with']),
+# (0, 0, 1, [u'combining chars.'])]])],
+["""\
++--------------+-------------+
+| A table with | two columns |
++--------------+-------------+
+| and | two rows. |
++--------------+-------------+
+""",
+[(0, 0, 2, 15, ['A table with']),
+ (0, 15, 2, 29, ['two columns']),
+ (2, 0, 4, 15, ['and']),
+ (2, 15, 4, 29, ['two rows.'])],
+([14, 13],
+ [],
+ [[(0, 0, 1, ['A table with']),
+ (0, 0, 1, ['two columns'])],
+ [(0, 0, 3, ['and']),
+ (0, 0, 3, ['two rows.'])]])],
+["""\
++--------------------------+
+| A table with three rows, |
++------------+-------------+
+| and two | columns. |
++------------+-------------+
+| First and last rows |
+| contain column spans. |
++--------------------------+
+""",
+[(0, 0, 2, 27, ['A table with three rows,']),
+ (2, 0, 4, 13, ['and two']),
+ (2, 13, 4, 27, ['columns.']),
+ (4, 0, 7, 27, ['First and last rows', 'contain column spans.'])],
+([12, 13],
+ [],
+ [[(0, 1, 1, ['A table with three rows,']),
+ None],
+ [(0, 0, 3, ['and two']),
+ (0, 0, 3, ['columns.'])],
+ [(0, 1, 5, ['First and last rows', 'contain column spans.']),
+ None]])],
+["""\
++------------+-------------+---------------+
+| A table | two rows in | and row spans |
+| with three +-------------+ to left and |
+| columns, | the middle, | right. |
++------------+-------------+---------------+
+""",
+[(0, 0, 4, 13, ['A table', 'with three', 'columns,']),
+ (0, 13, 2, 27, ['two rows in']),
+ (0, 27, 4, 43, ['and row spans', 'to left and', 'right.']),
+ (2, 13, 4, 27, ['the middle,'])],
+([12, 13, 15],
+ [],
+ [[(1, 0, 1, ['A table', 'with three', 'columns,']),
+ (0, 0, 1, ['two rows in']),
+ (1, 0, 1, ['and row spans', 'to left and', 'right.'])],
+ [None,
+ (0, 0, 3, ['the middle,']),
+ None]])],
+["""\
++------------+-------------+---------------+
+| A table | | two rows in | and funny |
+| with 3 +--+-------------+-+ stuff. |
+| columns, | the middle, | | |
++------------+-------------+---------------+
+""",
+[(0, 0, 4, 13, ['A table |', 'with 3 +--', 'columns,']),
+ (0, 13, 2, 27, ['two rows in']),
+ (0, 27, 4, 43, [' and funny', '-+ stuff.', ' |']),
+ (2, 13, 4, 27, ['the middle,'])],
+([12, 13, 15],
+ [],
+ [[(1, 0, 1, ['A table |', 'with 3 +--', 'columns,']),
+ (0, 0, 1, ['two rows in']),
+ (1, 0, 1, [' and funny', '-+ stuff.', ' |'])],
+ [None,
+ (0, 0, 3, ['the middle,']),
+ None]])],
+["""\
++-----------+-------------------------+
+| W/NW cell | N/NE cell |
+| +-------------+-----------+
+| | Middle cell | E/SE cell |
++-----------+-------------+ |
+| S/SE cell | |
++-------------------------+-----------+
+""",
+[(0, 0, 4, 12, ['W/NW cell', '', '']),
+ (0, 12, 2, 38, ['N/NE cell']),
+ (2, 12, 4, 26, ['Middle cell']),
+ (2, 26, 6, 38, ['E/SE cell', '', '']),
+ (4, 0, 6, 26, ['S/SE cell'])],
+([11, 13, 11],
+ [],
+ [[(1, 0, 1, ['W/NW cell', '', '']),
+ (0, 1, 1, ['N/NE cell']),
+ None],
+ [None,
+ (0, 0, 3, ['Middle cell']),
+ (1, 0, 3, ['E/SE cell', '', ''])],
+ [(0, 1, 5, ['S/SE cell']),
+ None,
+ None]])],
+["""\
++--------------+-------------+
+| A bad table. | |
++--------------+ |
+| Cells must be rectangles. |
++----------------------------+
+""",
+'TableMarkupError: Malformed table; parse incomplete.',
+'TableMarkupError: Malformed table; parse incomplete.'],
+["""\
++-------------------------------+
+| A table with two header rows, |
++------------+------------------+
+| the first | with a span. |
++============+==================+
+| Two body | rows, |
++------------+------------------+
+| the second with a span. |
++-------------------------------+
+""",
+[(0, 0, 2, 32, ['A table with two header rows,']),
+ (2, 0, 4, 13, ['the first']),
+ (2, 13, 4, 32, ['with a span.']),
+ (4, 0, 6, 13, ['Two body']),
+ (4, 13, 6, 32, ['rows,']),
+ (6, 0, 8, 32, ['the second with a span.'])],
+([12, 18],
+ [[(0, 1, 1, ['A table with two header rows,']),
+ None],
+ [(0, 0, 3, ['the first']),
+ (0, 0, 3, ['with a span.'])]],
+ [[(0, 0, 5, ['Two body']),
+ (0, 0, 5, ['rows,'])],
+ [(0, 1, 7, ['the second with a span.']),
+ None]])],
+["""\
++-------------------------------+
+| A table with two head/body |
++=============+=================+
+| row | separators. |
++=============+=================+
+| That's bad. | |
++-------------+-----------------+
+""",
+'TableMarkupError: Multiple head/body row separators '
+'(table lines 3 and 5); only one allowed.',
+'TableMarkupError: Multiple head/body row separators '
+'(table lines 3 and 5); only one allowed.'],
+["""\
++-------------------------------------+
+| |
++-------------------------------------+
+""",
+[(0, 0, 2, 38, [''])],
+([37],
+ [],
+ [[(0, 0, 1, [''])]])],
+]
+
+
+if __name__ == '__main__':
+ import unittest
+ unittest.main(defaultTest='suite')
--- /dev/null
+#! /usr/bin/env python
+
+# $Id: test_block_quotes.py 8356 2019-08-26 16:44:19Z milde $
+# Author: David Goodger <goodger@python.org>
+# Copyright: This module has been placed in the public domain.
+
+"""
+Tests for states.py.
+"""
+from __future__ import absolute_import
+
+from . import DocutilsTestSupport
+
+def suite():
+ s = DocutilsTestSupport.ParserTestSuite()
+ s.generateTests(totest)
+ return s
+
+totest = {}
+
+totest['block_quotes'] = [
+["""\
+Line 1.
+Line 2.
+
+ Indented.
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ Line 1.
+ Line 2.
+ <block_quote>
+ <paragraph>
+ Indented.
+"""],
+["""\
+Line 1.
+Line 2.
+
+ Indented 1.
+
+ Indented 2.
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ Line 1.
+ Line 2.
+ <block_quote>
+ <paragraph>
+ Indented 1.
+ <block_quote>
+ <paragraph>
+ Indented 2.
+"""],
+["""\
+Line 1.
+Line 2.
+ Unexpectedly indented.
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ Line 1.
+ Line 2.
+ <system_message level="3" line="3" source="test data" type="ERROR">
+ <paragraph>
+ Unexpected indentation.
+ <block_quote>
+ <paragraph>
+ Unexpectedly indented.
+"""],
+["""\
+Line 1.
+Line 2.
+
+ Indented.
+no blank line
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ Line 1.
+ Line 2.
+ <block_quote>
+ <paragraph>
+ Indented.
+ <system_message level="2" line="5" source="test data" type="WARNING">
+ <paragraph>
+ Block quote ends without a blank line; unexpected unindent.
+ <paragraph>
+ no blank line
+"""],
+["""\
+Here is a paragraph.
+
+ Indent 8 spaces.
+
+ Indent 4 spaces.
+
+Is this correct? Should it generate a warning?
+Yes, it is correct, no warning necessary.
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ Here is a paragraph.
+ <block_quote>
+ <block_quote>
+ <paragraph>
+ Indent 8 spaces.
+ <paragraph>
+ Indent 4 spaces.
+ <paragraph>
+ Is this correct? Should it generate a warning?
+ Yes, it is correct, no warning necessary.
+"""],
+["""\
+Paragraph.
+
+ Block quote.
+
+ -- Attribution
+
+Paragraph.
+
+ Block quote.
+
+ --Attribution
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ Paragraph.
+ <block_quote>
+ <paragraph>
+ Block quote.
+ <attribution>
+ Attribution
+ <paragraph>
+ Paragraph.
+ <block_quote>
+ <paragraph>
+ Block quote.
+ <attribution>
+ Attribution
+"""],
+[u"""\
+Alternative: true em-dash.
+
+ Block quote.
+
+ \u2014 Attribution
+
+Alternative: three hyphens.
+
+ Block quote.
+
+ --- Attribution
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ Alternative: true em-dash.
+ <block_quote>
+ <paragraph>
+ Block quote.
+ <attribution>
+ Attribution
+ <paragraph>
+ Alternative: three hyphens.
+ <block_quote>
+ <paragraph>
+ Block quote.
+ <attribution>
+ Attribution
+"""],
+["""\
+Paragraph.
+
+ Block quote.
+
+ -- Attribution line one
+ and line two
+
+Paragraph.
+
+ Block quote.
+
+ -- Attribution line one
+ and line two
+
+Paragraph.
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ Paragraph.
+ <block_quote>
+ <paragraph>
+ Block quote.
+ <attribution>
+ Attribution line one
+ and line two
+ <paragraph>
+ Paragraph.
+ <block_quote>
+ <paragraph>
+ Block quote.
+ <attribution>
+ Attribution line one
+ and line two
+ <paragraph>
+ Paragraph.
+"""],
+["""\
+Paragraph.
+
+ Block quote 1.
+
+ -- Attribution 1
+
+ Block quote 2.
+
+ --Attribution 2
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ Paragraph.
+ <block_quote>
+ <paragraph>
+ Block quote 1.
+ <attribution>
+ Attribution 1
+ <block_quote>
+ <paragraph>
+ Block quote 2.
+ <attribution>
+ Attribution 2
+"""],
+["""\
+Paragraph.
+
+ Block quote 1.
+
+ -- Attribution 1
+
+ Block quote 2.
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ Paragraph.
+ <block_quote>
+ <paragraph>
+ Block quote 1.
+ <attribution>
+ Attribution 1
+ <block_quote>
+ <paragraph>
+ Block quote 2.
+"""],
+["""\
+Unindented paragraph.
+
+ Block quote 1.
+
+ -- Attribution 1
+
+ Block quote 2.
+
+..
+
+ Block quote 3.
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ Unindented paragraph.
+ <block_quote>
+ <paragraph>
+ Block quote 1.
+ <attribution>
+ Attribution 1
+ <block_quote>
+ <paragraph>
+ Block quote 2.
+ <comment xml:space="preserve">
+ <block_quote>
+ <paragraph>
+ Block quote 3.
+"""],
+["""\
+Paragraph.
+
+ -- Not an attribution
+
+Paragraph.
+
+ Block quote.
+
+ \\-- Not an attribution
+
+Paragraph.
+
+ Block quote.
+
+ -- Not an attribution line one
+ and line two
+ and line three
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ Paragraph.
+ <block_quote>
+ <paragraph>
+ -- Not an attribution
+ <paragraph>
+ Paragraph.
+ <block_quote>
+ <paragraph>
+ Block quote.
+ <paragraph>
+ -- Not an attribution
+ <paragraph>
+ Paragraph.
+ <block_quote>
+ <paragraph>
+ Block quote.
+ <definition_list>
+ <definition_list_item>
+ <term>
+ -- Not an attribution line one
+ <definition>
+ <definition_list>
+ <definition_list_item>
+ <term>
+ and line two
+ <definition>
+ <paragraph>
+ and line three
+"""],
+["""\
+Paragraph.
+
+ -- Not a valid attribution
+
+ Block quote 1.
+
+ --Attribution 1
+
+ --Invalid attribution
+
+ Block quote 2.
+
+ --Attribution 2
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ Paragraph.
+ <block_quote>
+ <paragraph>
+ -- Not a valid attribution
+ <paragraph>
+ Block quote 1.
+ <attribution>
+ Attribution 1
+ <block_quote>
+ <paragraph>
+ --Invalid attribution
+ <paragraph>
+ Block quote 2.
+ <attribution>
+ Attribution 2
+"""],
+]
+
+
+if __name__ == '__main__':
+ import unittest
+ unittest.main(defaultTest='suite')
--- /dev/null
+#! /usr/bin/env python
+
+# $Id: test_bullet_lists.py 8356 2019-08-26 16:44:19Z milde $
+# Author: David Goodger <goodger@python.org>
+# Copyright: This module has been placed in the public domain.
+
+"""
+Tests for states.py.
+"""
+from __future__ import absolute_import
+
+from . import DocutilsTestSupport
+
+def suite():
+ s = DocutilsTestSupport.ParserTestSuite()
+ s.generateTests(totest)
+ return s
+
+totest = {}
+
+totest['bullet_lists'] = [
+["""\
+- item
+""",
+"""\
+<document source="test data">
+ <bullet_list bullet="-">
+ <list_item>
+ <paragraph>
+ item
+"""],
+["""\
+* item 1
+
+* item 2
+""",
+"""\
+<document source="test data">
+ <bullet_list bullet="*">
+ <list_item>
+ <paragraph>
+ item 1
+ <list_item>
+ <paragraph>
+ item 2
+"""],
+["""\
+No blank line between:
+
++ item 1
++ item 2
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ No blank line between:
+ <bullet_list bullet="+">
+ <list_item>
+ <paragraph>
+ item 1
+ <list_item>
+ <paragraph>
+ item 2
+"""],
+["""\
+- item 1, para 1.
+
+ item 1, para 2.
+
+- item 2
+""",
+"""\
+<document source="test data">
+ <bullet_list bullet="-">
+ <list_item>
+ <paragraph>
+ item 1, para 1.
+ <paragraph>
+ item 1, para 2.
+ <list_item>
+ <paragraph>
+ item 2
+"""],
+["""\
+- item 1, line 1
+ item 1, line 2
+- item 2
+""",
+"""\
+<document source="test data">
+ <bullet_list bullet="-">
+ <list_item>
+ <paragraph>
+ item 1, line 1
+ item 1, line 2
+ <list_item>
+ <paragraph>
+ item 2
+"""],
+["""\
+Different bullets:
+
+- item 1
+
++ item 2
+
+* item 3
+- item 4
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ Different bullets:
+ <bullet_list bullet="-">
+ <list_item>
+ <paragraph>
+ item 1
+ <bullet_list bullet="+">
+ <list_item>
+ <paragraph>
+ item 2
+ <bullet_list bullet="*">
+ <list_item>
+ <paragraph>
+ item 3
+ <system_message level="2" line="8" source="test data" type="WARNING">
+ <paragraph>
+ Bullet list ends without a blank line; unexpected unindent.
+ <bullet_list bullet="-">
+ <list_item>
+ <paragraph>
+ item 4
+"""],
+["""\
+- item
+no blank line
+""",
+"""\
+<document source="test data">
+ <bullet_list bullet="-">
+ <list_item>
+ <paragraph>
+ item
+ <system_message level="2" line="2" source="test data" type="WARNING">
+ <paragraph>
+ Bullet list ends without a blank line; unexpected unindent.
+ <paragraph>
+ no blank line
+"""],
+["""\
+-
+
+empty item above
+""",
+"""\
+<document source="test data">
+ <bullet_list bullet="-">
+ <list_item>
+ <paragraph>
+ empty item above
+"""],
+["""\
+-
+empty item above, no blank line
+""",
+"""\
+<document source="test data">
+ <bullet_list bullet="-">
+ <list_item>
+ <system_message level="2" line="2" source="test data" type="WARNING">
+ <paragraph>
+ Bullet list ends without a blank line; unexpected unindent.
+ <paragraph>
+ empty item above, no blank line
+"""],
+[u"""\
+Unicode bullets:
+
+\u2022 BULLET
+
+\u2023 TRIANGULAR BULLET
+
+\u2043 HYPHEN BULLET
+""",
+u"""\
+<document source="test data">
+ <paragraph>
+ Unicode bullets:
+ <bullet_list bullet="\u2022">
+ <list_item>
+ <paragraph>
+ BULLET
+ <bullet_list bullet="\u2023">
+ <list_item>
+ <paragraph>
+ TRIANGULAR BULLET
+ <bullet_list bullet="\u2043">
+ <list_item>
+ <paragraph>
+ HYPHEN BULLET
+"""],
+]
+
+if __name__ == '__main__':
+ import unittest
+ unittest.main(defaultTest='suite')
--- /dev/null
+#! /usr/bin/env python
+# -*- coding: utf-8 -*-
+
+# $Id: test_character_level_inline_markup.py 8356 2019-08-26 16:44:19Z milde $
+# Author: David Goodger <goodger@python.org>
+# Copyright: This module has been placed in the public domain.
+
+"""
+Tests for inline markup in docutils/parsers/rst/states.py
+with the "character-level-inline-markup" setting.
+
+Experimental.
+"""
+from __future__ import absolute_import
+
+from . import DocutilsTestSupport
+
+def suite():
+ s = DocutilsTestSupport.ParserTestSuite(suite_settings={'character_level_inline_markup': True})
+ s.generateTests(totest)
+ return s
+
+totest = {}
+
+totest['emphasis'] = [
+[r"""some punctuation is allowed around inline markup, e.g.
+/*emphasis*/, -*emphasis*-, and :*emphasis*: (delimiters),
+(*emphasis*), [*emphasis*], <*emphasis*>, {*emphasis*} (open/close pairs)
+*emphasis*., *emphasis*,, *emphasis*!, and *emphasis*\ (closing delimiters),
+
+With simple-inline-markup also
+)*emphasis*(, ]*emphasis*[, >*emphasis*>, }*emphasis*{ (close/open pairs),
+x*2* or 2*x* (alphanumeric char before),
+
+but not
+(*), [*], '*' or '"*"' ("quoted" start-string),
+\*args or * (escaped; whitespace behind start-string),
+or *the\* *stars\* *inside* (escaped; whitespace before end-string).
+
+However, '*args' triggers a warning.
+
+Also *this**.
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ some punctuation is allowed around inline markup, e.g.
+ /
+ <emphasis>
+ emphasis
+ /, -
+ <emphasis>
+ emphasis
+ -, and :
+ <emphasis>
+ emphasis
+ : (delimiters),
+ (
+ <emphasis>
+ emphasis
+ ), [
+ <emphasis>
+ emphasis
+ ], <
+ <emphasis>
+ emphasis
+ >, {
+ <emphasis>
+ emphasis
+ } (open/close pairs)
+ <emphasis>
+ emphasis
+ .,
+ <emphasis>
+ emphasis
+ ,,
+ <emphasis>
+ emphasis
+ !, and
+ <emphasis>
+ emphasis
+ (closing delimiters),
+ <paragraph>
+ With simple-inline-markup also
+ )
+ <emphasis>
+ emphasis
+ (, ]
+ <emphasis>
+ emphasis
+ [, >
+ <emphasis>
+ emphasis
+ >, }
+ <emphasis>
+ emphasis
+ { (close/open pairs),
+ x
+ <emphasis>
+ 2
+ or 2
+ <emphasis>
+ x
+ (alphanumeric char before),
+ <paragraph>
+ but not
+ (*), [*], '*' or '"*"' ("quoted" start-string),
+ *args or * (escaped; whitespace behind start-string),
+ or
+ <emphasis>
+ the* *stars* *inside
+ (escaped; whitespace before end-string).
+ <paragraph>
+ However, '
+ <problematic ids="id2" refid="id1">
+ *
+ args' triggers a warning.
+ <system_message backrefs="id2" ids="id1" level="2" line="15" source="test data" type="WARNING">
+ <paragraph>
+ Inline emphasis start-string without end-string.
+ <paragraph>
+ Also
+ <emphasis>
+ this
+ <problematic ids="id4" refid="id3">
+ *
+ .
+ <system_message backrefs="id4" ids="id3" level="2" line="17" source="test data" type="WARNING">
+ <paragraph>
+ Inline emphasis start-string without end-string.
+"""],
+[r"""
+Emphasized asterisk: *\**
+
+Emphasized double asterisk: *\*\** (requires two escape chars).
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ Emphasized asterisk: \n\
+ <emphasis>
+ *
+ <paragraph>
+ Emphasized double asterisk: \n\
+ <emphasis>
+ **
+ (requires two escape chars).
+"""],
+]
+
+totest['strong'] = [
+[r"""
+(**strong**) but not (**) or '(** '
+
+However, '**kwargs' and x**2 are recognized as strong markup
+and \**kwargs or ** as emphasized.
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ (
+ <strong>
+ strong
+ ) but not (**) or '(** '
+ <paragraph>
+ However, '
+ <strong>
+ kwargs' and x
+ 2 are recognized as strong markup
+ and *
+ <emphasis>
+ kwargs or *
+ as emphasized.
+"""],
+["""\
+Strong asterisk: **\\***
+and
+strong double asterisk: **\\*\\***
+require escaping with simple-inline-markup.
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ Strong asterisk: \n\
+ <strong>
+ *
+
+ and
+ strong double asterisk:
+ <strong>
+ **
+
+ require escaping with simple-inline-markup.
+"""],
+]
+
+totest['literal'] = [
+["""\
+With simple-inline-markup, this is ```interpreted text``` in backquotes!
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ With simple-inline-markup, this is
+ <literal>
+ `interpreted text
+ ` in backquotes!
+"""],
+["""\
+``literal without closing backquotes
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ <problematic ids="id2" refid="id1">
+ ``
+ literal without closing backquotes
+ <system_message backrefs="id2" ids="id1" level="2" line="1" source="test data" type="WARNING">
+ <paragraph>
+ Inline literal start-string without end-string.
+"""],
+[r"""
+Python ``list``s use square bracket syntax.
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ Python \n\
+ <literal>
+ list
+ s use square bracket syntax.
+"""],
+]
+
+totest['references'] = [
+["""\
+ref_, r_, r_e-f_, -ref_, and anonymousref__,
+beware of _ref_ or __attr__ or object.__attr__
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ <reference name="ref" refname="ref">
+ ref
+ , \n\
+ <reference name="r" refname="r">
+ r
+ , \n\
+ <reference name="r_e-f" refname="r_e-f">
+ r_e-f
+ , -
+ <reference name="ref" refname="ref">
+ ref
+ , and \n\
+ <reference anonymous="1" name="anonymousref">
+ anonymousref
+ ,
+ beware of _
+ <reference name="ref" refname="ref">
+ ref
+ or __
+ <reference anonymous="1" name="attr">
+ attr
+ or object.__
+ <reference anonymous="1" name="attr">
+ attr
+"""],
+]
+
+totest['embedded_URIs'] = [
+[r"""
+Escape chars in URIs:
+
+`<reference\:1>`_
+
+`<anonymous\\call>`__
+
+`<anonymous\_call>`__
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ Escape chars in URIs:
+ <paragraph>
+ <reference name="reference:1" refuri="reference:1">
+ reference:1
+ <target ids="reference-1" names="reference:1" refuri="reference:1">
+ <paragraph>
+ <reference name="anonymous\\call" refuri="anonymous\\call">
+ anonymous\\call
+ <paragraph>
+ <reference name="anonymous_call" refuri="anonymous_call">
+ anonymous_call
+"""],
+]
+
+totest['inline_targets'] = [
+["""\
+This isn't a _target; targets require backquotes.
+
+With simple-inline-markup, _`this`_ is a a target followed by an
+underscore.
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ This isn't a _target; targets require backquotes.
+ <paragraph>
+ With simple-inline-markup,
+ <target ids="this" names="this">
+ this
+ _ is a a target followed by an
+ underscore.
+"""],
+]
+
+totest['footnote_reference'] = [
+["""\
+Adjacent footnote refs are possible with simple-inline-markup:
+[*]_[#label]_ [#]_[2]_ [1]_[*]_
+
+.. [#] test1
+.. [*] test2
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ Adjacent footnote refs are possible with simple-inline-markup:
+ <footnote_reference auto="*" ids="id1">
+ <footnote_reference auto="1" ids="id2" refname="label">
+
+ <footnote_reference auto="1" ids="id3">
+ <footnote_reference ids="id4" refname="2">
+ 2
+
+ <footnote_reference ids="id5" refname="1">
+ 1
+ <footnote_reference auto="*" ids="id6">
+ <footnote auto="1" ids="id7">
+ <paragraph>
+ test1
+ <footnote auto="*" ids="id8">
+ <paragraph>
+ test2
+"""],
+]
+
+totest['citation_reference'] = [
+["""\
+Adjacent citation refs are possible with simple-inline-markup:
+[citation]_[CIT1]_
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ Adjacent citation refs are possible with simple-inline-markup:
+ <citation_reference ids="id1" refname="citation">
+ citation
+ <citation_reference ids="id2" refname="cit1">
+ CIT1
+"""],
+]
+
+totest['substitution_references'] = [
+["""\
+|sub|ref
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ <substitution_reference refname="sub">
+ sub
+ ref
+"""],
+]
+
+totest['standalone_hyperlink'] = [
+[r"""
+Valid URLs with escaped markup characters:
+
+http://example.com/\*content\*/whatever
+
+Invalid with the simple-inline-markup setting:
+
+http://example.com/\*content*/whatever
+http://example.com/rST_for_all.html
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ Valid URLs with escaped markup characters:
+ <paragraph>
+ <reference refuri="http://example.com/*content*/whatever">
+ http://example.com/*content*/whatever
+ <paragraph>
+ Invalid with the simple-inline-markup setting:
+ <paragraph>
+ <reference refuri="http://example.com/*content">
+ http://example.com/*content
+ <problematic ids="id2" refid="id1">
+ *
+ /whatever
+ <reference refuri="http://example.com/">
+ http://example.com/
+ <reference name="rST_for" refname="rst_for">
+ rST_for
+ all.html
+ <system_message backrefs="id2" ids="id1" level="2" line="8" source="test data" type="WARNING">
+ <paragraph>
+ Inline emphasis start-string without end-string.
+"""],
+]
+
+totest['markup recognition rules'] = [
+["""\
+__This__ is an anonymous reference with simple-inline-markup.
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ __
+ <reference anonymous="1" name="This">
+ This
+ is an anonymous reference with simple-inline-markup.
+"""],
+[r"""
+Character-level m*a***r**``k``\ `u`:title:\p
+with backslash-escaped whitespace, including new\
+lines.
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ Character-level m
+ <emphasis>
+ a
+ <strong>
+ r
+ <literal>
+ k
+ <title_reference>
+ u
+ p
+ with backslash-escaped whitespace, including newlines.
+"""],
+[u"""\
+text-*separated*\u2010*by*\u2011*various*\u2012*dashes*\u2013*and*\u2014*hyphens*.
+\u00bf*punctuation*? \u00a1*examples*!\xa0*no-break-space*\xa0.
+""",
+u"""\
+<document source="test data">
+ <paragraph>
+ text-
+ <emphasis>
+ separated
+ \u2010
+ <emphasis>
+ by
+ \u2011
+ <emphasis>
+ various
+ \u2012
+ <emphasis>
+ dashes
+ \u2013
+ <emphasis>
+ and
+ \u2014
+ <emphasis>
+ hyphens
+ .
+ \xbf
+ <emphasis>
+ punctuation
+ ? \xa1
+ <emphasis>
+ examples
+ !\xa0
+ <emphasis>
+ no-break-space
+ \xa0.
+"""],
+# Whitespace characters:
+[u"""\
+inline markup surrounded by various whitespace characters:
+*newline*
+or *space* or one of
+\xa0*NO-BREAK SPACE*\xa0,
+\u1680*OGHAM SPACE MARK*\u1680,
+\u180e*MONGOLIAN VOWEL SEPARATOR*\u180e,
+\u2000*EN QUAD*\u2000,
+\u2001*EM QUAD*\u2001,
+\u2002*EN SPACE*\u2002,
+\u2003*EM SPACE*\u2003,
+\u2004*THREE-PER-EM SPACE*\u2004,
+\u2005*FOUR-PER-EM SPACE*\u2005,
+\u2006*SIX-PER-EM SPACE*\u2006,
+\u2007*FIGURE SPACE*\u2007,
+\u2008*PUNCTUATION SPACE*\u2008,
+\u2009*THIN SPACE*\u2009,
+\u200a*HAIR SPACE*\u200a,
+\u202f*NARROW NO-BREAK SPACE*\u202f,
+\u205f*MEDIUM MATHEMATICAL SPACE*\u205f,
+\u3000*IDEOGRAPHIC SPACE*\u3000,
+\u2028*LINE SEPARATOR*\u2028
+""",
+u"""\
+<document source="test data">
+ <paragraph>
+ inline markup surrounded by various whitespace characters:
+ <emphasis>
+ newline
+ \n\
+ or \n\
+ <emphasis>
+ space
+ or one of
+ \xa0
+ <emphasis>
+ NO-BREAK SPACE
+ \xa0,
+ \u1680
+ <emphasis>
+ OGHAM SPACE MARK
+ \u1680,
+ \u180e
+ <emphasis>
+ MONGOLIAN VOWEL SEPARATOR
+ \u180e,
+ \u2000
+ <emphasis>
+ EN QUAD
+ \u2000,
+ \u2001
+ <emphasis>
+ EM QUAD
+ \u2001,
+ \u2002
+ <emphasis>
+ EN SPACE
+ \u2002,
+ \u2003
+ <emphasis>
+ EM SPACE
+ \u2003,
+ \u2004
+ <emphasis>
+ THREE-PER-EM SPACE
+ \u2004,
+ \u2005
+ <emphasis>
+ FOUR-PER-EM SPACE
+ \u2005,
+ \u2006
+ <emphasis>
+ SIX-PER-EM SPACE
+ \u2006,
+ \u2007
+ <emphasis>
+ FIGURE SPACE
+ \u2007,
+ \u2008
+ <emphasis>
+ PUNCTUATION SPACE
+ \u2008,
+ \u2009
+ <emphasis>
+ THIN SPACE
+ \u2009,
+ \u200a
+ <emphasis>
+ HAIR SPACE
+ \u200a,
+ \u202f
+ <emphasis>
+ NARROW NO-BREAK SPACE
+ \u202f,
+ \u205f
+ <emphasis>
+ MEDIUM MATHEMATICAL SPACE
+ \u205f,
+ \u3000
+ <emphasis>
+ IDEOGRAPHIC SPACE
+ \u3000,
+ <paragraph>
+ <emphasis>
+ LINE SEPARATOR
+"""],
+[u"""\
+no inline markup due to whitespace inside and behind: *
+newline
+*
+* space * or one of
+*\xa0NO-BREAK SPACE\xa0*
+*\u1680OGHAM SPACE MARK\u1680*
+*\u2000EN QUAD\u2000*
+*\u2001EM QUAD\u2001*
+*\u2002EN SPACE\u2002*
+*\u2003EM SPACE\u2003*
+*\u2004THREE-PER-EM SPACE\u2004*
+*\u2005FOUR-PER-EM SPACE\u2005*
+*\u2006SIX-PER-EM SPACE\u2006*
+*\u2007FIGURE SPACE\u2007*
+*\u2008PUNCTUATION SPACE\u2008*
+*\u2009THIN SPACE\u2009*
+*\u200aHAIR SPACE\u200a*
+*\u202fNARROW NO-BREAK SPACE\u202f*
+*\u205fMEDIUM MATHEMATICAL SPACE\u205f*
+*\u3000IDEOGRAPHIC SPACE\u3000*
+*\u2028LINE SEPARATOR\u2028*
+""",
+u"""\
+<document source="test data">
+ <paragraph>
+ no inline markup due to whitespace inside and behind: *
+ newline
+ *
+ * space * or one of
+ *\xa0NO-BREAK SPACE\xa0*
+ *\u1680OGHAM SPACE MARK\u1680*
+ *\u2000EN QUAD\u2000*
+ *\u2001EM QUAD\u2001*
+ *\u2002EN SPACE\u2002*
+ *\u2003EM SPACE\u2003*
+ *\u2004THREE-PER-EM SPACE\u2004*
+ *\u2005FOUR-PER-EM SPACE\u2005*
+ *\u2006SIX-PER-EM SPACE\u2006*
+ *\u2007FIGURE SPACE\u2007*
+ *\u2008PUNCTUATION SPACE\u2008*
+ *\u2009THIN SPACE\u2009*
+ *\u200aHAIR SPACE\u200a*
+ *\u202fNARROW NO-BREAK SPACE\u202f*
+ *\u205fMEDIUM MATHEMATICAL SPACE\u205f*
+ *\u3000IDEOGRAPHIC SPACE\u3000*
+ *
+ LINE SEPARATOR
+ *"""],
+# « * » ‹ * › « * » ‹ * › « * » ‹ * › French,
+[u"""\
+"Quoted" markup start-string (matched openers & closers) -> no markup:
+
+'*' "*" (*) <*> [*] {*}
+⁅*⁆
+
+Some international quoting styles:
+‘*’ “*” English, ...,
+„*“ ‚*‘ »*« ›*‹ German, Czech, ...,
+„*” «*» Romanian,
+“*„ ‘*‚ Greek,
+「*」 『*』traditional Chinese,
+”*” ’*’ »*» ›*› Swedish, Finnish,
+„*” ‚*’ Polish,
+„*” »*« ’*’ Hungarian,
+
+But this is „*’ emphasized »*‹.
+""",
+u"""\
+<document source="test data">
+ <paragraph>
+ "Quoted" markup start-string (matched openers & closers) -> no markup:
+ <paragraph>
+ '*' "*" (*) <*> [*] {*}
+ ⁅*⁆
+ <paragraph>
+ Some international quoting styles:
+ ‘*’ “*” English, ...,
+ „*“ ‚*‘ »*« ›*‹ German, Czech, ...,
+ „*” «*» Romanian,
+ “*„ ‘*‚ Greek,
+ 「*」 『*』traditional Chinese,
+ ”*” ’*’ »*» ›*› Swedish, Finnish,
+ „*” ‚*’ Polish,
+ „*” »*« ’*’ Hungarian,
+ <paragraph>
+ But this is „
+ <emphasis>
+ ’ emphasized »
+ ‹.
+"""],
+]
+
+
+if __name__ == '__main__':
+ import unittest
+ unittest.main(defaultTest='suite')
--- /dev/null
+#! /usr/bin/env python
+
+# $Id: test_citations.py 8356 2019-08-26 16:44:19Z milde $
+# Author: David Goodger <goodger@python.org>
+# Copyright: This module has been placed in the public domain.
+
+"""
+Tests for states.py.
+"""
+from __future__ import absolute_import
+
+from . import DocutilsTestSupport
+
+def suite():
+ s = DocutilsTestSupport.ParserTestSuite()
+ s.generateTests(totest)
+ return s
+
+totest = {}
+
+totest['citations'] = [
+["""\
+.. [citation] This is a citation.
+""",
+"""\
+<document source="test data">
+ <citation ids="citation" names="citation">
+ <label>
+ citation
+ <paragraph>
+ This is a citation.
+"""],
+["""\
+.. [citation1234] This is a citation with year.
+""",
+"""\
+<document source="test data">
+ <citation ids="citation1234" names="citation1234">
+ <label>
+ citation1234
+ <paragraph>
+ This is a citation with year.
+"""],
+["""\
+.. [citation] This is a citation
+ on multiple lines.
+""",
+"""\
+<document source="test data">
+ <citation ids="citation" names="citation">
+ <label>
+ citation
+ <paragraph>
+ This is a citation
+ on multiple lines.
+"""],
+["""\
+.. [citation1] This is a citation
+ on multiple lines with more space.
+
+.. [citation2] This is a citation
+ on multiple lines with less space.
+""",
+"""\
+<document source="test data">
+ <citation ids="citation1" names="citation1">
+ <label>
+ citation1
+ <paragraph>
+ This is a citation
+ on multiple lines with more space.
+ <citation ids="citation2" names="citation2">
+ <label>
+ citation2
+ <paragraph>
+ This is a citation
+ on multiple lines with less space.
+"""],
+["""\
+.. [citation]
+ This is a citation on multiple lines
+ whose block starts on line 2.
+""",
+"""\
+<document source="test data">
+ <citation ids="citation" names="citation">
+ <label>
+ citation
+ <paragraph>
+ This is a citation on multiple lines
+ whose block starts on line 2.
+"""],
+["""\
+.. [citation]
+
+That was an empty citation.
+""",
+"""\
+<document source="test data">
+ <citation ids="citation" names="citation">
+ <label>
+ citation
+ <paragraph>
+ That was an empty citation.
+"""],
+["""\
+.. [citation]
+No blank line.
+""",
+"""\
+<document source="test data">
+ <citation ids="citation" names="citation">
+ <label>
+ citation
+ <system_message level="2" line="2" source="test data" type="WARNING">
+ <paragraph>
+ Explicit markup ends without a blank line; unexpected unindent.
+ <paragraph>
+ No blank line.
+"""],
+["""\
+.. [citation label with spaces] this isn't a citation
+
+.. [*citationlabelwithmarkup*] this isn't a citation
+""",
+"""\
+<document source="test data">
+ <comment xml:space="preserve">
+ [citation label with spaces] this isn't a citation
+ <comment xml:space="preserve">
+ [*citationlabelwithmarkup*] this isn't a citation
+"""],
+["""
+isolated internals : ``.-_``.
+
+.. [citation.withdot] one dot
+
+.. [citation-withdot] one hyphen
+
+.. [citation_withunderscore] one underscore
+
+.. [citation:with:colons] two colons
+
+.. [citation+withplus] one plus
+""",
+"""<document source="test data">
+ <paragraph>
+ isolated internals : \n\
+ <literal>
+ .-_
+ .
+ <citation ids="citation-withdot" names="citation.withdot">
+ <label>
+ citation.withdot
+ <paragraph>
+ one dot
+ <citation ids="id1" names="citation-withdot">
+ <label>
+ citation-withdot
+ <paragraph>
+ one hyphen
+ <citation ids="citation-withunderscore" names="citation_withunderscore">
+ <label>
+ citation_withunderscore
+ <paragraph>
+ one underscore
+ <citation ids="citation-with-colons" names="citation:with:colons">
+ <label>
+ citation:with:colons
+ <paragraph>
+ two colons
+ <citation ids="citation-withplus" names="citation+withplus">
+ <label>
+ citation+withplus
+ <paragraph>
+ one plus
+"""],
+]
+
+
+if __name__ == '__main__':
+ import unittest
+ unittest.main(defaultTest='suite')
--- /dev/null
+#! /usr/bin/env python
+
+# $Id: test_comments.py 8356 2019-08-26 16:44:19Z milde $
+# Author: David Goodger <goodger@python.org>
+# Copyright: This module has been placed in the public domain.
+
+"""
+Tests for states.py.
+"""
+from __future__ import absolute_import
+
+from . import DocutilsTestSupport
+
+def suite():
+ s = DocutilsTestSupport.ParserTestSuite()
+ s.generateTests(totest)
+ return s
+
+totest = {}
+
+totest['comments'] = [
+["""\
+.. A comment
+
+Paragraph.
+""",
+"""\
+<document source="test data">
+ <comment xml:space="preserve">
+ A comment
+ <paragraph>
+ Paragraph.
+"""],
+["""\
+.. A comment
+ block.
+
+Paragraph.
+""",
+"""\
+<document source="test data">
+ <comment xml:space="preserve">
+ A comment
+ block.
+ <paragraph>
+ Paragraph.
+"""],
+["""\
+..
+ A comment consisting of multiple lines
+ starting on the line after the
+ explicit markup start.
+""",
+"""\
+<document source="test data">
+ <comment xml:space="preserve">
+ A comment consisting of multiple lines
+ starting on the line after the
+ explicit markup start.
+"""],
+["""\
+.. A comment.
+.. Another.
+
+Paragraph.
+""",
+"""\
+<document source="test data">
+ <comment xml:space="preserve">
+ A comment.
+ <comment xml:space="preserve">
+ Another.
+ <paragraph>
+ Paragraph.
+"""],
+["""\
+.. A comment
+no blank line
+
+Paragraph.
+""",
+"""\
+<document source="test data">
+ <comment xml:space="preserve">
+ A comment
+ <system_message level="2" line="2" source="test data" type="WARNING">
+ <paragraph>
+ Explicit markup ends without a blank line; unexpected unindent.
+ <paragraph>
+ no blank line
+ <paragraph>
+ Paragraph.
+"""],
+["""\
+.. A comment.
+.. Another.
+no blank line
+
+Paragraph.
+""",
+"""\
+<document source="test data">
+ <comment xml:space="preserve">
+ A comment.
+ <comment xml:space="preserve">
+ Another.
+ <system_message level="2" line="3" source="test data" type="WARNING">
+ <paragraph>
+ Explicit markup ends without a blank line; unexpected unindent.
+ <paragraph>
+ no blank line
+ <paragraph>
+ Paragraph.
+"""],
+["""\
+.. A comment::
+
+Paragraph.
+""",
+"""\
+<document source="test data">
+ <comment xml:space="preserve">
+ A comment::
+ <paragraph>
+ Paragraph.
+"""],
+["""\
+..
+ comment::
+
+The extra newline before the comment text prevents
+the parser from recognizing a directive.
+""",
+"""\
+<document source="test data">
+ <comment xml:space="preserve">
+ comment::
+ <paragraph>
+ The extra newline before the comment text prevents
+ the parser from recognizing a directive.
+"""],
+["""\
+..
+ _comment: http://example.org
+
+The extra newline before the comment text prevents
+the parser from recognizing a hyperlink target.
+""",
+"""\
+<document source="test data">
+ <comment xml:space="preserve">
+ _comment: http://example.org
+ <paragraph>
+ The extra newline before the comment text prevents
+ the parser from recognizing a hyperlink target.
+"""],
+["""\
+..
+ [comment] Not a citation.
+
+The extra newline before the comment text prevents
+the parser from recognizing a citation.
+""",
+"""\
+<document source="test data">
+ <comment xml:space="preserve">
+ [comment] Not a citation.
+ <paragraph>
+ The extra newline before the comment text prevents
+ the parser from recognizing a citation.
+"""],
+["""\
+..
+ |comment| image:: bogus.png
+
+The extra newline before the comment text prevents
+the parser from recognizing a substitution definition.
+""",
+"""\
+<document source="test data">
+ <comment xml:space="preserve">
+ |comment| image:: bogus.png
+ <paragraph>
+ The extra newline before the comment text prevents
+ the parser from recognizing a substitution definition.
+"""],
+["""\
+.. Next is an empty comment, which serves to end this comment and
+ prevents the following block quote being swallowed up.
+
+..
+
+ A block quote.
+""",
+"""\
+<document source="test data">
+ <comment xml:space="preserve">
+ Next is an empty comment, which serves to end this comment and
+ prevents the following block quote being swallowed up.
+ <comment xml:space="preserve">
+ <block_quote>
+ <paragraph>
+ A block quote.
+"""],
+["""\
+term 1
+ definition 1
+
+ .. a comment
+
+term 2
+ definition 2
+""",
+"""\
+<document source="test data">
+ <definition_list>
+ <definition_list_item>
+ <term>
+ term 1
+ <definition>
+ <paragraph>
+ definition 1
+ <comment xml:space="preserve">
+ a comment
+ <definition_list_item>
+ <term>
+ term 2
+ <definition>
+ <paragraph>
+ definition 2
+"""],
+["""\
+term 1
+ definition 1
+
+.. a comment
+
+term 2
+ definition 2
+""",
+"""\
+<document source="test data">
+ <definition_list>
+ <definition_list_item>
+ <term>
+ term 1
+ <definition>
+ <paragraph>
+ definition 1
+ <comment xml:space="preserve">
+ a comment
+ <definition_list>
+ <definition_list_item>
+ <term>
+ term 2
+ <definition>
+ <paragraph>
+ definition 2
+"""],
+["""\
++ bullet paragraph 1
+
+ bullet paragraph 2
+
+ .. comment between bullet paragraphs 2 and 3
+
+ bullet paragraph 3
+""",
+"""\
+<document source="test data">
+ <bullet_list bullet="+">
+ <list_item>
+ <paragraph>
+ bullet paragraph 1
+ <paragraph>
+ bullet paragraph 2
+ <comment xml:space="preserve">
+ comment between bullet paragraphs 2 and 3
+ <paragraph>
+ bullet paragraph 3
+"""],
+["""\
++ bullet paragraph 1
+
+ .. comment between bullet paragraphs 1 (leader) and 2
+
+ bullet paragraph 2
+""",
+"""\
+<document source="test data">
+ <bullet_list bullet="+">
+ <list_item>
+ <paragraph>
+ bullet paragraph 1
+ <comment xml:space="preserve">
+ comment between bullet paragraphs 1 (leader) and 2
+ <paragraph>
+ bullet paragraph 2
+"""],
+["""\
++ bullet
+
+ .. trailing comment
+""",
+"""\
+<document source="test data">
+ <bullet_list bullet="+">
+ <list_item>
+ <paragraph>
+ bullet
+ <comment xml:space="preserve">
+ trailing comment
+"""],
+]
+
+if __name__ == '__main__':
+ import unittest
+ unittest.main(defaultTest='suite')
--- /dev/null
+#! /usr/bin/env python
+
+# $Id: test_definition_lists.py 8356 2019-08-26 16:44:19Z milde $
+# Author: David Goodger <goodger@python.org>
+# Copyright: This module has been placed in the public domain.
+
+"""
+Tests for states.py.
+"""
+from __future__ import absolute_import
+
+from . import DocutilsTestSupport
+
+def suite():
+ s = DocutilsTestSupport.ParserTestSuite()
+ s.generateTests(totest)
+ return s
+
+totest = {}
+
+totest['definition_lists'] = [
+["""\
+term
+ definition
+""",
+"""\
+<document source="test data">
+ <definition_list>
+ <definition_list_item>
+ <term>
+ term
+ <definition>
+ <paragraph>
+ definition
+"""],
+["""\
+term
+ definition
+
+paragraph
+""",
+"""\
+<document source="test data">
+ <definition_list>
+ <definition_list_item>
+ <term>
+ term
+ <definition>
+ <paragraph>
+ definition
+ <paragraph>
+ paragraph
+"""],
+["""\
+term
+ definition
+no blank line
+""",
+"""\
+<document source="test data">
+ <definition_list>
+ <definition_list_item>
+ <term>
+ term
+ <definition>
+ <paragraph>
+ definition
+ <system_message level="2" line="3" source="test data" type="WARNING">
+ <paragraph>
+ Definition list ends without a blank line; unexpected unindent.
+ <paragraph>
+ no blank line
+"""],
+["""\
+A paragraph::
+ A literal block without a blank line first?
+""",
+"""\
+<document source="test data">
+ <definition_list>
+ <definition_list_item>
+ <term>
+ A paragraph::
+ <definition>
+ <system_message level="1" line="2" source="test data" type="INFO">
+ <paragraph>
+ Blank line missing before literal block (after the "::")? Interpreted as a definition list item.
+ <paragraph>
+ A literal block without a blank line first?
+"""],
+["""\
+this is not a term;
+a term may only be one line long
+ this is not a definition
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ this is not a term;
+ a term may only be one line long
+ <system_message level="3" line="3" source="test data" type="ERROR">
+ <paragraph>
+ Unexpected indentation.
+ <block_quote>
+ <paragraph>
+ this is not a definition
+"""],
+["""\
+term 1
+ definition 1
+
+term 2
+ definition 2
+""",
+"""\
+<document source="test data">
+ <definition_list>
+ <definition_list_item>
+ <term>
+ term 1
+ <definition>
+ <paragraph>
+ definition 1
+ <definition_list_item>
+ <term>
+ term 2
+ <definition>
+ <paragraph>
+ definition 2
+"""],
+["""\
+term 1
+ definition 1 (no blank line below)
+term 2
+ definition 2
+""",
+"""\
+<document source="test data">
+ <definition_list>
+ <definition_list_item>
+ <term>
+ term 1
+ <definition>
+ <paragraph>
+ definition 1 (no blank line below)
+ <definition_list_item>
+ <term>
+ term 2
+ <definition>
+ <paragraph>
+ definition 2
+"""],
+["""\
+term 1
+ definition 1 (no blank line below)
+term 2
+ definition 2
+No blank line after the definition list.
+""",
+"""\
+<document source="test data">
+ <definition_list>
+ <definition_list_item>
+ <term>
+ term 1
+ <definition>
+ <paragraph>
+ definition 1 (no blank line below)
+ <definition_list_item>
+ <term>
+ term 2
+ <definition>
+ <paragraph>
+ definition 2
+ <system_message level="2" line="5" source="test data" type="WARNING">
+ <paragraph>
+ Definition list ends without a blank line; unexpected unindent.
+ <paragraph>
+ No blank line after the definition list.
+"""],
+["""\
+term 1
+ definition 1
+
+ term 1a
+ definition 1a
+
+ term 1b
+ definition 1b
+
+term 2
+ definition 2
+
+paragraph
+""",
+"""\
+<document source="test data">
+ <definition_list>
+ <definition_list_item>
+ <term>
+ term 1
+ <definition>
+ <paragraph>
+ definition 1
+ <definition_list>
+ <definition_list_item>
+ <term>
+ term 1a
+ <definition>
+ <paragraph>
+ definition 1a
+ <definition_list_item>
+ <term>
+ term 1b
+ <definition>
+ <paragraph>
+ definition 1b
+ <definition_list_item>
+ <term>
+ term 2
+ <definition>
+ <paragraph>
+ definition 2
+ <paragraph>
+ paragraph
+"""],
+["""\
+Term : classifier
+ The ' : ' indicates a classifier in
+ definition list item terms only.
+""",
+"""\
+<document source="test data">
+ <definition_list>
+ <definition_list_item>
+ <term>
+ Term
+ <classifier>
+ classifier
+ <definition>
+ <paragraph>
+ The ' : ' indicates a classifier in
+ definition list item terms only.
+"""],
+["""\
+Term: not a classifier
+ Because there's no space before the colon.
+Term :not a classifier
+ Because there's no space after the colon.
+Term \\: not a classifier
+ Because the colon is escaped.
+""",
+"""\
+<document source="test data">
+ <definition_list>
+ <definition_list_item>
+ <term>
+ Term: not a classifier
+ <definition>
+ <paragraph>
+ Because there's no space before the colon.
+ <definition_list_item>
+ <term>
+ Term :not a classifier
+ <definition>
+ <paragraph>
+ Because there's no space after the colon.
+ <definition_list_item>
+ <term>
+ Term : not a classifier
+ <definition>
+ <paragraph>
+ Because the colon is escaped.
+"""],
+["""\
+``Term : not a classifier``
+ Because the ' : ' is inside an inline literal.
+""",
+"""\
+<document source="test data">
+ <definition_list>
+ <definition_list_item>
+ <term>
+ <literal>
+ Term : not a classifier
+ <definition>
+ <paragraph>
+ Because the ' : ' is inside an inline literal.
+"""],
+["""\
+Term `with *inline ``text **errors : classifier `with *errors ``too
+ Definition `with *inline ``text **markup errors.
+""",
+"""\
+<document source="test data">
+ <definition_list>
+ <definition_list_item>
+ <term>
+ Term \n\
+ <problematic ids="id2" refid="id1">
+ `
+ with \n\
+ <problematic ids="id4" refid="id3">
+ *
+ inline \n\
+ <problematic ids="id6" refid="id5">
+ ``
+ text \n\
+ <problematic ids="id8" refid="id7">
+ **
+ errors
+ <classifier>
+ classifier \n\
+ <problematic ids="id10" refid="id9">
+ `
+ with \n\
+ <problematic ids="id12" refid="id11">
+ *
+ errors \n\
+ <problematic ids="id14" refid="id13">
+ ``
+ too
+ <definition>
+ <system_message backrefs="id2" ids="id1" level="2" line="1" source="test data" type="WARNING">
+ <paragraph>
+ Inline interpreted text or phrase reference start-string without end-string.
+ <system_message backrefs="id4" ids="id3" level="2" line="1" source="test data" type="WARNING">
+ <paragraph>
+ Inline emphasis start-string without end-string.
+ <system_message backrefs="id6" ids="id5" level="2" line="1" source="test data" type="WARNING">
+ <paragraph>
+ Inline literal start-string without end-string.
+ <system_message backrefs="id8" ids="id7" level="2" line="1" source="test data" type="WARNING">
+ <paragraph>
+ Inline strong start-string without end-string.
+ <system_message backrefs="id10" ids="id9" level="2" line="1" source="test data" type="WARNING">
+ <paragraph>
+ Inline interpreted text or phrase reference start-string without end-string.
+ <system_message backrefs="id12" ids="id11" level="2" line="1" source="test data" type="WARNING">
+ <paragraph>
+ Inline emphasis start-string without end-string.
+ <system_message backrefs="id14" ids="id13" level="2" line="1" source="test data" type="WARNING">
+ <paragraph>
+ Inline literal start-string without end-string.
+ <paragraph>
+ Definition \n\
+ <problematic ids="id16" refid="id15">
+ `
+ with \n\
+ <problematic ids="id18" refid="id17">
+ *
+ inline \n\
+ <problematic ids="id20" refid="id19">
+ ``
+ text \n\
+ <problematic ids="id22" refid="id21">
+ **
+ markup errors.
+ <system_message backrefs="id16" ids="id15" level="2" line="2" source="test data" type="WARNING">
+ <paragraph>
+ Inline interpreted text or phrase reference start-string without end-string.
+ <system_message backrefs="id18" ids="id17" level="2" line="2" source="test data" type="WARNING">
+ <paragraph>
+ Inline emphasis start-string without end-string.
+ <system_message backrefs="id20" ids="id19" level="2" line="2" source="test data" type="WARNING">
+ <paragraph>
+ Inline literal start-string without end-string.
+ <system_message backrefs="id22" ids="id21" level="2" line="2" source="test data" type="WARNING">
+ <paragraph>
+ Inline strong start-string without end-string.
+"""],
+["""\
+Term : `reference`_
+ classifier starting with a reference crashes from release 8197 to ...
+""",
+"""\
+<document source="test data">
+ <definition_list>
+ <definition_list_item>
+ <term>
+ Term
+ <classifier>
+ <reference name="reference" refname="reference">
+ reference
+ <definition>
+ <paragraph>
+ classifier starting with a reference crashes from release 8197 to ...
+"""],
+["""\
+Term : a `reference`_ in text : second
+ classifier with reference crashes from release 8197 to ...
+""",
+"""\
+<document source="test data">
+ <definition_list>
+ <definition_list_item>
+ <term>
+ Term
+ <classifier>
+ a \n\
+ <reference name="reference" refname="reference">
+ reference
+ in text
+ <classifier>
+ second
+ <definition>
+ <paragraph>
+ classifier with reference crashes from release 8197 to ...
+"""],
+["""\
+Term : classifier one : classifier two
+ Definition
+""",
+"""\
+<document source="test data">
+ <definition_list>
+ <definition_list_item>
+ <term>
+ Term
+ <classifier>
+ classifier one
+ <classifier>
+ classifier two
+ <definition>
+ <paragraph>
+ Definition
+"""],
+]
+
+if __name__ == '__main__':
+ import unittest
+ unittest.main(defaultTest='suite')
--- /dev/null
+import os
+import os.path
+import sys
+
+sys.path.insert(0, os.path.abspath(os.path.dirname(__file__)))
+prev = ''
+while sys.path[0] != prev:
+ try:
+ import DocutilsTestSupport
+ break
+ except ImportError:
+ prev = sys.path[0]
+ sys.path[0] = os.path.dirname(prev)
+sys.path.pop(0)
--- /dev/null
+Inclusion 1
+-----------
+
+This file is used by ``test_include.py``.
--- /dev/null
+.. |bad| unicode:: 0x11111111
+
+hi
+-----
+
+ indent
+error
+
+hi
+-----
+
+.. include:: <nonexistent>
+
+.. note::
+
+.. admonition::
+ without title
+
+.. epigraph::
+
+.. highlights::
+
+.. pull-quote::
+
+.. date::
+
+not a
+definition list:
+ as a term may only be one line long.
+
+.. admonition::
+
+ without title and content following a blank line
+
+section underline too short
+-----
+
+============== ======
+A simple table cell 2
+============== ======
+cell 3 cell 4
+============== ======
+No blank line after table.
+
+.. |empty| unicode::
+
+.. topic::
+
+.. rubric::
+.. rubric:: A rubric has no content
+
+.. _`target: No matching backquote.
+.. __malformed: no good
+
+A literal block::
+ with no blank line above.
+
+::
+
+> A literal block.
+$ with inconsistent quoting.
+
+:unknown-role:`role`
+and *unbalanced
+`inline
+**markup
+
+:PEP:`-1`
+
+.. unknown:: directive (info still reported with wrong line)
+
+============== ======
+A simple table with
+no bottom border
--- /dev/null
+In include12.txt (but before "start here")
+
+.. start here
+
+In include12.txt (after "start here", before "stop here")
+
+.. stop here
+
+In include12.txt (after "stop here")
--- /dev/null
+In include13.txt (but before header)
+
+From: me
+To: you
+
+In include13.txt (between header and signature)
+
+-------
+ -- mork of ork
+
+In include13.txt (after signature)
--- /dev/null
+Here are some paragraphs
+that can appear at any level.
+
+This file (include2.txt) is used by
+``test_include.py``.
--- /dev/null
+In include3.txt
+
+.. include:: includes/include4.txt
--- /dev/null
+In include8.txt
+
+.. include:: ../includes/include9.txt
--- /dev/null
+Literal included this should **not** be *marked* `up`.
+ <- leading raw tab.
+
+Newlines
+are
+normalized.
--- /dev/null
+Including more/include6.txt as rst-code from includes/include14.txt:
+
+.. include:: more/include6.txt
+ :code: rst
--- /dev/null
+In includes/include4.txt
+
+.. include:: include5.txt
+
+.. include:: include5.txt
+ :literal:
+
+.. csv-table::
+ :file: sibling/include7.txt
+ :delim: space
--- /dev/null
+In includes/include5.txt
+
+.. include:: more/include6.txt
--- /dev/null
+In includes/more/include6.txt
+
+.. include:: ../sibling/include7.txt
--- /dev/null
+In includes/sibling/include7.txt
--- /dev/null
+<p>This file is used by <tt>test_raw.py</tt>.</p>
--- /dev/null
+#! /usr/bin/env python
+
+# $Id: test_admonitions.py 8452 2020-01-09 10:50:44Z milde $
+# Author: David Goodger <goodger@python.org>
+# Copyright: This module has been placed in the public domain.
+
+"""
+Tests for admonitions.py directives.
+"""
+from __future__ import absolute_import
+
+try:
+ from . import DocutilsTestSupport
+except ValueError: # when running as stand-alone test
+ from __init__ import DocutilsTestSupport
+
+def suite():
+ s = DocutilsTestSupport.ParserTestSuite()
+ s.generateTests(totest)
+ return s
+
+totest = {}
+
+totest['admonitions'] = [
+["""\
+.. Attention:: Directives at large.
+
+.. Note:: :name: mynote
+ :class: testnote
+
+ Admonitions support the generic "name" and "class" options.
+
+.. Tip:: 15% if the
+ service is good.
+
+.. Hint:: It's bigger than a bread box.
+
+- .. WARNING:: Strong prose may provoke extreme mental exertion.
+ Reader discretion is strongly advised.
+- .. Error:: Does not compute.
+
+.. Caution::
+
+ Don't take any wooden nickels.
+
+.. DANGER:: Mad scientist at work!
+
+.. Important::
+ - Wash behind your ears.
+ - Clean up your room.
+ - Call your mother.
+ - Back up your data.
+""",
+"""\
+<document source="test data">
+ <attention>
+ <paragraph>
+ Directives at large.
+ <note classes="testnote" ids="mynote" names="mynote">
+ <paragraph>
+ Admonitions support the generic "name" and "class" options.
+ <tip>
+ <paragraph>
+ 15% if the
+ service is good.
+ <hint>
+ <paragraph>
+ It's bigger than a bread box.
+ <bullet_list bullet="-">
+ <list_item>
+ <warning>
+ <paragraph>
+ Strong prose may provoke extreme mental exertion.
+ Reader discretion is strongly advised.
+ <list_item>
+ <error>
+ <paragraph>
+ Does not compute.
+ <caution>
+ <paragraph>
+ Don't take any wooden nickels.
+ <danger>
+ <paragraph>
+ Mad scientist at work!
+ <important>
+ <bullet_list bullet="-">
+ <list_item>
+ <paragraph>
+ Wash behind your ears.
+ <list_item>
+ <paragraph>
+ Clean up your room.
+ <list_item>
+ <paragraph>
+ Call your mother.
+ <list_item>
+ <paragraph>
+ Back up your data.
+"""],
+["""\
+.. note:: One-line notes.
+.. note:: One after the other.
+.. note:: No blank lines in-between.
+""",
+"""\
+<document source="test data">
+ <note>
+ <paragraph>
+ One-line notes.
+ <note>
+ <paragraph>
+ One after the other.
+ <note>
+ <paragraph>
+ No blank lines in-between.
+"""],
+["""\
+.. note:: Content before options
+ is possible too.
+ :class: mynote
+
+.. note:: :strong:`a role is not an option`.
+ :name: role not option
+
+.. note:: a role is
+ :strong:`not an option`, even if its starts a line.
+""",
+"""\
+<document source="test data">
+ <note classes="mynote">
+ <paragraph>
+ Content before options
+ is possible too.
+ <note ids="role-not-option" names="role\\ not\\ option">
+ <paragraph>
+ <strong>
+ a role is not an option
+ .
+ <note>
+ <paragraph>
+ a role is
+ <strong>
+ not an option
+ , even if its starts a line.
+"""],
+["""\
+.. note::
+""",
+"""\
+<document source="test data">
+ <system_message level="3" line="1" source="test data" type="ERROR">
+ <paragraph>
+ Content block expected for the "note" directive; none found.
+ <literal_block xml:space="preserve">
+ .. note::
+"""],
+["""\
+.. admonition:: Admonition
+
+ This is a generic admonition.
+""",
+"""\
+<document source="test data">
+ <admonition classes="admonition-admonition">
+ <title>
+ Admonition
+ <paragraph>
+ This is a generic admonition.
+"""],
+["""\
+.. admonition:: And, by the way...
+
+ You can make up your own admonition too.
+""",
+"""\
+<document source="test data">
+ <admonition classes="admonition-and-by-the-way">
+ <title>
+ And, by the way...
+ <paragraph>
+ You can make up your own admonition too.
+"""],
+["""\
+.. admonition:: Admonition
+ :class: emergency
+ :name: reference name
+
+ Test the "class" override.
+""",
+"""\
+<document source="test data">
+ <admonition classes="emergency" ids="reference-name" names="reference\\ name">
+ <title>
+ Admonition
+ <paragraph>
+ Test the "class" override.
+"""],
+["""\
+.. admonition::
+
+ Generic admonitions require a title.
+""",
+"""\
+<document source="test data">
+ <system_message level="3" line="1" source="test data" type="ERROR">
+ <paragraph>
+ Error in "admonition" directive:
+ 1 argument(s) required, 0 supplied.
+ <literal_block xml:space="preserve">
+ .. admonition::
+
+ Generic admonitions require a title.
+"""],
+]
+
+
+if __name__ == '__main__':
+ import unittest
+ unittest.main(defaultTest='suite')
--- /dev/null
+#! /usr/bin/env python
+
+# $Id: test_admonitions_de.py 8452 2020-01-09 10:50:44Z milde $
+# Author: David Goodger <goodger@python.org>
+# Copyright: This module has been placed in the public domain.
+
+"""
+Tests for admonitions.py directives in German document.
+"""
+from __future__ import absolute_import
+
+try:
+ from . import DocutilsTestSupport
+except ValueError: # when running as stand-alone test
+ from __init__ import DocutilsTestSupport
+
+def suite():
+ settings = {'language_code': 'de'}
+ s = DocutilsTestSupport.ParserTestSuite(suite_settings=settings)
+ s.generateTests(totest)
+ return s
+
+totest = {}
+
+totest['admonitions'] = [
+["""\
+.. Achtung:: Directives at large.
+
+.. Notiz:: :name: mynote
+ :class: testnote
+
+ Admonitions support the generic "name" and "class" options.
+
+.. Tipp:: 15% if the
+ service is good.
+
+.. Hinweis:: It's bigger than a bread box.
+
+- .. WARNUNG:: Strong prose may provoke extreme mental exertion.
+ Reader discretion is strongly advised.
+- .. Fehler:: Does not compute.
+
+.. Vorsicht::
+
+ Don't take any wooden nickels.
+
+.. GEFAHR:: Mad scientist at work!
+
+.. Wichtig::
+ - Wash behind your ears.
+ - Clean up your room.
+ - Call your mother.
+ - Back up your data.
+""",
+"""\
+<document source="test data">
+ <attention>
+ <paragraph>
+ Directives at large.
+ <note classes="testnote" ids="mynote" names="mynote">
+ <paragraph>
+ Admonitions support the generic "name" and "class" options.
+ <tip>
+ <paragraph>
+ 15% if the
+ service is good.
+ <hint>
+ <paragraph>
+ It's bigger than a bread box.
+ <bullet_list bullet="-">
+ <list_item>
+ <warning>
+ <paragraph>
+ Strong prose may provoke extreme mental exertion.
+ Reader discretion is strongly advised.
+ <list_item>
+ <error>
+ <paragraph>
+ Does not compute.
+ <caution>
+ <paragraph>
+ Don't take any wooden nickels.
+ <danger>
+ <paragraph>
+ Mad scientist at work!
+ <important>
+ <bullet_list bullet="-">
+ <list_item>
+ <paragraph>
+ Wash behind your ears.
+ <list_item>
+ <paragraph>
+ Clean up your room.
+ <list_item>
+ <paragraph>
+ Call your mother.
+ <list_item>
+ <paragraph>
+ Back up your data.
+"""],
+["""\
+.. Notiz:: One-line notes.
+.. Notiz:: One after the other.
+.. Notiz:: No blank lines in-between.
+""",
+"""\
+<document source="test data">
+ <note>
+ <paragraph>
+ One-line notes.
+ <note>
+ <paragraph>
+ One after the other.
+ <note>
+ <paragraph>
+ No blank lines in-between.
+"""],
+["""\
+.. Notiz:: Content before options
+ is possible too.
+ :class: mynote
+
+.. Notiz:: :strong:`a role is not an option`.
+ :name: role not option
+
+.. Notiz:: a role is
+ :strong:`not an option`, even if its starts a line.
+""",
+"""\
+<document source="test data">
+ <note classes="mynote">
+ <paragraph>
+ Content before options
+ is possible too.
+ <note ids="role-not-option" names="role\\ not\\ option">
+ <paragraph>
+ <strong>
+ a role is not an option
+ .
+ <system_message level="1" line="5" source="test data" type="INFO">
+ <paragraph>
+ No role entry for "strong" in module "docutils.parsers.rst.languages.de".
+ Using English fallback for role "strong".
+ <note>
+ <paragraph>
+ a role is
+ <strong>
+ not an option
+ , even if its starts a line.
+"""],
+["""\
+.. Notiz::
+""",
+"""\
+<document source="test data">
+ <system_message level="3" line="1" source="test data" type="ERROR">
+ <paragraph>
+ Content block expected for the "Notiz" directive; none found.
+ <literal_block xml:space="preserve">
+ .. Notiz::
+"""],
+["""\
+.. admonition:: Admonition
+
+ This is a generic admonition.
+""",
+"""\
+<document source="test data">
+ <admonition classes="admonition-admonition">
+ <title>
+ Admonition
+ <paragraph>
+ This is a generic admonition.
+"""],
+["""\
+.. admonition:: And, by the way...
+
+ You can make up your own admonition too.
+""",
+"""\
+<document source="test data">
+ <admonition classes="admonition-and-by-the-way">
+ <title>
+ And, by the way...
+ <paragraph>
+ You can make up your own admonition too.
+"""],
+["""\
+.. admonition:: Admonition
+ :class: emergency
+ :name: reference name
+
+ Test the "class" override.
+""",
+"""\
+<document source="test data">
+ <admonition classes="emergency" ids="reference-name" names="reference\\ name">
+ <title>
+ Admonition
+ <paragraph>
+ Test the "class" override.
+"""],
+["""\
+.. admonition::
+
+ Generic admonitions require a title.
+""",
+"""\
+<document source="test data">
+ <system_message level="3" line="1" source="test data" type="ERROR">
+ <paragraph>
+ Error in "admonition" directive:
+ 1 argument(s) required, 0 supplied.
+ <literal_block xml:space="preserve">
+ .. admonition::
+
+ Generic admonitions require a title.
+"""],
+]
+
+
+if __name__ == '__main__':
+ import unittest
+ unittest.main(defaultTest='suite')
--- /dev/null
+#! /usr/bin/env python
+
+# $Id: test_admonitions_dummy_lang.py 8452 2020-01-09 10:50:44Z milde $
+# Author: David Goodger <goodger@python.org>
+# Copyright: This module has been placed in the public domain.
+
+"""
+Tests for admonition directives with local language module.
+"""
+from __future__ import absolute_import
+
+try:
+ from . import DocutilsTestSupport
+except ValueError: # when running as stand-alone test
+ from __init__ import DocutilsTestSupport
+
+def suite():
+ settings = {'language_code': 'local-dummy-lang',
+ 'report_level': 2} # warning (has no effect on test output is run as __main__).
+ s = DocutilsTestSupport.ParserTestSuite(suite_settings=settings)
+ s.generateTests(totest)
+ return s
+
+totest = {}
+
+totest['admonitions'] = [
+["""\
+.. Dummy-Attention:: directive with silly localised name.
+
+.. Attention:: English fallback (an INFO is written).
+""",
+"""\
+<document source="test data">
+ <attention>
+ <paragraph>
+ directive with silly localised name.
+ <attention>
+ <paragraph>
+ English fallback (an INFO is written).
+"""],
+]
+
+
+if __name__ == '__main__':
+ import unittest
+ unittest.main(defaultTest='suite')
--- /dev/null
+#! /usr/bin/env python
+
+# $Id: test_block_quotes.py 8356 2019-08-26 16:44:19Z milde $
+# Author: Lea Wiemann <LeWiemann@gmail.com>
+# Copyright: This module has been placed in the public domain.
+
+"""
+Tests for the block quote directives "epigraph", "highlights", and
+"pull-quote".
+"""
+from __future__ import absolute_import
+
+from . import DocutilsTestSupport
+
+def suite():
+ s = DocutilsTestSupport.ParserTestSuite()
+ s.generateTests(totest)
+ return s
+
+generic_tests = [
+["""\
+.. %(type)s::
+
+ This is a block quote.
+
+ -- Attribution
+
+ This is another block quote.
+
+ -- Another Attribution,
+ Second Line
+""",
+"""\
+<document source="test data">
+ <block_quote classes="%(type)s">
+ <paragraph>
+ This is a block quote.
+ <attribution>
+ Attribution
+ <block_quote classes="%(type)s">
+ <paragraph>
+ This is another block quote.
+ <attribution>
+ Another Attribution,
+ Second Line
+"""],
+# TODO: Add class option.
+["""\
+.. %(type)s::
+""",
+"""\
+<document source="test data">
+ <system_message level="3" line="1" source="test data" type="ERROR">
+ <paragraph>
+ Content block expected for the "%(type)s" directive; none found.
+ <literal_block xml:space="preserve">
+ .. %(type)s::
+"""],
+]
+
+totest = {}
+for block_quote_type in ('epigraph', 'highlights', 'pull-quote'):
+ totest[block_quote_type] = [
+ [text % {'type': block_quote_type} for text in pair]
+ for pair in generic_tests]
+
+
+if __name__ == '__main__':
+ import unittest
+ unittest.main(defaultTest='suite')
--- /dev/null
+#! /usr/bin/env python
+
+# $Id: test_class.py 8356 2019-08-26 16:44:19Z milde $
+# Author: Lea Wiemann <LeWiemann@gmail.com>
+# Copyright: This module has been placed in the public domain.
+
+"""
+Tests for the 'class' directive.
+"""
+from __future__ import absolute_import
+
+from . import DocutilsTestSupport
+
+def suite():
+ s = DocutilsTestSupport.ParserTestSuite()
+ s.generateTests(totest)
+ return s
+
+totest = {}
+
+totest['class'] = [
+["""\
+.. class:: class1 class2
+""",
+"""\
+<document source="test data">
+ <pending>
+ .. internal attributes:
+ .transform: docutils.transforms.misc.ClassAttribute
+ .details:
+ class: ['class1', 'class2']
+ directive: 'class'
+"""],
+["""\
+.. class:: class1 class2
+
+ The classes are applied to this paragraph.
+
+ And this one.
+""",
+"""\
+<document source="test data">
+ <paragraph classes="class1 class2">
+ The classes are applied to this paragraph.
+ <paragraph classes="class1 class2">
+ And this one.
+"""],
+]
+
+
+if __name__ == '__main__':
+ import unittest
+ unittest.main(defaultTest='suite')
--- /dev/null
+#! /usr/bin/env python
+
+# $Id: test_code.py 8356 2019-08-26 16:44:19Z milde $
+# Author: Guenter Milde
+# Copyright: This module has been placed in the public domain.
+
+"""
+Test the 'code' directive in parsers/rst/directives/body.py.
+"""
+from __future__ import absolute_import
+
+from . import DocutilsTestSupport
+from docutils.utils.code_analyzer import with_pygments
+
+def suite():
+ s = DocutilsTestSupport.ParserTestSuite()
+ if not with_pygments:
+ del(totest['code-parsing'])
+ s.generateTests(totest)
+ return s
+
+totest = {}
+
+totest['code'] = [
+["""\
+.. code::
+
+ This is a code block.
+""",
+"""\
+<document source="test data">
+ <literal_block classes="code" xml:space="preserve">
+ This is a code block.
+"""],
+["""\
+.. code::
+ :class: testclass
+ :name: without argument
+
+ This is a code block with generic options.
+""",
+"""\
+<document source="test data">
+ <literal_block classes="code testclass" ids="without-argument" names="without\\ argument" xml:space="preserve">
+ This is a code block with generic options.
+"""],
+["""\
+.. code:: text
+ :class: testclass
+
+ This is a code block with text.
+""",
+"""\
+<document source="test data">
+ <literal_block classes="code text testclass" xml:space="preserve">
+ This is a code block with text.
+"""],
+["""\
+.. code::
+ :number-lines:
+
+ This is a code block with text.
+""",
+"""\
+<document source="test data">
+ <literal_block classes="code" xml:space="preserve">
+ <inline classes="ln">
+ 1 \n\
+ This is a code block with text.
+"""],
+["""\
+.. code::
+ :number-lines: 30
+
+ This is a code block with text.
+""",
+"""\
+<document source="test data">
+ <literal_block classes="code" xml:space="preserve">
+ <inline classes="ln">
+ 30 \n\
+ This is a code block with text.
+"""],
+["""\
+.. code::
+""",
+"""\
+<document source="test data">
+ <system_message level="3" line="1" source="test data" type="ERROR">
+ <paragraph>
+ Content block expected for the "code" directive; none found.
+ <literal_block xml:space="preserve">
+ .. code::
+"""],
+]
+
+totest['code-parsing'] = [
+["""\
+.. code:: python
+ :class: testclass
+
+ print('hello world') # to stdout
+""",
+"""\
+<document source="test data">
+ <literal_block classes="code python testclass" xml:space="preserve">
+ \n\
+ <inline classes="keyword">
+ print
+ <inline classes="punctuation">
+ (
+ <inline classes="literal string single">
+ 'hello world'
+ <inline classes="punctuation">
+ )
+ \n\
+ <inline classes="comment single">
+ # to stdout
+"""],
+["""\
+.. code:: python
+ :class: testclass
+ :name: my_function
+ :number-lines: 7
+
+ def my_function():
+ '''Test the lexer.
+ '''
+
+ # and now for something completely different
+ print(8/2)
+""",
+"""\
+<document source="test data">
+ <literal_block classes="code python testclass" ids="my-function" names="my_function" xml:space="preserve">
+ <inline classes="ln">
+ 7 \n\
+ <inline classes="keyword">
+ def
+ \n\
+ <inline classes="name function">
+ my_function
+ <inline classes="punctuation">
+ ():
+ \n\
+ <inline classes="ln">
+ 8 \n\
+ \n\
+ <inline classes="literal string doc">
+ \'\'\'Test the lexer.
+ <inline classes="ln">
+ 9 \n\
+ <inline classes="literal string doc">
+ \'\'\'
+ \n\
+ <inline classes="ln">
+ 10 \n\
+ \n\
+ <inline classes="ln">
+ 11 \n\
+ \n\
+ <inline classes="comment single">
+ # and now for something completely different
+ \n\
+ <inline classes="ln">
+ 12 \n\
+ \n\
+ <inline classes="keyword">
+ print
+ <inline classes="punctuation">
+ (
+ <inline classes="literal number integer">
+ 8
+ <inline classes="operator">
+ /
+ <inline classes="literal number integer">
+ 2
+ <inline classes="punctuation">
+ )
+"""],
+["""\
+.. code:: latex
+ :class: testclass
+
+ hello \\emph{world} % emphasize
+""",
+"""\
+<document source="test data">
+ <literal_block classes="code latex testclass" xml:space="preserve">
+ hello \n\
+ <inline classes="keyword">
+ \\emph
+ <inline classes="name builtin">
+ {
+ world
+ <inline classes="name builtin">
+ }
+ \n\
+ <inline classes="comment">
+ % emphasize"""],
+["""\
+.. code:: rst
+ :number-lines:
+
+ This is a code block with text.
+""",
+"""\
+<document source="test data">
+ <literal_block classes="code rst" xml:space="preserve">
+ <inline classes="ln">
+ 1 \n\
+ This is a code block with text.
+"""],
+["""\
+.. code:: s-lang
+
+ % abc.sl
+ autoload("abc_mode", "abc");
+""",
+"""\
+<document source="test data">
+ <system_message level="2" line="1" source="test data" type="WARNING">
+ <paragraph>
+ Cannot analyze code. No Pygments lexer found for "s-lang".
+ <literal_block xml:space="preserve">
+ .. code:: s-lang
+ \n\
+ % abc.sl
+ autoload("abc_mode", "abc");
+"""],
+["""\
+Place the language name in a class argument to avoid the no-lexer warning:
+
+.. code::
+ :class: s-lang
+
+ % abc.sl
+ autoload("abc_mode", "abc");
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ Place the language name in a class argument to avoid the no-lexer warning:
+ <literal_block classes="code s-lang" xml:space="preserve">
+ % abc.sl
+ autoload("abc_mode", "abc");
+"""],
+]
+
+
+if __name__ == '__main__':
+ import unittest
+ unittest.main(defaultTest='suite')
--- /dev/null
+#! /usr/bin/env python
+
+# $Id: test_code_long.py 8356 2019-08-26 16:44:19Z milde $
+# Author: Guenter Milde
+# Copyright: This module has been placed in the public domain.
+
+"""
+Test the 'code' directive in body.py with syntax_highlight = 'long'.
+"""
+from __future__ import absolute_import
+
+from . import DocutilsTestSupport
+from docutils.utils.code_analyzer import with_pygments
+
+def suite():
+ s = DocutilsTestSupport.ParserTestSuite(suite_settings={'syntax_highlight':'long'})
+ if with_pygments:
+ s.generateTests(totest)
+ return s
+
+totest = {}
+
+totest['code-parsing-long'] = [
+["""\
+.. code:: python
+ :number-lines: 7
+
+ def my_function():
+ '''Test the lexer.
+ '''
+
+ # and now for something completely different
+ print(8/2)
+""",
+"""\
+<document source="test data">
+ <literal_block classes="code python" xml:space="preserve">
+ <inline classes="ln">
+ 7 \n\
+ <inline classes="keyword">
+ def
+ \n\
+ <inline classes="name function">
+ my_function
+ <inline classes="punctuation">
+ ():
+ \n\
+ <inline classes="ln">
+ 8 \n\
+ \n\
+ <inline classes="literal string doc">
+ \'\'\'Test the lexer.
+ <inline classes="ln">
+ 9 \n\
+ <inline classes="literal string doc">
+ \'\'\'
+ \n\
+ <inline classes="ln">
+ 10 \n\
+ \n\
+ <inline classes="ln">
+ 11 \n\
+ \n\
+ <inline classes="comment single">
+ # and now for something completely different
+ \n\
+ <inline classes="ln">
+ 12 \n\
+ \n\
+ <inline classes="keyword">
+ print
+ <inline classes="punctuation">
+ (
+ <inline classes="literal number integer">
+ 8
+ <inline classes="operator">
+ /
+ <inline classes="literal number integer">
+ 2
+ <inline classes="punctuation">
+ )
+"""],
+["""\
+.. code:: latex
+
+ hello \\emph{world} % emphasize
+""",
+"""\
+<document source="test data">
+ <literal_block classes="code latex" xml:space="preserve">
+ hello \n\
+ <inline classes="keyword">
+ \\emph
+ <inline classes="name builtin">
+ {
+ world
+ <inline classes="name builtin">
+ }
+ \n\
+ <inline classes="comment">
+ % emphasize"""],
+]
+
+
+if __name__ == '__main__':
+ import unittest
+ unittest.main(defaultTest='suite')
--- /dev/null
+#! /usr/bin/env python
+
+# $Id: test_code_none.py 8356 2019-08-26 16:44:19Z milde $
+# Author: Guenter Milde
+# Copyright: This module has been placed in the public domain.
+
+"""
+Test the 'code' directive in body.py with syntax_highlight = 'none'.
+"""
+from __future__ import absolute_import
+
+from . import DocutilsTestSupport
+
+def suite():
+ s = DocutilsTestSupport.ParserTestSuite(suite_settings={'syntax_highlight':'none'})
+ s.generateTests(totest)
+ return s
+
+totest = {}
+
+totest['code-parsing-none'] = [
+["""\
+.. code::
+
+ This is a code block.
+""",
+"""\
+<document source="test data">
+ <literal_block classes="code" xml:space="preserve">
+ This is a code block.
+"""],
+["""\
+.. code:: python
+ :number-lines: 7
+
+ def my_function():
+ '''Test the lexer.
+ '''
+
+ # and now for something completely different
+ print(8/2)
+""",
+"""\
+<document source="test data">
+ <literal_block classes="code python" xml:space="preserve">
+ <inline classes="ln">
+ 7 \n\
+ def my_function():
+ <inline classes="ln">
+ 8 \n\
+ \'\'\'Test the lexer.
+ <inline classes="ln">
+ 9 \n\
+ \'\'\'
+ <inline classes="ln">
+ 10 \n\
+ \n\
+ <inline classes="ln">
+ 11 \n\
+ # and now for something completely different
+ <inline classes="ln">
+ 12 \n\
+ print(8/2)
+"""],
+["""\
+.. code:: latex
+
+ hello \\emph{world} % emphasize
+""",
+"""\
+<document source="test data">
+ <literal_block classes="code latex" xml:space="preserve">
+ hello \\emph{world} % emphasize
+"""],
+]
+
+
+if __name__ == '__main__':
+ import unittest
+ unittest.main(defaultTest='suite')
--- /dev/null
+#! /usr/bin/env python
+
+# $Id: test_compound.py 8356 2019-08-26 16:44:19Z milde $
+# Author: David Goodger <goodger@python.org>
+# Copyright: This module has been placed in the public domain.
+
+"""
+Tests for the 'compound' directive from body.py.
+"""
+from __future__ import absolute_import
+
+from . import DocutilsTestSupport
+
+def suite():
+ s = DocutilsTestSupport.ParserTestSuite()
+ s.generateTests(totest)
+ return s
+
+totest = {}
+
+totest['compound'] = [
+["""\
+.. compound::
+
+ Compound paragraphs are single logical paragraphs
+ which contain embedded
+
+ * lists
+ * tables
+ * literal blocks
+ * and other body elements
+
+ and are split into multiple physical paragraphs.
+""",
+"""\
+<document source="test data">
+ <compound>
+ <paragraph>
+ Compound paragraphs are single logical paragraphs
+ which contain embedded
+ <bullet_list bullet="*">
+ <list_item>
+ <paragraph>
+ lists
+ <list_item>
+ <paragraph>
+ tables
+ <list_item>
+ <paragraph>
+ literal blocks
+ <list_item>
+ <paragraph>
+ and other body elements
+ <paragraph>
+ and are split into multiple physical paragraphs.
+"""],
+["""\
+.. compound::
+ :name: interesting
+ :class: log
+
+ This is an extremely interesting compound paragraph containing a
+ simple paragraph, a literal block with some useless log messages::
+
+ Connecting... OK
+ Transmitting data... OK
+ Disconnecting... OK
+
+ and another simple paragraph which is actually just a continuation
+ of the first simple paragraph, with the literal block in between.
+""",
+"""\
+<document source="test data">
+ <compound classes="log" ids="interesting" names="interesting">
+ <paragraph>
+ This is an extremely interesting compound paragraph containing a
+ simple paragraph, a literal block with some useless log messages:
+ <literal_block xml:space="preserve">
+ Connecting... OK
+ Transmitting data... OK
+ Disconnecting... OK
+ <paragraph>
+ and another simple paragraph which is actually just a continuation
+ of the first simple paragraph, with the literal block in between.
+"""],
+["""\
+.. compound:: content may start on same line
+
+ second paragraph
+""",
+"""\
+<document source="test data">
+ <compound>
+ <paragraph>
+ content may start on same line
+ <paragraph>
+ second paragraph
+"""],
+]
+
+
+if __name__ == '__main__':
+ import unittest
+ unittest.main(defaultTest='suite')
--- /dev/null
+#! /usr/bin/env python
+
+# $Id: test_container.py 8356 2019-08-26 16:44:19Z milde $
+# Author: David Goodger <goodger@python.org>
+# Copyright: This module has been placed in the public domain.
+
+"""
+Tests for the 'container' directive from body.py.
+"""
+from __future__ import absolute_import
+
+from . import DocutilsTestSupport
+
+def suite():
+ s = DocutilsTestSupport.ParserTestSuite()
+ s.generateTests(totest)
+ return s
+
+totest = {}
+
+totest['container'] = [
+["""\
+.. container::
+
+ "container" is a generic element, an extension mechanism for
+ users & applications.
+
+ Containers may contain arbitrary body elements.
+""",
+"""\
+<document source="test data">
+ <container>
+ <paragraph>
+ "container" is a generic element, an extension mechanism for
+ users & applications.
+ <paragraph>
+ Containers may contain arbitrary body elements.
+"""],
+["""\
+.. container:: custom
+
+ Some text.
+""",
+"""\
+<document source="test data">
+ <container classes="custom">
+ <paragraph>
+ Some text.
+"""],
+["""\
+.. container:: one two three
+ four
+
+ Multiple classes.
+
+ Multi-line argument.
+
+ Multiple paragraphs in the container.
+""",
+"""\
+<document source="test data">
+ <container classes="one two three four">
+ <paragraph>
+ Multiple classes.
+ <paragraph>
+ Multi-line argument.
+ <paragraph>
+ Multiple paragraphs in the container.
+"""],
+["""\
+.. container::
+ :name: my name
+
+ The name argument allows hyperlinks to `my name`_.
+""",
+"""\
+<document source="test data">
+ <container ids="my-name" names="my\\ name">
+ <paragraph>
+ The name argument allows hyperlinks to
+ <reference name="my name" refname="my name">
+ my name
+ .
+"""],
+]
+
+
+if __name__ == '__main__':
+ import unittest
+ unittest.main(defaultTest='suite')
--- /dev/null
+#! /usr/bin/env python
+
+# $Id: test_contents.py 8356 2019-08-26 16:44:19Z milde $
+# Author: David Goodger <goodger@python.org>
+# Copyright: This module has been placed in the public domain.
+
+"""
+Tests for parts.py contents directive.
+"""
+from __future__ import absolute_import
+
+from . import DocutilsTestSupport
+
+def suite():
+ s = DocutilsTestSupport.ParserTestSuite()
+ s.generateTests(totest)
+ return s
+
+totest = {}
+
+totest['contents'] = [
+["""\
+.. contents::
+""",
+"""\
+<document source="test data">
+ <topic classes="contents" ids="contents" names="contents">
+ <title>
+ Contents
+ <pending>
+ .. internal attributes:
+ .transform: docutils.transforms.parts.Contents
+ .details:
+"""],
+["""\
+.. contents:: Table of Contents
+""",
+"""\
+<document source="test data">
+ <topic classes="contents" ids="table-of-contents" names="table\\ of\\ contents">
+ <title>
+ Table of Contents
+ <pending>
+ .. internal attributes:
+ .transform: docutils.transforms.parts.Contents
+ .details:
+"""],
+["""\
+.. contents::
+ Table of Contents
+""",
+"""\
+<document source="test data">
+ <topic classes="contents" ids="table-of-contents" names="table\\ of\\ contents">
+ <title>
+ Table of Contents
+ <pending>
+ .. internal attributes:
+ .transform: docutils.transforms.parts.Contents
+ .details:
+"""],
+["""\
+.. contents:: Table
+ of
+ Contents
+""",
+"""\
+<document source="test data">
+ <topic classes="contents" ids="table-of-contents" names="table\\ of\\ contents">
+ <title>
+ Table
+ of
+ Contents
+ <pending>
+ .. internal attributes:
+ .transform: docutils.transforms.parts.Contents
+ .details:
+"""],
+["""\
+.. contents:: *Table* of ``Contents``
+""",
+"""\
+<document source="test data">
+ <topic classes="contents" ids="table-of-contents" names="table\\ of\\ contents">
+ <title>
+ <emphasis>
+ Table
+ of
+ <literal>
+ Contents
+ <pending>
+ .. internal attributes:
+ .transform: docutils.transforms.parts.Contents
+ .details:
+"""],
+["""\
+.. contents::
+ :depth: 2
+ :local:
+""",
+"""\
+<document source="test data">
+ <topic classes="contents local" ids="contents" names="contents">
+ <pending>
+ .. internal attributes:
+ .transform: docutils.transforms.parts.Contents
+ .details:
+ depth: 2
+ local: None
+"""],
+["""\
+.. contents::
+ :local: arg
+""",
+"""\
+<document source="test data">
+ <system_message level="3" line="1" source="test data" type="ERROR">
+ <paragraph>
+ Error in "contents" directive:
+ invalid option value: (option: "local"; value: 'arg')
+ no argument is allowed; "arg" supplied.
+ <literal_block xml:space="preserve">
+ .. contents::
+ :local: arg
+"""],
+["""\
+.. contents:: Table of Contents
+ :local:
+ :depth: 2
+ :backlinks: none
+""",
+"""\
+<document source="test data">
+ <topic classes="contents local" ids="table-of-contents" names="table\\ of\\ contents">
+ <title>
+ Table of Contents
+ <pending>
+ .. internal attributes:
+ .transform: docutils.transforms.parts.Contents
+ .details:
+ backlinks: None
+ depth: 2
+ local: None
+"""],
+["""\
+.. contents::
+ :depth: two
+""",
+"""\
+<document source="test data">
+ <system_message level="3" line="1" source="test data" type="ERROR">
+ <paragraph>
+ Error in "contents" directive:
+ invalid option value: (option: "depth"; value: 'two')
+ %s.
+ <literal_block xml:space="preserve">
+ .. contents::
+ :depth: two
+""" % DocutilsTestSupport.exception_data(int, "two")[1][0]],
+["""\
+.. contents::
+ :width: 2
+""",
+"""\
+<document source="test data">
+ <system_message level="3" line="1" source="test data" type="ERROR">
+ <paragraph>
+ Error in "contents" directive:
+ unknown option: "width".
+ <literal_block xml:space="preserve">
+ .. contents::
+ :width: 2
+"""],
+["""\
+.. contents::
+ :backlinks: no way!
+""",
+"""\
+<document source="test data">
+ <system_message level="3" line="1" source="test data" type="ERROR">
+ <paragraph>
+ Error in "contents" directive:
+ invalid option value: (option: "backlinks"; value: 'no way!')
+ "no way!" unknown; choose from "top", "entry", or "none".
+ <literal_block xml:space="preserve">
+ .. contents::
+ :backlinks: no way!
+"""],
+["""\
+.. contents::
+ :backlinks:
+""",
+"""\
+<document source="test data">
+ <system_message level="3" line="1" source="test data" type="ERROR">
+ <paragraph>
+ Error in "contents" directive:
+ invalid option value: (option: "backlinks"; value: None)
+ must supply an argument; choose from "top", "entry", or "none".
+ <literal_block xml:space="preserve">
+ .. contents::
+ :backlinks:
+"""],
+["""\
+* .. contents::
+""",
+"""\
+<document source="test data">
+ <bullet_list bullet="*">
+ <list_item>
+ <system_message level="3" line="1" source="test data" type="ERROR">
+ <paragraph>
+ The "contents" directive may not be used within topics or body elements.
+ <literal_block xml:space="preserve">
+ .. contents::
+"""],
+["""\
+.. sidebar:: containing contents
+
+ .. contents::
+""",
+"""\
+<document source="test data">
+ <sidebar>
+ <title>
+ containing contents
+ <topic classes="contents" ids="contents" names="contents">
+ <title>
+ Contents
+ <pending>
+ .. internal attributes:
+ .transform: docutils.transforms.parts.Contents
+ .details:
+"""],
+]
+
+
+if __name__ == '__main__':
+ import unittest
+ unittest.main(defaultTest='suite')
--- /dev/null
+#! /usr/bin/env python
+
+# $Id: test_date.py 8356 2019-08-26 16:44:19Z milde $
+# Author: David Goodger <goodger@python.org>
+# Copyright: This module has been placed in the public domain.
+
+"""
+Tests for the misc.py "date" directive.
+"""
+from __future__ import absolute_import
+
+from . import DocutilsTestSupport
+import time
+
+from docutils.utils.error_reporting import locale_encoding
+
+def suite():
+ s = DocutilsTestSupport.ParserTestSuite()
+ s.generateTests(totest)
+ return s
+
+totest = {}
+
+totest['date'] = [
+["""\
+.. |date| date::
+
+Today's date is |date|.
+""",
+"""\
+<document source="test data">
+ <substitution_definition names="date">
+ %s
+ <paragraph>
+ Today's date is \n\
+ <substitution_reference refname="date">
+ date
+ .
+""" % time.strftime('%Y-%m-%d')],
+["""\
+.. |date| date:: %a, %d %b %Y
+""",
+"""\
+<document source="test data">
+ <substitution_definition names="date">
+ %s
+""" % time.strftime('%a, %d %b %Y')],
+["""\
+.. date::
+""",
+"""\
+<document source="test data">
+ <system_message level="3" line="1" source="test data" type="ERROR">
+ <paragraph>
+ Invalid context: the "date" directive can only be used within a substitution definition.
+ <literal_block xml:space="preserve">
+ .. date::
+"""],
+]
+
+# some locales return non-ASCII characters for names of days or months
+if locale_encoding in ['utf8', 'utf-8', 'latin-1']:
+ totest['decode date'] = [
+ [u"""\
+.. |date| date:: t\xc3glich
+""",
+ u"""\
+<document source="test data">
+ <substitution_definition names="date">
+ t\xc3glich
+"""],
+ ]
+
+if __name__ == '__main__':
+ import unittest
+ unittest.main(defaultTest='suite')
--- /dev/null
+#! /usr/bin/env python
+
+# $Id: test_decorations.py 8356 2019-08-26 16:44:19Z milde $
+# Author: David Goodger <goodger@python.org>
+# Copyright: This module has been placed in the public domain.
+
+"""
+Tests for the "header" & "footer" directives.
+"""
+from __future__ import absolute_import
+
+from . import DocutilsTestSupport
+
+
+def suite():
+ s = DocutilsTestSupport.ParserTestSuite()
+ s.generateTests(totest)
+ return s
+
+totest = {}
+
+totest['headers'] = [
+["""\
+.. header:: a paragraph for the header
+""",
+"""\
+<document source="test data">
+ <decoration>
+ <header>
+ <paragraph>
+ a paragraph for the header
+"""],
+["""\
+.. header::
+""",
+"""\
+<document source="test data">
+ <system_message level="3" line="1" source="test data" type="ERROR">
+ <paragraph>
+ Content block expected for the "header" directive; none found.
+ <literal_block xml:space="preserve">
+ .. header::
+"""],
+["""\
+.. header:: first part of the header
+.. header:: second part of the header
+""",
+"""\
+<document source="test data">
+ <decoration>
+ <header>
+ <paragraph>
+ first part of the header
+ <paragraph>
+ second part of the header
+"""],
+]
+
+totest['footers'] = [
+["""\
+.. footer:: a paragraph for the footer
+""",
+"""\
+<document source="test data">
+ <decoration>
+ <footer>
+ <paragraph>
+ a paragraph for the footer
+"""],
+["""\
+.. footer:: even if a footer is declared first
+.. header:: the header appears first
+""",
+"""\
+<document source="test data">
+ <decoration>
+ <header>
+ <paragraph>
+ the header appears first
+ <footer>
+ <paragraph>
+ even if a footer is declared first
+"""],
+]
+
+
+if __name__ == '__main__':
+ import unittest
+ unittest.main(defaultTest='suite')
--- /dev/null
+#! /usr/bin/env python
+
+# $Id: test_default_role.py 8356 2019-08-26 16:44:19Z milde $
+# Author: David Goodger <goodger@python.org>
+# Copyright: This module has been placed in the public domain.
+
+"""
+Tests for misc.py "default-role" directive.
+"""
+from __future__ import absolute_import
+
+from . import DocutilsTestSupport
+
+
+def suite():
+ s = DocutilsTestSupport.ParserTestSuite()
+ s.generateTests(totest)
+ return s
+
+totest = {}
+
+totest['default-role'] = [
+["""\
+.. default-role:: subscript
+
+This is a `subscript`.
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ This is a \n\
+ <subscript>
+ subscript
+ .
+"""],
+["""\
+Must define a custom role before using it.
+
+.. default-role:: custom
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ Must define a custom role before using it.
+ <system_message level="1" line="3" source="test data" type="INFO">
+ <paragraph>
+ No role entry for "custom" in module "docutils.parsers.rst.languages.en".
+ Trying "custom" as canonical role name.
+ <system_message level="3" line="3" source="test data" type="ERROR">
+ <paragraph>
+ Unknown interpreted text role "custom".
+ <literal_block xml:space="preserve">
+ .. default-role:: custom
+"""],
+["""\
+.. role:: custom
+.. default-role:: custom
+
+This text uses the `default role`.
+
+.. default-role::
+
+Returned the `default role` to its standard default.
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ This text uses the \n\
+ <inline classes="custom">
+ default role
+ .
+ <paragraph>
+ Returned the \n\
+ <title_reference>
+ default role
+ to its standard default.
+"""],
+]
+
+
+if __name__ == '__main__':
+ import unittest
+ unittest.main(defaultTest='suite')
--- /dev/null
+#! /usr/bin/env python
+
+# $Id: test_figures.py 8356 2019-08-26 16:44:19Z milde $
+# Author: David Goodger <goodger@python.org>
+# Copyright: This module has been placed in the public domain.
+
+"""
+Tests for images.py figure directives.
+"""
+from __future__ import absolute_import
+
+from . import DocutilsTestSupport
+
+
+def suite():
+ s = DocutilsTestSupport.ParserTestSuite()
+ s.generateTests(totest)
+ return s
+
+totest = {}
+
+totest['figures'] = [
+["""\
+.. figure:: picture.png
+""",
+"""\
+<document source="test data">
+ <figure>
+ <image uri="picture.png">
+"""],
+["""\
+.. figure:: picture.png
+
+ A picture with a caption.
+""",
+"""\
+<document source="test data">
+ <figure>
+ <image uri="picture.png">
+ <caption>
+ A picture with a caption.
+"""],
+["""\
+.. figure:: picture.png
+
+ - A picture with an invalid caption.
+""",
+"""\
+<document source="test data">
+ <figure>
+ <image uri="picture.png">
+ <system_message level="3" line="1" source="test data" type="ERROR">
+ <paragraph>
+ Figure caption must be a paragraph or empty comment.
+ <literal_block xml:space="preserve">
+ .. figure:: picture.png
+ \n\
+ - A picture with an invalid caption.
+"""],
+["""\
+.. figure:: picture.png
+
+ ..
+
+ A picture with a legend but no caption.
+""",
+"""\
+<document source="test data">
+ <figure>
+ <image uri="picture.png">
+ <legend>
+ <paragraph>
+ A picture with a legend but no caption.
+"""],
+["""\
+.. Figure:: picture.png
+ :height: 100
+ :width: 200
+ :scale: 50
+
+ A picture with image options and a caption.
+""",
+"""\
+<document source="test data">
+ <figure>
+ <image height="100" scale="50" uri="picture.png" width="200">
+ <caption>
+ A picture with image options and a caption.
+"""],
+["""\
+.. Figure:: picture.png
+ :height: 100
+ :alt: alternate text
+ :width: 200
+ :scale: 50
+ :figwidth: 300
+ :figclass: class1 class2
+ :name: fig:pix
+
+ A picture with image options on individual lines, and this caption.
+""",
+"""\
+<document source="test data">
+ <figure classes="class1 class2" width="300px">
+ <image alt="alternate text" height="100" ids="fig-pix" names="fig:pix" scale="50" uri="picture.png" width="200">
+ <caption>
+ A picture with image options on individual lines, and this caption.
+"""],
+["""\
+.. figure:: picture.png
+ :align: center
+
+ A figure with explicit alignment.
+""",
+"""\
+<document source="test data">
+ <figure align="center">
+ <image uri="picture.png">
+ <caption>
+ A figure with explicit alignment.
+"""],
+["""\
+.. figure:: picture.png
+ :align: top
+
+ A figure with wrong alignment.
+""",
+"""\
+<document source="test data">
+ <system_message level="3" line="1" source="test data" type="ERROR">
+ <paragraph>
+ Error in "figure" directive:
+ invalid option value: (option: "align"; value: 'top')
+ "top" unknown; choose from "left", "center", or "right".
+ <literal_block xml:space="preserve">
+ .. figure:: picture.png
+ :align: top
+
+ A figure with wrong alignment.
+"""],
+["""\
+This figure lacks a caption. It may still have a
+"Figure 1."-style caption appended in the output.
+
+.. figure:: picture.png
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ This figure lacks a caption. It may still have a
+ "Figure 1."-style caption appended in the output.
+ <figure>
+ <image uri="picture.png">
+"""],
+["""\
+.. figure:: picture.png
+
+ A picture with a caption and a legend.
+
+ +-----------------------+-----------------------+
+ | Symbol | Meaning |
+ +=======================+=======================+
+ | .. image:: tent.png | Campground |
+ +-----------------------+-----------------------+
+ | .. image:: waves.png | Lake |
+ +-----------------------+-----------------------+
+ | .. image:: peak.png | Mountain |
+ +-----------------------+-----------------------+
+""",
+"""\
+<document source="test data">
+ <figure>
+ <image uri="picture.png">
+ <caption>
+ A picture with a caption and a legend.
+ <legend>
+ <table>
+ <tgroup cols="2">
+ <colspec colwidth="23">
+ <colspec colwidth="23">
+ <thead>
+ <row>
+ <entry>
+ <paragraph>
+ Symbol
+ <entry>
+ <paragraph>
+ Meaning
+ <tbody>
+ <row>
+ <entry>
+ <image uri="tent.png">
+ <entry>
+ <paragraph>
+ Campground
+ <row>
+ <entry>
+ <image uri="waves.png">
+ <entry>
+ <paragraph>
+ Lake
+ <row>
+ <entry>
+ <image uri="peak.png">
+ <entry>
+ <paragraph>
+ Mountain
+"""],
+["""\
+.. figure:: picture.png
+
+ ..
+
+ A picture with a legend but no caption.
+ (The empty comment replaces the caption, which must
+ be a single paragraph.)
+""",
+"""\
+<document source="test data">
+ <figure>
+ <image uri="picture.png">
+ <legend>
+ <paragraph>
+ A picture with a legend but no caption.
+ (The empty comment replaces the caption, which must
+ be a single paragraph.)
+"""],
+["""\
+Testing for line-leaks:
+
+.. figure:: picture.png
+
+ A picture with a caption.
+.. figure:: picture.png
+
+ A picture with a caption.
+.. figure:: picture.png
+
+ A picture with a caption.
+.. figure:: picture.png
+.. figure:: picture.png
+.. figure:: picture.png
+.. figure:: picture.png
+
+ A picture with a caption.
+
+.. figure:: picture.png
+
+.. figure:: picture.png
+
+ A picture with a caption.
+
+.. figure:: picture.png
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ Testing for line-leaks:
+ <figure>
+ <image uri="picture.png">
+ <caption>
+ A picture with a caption.
+ <figure>
+ <image uri="picture.png">
+ <caption>
+ A picture with a caption.
+ <figure>
+ <image uri="picture.png">
+ <caption>
+ A picture with a caption.
+ <figure>
+ <image uri="picture.png">
+ <figure>
+ <image uri="picture.png">
+ <figure>
+ <image uri="picture.png">
+ <figure>
+ <image uri="picture.png">
+ <caption>
+ A picture with a caption.
+ <figure>
+ <image uri="picture.png">
+ <figure>
+ <image uri="picture.png">
+ <caption>
+ A picture with a caption.
+ <figure>
+ <image uri="picture.png">
+"""],
+]
+
+
+if __name__ == '__main__':
+ import unittest
+ unittest.main(defaultTest='suite')
--- /dev/null
+#! /usr/bin/env python
+
+# $Id: test_images.py 8356 2019-08-26 16:44:19Z milde $
+# Author: David Goodger <goodger@python.org>
+# Copyright: This module has been placed in the public domain.
+
+"""
+Tests for images.py image directives.
+"""
+from __future__ import absolute_import
+
+from . import DocutilsTestSupport
+
+from docutils.nodes import reprunicode
+
+
+def suite():
+ s = DocutilsTestSupport.ParserTestSuite()
+ s.generateTests(totest)
+ return s
+
+totest = {}
+
+totest['images'] = [
+["""\
+.. image:: picture.png
+""",
+"""\
+<document source="test data">
+ <image uri="picture.png">
+"""],
+["""\
+.. image::
+""",
+"""\
+<document source="test data">
+ <system_message level="3" line="1" source="test data" type="ERROR">
+ <paragraph>
+ Error in "image" directive:
+ 1 argument(s) required, 0 supplied.
+ <literal_block xml:space="preserve">
+ .. image::
+"""],
+["""\
+.. image:: one two three.png
+""",
+"""\
+<document source="test data">
+ <image uri="onetwothree.png">
+"""],
+["""\
+.. image:: picture.png
+ :height: 100
+ :width: 200
+ :scale: 50
+""",
+"""\
+<document source="test data">
+ <image height="100" scale="50" uri="picture.png" width="200">
+"""],
+["""\
+.. image::
+ picture.png
+ :height: 100
+ :width: 200
+ :scale: 50
+""",
+"""\
+<document source="test data">
+ <image height="100" scale="50" uri="picture.png" width="200">
+"""],
+["""\
+.. image::
+ :height: 100
+ :width: 200
+ :scale: 50
+""",
+"""\
+<document source="test data">
+ <system_message level="3" line="1" source="test data" type="ERROR">
+ <paragraph>
+ Error in "image" directive:
+ 1 argument(s) required, 0 supplied.
+ <literal_block xml:space="preserve">
+ .. image::
+ :height: 100
+ :width: 200
+ :scale: 50
+"""],
+# If there are multiple lines in the link block, they are stripped of
+# leading and trailing whitespace and joined together:
+["""\
+.. image:: a/very/long/path/to/
+ picture.png
+ :height: 100
+ :width: 200
+ :scale: 50
+""",
+"""\
+<document source="test data">
+ <image height="100" scale="50" uri="a/very/long/path/to/picture.png" width="200">
+"""],
+# The following two misspellings were detected in Docutils <= 0.8
+# (the option block was started by any line starting with a colon
+# which led to problems with named roles in other directives):
+["""\
+.. image:: picture.png
+ :scale 50
+""",
+"""\
+<document source="test data">
+ <image uri="picture.png:scale50">
+"""],
+["""\
+.. image:: picture.png
+ :: 50
+""",
+"""\
+<document source="test data">
+ <image uri="picture.png::50">
+"""],
+# a missing leading colon went undetected also in Docutils <= 0.8:
+["""\
+.. image:: picture.png
+ scale: 50
+""",
+"""\
+<document source="test data">
+ <image uri="picture.pngscale:50">
+"""],
+["""\
+.. image:: picture.png
+ :width: 200px
+ :height: 100 em
+""",
+"""\
+<document source="test data">
+ <image height="100em" uri="picture.png" width="200px">
+"""],
+["""\
+.. image:: picture.png
+ :width: 50%
+ :height: 10mm
+""",
+"""\
+<document source="test data">
+ <image height="10mm" uri="picture.png" width="50%">
+"""],
+["""\
+.. image:: picture.png
+ :width: 50%
+ :height: 40%
+""",
+"""\
+<document source="test data">
+ <system_message level="3" line="1" source="test data" type="ERROR">
+ <paragraph>
+ Error in "image" directive:
+ invalid option value: (option: "height"; value: \'40%\')
+ not a positive measure of one of the following units:
+ "em" "ex" "px" "in" "cm" "mm" "pt" "pc" "".
+ <literal_block xml:space="preserve">
+ .. image:: picture.png
+ :width: 50%
+ :height: 40%
+"""],
+["""\
+.. image:: picture.png
+ :width: 20mc
+""",
+"""\
+<document source="test data">
+ <system_message level="3" line="1" source="test data" type="ERROR">
+ <paragraph>
+ Error in "image" directive:
+ invalid option value: (option: "width"; value: \'20mc\')
+ not a positive measure of one of the following units:
+ "em" "ex" "px" "in" "cm" "mm" "pt" "pc" "%".
+ <literal_block xml:space="preserve">
+ .. image:: picture.png
+ :width: 20mc
+"""],
+["""\
+.. image:: picture.png
+ :height: 100
+ :width: 200
+ :scale: 50
+ :alt: Alternate text for the picture
+""",
+"""\
+<document source="test data">
+ <image alt="Alternate text for the picture" height="100" scale="50" uri="picture.png" width="200">
+"""],
+["""\
+.. image:: picture.png
+ :scale: -50
+""",
+"""\
+<document source="test data">
+ <system_message level="3" line="1" source="test data" type="ERROR">
+ <paragraph>
+ Error in "image" directive:
+ invalid option value: (option: "scale"; value: '-50')
+ negative value; must be positive or zero.
+ <literal_block xml:space="preserve">
+ .. image:: picture.png
+ :scale: -50
+"""],
+["""\
+.. image:: picture.png
+ :scale:
+""",
+"""\
+<document source="test data">
+ <system_message level="3" line="1" source="test data" type="ERROR">
+ <paragraph>
+ Error in "image" directive:
+ invalid option value: (option: "scale"; value: None)
+ %s.
+ <literal_block xml:space="preserve">
+ .. image:: picture.png
+ :scale:
+""" % DocutilsTestSupport.exception_data(int, None)[1][0]],
+["""\
+.. image:: picture.png
+ :height: 100
+ :scale 50
+""",
+"""\
+<document source="test data">
+ <system_message level="3" line="1" source="test data" type="ERROR">
+ <paragraph>
+ Error in "image" directive:
+ invalid option block.
+ <literal_block xml:space="preserve">
+ .. image:: picture.png
+ :height: 100
+ :scale 50
+"""],
+["""\
+.. image:: picture.png
+ :sale: 50
+""",
+"""\
+<document source="test data">
+ <system_message level="3" line="1" source="test data" type="ERROR">
+ <paragraph>
+ Error in "image" directive:
+ unknown option: "sale".
+ <literal_block xml:space="preserve">
+ .. image:: picture.png
+ :sale: 50
+"""],
+["""\
+.. image:: picture.png
+ :scale is: 50
+""",
+"""\
+<document source="test data">
+ <system_message level="3" line="1" source="test data" type="ERROR">
+ <paragraph>
+ Error in "image" directive:
+ invalid option data: extension option field name may not contain multiple words.
+ <literal_block xml:space="preserve">
+ .. image:: picture.png
+ :scale is: 50
+"""],
+["""\
+.. image:: picture.png
+ :scale: fifty
+""",
+"""\
+<document source="test data">
+ <system_message level="3" line="1" source="test data" type="ERROR">
+ <paragraph>
+ Error in "image" directive:
+ invalid option value: (option: "scale"; value: 'fifty')
+ %s.
+ <literal_block xml:space="preserve">
+ .. image:: picture.png
+ :scale: fifty
+""" % DocutilsTestSupport.exception_data(int, u"fifty")[1][0]],
+["""\
+.. image:: picture.png
+ :scale: 50
+ :scale: 50
+""",
+"""\
+<document source="test data">
+ <system_message level="3" line="1" source="test data" type="ERROR">
+ <paragraph>
+ Error in "image" directive:
+ invalid option data: duplicate option "scale".
+ <literal_block xml:space="preserve">
+ .. image:: picture.png
+ :scale: 50
+ :scale: 50
+"""],
+["""\
+.. image:: picture.png
+ :alt:
+
+(Empty "alt" option.)
+""",
+"""\
+<document source="test data">
+ <image alt="" uri="picture.png">
+ <paragraph>
+ (Empty "alt" option.)
+"""],
+["""\
+.. image:: picture.png
+ :target: bigpicture.png
+ :name: fig:pix
+""",
+"""\
+<document source="test data">
+ <reference refuri="bigpicture.png">
+ <image ids="fig-pix" names="fig:pix" uri="picture.png">
+"""],
+["""\
+.. image:: picture.png
+ :target: indirect_
+""",
+"""\
+<document source="test data">
+ <reference name="indirect" refname="indirect">
+ <image uri="picture.png">
+"""],
+["""\
+.. image:: picture.png
+ :target: a/multi/
+ line/uri
+
+.. image:: picture.png
+ :target: `a multi line
+ internal reference`_
+""",
+"""\
+<document source="test data">
+ <reference refuri="a/multi/line/uri">
+ <image uri="picture.png">
+ <reference name="a multi line internal reference" refname="a multi line internal reference">
+ <image uri="picture.png">
+"""],
+["""\
+.. image:: picture.png
+ :target:
+""",
+"""\
+<document source="test data">
+ <system_message level="3" line="1" source="test data" type="ERROR">
+ <paragraph>
+ Error in "image" directive:
+ invalid option value: (option: "target"; value: None)
+ argument required but none supplied.
+ <literal_block xml:space="preserve">
+ .. image:: picture.png
+ :target:
+"""],
+["""\
+.. image:: picture.png
+ :align: left
+""",
+"""\
+<document source="test data">
+ <image align="left" uri="picture.png">
+"""],
+["""\
+.. image:: picture.png
+ :align: top
+""",
+"""\
+<document source="test data">
+ <system_message level="3" line="1" source="test data" type="ERROR">
+ <paragraph>
+ Error in "image" directive: "top" is not a valid value for the "align" option. Valid values for "align" are: "left", "center", "right".
+ <literal_block xml:space="preserve">
+ .. image:: picture.png
+ :align: top
+"""],
+["""\
+.. |img| image:: picture.png
+ :align: top
+""",
+"""\
+<document source="test data">
+ <substitution_definition names="img">
+ <image align="top" alt="img" uri="picture.png">
+"""],
+["""\
+.. |img| image:: picture.png
+ :align: left
+""",
+"""\
+<document source="test data">
+ <system_message level="3" line="1" source="test data" type="ERROR">
+ <paragraph>
+ Error in "image" directive: "left" is not a valid value for the "align" option within a substitution definition. Valid values for "align" are: "top", "middle", "bottom".
+ <literal_block xml:space="preserve">
+ image:: picture.png
+ :align: left
+ <system_message level="2" line="1" source="test data" type="WARNING">
+ <paragraph>
+ Substitution definition "img" empty or invalid.
+ <literal_block xml:space="preserve">
+ .. |img| image:: picture.png
+ :align: left
+"""],
+[u"""\
+.. image:: picture.png
+ :align: \xe4
+""",
+u"""\
+<document source="test data">
+ <system_message level="3" line="1" source="test data" type="ERROR">
+ <paragraph>
+ Error in "image" directive:
+ invalid option value: (option: "align"; value: %s)
+ "\xe4" unknown; choose from "top", "middle", "bottom", "left", "center", or "right".
+ <literal_block xml:space="preserve">
+ .. image:: picture.png
+ :align: \xe4
+""" % repr(reprunicode(u'\xe4'))],
+["""
+.. image:: test.png
+ :target: Uppercase_
+
+.. _Uppercase: http://docutils.sourceforge.net/
+""",
+"""\
+<document source="test data">
+ <reference name="Uppercase" refname="uppercase">
+ <image uri="test.png">
+ <target ids="uppercase" names="uppercase" refuri="http://docutils.sourceforge.net/">
+"""],
+[r"""
+.. image:: path\ with\ spaces/name\ with\ spaces.png
+ :target: path\ with\ spaces/
+ target\ with\ spaces\ across\ lines.html
+""",
+"""\
+<document source="test data">
+ <reference refuri="path with spaces/target with spaces across lines.html">
+ <image uri="path with spaces/name with spaces.png">
+"""],
+]
+
+
+if __name__ == '__main__':
+ import unittest
+ unittest.main(defaultTest='suite')
--- /dev/null
+#! /usr/bin/env python
+
+# $Id: test_include.py 8367 2019-08-27 12:09:56Z milde $
+# Author: David Goodger <goodger@python.org>
+# Copyright: This module has been placed in the public domain.
+
+"""
+Tests for misc.py "include" directive.
+"""
+from __future__ import absolute_import
+
+import os.path
+import sys
+from . import DocutilsTestSupport
+from docutils.parsers.rst import states
+from docutils.utils.code_analyzer import with_pygments
+
+
+if sys.version_info >= (3, 0):
+ unichr = chr # noqa
+
+
+def suite():
+ s = DocutilsTestSupport.ParserTestSuite()
+ if not with_pygments:
+ del(totest['include-code'])
+ s.generateTests(totest)
+ return s
+
+# prepend this directory (relative to the test root):
+def mydir(path):
+ return os.path.join('test_parsers/test_rst/test_directives/', path)
+# make `path` relative with utils.relative_path():
+def reldir(path):
+ return DocutilsTestSupport.utils.relative_path(None, path)
+
+include1 = mydir('include1.txt')
+include2 = mydir('include2.txt')
+include3 = mydir('include3.txt')
+include6 = mydir('includes/more/include6.txt')
+include8 = mydir('include8.txt')
+include10 = mydir('include10.txt')
+include11 = mydir('include 11.txt')
+include12 = mydir('include12.txt')
+include13 = mydir('include13.txt')
+include14 = mydir('includes/include14.txt')
+include_literal = mydir('include_literal.txt')
+utf_16_file = mydir('utf-16.csv')
+utf_16_error_str = ("UnicodeDecodeError: 'ascii' codec can't decode byte 0xfe "
+ "in position 0: ordinal not in range(128)")
+if sys.version_info < (3, 0):
+ utf_16_error_str = ("UnicodeError: Unable to decode input data. "
+ "Tried the following encodings: 'ascii'.\n"
+ " (%s)" % utf_16_error_str)
+nonexistent = os.path.join(os.path.dirname(states.__file__),
+ 'include', 'nonexistent')
+nonexistent_rel = DocutilsTestSupport.utils.relative_path(
+ os.path.join(DocutilsTestSupport.testroot, 'dummy'), nonexistent)
+
+# Different error for path with 8bit chars with locale == C or None:
+try:
+ open(u'\u043c\u0438\u0440.txt')
+except UnicodeEncodeError:
+ errstr_8bit_path = u"""\
+Cannot encode input file path "\u043c\u0438\u0440.txt" (wrong locale?).\
+"""
+except:
+ errstr_8bit_path = u"""\
+InputError: [Errno 2] No such file or directory: '\u043c\u0438\u0440.txt'.\
+"""
+
+totest = {}
+
+totest['include'] = [
+["""\
+Include Test
+============
+
+.. include:: %s
+
+A paragraph.
+""" % include1,
+"""\
+<document source="test data">
+ <section ids="include-test" names="include\\ test">
+ <title>
+ Include Test
+ <section ids="inclusion-1" names="inclusion\\ 1">
+ <title>
+ Inclusion 1
+ <paragraph>
+ This file is used by \n\
+ <literal>
+ test_include.py
+ .
+ <paragraph>
+ A paragraph.
+"""],
+["""\
+Include Test
+============
+
+.. include:: %s
+ :literal:
+ :class: test
+ :name: my name
+
+A paragraph.
+""" % include1,
+"""\
+<document source="test data">
+ <section ids="include-test" names="include\\ test">
+ <title>
+ Include Test
+ <literal_block classes="test" ids="my-name" names="my\\ name" source="%s" xml:space="preserve">
+ Inclusion 1
+ -----------
+ \n\
+ This file is used by ``test_include.py``.
+ <paragraph>
+ A paragraph.
+""" % reldir(include1)],
+["""\
+Literal include, add line numbers
+
+.. include:: %s
+ :literal:
+ :number-lines:
+""" % include1,
+"""\
+<document source="test data">
+ <paragraph>
+ Literal include, add line numbers
+ <literal_block source="%s" xml:space="preserve">
+ <inline classes="ln">
+ 1 \n\
+ Inclusion 1
+ <inline classes="ln">
+ 2 \n\
+ -----------
+ <inline classes="ln">
+ 3 \n\
+ \n\
+ <inline classes="ln">
+ 4 \n\
+ This file is used by ``test_include.py``.
+""" % reldir(include1)],
+["""\
+Include code
+
+.. include:: %s
+ :code:
+ :class: test
+ :name: my name
+""" % include1,
+"""\
+<document source="test data">
+ <paragraph>
+ Include code
+ <literal_block classes="code test" ids="my-name" names="my\\ name" source="%s" xml:space="preserve">
+ Inclusion 1
+ -----------
+ \n\
+ This file is used by ``test_include.py``.
+""" % reldir(include1)],
+["""\
+Include code, add line numbers
+
+.. include:: %s
+ :code:
+ :number-lines:
+""" % include1,
+"""\
+<document source="test data">
+ <paragraph>
+ Include code, add line numbers
+ <literal_block classes="code" source="%s" xml:space="preserve">
+ <inline classes="ln">
+ 1 \n\
+ Inclusion 1
+ <inline classes="ln">
+ 2 \n\
+ -----------
+ <inline classes="ln">
+ 3 \n\
+ \n\
+ <inline classes="ln">
+ 4 \n\
+ This file is used by ``test_include.py``.
+""" % reldir(include1)],
+["""\
+Let's test the parse context.
+
+ This paragraph is in a block quote.
+
+ .. include:: %s
+
+The included paragraphs should also be in the block quote.
+""" % include2,
+"""\
+<document source="test data">
+ <paragraph>
+ Let's test the parse context.
+ <block_quote>
+ <paragraph>
+ This paragraph is in a block quote.
+ <paragraph>
+ Here are some paragraphs
+ that can appear at any level.
+ <paragraph>
+ This file (include2.txt) is used by
+ <literal>
+ test_include.py
+ .
+ <paragraph>
+ The included paragraphs should also be in the block quote.
+"""],
+["""\
+Include Test
+============
+
+.. include:: nonexistent.txt
+
+A paragraph.
+""",
+"""\
+<document source="test data">
+ <section ids="include-test" names="include\\ test">
+ <title>
+ Include Test
+ <system_message level="4" line="4" source="test data" type="SEVERE">
+ <paragraph>
+ Problems with "include" directive path:
+ InputError: [Errno 2] No such file or directory: 'nonexistent.txt'.
+ <literal_block xml:space="preserve">
+ .. include:: nonexistent.txt
+ <paragraph>
+ A paragraph.
+"""],
+["""\
+Include Test
+============
+
+.. include:: %s
+
+.. include:: %s
+
+A paragraph.
+""" % (include1, include1),
+"""\
+<document source="test data">
+ <section ids="include-test" names="include\\ test">
+ <title>
+ Include Test
+ <section dupnames="inclusion\\ 1" ids="inclusion-1">
+ <title>
+ Inclusion 1
+ <paragraph>
+ This file is used by
+ <literal>
+ test_include.py
+ .
+ <section dupnames="inclusion\\ 1" ids="id1">
+ <title>
+ Inclusion 1
+ <system_message backrefs="id1" level="1" line="2" source="%s" type="INFO">
+ <paragraph>
+ Duplicate implicit target name: "inclusion 1".
+ <paragraph>
+ This file is used by
+ <literal>
+ test_include.py
+ .
+ <paragraph>
+ A paragraph.
+""" % reldir(include1)],
+["""\
+Include Test
+============
+
+.. include:: %s
+
+----------
+
+.. include:: %s
+
+A paragraph.
+""" % (include1, include1),
+"""\
+<document source="test data">
+ <section ids="include-test" names="include\\ test">
+ <title>
+ Include Test
+ <section dupnames="inclusion\\ 1" ids="inclusion-1">
+ <title>
+ Inclusion 1
+ <paragraph>
+ This file is used by \n\
+ <literal>
+ test_include.py
+ .
+ <transition>
+ <section dupnames="inclusion\\ 1" ids="id1">
+ <title>
+ Inclusion 1
+ <system_message backrefs="id1" level="1" line="2" source="%s" type="INFO">
+ <paragraph>
+ Duplicate implicit target name: "inclusion 1".
+ <paragraph>
+ This file is used by \n\
+ <literal>
+ test_include.py
+ .
+ <paragraph>
+ A paragraph.
+""" % reldir(include1)],
+["""\
+Recursive inclusions: adapt paths.
+
+In test data
+
+.. include:: %s
+""" % include3,
+"""\
+<document source="test data">
+ <paragraph>
+ Recursive inclusions: adapt paths.
+ <paragraph>
+ In test data
+ <paragraph>
+ In include3.txt
+ <paragraph>
+ In includes/include4.txt
+ <paragraph>
+ In includes/include5.txt
+ <paragraph>
+ In includes/more/include6.txt
+ <paragraph>
+ In includes/sibling/include7.txt
+ <literal_block source="test_parsers/test_rst/test_directives/includes/include5.txt" xml:space="preserve">
+ In includes/include5.txt
+
+ .. include:: more/include6.txt
+ <table>
+ <tgroup cols="2">
+ <colspec colwidth="50">
+ <colspec colwidth="50">
+ <tbody>
+ <row>
+ <entry>
+ <paragraph>
+ In
+ <entry>
+ <paragraph>
+ includes/sibling/include7.txt
+"""],
+["""\
+In test data
+
+Section
+=======
+
+(Section contents in nested parse; slice of input_lines ViewList.)
+
+.. include:: %s
+""" % include3,
+"""\
+<document source="test data">
+ <paragraph>
+ In test data
+ <section ids="section" names="section">
+ <title>
+ Section
+ <paragraph>
+ (Section contents in nested parse; slice of input_lines ViewList.)
+ <paragraph>
+ In include3.txt
+ <paragraph>
+ In includes/include4.txt
+ <paragraph>
+ In includes/include5.txt
+ <paragraph>
+ In includes/more/include6.txt
+ <paragraph>
+ In includes/sibling/include7.txt
+ <literal_block source="test_parsers/test_rst/test_directives/includes/include5.txt" xml:space="preserve">
+ In includes/include5.txt
+
+ .. include:: more/include6.txt
+ <table>
+ <tgroup cols="2">
+ <colspec colwidth="50">
+ <colspec colwidth="50">
+ <tbody>
+ <row>
+ <entry>
+ <paragraph>
+ In
+ <entry>
+ <paragraph>
+ includes/sibling/include7.txt
+"""],
+["""\
+Testing relative includes:
+
+.. include:: %s
+""" % include8,
+"""\
+<document source="test data">
+ <paragraph>
+ Testing relative includes:
+ <paragraph>
+ In include8.txt
+ <paragraph>
+ In ../includes/include9.txt.
+ <paragraph>
+ Here are some paragraphs
+ that can appear at any level.
+ <paragraph>
+ This file (include2.txt) is used by
+ <literal>
+ test_include.py
+ .
+"""],
+["""\
+Encoding:
+
+.. include:: %s
+ :encoding: utf-16
+""" % reldir(utf_16_file),
+b"""\
+<document source="test data">
+ <paragraph>
+ Encoding:
+ <paragraph>
+ "Treat", "Quantity", "Description"
+ "Albatr\xb0\xdf", 2.99, "\xa1On a \\u03c3\\u03c4\\u03b9\\u03ba!"
+ "Crunchy Frog", 1.49, "If we took the b\xf6nes out, it wouldn\\u2019t be
+ crunchy, now would it?"
+ "Gannet Ripple", 1.99, "\xbfOn a \\u03c3\\u03c4\\u03b9\\u03ba?"
+""".decode('raw_unicode_escape')],
+["""\
+Include file is UTF-16-encoded, and is not valid ASCII.
+
+.. include:: %s
+ :encoding: ascii
+""" % reldir(utf_16_file),
+"""\
+<document source="test data">
+ <paragraph>
+ Include file is UTF-16-encoded, and is not valid ASCII.
+ <system_message level="4" line="3" source="test data" type="SEVERE">
+ <paragraph>
+ Problem with "include" directive:
+ %s
+ <literal_block xml:space="preserve">
+ .. include:: %s
+ :encoding: ascii
+""" % (utf_16_error_str, reldir(utf_16_file))],
+[u"""\
+cyrillic filename:
+
+.. include:: \u043c\u0438\u0440.txt
+""",
+u"""\
+<document source="test data">
+ <paragraph>
+ cyrillic filename:
+ <system_message level="4" line="3" source="test data" type="SEVERE">
+ <paragraph>
+ Problems with "include" directive path:
+ %s
+ <literal_block xml:space="preserve">
+ .. include:: \u043c\u0438\u0440.txt
+""" % errstr_8bit_path],
+["""\
+Testing errors in included file:
+
+.. include:: %s
+""" % include10,
+"""\
+<document source="test data">
+ <paragraph>
+ Testing errors in included file:
+ <system_message level="3" line="1" source="%(source)s" type="ERROR">
+ <paragraph>
+ Invalid character code: 0x11111111
+ %(unichr_exception)s
+ <literal_block xml:space="preserve">
+ unicode:: 0x11111111
+ <system_message level="2" line="1" source="%(source)s" type="WARNING">
+ <paragraph>
+ Substitution definition "bad" empty or invalid.
+ <literal_block xml:space="preserve">
+ .. |bad| unicode:: 0x11111111
+ <section dupnames="hi" ids="hi">
+ <title>
+ hi
+ <block_quote>
+ <paragraph>
+ indent
+ <system_message level="2" line="7" source="%(source)s" type="WARNING">
+ <paragraph>
+ Block quote ends without a blank line; unexpected unindent.
+ <paragraph>
+ error
+ <section dupnames="hi" ids="id1">
+ <title>
+ hi
+ <system_message backrefs="id1" level="1" line="10" source="%(source)s" type="INFO">
+ <paragraph>
+ Duplicate implicit target name: "hi".
+ <system_message level="4" line="12" source="%(source)s" type="SEVERE">
+ <paragraph>
+ Problems with "include" directive path:
+ InputError: [Errno 2] No such file or directory: '%(nonexistent)s'.
+ <literal_block xml:space="preserve">
+ .. include:: <nonexistent>
+ <system_message level="3" line="14" source="%(source)s" type="ERROR">
+ <paragraph>
+ Content block expected for the "note" directive; none found.
+ <literal_block xml:space="preserve">
+ .. note::
+ <system_message level="3" line="16" source="%(source)s" type="ERROR">
+ <paragraph>
+ Content block expected for the "admonition" directive; none found.
+ <literal_block xml:space="preserve">
+ .. admonition::
+ without title
+ <system_message level="3" line="19" source="%(source)s" type="ERROR">
+ <paragraph>
+ Content block expected for the "epigraph" directive; none found.
+ <literal_block xml:space="preserve">
+ .. epigraph::
+ <system_message level="3" line="21" source="%(source)s" type="ERROR">
+ <paragraph>
+ Content block expected for the "highlights" directive; none found.
+ <literal_block xml:space="preserve">
+ .. highlights::
+ <system_message level="3" line="23" source="%(source)s" type="ERROR">
+ <paragraph>
+ Content block expected for the "pull-quote" directive; none found.
+ <literal_block xml:space="preserve">
+ .. pull-quote::
+ <system_message level="3" line="25" source="%(source)s" type="ERROR">
+ <paragraph>
+ Invalid context: the "date" directive can only be used within a substitution definition.
+ <literal_block xml:space="preserve">
+ .. date::
+ <paragraph>
+ not a
+ definition list:
+ <system_message level="3" line="29" source="%(source)s" type="ERROR">
+ <paragraph>
+ Unexpected indentation.
+ <block_quote>
+ <paragraph>
+ as a term may only be one line long.
+ <system_message level="3" line="31" source="%(source)s" type="ERROR">
+ <paragraph>
+ Error in "admonition" directive:
+ 1 argument(s) required, 0 supplied.
+ <literal_block xml:space="preserve">
+ .. admonition::
+
+ without title and content following a blank line
+ <section ids="section-underline-too-short" names="section\\ underline\\ too\\ short">
+ <title>
+ section underline too short
+ <system_message level="2" line="36" source="%(source)s" type="WARNING">
+ <paragraph>
+ Title underline too short.
+ <literal_block xml:space="preserve">
+ section underline too short
+ -----
+ <table>
+ <tgroup cols="2">
+ <colspec colwidth="14">
+ <colspec colwidth="6">
+ <thead>
+ <row>
+ <entry>
+ <paragraph>
+ A simple table
+ <entry>
+ <paragraph>
+ cell 2
+ <tbody>
+ <row>
+ <entry>
+ <paragraph>
+ cell 3
+ <entry>
+ <paragraph>
+ cell 4
+ <system_message level="2" line="43" source="%(source)s" type="WARNING">
+ <paragraph>
+ Blank line required after table.
+ <paragraph>
+ No blank line after table.
+ <system_message level="3" line="45" source="%(source)s" type="ERROR">
+ <paragraph>
+ Error in "unicode" directive:
+ 1 argument(s) required, 0 supplied.
+ <literal_block xml:space="preserve">
+ unicode::
+ <system_message level="2" line="45" source="%(source)s" type="WARNING">
+ <paragraph>
+ Substitution definition "empty" empty or invalid.
+ <literal_block xml:space="preserve">
+ .. |empty| unicode::
+ <system_message level="3" line="47" source="%(source)s" type="ERROR">
+ <paragraph>
+ Error in "topic" directive:
+ 1 argument(s) required, 0 supplied.
+ <literal_block xml:space="preserve">
+ .. topic::
+ <system_message level="3" line="49" source="%(source)s" type="ERROR">
+ <paragraph>
+ Error in "rubric" directive:
+ 1 argument(s) required, 0 supplied.
+ <literal_block xml:space="preserve">
+ .. rubric::
+ <rubric>
+ A rubric has no content
+ <comment xml:space="preserve">
+ _`target: No matching backquote.
+ <system_message level="2" line="52" source="%(source)s" type="WARNING">
+ <paragraph>
+ malformed hyperlink target.
+ <comment xml:space="preserve">
+ __malformed: no good
+ <system_message level="2" line="53" source="%(source)s" type="WARNING">
+ <paragraph>
+ malformed hyperlink target.
+ <definition_list>
+ <definition_list_item>
+ <term>
+ A literal block::
+ <definition>
+ <system_message level="1" line="57" source="%(source)s" type="INFO">
+ <paragraph>
+ Blank line missing before literal block (after the "::")? Interpreted as a definition list item.
+ <paragraph>
+ with no blank line above.
+ <literal_block xml:space="preserve">
+ > A literal block.
+ <system_message level="3" line="61" source="%(source)s" type="ERROR">
+ <paragraph>
+ Inconsistent literal block quoting.
+ <paragraph>
+ $ with inconsistent quoting.
+ <paragraph>
+ <problematic ids="id3" refid="id2">
+ :unknown-role:`role`
+
+ and
+ <problematic ids="id5" refid="id4">
+ *
+ unbalanced
+ <problematic ids="id7" refid="id6">
+ `
+ inline
+ <problematic ids="id9" refid="id8">
+ **
+ markup
+ <system_message level="1" line="63" source="%(source)s" type="INFO">
+ <paragraph>
+ No role entry for "unknown-role" in module "docutils.parsers.rst.languages.en".
+ Trying "unknown-role" as canonical role name.
+ <system_message backrefs="id3" ids="id2" level="3" line="63" source="%(source)s" type="ERROR">
+ <paragraph>
+ Unknown interpreted text role "unknown-role".
+ <system_message backrefs="id5" ids="id4" level="2" line="63" source="%(source)s" type="WARNING">
+ <paragraph>
+ Inline emphasis start-string without end-string.
+ <system_message backrefs="id7" ids="id6" level="2" line="63" source="%(source)s" type="WARNING">
+ <paragraph>
+ Inline interpreted text or phrase reference start-string without end-string.
+ <system_message backrefs="id9" ids="id8" level="2" line="63" source="%(source)s" type="WARNING">
+ <paragraph>
+ Inline strong start-string without end-string.
+ <paragraph>
+ <problematic ids="id11" refid="id10">
+ :PEP:`-1`
+ <system_message backrefs="id11" ids="id10" level="3" line="68" source="%(source)s" type="ERROR">
+ <paragraph>
+ PEP number must be a number from 0 to 9999; "-1" is invalid.
+ <system_message level="1" line="66" source="%(source)s" type="INFO">
+ <paragraph>
+ No directive entry for "unknown" in module "docutils.parsers.rst.languages.en".
+ Trying "unknown" as canonical directive name.
+ <system_message level="3" line="70" source="%(source)s" type="ERROR">
+ <paragraph>
+ Unknown directive type "unknown".
+ <literal_block xml:space="preserve">
+ .. unknown:: directive (info still reported with wrong line)
+ <system_message level="3" line="72" source="%(source)s" type="ERROR">
+ <paragraph>
+ Malformed table.
+ No bottom table border found.
+ <literal_block xml:space="preserve">
+ ============== ======
+ A simple table with
+ no bottom border
+""" % {'source': reldir(include10), 'nonexistent': reldir(nonexistent),
+ 'unichr_exception':
+ DocutilsTestSupport.exception_data(unichr, int("11111111", 16))[2]
+ }],
+["""\
+Include file with whitespace in the path:
+
+.. include:: %s
+""" % reldir(include11),
+"""\
+<document source="test data">
+ <paragraph>
+ Include file with whitespace in the path:
+ <paragraph>
+ some text
+"""],
+["""\
+Standard include data file:
+
+.. include:: <isogrk4.txt>
+""",
+b"""\
+<document source="test data">
+ <paragraph>
+ Standard include data file:
+ <comment xml:space="preserve">
+ This data file has been placed in the public domain.
+ <comment xml:space="preserve">
+ Derived from the Unicode character mappings available from
+ <http://www.w3.org/2003/entities/xml/>.
+ Processed by unicode2rstsubs.py, part of Docutils:
+ <http://docutils.sourceforge.net>.
+ <substitution_definition names="b.Gammad">
+ \\u03dc
+ <substitution_definition names="b.gammad">
+ \\u03dd
+""".decode('raw_unicode_escape')],
+["""\
+Nonexistent standard include data file:
+
+.. include:: <nonexistent>
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ Nonexistent standard include data file:
+ <system_message level="4" line="3" source="test data" type="SEVERE">
+ <paragraph>
+ Problems with "include" directive path:
+ InputError: [Errno 2] No such file or directory: '%s'.
+ <literal_block xml:space="preserve">
+ .. include:: <nonexistent>
+""" % nonexistent_rel],
+["""\
+Include start-line/end-line Test
+
+.. include:: %s
+ :start-line: 3
+ :end-line: 4
+""" % include2,
+"""\
+<document source="test data">
+ <paragraph>
+ Include start-line/end-line Test
+ <paragraph>
+ This file (include2.txt) is used by
+"""],
+["""\
+Include start-line/end-line + start-after Test
+
+.. include:: %s
+ :start-line: 2
+ :end-line: 5
+ :start-after: here
+
+Text search is limited to the specified lines.
+""" % include12,
+"""\
+<document source="test data">
+ <paragraph>
+ Include start-line/end-line + start-after Test
+ <paragraph>
+ In include12.txt (after "start here", before "stop here")
+ <paragraph>
+ Text search is limited to the specified lines.
+"""],
+["""\
+Include start-after/end-before Test
+
+.. include:: %s
+ :start-after: .. start here
+ :end-before: .. stop here
+
+A paragraph.
+""" % include12,
+"""\
+<document source="test data">
+ <paragraph>
+ Include start-after/end-before Test
+ <paragraph>
+ In include12.txt (after "start here", before "stop here")
+ <paragraph>
+ A paragraph.
+"""],
+["""\
+Include start-after/end-before Test, single option variant
+
+.. include:: %s
+ :end-before: .. start here
+
+.. include:: %s
+ :start-after: .. stop here
+
+A paragraph.
+""" % (include12, include12),
+"""\
+<document source="test data">
+ <paragraph>
+ Include start-after/end-before Test, single option variant
+ <paragraph>
+ In include12.txt (but before "start here")
+ <paragraph>
+ In include12.txt (after "stop here")
+ <paragraph>
+ A paragraph.
+"""],
+["""\
+Include start-after/end-before multi-line test.
+
+.. include:: %s
+ :start-after: From: me
+ To: you
+ :end-before: -------
+ -- mork of ork
+
+.. include:: %s
+ :start-after: From: me
+ To: you
+ :end-before:
+ -------
+ -- mork of ork
+
+A paragraph.
+""" % (include13, include13),
+"""\
+<document source="test data">
+ <paragraph>
+ Include start-after/end-before multi-line test.
+ <system_message level="4" line="3" source="test data" type="SEVERE">
+ <paragraph>
+ Problem with "end-before" option of "include" directive:
+ Text not found.
+ <literal_block xml:space="preserve">
+ .. include:: %s
+ :start-after: From: me
+ To: you
+ :end-before: -------
+ -- mork of ork
+ <paragraph>
+ In include13.txt (between header and signature)
+ <paragraph>
+ A paragraph.
+""" % include13],
+["""\
+Error handling test; "end-before" error handling tested in previous test.
+
+.. include:: %s
+ :start-after: bad string
+ :end-before: mork of ork
+""" % include13,
+"""\
+<document source="test data">
+ <paragraph>
+ Error handling test; "end-before" error handling tested in previous test.
+ <system_message level="4" line="3" source="test data" type="SEVERE">
+ <paragraph>
+ Problem with "start-after" option of "include" directive:
+ Text not found.
+ <literal_block xml:space="preserve">
+ .. include:: %s
+ :start-after: bad string
+ :end-before: mork of ork
+""" % include13],
+["""\
+TAB expansion with literal include:
+
+.. include:: %s
+ :literal:
+""" % include_literal,
+"""\
+<document source="test data">
+ <paragraph>
+ TAB expansion with literal include:
+ <literal_block source="%s" xml:space="preserve">
+ Literal included this should **not** be *marked* `up`.
+ <- leading raw tab.
+
+ Newlines
+ are
+ normalized.
+""" % include_literal],
+["""\
+Custom TAB expansion with literal include:
+
+.. include:: %s
+ :literal:
+ :tab-width: 2
+""" % include_literal,
+"""\
+<document source="test data">
+ <paragraph>
+ Custom TAB expansion with literal include:
+ <literal_block source="%s" xml:space="preserve">
+ Literal included this should **not** be *marked* `up`.
+ <- leading raw tab.
+
+ Newlines
+ are
+ normalized.
+""" % include_literal],
+["""\
+No TAB expansion with literal include:
+
+.. include:: %s
+ :literal:
+ :tab-width: -1
+""" % include_literal,
+"""\
+<document source="test data">
+ <paragraph>
+ No TAB expansion with literal include:
+ <literal_block source="%s" xml:space="preserve">
+ Literal included this should **not** be *marked* `up`.
+ \t<- leading raw tab.
+
+ Newlines
+ are
+ normalized.
+""" % include_literal],
+]
+
+totest['include-code'] = [
+["""\
+Included code
+
+.. include:: %s
+ :code: rst
+""" % include1,
+"""\
+<document source="test data">
+ <paragraph>
+ Included code
+ <literal_block classes="code rst" source="%s" xml:space="preserve">
+ <inline classes="generic heading">
+ Inclusion 1
+ \n\
+ <inline classes="generic heading">
+ -----------
+ \n\
+ \n\
+ This file is used by \n\
+ <inline classes="literal string">
+ ``test_include.py``
+ .
+""" % reldir(include1)],
+["""\
+Included code
+
+.. include:: %s
+ :code: rst
+ :number-lines:
+""" % include1,
+"""\
+<document source="test data">
+ <paragraph>
+ Included code
+ <literal_block classes="code rst" source="%s" xml:space="preserve">
+ <inline classes="ln">
+ 1 \n\
+ <inline classes="generic heading">
+ Inclusion 1
+ \n\
+ <inline classes="ln">
+ 2 \n\
+ <inline classes="generic heading">
+ -----------
+ \n\
+ <inline classes="ln">
+ 3 \n\
+ \n\
+ <inline classes="ln">
+ 4 \n\
+ This file is used by \n\
+ <inline classes="literal string">
+ ``test_include.py``
+ .
+""" % reldir(include1)],
+["""\
+Including includes/include14.txt
+
+.. include:: %s
+""" % include14,
+"""\
+<document source="test data">
+ <paragraph>
+ Including includes/include14.txt
+ <paragraph>
+ Including more/include6.txt as rst-code from includes/include14.txt:
+ <literal_block classes="code rst" source="%s" xml:space="preserve">
+ In includes/more/include6.txt
+ \n\
+ <inline classes="punctuation">
+ ..
+ \n\
+ <inline classes="operator word">
+ include
+ <inline classes="punctuation">
+ ::
+ ../sibling/include7.txt
+""" % reldir(include6)],
+]
+
+if __name__ == '__main__':
+ import unittest
+ unittest.main(defaultTest='suite')
--- /dev/null
+#! /usr/bin/env python
+
+# $Id: test_line_blocks.py 8356 2019-08-26 16:44:19Z milde $
+# Author: David Goodger <goodger@python.org>
+# Copyright: This module has been placed in the public domain.
+
+"""
+Tests for the body.py 'line-block' directive.
+"""
+from __future__ import absolute_import
+
+from . import DocutilsTestSupport
+
+
+def suite():
+ s = DocutilsTestSupport.ParserTestSuite()
+ s.generateTests(totest)
+ return s
+
+totest = {}
+
+totest['line_blocks'] = [
+["""\
+.. line-block::
+
+ This is a line block.
+ Newlines are *preserved*.
+ As is initial whitespace.
+""",
+"""\
+<document source="test data">
+ <line_block>
+ <line>
+ This is a line block.
+ <line>
+ Newlines are \n\
+ <emphasis>
+ preserved
+ .
+ <line_block>
+ <line>
+ As is initial whitespace.
+"""],
+["""\
+.. line-block::
+ :class: linear
+ :name: cit:short
+
+ This is a line block with options.
+""",
+"""\
+<document source="test data">
+ <line_block classes="linear" ids="cit-short" names="cit:short">
+ <line>
+ This is a line block with options.
+"""],
+["""\
+.. line-block::
+
+ Inline markup *may not span
+ multiple lines* of a line block.
+""",
+"""\
+<document source="test data">
+ <line_block>
+ <line>
+ Inline markup \n\
+ <problematic ids="id2" refid="id1">
+ *
+ may not span
+ <line_block>
+ <line>
+ multiple lines* of a line block.
+ <system_message backrefs="id2" ids="id1" level="2" line="3" source="test data" type="WARNING">
+ <paragraph>
+ Inline emphasis start-string without end-string.
+"""],
+["""\
+.. line-block::
+""",
+"""\
+<document source="test data">
+ <system_message level="3" line="1" source="test data" type="ERROR">
+ <paragraph>
+ Content block expected for the "line-block" directive; none found.
+ <literal_block xml:space="preserve">
+ .. line-block::
+"""],
+]
+
+
+if __name__ == '__main__':
+ import unittest
+ unittest.main(defaultTest='suite')
--- /dev/null
+#! /usr/bin/env python
+
+# $Id: test_math.py 8356 2019-08-26 16:44:19Z milde $
+# Author: Guenter Milde <milde@users.sf.net>
+# Copyright: This module has been placed in the public domain.
+
+"""
+Tests for the 'math' directive.
+"""
+from __future__ import absolute_import
+
+from . import DocutilsTestSupport
+
+
+def suite():
+ s = DocutilsTestSupport.ParserTestSuite()
+ s.generateTests(totest)
+ return s
+
+totest = {}
+
+totest['argument'] = [
+["""\
+.. math:: y = f(x)
+""",
+"""\
+<document source="test data">
+ <math_block xml:space="preserve">
+ y = f(x)
+"""],
+]
+
+totest['content'] = [
+["""\
+.. math::
+
+ 1+1=2
+""",
+"""\
+<document source="test data">
+ <math_block xml:space="preserve">
+ 1+1=2
+"""],
+]
+
+totest['options'] = [
+["""\
+.. math::
+ :class: new
+ :name: eq:Eulers law
+
+ e^i*2*\\pi = 1
+""",
+"""\
+<document source="test data">
+ <math_block classes="new" ids="eq-eulers-law" names="eq:eulers\\ law" xml:space="preserve">
+ e^i*2*\\pi = 1
+"""],
+]
+
+totest['argument_and_content'] = [
+["""\
+.. math:: y = f(x)
+
+ 1+1=2
+
+""",
+"""\
+<document source="test data">
+ <math_block xml:space="preserve">
+ y = f(x)
+ <math_block xml:space="preserve">
+ 1+1=2
+"""],
+]
+
+totest['content with blank line'] = [
+["""\
+.. math::
+
+ 1+1=2
+
+ E = mc^2
+""",
+"""\
+<document source="test data">
+ <math_block xml:space="preserve">
+ 1+1=2
+ <math_block xml:space="preserve">
+ E = mc^2
+"""],
+]
+
+
+if __name__ == '__main__':
+ import unittest
+ unittest.main(defaultTest='suite')
--- /dev/null
+#! /usr/bin/env python
+
+# $Id: test_meta.py 8356 2019-08-26 16:44:19Z milde $
+# Author: David Goodger <goodger@python.org>
+# Copyright: This module has been placed in the public domain.
+
+"""
+Tests for html meta directives.
+"""
+from __future__ import absolute_import
+
+from . import DocutilsTestSupport
+
+
+def suite():
+ s = DocutilsTestSupport.ParserTestSuite()
+ s.generateTests(totest)
+ return s
+
+totest = {}
+
+totest['meta'] = [
+["""\
+.. meta::
+ :description: The reStructuredText plaintext markup language
+ :keywords: plaintext,markup language
+""",
+"""\
+<document source="test data">
+ <pending>
+ .. internal attributes:
+ .transform: docutils.transforms.components.Filter
+ .details:
+ component: 'writer'
+ format: 'html'
+ nodes:
+ <meta content="The reStructuredText plaintext markup language" name="description">
+ <pending>
+ .. internal attributes:
+ .transform: docutils.transforms.components.Filter
+ .details:
+ component: 'writer'
+ format: 'html'
+ nodes:
+ <meta content="plaintext,markup language" name="keywords">
+"""],
+["""\
+.. meta::
+ :description lang=en: An amusing story
+ :description lang=fr: Un histoire amusant
+""",
+"""\
+<document source="test data">
+ <pending>
+ .. internal attributes:
+ .transform: docutils.transforms.components.Filter
+ .details:
+ component: 'writer'
+ format: 'html'
+ nodes:
+ <meta content="An amusing story" lang="en" name="description">
+ <pending>
+ .. internal attributes:
+ .transform: docutils.transforms.components.Filter
+ .details:
+ component: 'writer'
+ format: 'html'
+ nodes:
+ <meta content="Un histoire amusant" lang="fr" name="description">
+"""],
+["""\
+.. meta::
+ :http-equiv=Content-Type: text/html; charset=ISO-8859-1
+""",
+"""\
+<document source="test data">
+ <pending>
+ .. internal attributes:
+ .transform: docutils.transforms.components.Filter
+ .details:
+ component: 'writer'
+ format: 'html'
+ nodes:
+ <meta content="text/html; charset=ISO-8859-1" http-equiv="Content-Type">
+"""],
+["""\
+.. meta::
+ :name: content
+ over multiple lines
+""",
+"""\
+<document source="test data">
+ <pending>
+ .. internal attributes:
+ .transform: docutils.transforms.components.Filter
+ .details:
+ component: 'writer'
+ format: 'html'
+ nodes:
+ <meta content="content over multiple lines" name="name">
+"""],
+["""\
+Paragraph
+
+.. meta::
+ :name: content
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ Paragraph
+ <pending>
+ .. internal attributes:
+ .transform: docutils.transforms.components.Filter
+ .details:
+ component: 'writer'
+ format: 'html'
+ nodes:
+ <meta content="content" name="name">
+"""],
+["""\
+.. meta::
+""",
+"""\
+<document source="test data">
+ <system_message level="3" line="1" source="test data" type="ERROR">
+ <paragraph>
+ Content block expected for the "meta" directive; none found.
+ <literal_block xml:space="preserve">
+ .. meta::
+"""],
+["""\
+.. meta::
+ :empty:
+""",
+"""\
+<document source="test data">
+ <system_message level="1" line="2" source="test data" type="INFO">
+ <paragraph>
+ No content for meta tag "empty".
+ <literal_block xml:space="preserve">
+ :empty:
+"""],
+["""\
+.. meta::
+ not a field list
+""",
+"""\
+<document source="test data">
+ <system_message level="3" line="1" source="test data" type="ERROR">
+ <paragraph>
+ Invalid meta directive.
+ <literal_block xml:space="preserve">
+ .. meta::
+ not a field list
+"""],
+["""\
+.. meta::
+ :name: content
+ not a field
+ :name: content
+""",
+"""\
+<document source="test data">
+ <pending>
+ .. internal attributes:
+ .transform: docutils.transforms.components.Filter
+ .details:
+ component: 'writer'
+ format: 'html'
+ nodes:
+ <meta content="content" name="name">
+ <system_message level="3" line="1" source="test data" type="ERROR">
+ <paragraph>
+ Invalid meta directive.
+ <literal_block xml:space="preserve">
+ .. meta::
+ :name: content
+ not a field
+ :name: content
+"""],
+["""\
+.. meta::
+ :name: content
+ :name: content
+ not a field
+""",
+"""\
+<document source="test data">
+ <pending>
+ .. internal attributes:
+ .transform: docutils.transforms.components.Filter
+ .details:
+ component: 'writer'
+ format: 'html'
+ nodes:
+ <meta content="content" name="name">
+ <pending>
+ .. internal attributes:
+ .transform: docutils.transforms.components.Filter
+ .details:
+ component: 'writer'
+ format: 'html'
+ nodes:
+ <meta content="content" name="name">
+ <system_message level="3" line="1" source="test data" type="ERROR">
+ <paragraph>
+ Invalid meta directive.
+ <literal_block xml:space="preserve">
+ .. meta::
+ :name: content
+ :name: content
+ not a field
+"""],
+["""\
+.. meta::
+ :name notattval: content
+""",
+"""\
+<document source="test data">
+ <system_message level="3" line="2" source="test data" type="ERROR">
+ <paragraph>
+ Error parsing meta tag attribute "notattval": missing "=".
+ <literal_block xml:space="preserve">
+ :name notattval: content
+"""],
+[r"""
+.. meta::
+ :name\:with\:colons: escaped line\
+ break
+ :unescaped:embedded:colons: content
+""",
+"""\
+<document source="test data">
+ <pending>
+ .. internal attributes:
+ .transform: docutils.transforms.components.Filter
+ .details:
+ component: 'writer'
+ format: 'html'
+ nodes:
+ <meta content="escaped linebreak" name="name:with:colons">
+ <pending>
+ .. internal attributes:
+ .transform: docutils.transforms.components.Filter
+ .details:
+ component: \'writer\'
+ format: \'html\'
+ nodes:
+ <meta content="content" name="unescaped:embedded:colons">
+"""],
+]
+
+
+if __name__ == '__main__':
+ import unittest
+ unittest.main(defaultTest='suite')
--- /dev/null
+#! /usr/bin/env python
+
+# $Id: test_parsed_literals.py 8356 2019-08-26 16:44:19Z milde $
+# Author: Lea Wiemann <LeWiemann@gmail.com>
+# Copyright: This module has been placed in the public domain.
+
+"""
+Tests for the body.py 'parsed-literal' directive.
+"""
+from __future__ import absolute_import
+
+from . import DocutilsTestSupport
+
+
+def suite():
+ s = DocutilsTestSupport.ParserTestSuite()
+ s.generateTests(totest)
+ return s
+
+totest = {}
+
+totest['parsed_literals'] = [
+["""\
+.. parsed-literal::
+
+ This is a parsed literal block.
+ It may contain *inline markup
+ spanning lines.*
+""",
+"""\
+<document source="test data">
+ <literal_block xml:space="preserve">
+ This is a parsed literal block.
+ It may contain \n\
+ <emphasis>
+ inline markup
+ spanning lines.
+"""],
+["""\
+.. parsed-literal::
+ :class: myliteral
+ :name: example: parsed
+
+ This is a parsed literal block with options.
+""",
+"""\
+<document source="test data">
+ <literal_block classes="myliteral" ids="example-parsed" names="example:\\ parsed" xml:space="preserve">
+ This is a parsed literal block with options.
+"""],
+["""\
+.. parsed-literal:: content may start on same line
+""",
+"""\
+<document source="test data">
+ <literal_block xml:space="preserve">
+ content may start on same line
+"""],
+["""\
+.. parsed-literal::
+""",
+"""\
+<document source="test data">
+ <system_message level="3" line="1" source="test data" type="ERROR">
+ <paragraph>
+ Content block expected for the "parsed-literal" directive; none found.
+ <literal_block xml:space="preserve">
+ .. parsed-literal::
+"""],
+]
+
+
+if __name__ == '__main__':
+ import unittest
+ unittest.main(defaultTest='suite')
--- /dev/null
+#! /usr/bin/env python
+
+# $Id: test_raw.py 8367 2019-08-27 12:09:56Z milde $
+# Author: David Goodger <goodger@python.org>
+# Copyright: This module has been placed in the public domain.
+
+"""
+Tests for misc.py "raw" directive.
+"""
+from __future__ import absolute_import
+
+import os.path
+import sys
+
+from . import DocutilsTestSupport
+
+
+def suite():
+ s = DocutilsTestSupport.ParserTestSuite()
+ s.generateTests(totest)
+ return s
+
+mydir = 'test_parsers/test_rst/test_directives/'
+raw1 = os.path.join(mydir, 'raw1.txt')
+utf_16_file = os.path.join(mydir, 'utf-16.csv')
+utf_16_file_rel = DocutilsTestSupport.utils.relative_path(None, utf_16_file)
+utf_16_error_str = ("UnicodeDecodeError: 'ascii' codec can't decode byte 0xfe "
+ "in position 0: ordinal not in range(128)")
+if sys.version_info < (3, 0):
+ utf_16_error_str = ("UnicodeError: Unable to decode input data. "
+ "Tried the following encodings: 'ascii'.\n"
+ " (%s)" % utf_16_error_str)
+
+totest = {}
+
+totest['raw'] = [
+["""\
+.. raw:: html
+
+ <span>This is some plain old raw text.</span>
+""",
+"""\
+<document source="test data">
+ <raw format="html" xml:space="preserve">
+ <span>This is some plain old raw text.</span>
+"""],
+["""\
+.. raw:: html
+ :file: %s
+""" % raw1,
+"""\
+<document source="test data">
+ <raw format="html" source="%s" xml:space="preserve">
+ <p>This file is used by <tt>test_raw.py</tt>.</p>
+""" % DocutilsTestSupport.utils.relative_path(None, raw1)],
+["""\
+.. raw:: html
+ :file: rawfile.html
+ :url: http://example.org/
+""",
+"""\
+<document source="test data">
+ <system_message level="3" line="1" source="test data" type="ERROR">
+ <paragraph>
+ The "file" and "url" options may not be simultaneously specified for the "raw" directive.
+ <literal_block xml:space="preserve">
+ .. raw:: html
+ :file: rawfile.html
+ :url: http://example.org/
+"""],
+["""\
+.. raw:: html
+ :file: rawfile.html
+
+ <p>Can't have both content and file attribute.</p>
+""",
+"""\
+<document source="test data">
+ <system_message level="3" line="1" source="test data" type="ERROR">
+ <paragraph>
+ "raw" directive may not both specify an external file and have content.
+ <literal_block xml:space="preserve">
+ .. raw:: html
+ :file: rawfile.html
+
+ <p>Can't have both content and file attribute.</p>
+"""],
+[r"""
+.. raw:: latex html
+
+ \[ \sum_{n=1}^\infty \frac{1}{n} \text{ etc.} \]
+""",
+"""\
+<document source="test data">
+ <raw format="latex html" xml:space="preserve">
+ \\[ \\sum_{n=1}^\\infty \\frac{1}{n} \\text{ etc.} \\]
+"""],
+["""\
+.. raw:: html
+ :file: %s
+ :encoding: utf-16
+""" % utf_16_file_rel,
+b"""\
+<document source="test data">
+ <raw format="html" source="%s" xml:space="preserve">
+ "Treat", "Quantity", "Description"
+ "Albatr\xb0\xdf", 2.99, "\xa1On a \\u03c3\\u03c4\\u03b9\\u03ba!"
+ "Crunchy Frog", 1.49, "If we took the b\xf6nes out, it wouldn\\u2019t be
+ crunchy, now would it?"
+ "Gannet Ripple", 1.99, "\xbfOn a \\u03c3\\u03c4\\u03b9\\u03ba?"
+""".decode('raw_unicode_escape') % utf_16_file_rel],
+["""\
+Raw input file is UTF-16-encoded, and is not valid ASCII.
+
+.. raw:: html
+ :file: %s
+ :encoding: ascii
+""" % utf_16_file_rel,
+"""\
+<document source="test data">
+ <paragraph>
+ Raw input file is UTF-16-encoded, and is not valid ASCII.
+ <system_message level="4" line="3" source="test data" type="SEVERE">
+ <paragraph>
+ Problem with "raw" directive:
+ %s
+ <literal_block xml:space="preserve">
+ .. raw:: html
+ :file: %s
+ :encoding: ascii
+""" % (utf_16_error_str, utf_16_file_rel)],
+[u"""\
+.. raw:: html
+ :encoding: utf-8
+
+ Should the parser complain becau\xdfe there is no :file:? BUG?
+""",
+"""\
+<document source="test data">
+ <raw format="html" xml:space="preserve">
+ Should the parser complain becau\xdfe there is no :file:? BUG?
+"""],
+["""\
+.. raw:: html
+""",
+"""\
+<document source="test data">
+ <system_message level="3" line="1" source="test data" type="ERROR">
+ <paragraph>
+ Content block expected for the "raw" directive; none found.
+ <literal_block xml:space="preserve">
+ .. raw:: html
+"""],
+["""\
+.. raw:: html
+ :file: non-existent.file
+""",
+"""\
+<document source="test data">
+ <system_message level="4" line="1" source="test data" type="SEVERE">
+ <paragraph>
+ Problems with "raw" directive path:
+ InputError: [Errno 2] No such file or directory: 'non-existent.file'.
+ <literal_block xml:space="preserve">
+ .. raw:: html
+ :file: non-existent.file
+"""],
+# note that this output is rewritten below for certain python versions
+]
+
+if __name__ == '__main__':
+ import unittest
+ unittest.main(defaultTest='suite')
--- /dev/null
+#! /usr/bin/env python
+
+# $Id: test_replace.py 8356 2019-08-26 16:44:19Z milde $
+# Author: David Goodger <goodger@python.org>
+# Copyright: This module has been placed in the public domain.
+
+"""
+Tests for misc.py "replace" directive.
+"""
+from __future__ import absolute_import
+
+from . import DocutilsTestSupport
+
+
+def suite():
+ s = DocutilsTestSupport.ParserTestSuite()
+ s.generateTests(totest)
+ return s
+
+totest = {}
+
+totest['replace'] = [
+["""\
+Test the |name| directive.
+
+.. |name| replace:: "**replace**"
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ Test the \n\
+ <substitution_reference refname="name">
+ name
+ directive.
+ <substitution_definition names="name">
+ "
+ <strong>
+ replace
+ "
+"""],
+["""\
+.. |name| replace:: paragraph 1
+
+ paragraph 2
+""",
+"""\
+<document source="test data">
+ <system_message level="3" line="1" source="test data" type="ERROR">
+ <paragraph>
+ Error in "replace" directive: may contain a single paragraph only.
+ <system_message level="2" line="1" source="test data" type="WARNING">
+ <paragraph>
+ Substitution definition "name" empty or invalid.
+ <literal_block xml:space="preserve">
+ .. |name| replace:: paragraph 1
+
+ paragraph 2
+"""],
+["""\
+.. |name| replace::
+""",
+"""\
+<document source="test data">
+ <system_message level="3" line="1" source="test data" type="ERROR">
+ <paragraph>
+ Content block expected for the "replace" directive; none found.
+ <literal_block xml:space="preserve">
+ replace::
+ <system_message level="2" line="1" source="test data" type="WARNING">
+ <paragraph>
+ Substitution definition "name" empty or invalid.
+ <literal_block xml:space="preserve">
+ .. |name| replace::
+"""],
+["""\
+.. |Python| replace:: Python, *the* best language around
+
+.. _Python: http://www.python.org/
+
+I recommend you try |Python|_.
+""",
+"""\
+<document source="test data">
+ <substitution_definition names="Python">
+ Python,
+ <emphasis>
+ the
+ best language around
+ <target ids="python" names="python" refuri="http://www.python.org/">
+ <paragraph>
+ I recommend you try
+ <reference refname="python">
+ <substitution_reference refname="Python">
+ Python
+ .
+"""],
+["""\
+.. |name| replace:: *error in **inline ``markup
+""",
+"""\
+<document source="test data">
+ <system_message ids="id1" level="2" line="1" source="test data" type="WARNING">
+ <paragraph>
+ Inline emphasis start-string without end-string.
+ <system_message ids="id3" level="2" line="1" source="test data" type="WARNING">
+ <paragraph>
+ Inline strong start-string without end-string.
+ <system_message ids="id5" level="2" line="1" source="test data" type="WARNING">
+ <paragraph>
+ Inline literal start-string without end-string.
+ <system_message level="3" line="1" source="test data" type="ERROR">
+ <paragraph>
+ Substitution definition contains illegal element <problematic>:
+ <literal_block xml:space="preserve">
+ <problematic ids="id2" refid="id1">
+ *
+ <literal_block xml:space="preserve">
+ .. |name| replace:: *error in **inline ``markup
+"""],
+["""\
+.. replace:: not valid outside of a substitution definition
+""",
+"""\
+<document source="test data">
+ <system_message level="3" line="1" source="test data" type="ERROR">
+ <paragraph>
+ Invalid context: the "replace" directive can only be used within a substitution definition.
+ <literal_block xml:space="preserve">
+ .. replace:: not valid outside of a substitution definition
+"""],
+]
+
+
+if __name__ == '__main__':
+ import unittest
+ unittest.main(defaultTest='suite')
--- /dev/null
+#! /usr/bin/env python
+
+# $Id: test_replace.py 4667 2006-07-12 21:40:56Z wiemann $
+# Author: David Goodger <goodger@python.org>
+# Copyright: This module has been placed in the public domain.
+
+"""
+Tests for misc.py "replace" directive.
+Test in french (not default/fallback language).
+"""
+from __future__ import absolute_import
+
+from . import DocutilsTestSupport
+
+
+def suite():
+ s = DocutilsTestSupport.ParserTestSuite(suite_settings={'language_code':'fr'})
+ s.generateTests(totest)
+ return s
+
+totest = {}
+
+totest['replace'] = [
+["""\
+Test directive containing french role exposant (superscript).
+
+.. |Na+| remplace:: Na\\ :exp:`+`
+
+Le |Na+| est l'ion sodium.
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ Test directive containing french role exposant (superscript).
+ <substitution_definition names="Na+">
+ Na
+ <superscript>
+ +
+ <paragraph>
+ Le \n\
+ <substitution_reference refname="Na+">
+ Na+
+ est l\'ion sodium.
+"""],
+["""\
+Test directive containing english role superscript.
+
+.. |Na+| remplace:: Na\\ :sup:`+`
+
+Le |Na+| est l'ion sodium.
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ Test directive containing english role superscript.
+ <system_message level="1" line="3" source="test data" type="INFO">
+ <paragraph>
+ No role entry for "sup" in module "docutils.parsers.rst.languages.fr".
+ Using English fallback for role "sup".
+ <substitution_definition names="Na+">
+ Na
+ <superscript>
+ +
+ <paragraph>
+ Le \n\
+ <substitution_reference refname="Na+">
+ Na+
+ est l\'ion sodium."""],
+]
+
+
+if __name__ == '__main__':
+ import unittest
+ unittest.main(defaultTest='suite')
--- /dev/null
+#! /usr/bin/env python
+
+# $Id: test_role.py 8356 2019-08-26 16:44:19Z milde $
+# Author: David Goodger <goodger@python.org>
+# Copyright: This module has been placed in the public domain.
+
+"""
+Tests for misc.py "role" directive.
+"""
+from __future__ import absolute_import
+
+from . import DocutilsTestSupport
+
+
+def suite():
+ s = DocutilsTestSupport.ParserTestSuite()
+ s.generateTests(totest)
+ return s
+
+totest = {}
+
+totest['role'] = [
+["""\
+.. role:: custom
+.. role:: special
+
+:custom:`interpreted` and :special:`interpreted`
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ <inline classes="custom">
+ interpreted
+ and \n\
+ <inline classes="special">
+ interpreted
+"""],
+["""\
+.. role:: custom
+ :class: custom-class
+.. role:: special
+ :class: special-class
+
+:custom:`interpreted` and :special:`interpreted`
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ <inline classes="custom-class">
+ interpreted
+ and \n\
+ <inline classes="special-class">
+ interpreted
+"""],
+["""\
+Must define :custom:`interpreted` before using it.
+
+.. role:: custom
+
+Now that it's defined, :custom:`interpreted` works.
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ Must define
+ <problematic ids="id2" refid="id1">
+ :custom:`interpreted`
+ before using it.
+ <system_message level="1" line="1" source="test data" type="INFO">
+ <paragraph>
+ No role entry for "custom" in module "docutils.parsers.rst.languages.en".
+ Trying "custom" as canonical role name.
+ <system_message backrefs="id2" ids="id1" level="3" line="1" source="test data" type="ERROR">
+ <paragraph>
+ Unknown interpreted text role "custom".
+ <paragraph>
+ Now that it's defined, \n\
+ <inline classes="custom">
+ interpreted
+ works.
+"""],
+["""\
+.. role:: custom(emphasis)
+
+:custom:`text`
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ <emphasis classes="custom">
+ text
+"""],
+["""\
+.. role:: custom ( emphasis )
+
+:custom:`text`
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ <emphasis classes="custom">
+ text
+"""],
+["""\
+.. role:: custom(emphasis)
+ :class: special
+
+:custom:`text`
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ <emphasis classes="special">
+ text
+"""],
+["""\
+.. role:: custom(unknown-role)
+""",
+"""\
+<document source="test data">
+ <system_message level="1" line="1" source="test data" type="INFO">
+ <paragraph>
+ No role entry for "unknown-role" in module "docutils.parsers.rst.languages.en".
+ Trying "unknown-role" as canonical role name.
+ <system_message level="3" line="1" source="test data" type="ERROR">
+ <paragraph>
+ Unknown interpreted text role "unknown-role".
+ <literal_block xml:space="preserve">
+ .. role:: custom(unknown-role)
+"""],
+["""\
+.. role:: custom
+ :class: 1
+""",
+"""\
+<document source="test data">
+ <system_message level="3" line="1" source="test data" type="ERROR">
+ <paragraph>
+ Error in "role" directive:
+ invalid option value: (option: "class"; value: '1')
+ cannot make "1" into a class name.
+ <literal_block xml:space="preserve">
+ .. role:: custom
+ :class: 1
+"""],
+["""\
+.. role:: 1
+""",
+"""\
+<document source="test data">
+ <system_message level="3" line="1" source="test data" type="ERROR">
+ <paragraph>
+ Invalid argument for "role" directive:
+ cannot make "1" into a class name.
+ <literal_block xml:space="preserve">
+ .. role:: 1
+"""],
+["""\
+.. role:: (error)
+""",
+"""\
+<document source="test data">
+ <system_message level="3" line="1" source="test data" type="ERROR">
+ <paragraph>
+ "role" directive arguments not valid role names: "(error)".
+ <literal_block xml:space="preserve">
+ .. role:: (error)
+"""],
+["""\
+.. role::
+""",
+"""\
+<document source="test data">
+ <system_message level="3" line="1" source="test data" type="ERROR">
+ <paragraph>
+ "role" directive requires arguments on the first line.
+ <literal_block xml:space="preserve">
+ .. role::
+"""],
+["""\
+Test
+----
+
+.. role:: fileref(emphasis)
+
+Testing a :fileref:`role` in a nested parse.
+""",
+"""\
+<document source="test data">
+ <section ids="test" names="test">
+ <title>
+ Test
+ <paragraph>
+ Testing a \n\
+ <emphasis classes="fileref">
+ role
+ in a nested parse.
+"""],
+["""\
+.. role:: custom
+.. role:: special
+
+Empty :custom:`\\ ` and empty `\\ `:special:
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ Empty
+ <inline classes="custom">
+ and empty
+ <inline classes="special">
+"""],
+]
+
+totest['raw_role'] = [
+["""\
+.. role:: html(raw)
+ :format: html
+
+Here's some :html:`<i>raw HTML data</i>`.
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ Here's some \n\
+ <raw classes="html" format="html" xml:space="preserve">
+ <i>raw HTML data</i>
+ .
+"""],
+["""\
+.. role:: itex(raw)
+ :format: latex html
+
+Here's some itex markup: :itex:`$x^\\infty$`.
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ Here's some itex markup: \n\
+ <raw classes="itex" format="latex html" xml:space="preserve">
+ $x^\\infty$
+ .
+"""],
+["""\
+Can't use the :raw:`role` directly.
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ Can't use the \n\
+ <problematic ids="id2" refid="id1">
+ :raw:`role`
+ directly.
+ <system_message backrefs="id2" ids="id1" level="3" line="1" source="test data" type="ERROR">
+ <paragraph>
+ No format (Writer name) is associated with this role: "raw".
+ The "raw" role cannot be used directly.
+ Instead, use the "role" directive to create a new role with an associated format.
+"""],
+]
+
+
+if __name__ == '__main__':
+ import unittest
+ unittest.main(defaultTest='suite')
--- /dev/null
+#! /usr/bin/env python
+
+# $Id: test_rubrics.py 8356 2019-08-26 16:44:19Z milde $
+# Author: David Goodger <goodger@python.org>
+# Copyright: This module has been placed in the public domain.
+
+"""
+Tests for the "rubric" directive.
+"""
+from __future__ import absolute_import
+
+from . import DocutilsTestSupport
+
+def suite():
+ s = DocutilsTestSupport.ParserTestSuite()
+ s.generateTests(totest)
+ return s
+
+totest = {}
+
+totest['rubrics'] = [
+["""\
+.. rubric:: This is a rubric
+""",
+"""\
+<document source="test data">
+ <rubric>
+ This is a rubric
+"""],
+["""\
+.. rubric::
+.. rubric:: A rubric has no content
+
+ Invalid content
+""",
+"""\
+<document source="test data">
+ <system_message level="3" line="1" source="test data" type="ERROR">
+ <paragraph>
+ Error in "rubric" directive:
+ 1 argument(s) required, 0 supplied.
+ <literal_block xml:space="preserve">
+ .. rubric::
+ <system_message level="3" line="2" source="test data" type="ERROR">
+ <paragraph>
+ Error in "rubric" directive:
+ no content permitted.
+ <literal_block xml:space="preserve">
+ .. rubric:: A rubric has no content
+ \n\
+ Invalid content
+"""],
+["""\
+.. rubric:: A rubric followed by a block quote
+..
+
+ Block quote
+""",
+"""\
+<document source="test data">
+ <rubric>
+ A rubric followed by a block quote
+ <comment xml:space="preserve">
+ <block_quote>
+ <paragraph>
+ Block quote
+"""],
+["""\
+.. rubric:: A Rubric
+ :class: foo bar
+ :name: Foo Rubric
+""",
+"""\
+<document source="test data">
+ <rubric classes="foo bar" ids="foo-rubric" names="foo\\ rubric">
+ A Rubric
+"""],
+]
+
+
+if __name__ == '__main__':
+ import unittest
+ unittest.main(defaultTest='suite')
--- /dev/null
+#! /usr/bin/env python
+
+# $Id: test_sectnum.py 8356 2019-08-26 16:44:19Z milde $
+# Author: Lea Wiemann <LeWiemann@gmail.com>
+# Copyright: This module has been placed in the public domain.
+
+"""
+Tests for the 'sectnum' directive.
+"""
+from __future__ import absolute_import
+
+from . import DocutilsTestSupport
+
+
+def suite():
+ s = DocutilsTestSupport.ParserTestSuite()
+ s.generateTests(totest)
+ return s
+
+totest = {}
+
+totest['sectnum'] = [
+["""\
+.. sectnum::
+""",
+"""\
+<document source="test data">
+ <pending>
+ .. internal attributes:
+ .transform: docutils.transforms.parts.SectNum
+ .details:
+"""],
+["""\
+.. sectnum::
+ :depth: 23
+ :start: 42
+ :prefix: A Prefix
+ :suffix: A Suffix
+""",
+"""\
+<document source="test data">
+ <pending>
+ .. internal attributes:
+ .transform: docutils.transforms.parts.SectNum
+ .details:
+ depth: 23
+ prefix: 'A Prefix'
+ start: 42
+ suffix: 'A Suffix'
+"""],
+]
+
+
+if __name__ == '__main__':
+ import unittest
+ unittest.main(defaultTest='suite')
--- /dev/null
+#! /usr/bin/env python
+
+# $Id: test_sidebars.py 8356 2019-08-26 16:44:19Z milde $
+# Author: David Goodger <goodger@python.org>
+# Copyright: This module has been placed in the public domain.
+
+"""
+Tests for the "sidebar" directive.
+"""
+from __future__ import absolute_import
+
+from . import DocutilsTestSupport
+
+
+def suite():
+ s = DocutilsTestSupport.ParserTestSuite()
+ s.generateTests(totest)
+ return s
+
+totest = {}
+
+totest['sidebars'] = [
+["""\
+.. sidebar:: Outer
+
+ .. sidebar:: Nested
+
+ Body.
+""",
+"""\
+<document source="test data">
+ <sidebar>
+ <title>
+ Outer
+ <system_message level="3" line="3" source="test data" type="ERROR">
+ <paragraph>
+ The "sidebar" directive may not be used within a sidebar element.
+ <literal_block xml:space="preserve">
+ .. sidebar:: Nested
+ \n\
+ Body.
+"""],
+["""\
+.. sidebar:: Margin Notes
+ :subtitle: with options
+ :class: margin
+ :name: note:Options
+
+ Body.
+""",
+"""\
+<document source="test data">
+ <sidebar classes="margin" ids="note-options" names="note:options">
+ <title>
+ Margin Notes
+ <subtitle>
+ with options
+ <paragraph>
+ Body.
+"""],
+["""\
+.. sidebar:: Outer
+
+ .. topic:: Topic
+
+ .. sidebar:: Inner
+
+ text
+""",
+"""\
+<document source="test data">
+ <sidebar>
+ <title>
+ Outer
+ <topic>
+ <title>
+ Topic
+ <system_message level="3" line="5" source="test data" type="ERROR">
+ <paragraph>
+ The "sidebar" directive may not be used within topics or body elements.
+ <literal_block xml:space="preserve">
+ .. sidebar:: Inner
+ \n\
+ text
+"""],
+]
+
+
+if __name__ == '__main__':
+ import unittest
+ unittest.main(defaultTest='suite')
--- /dev/null
+#! /usr/bin/env python
+
+# $Id: test_tables.py 8367 2019-08-27 12:09:56Z milde $
+# Author: David Goodger <goodger@python.org>
+# Copyright: This module has been placed in the public domain.
+
+"""
+Tests for tables.py directives.
+"""
+from __future__ import absolute_import
+
+import os
+import sys
+import csv
+import platform
+
+from . import DocutilsTestSupport
+from docutils.parsers.rst.directives import tables
+
+
+if sys.version_info >= (3, 0):
+ unicode = str # noqa
+ unichr = chr # noqa
+
+
+def suite():
+ s = DocutilsTestSupport.ParserTestSuite()
+ s.generateTests(totest)
+ return s
+
+mydir = 'test_parsers/test_rst/test_directives/'
+utf_16_csv = os.path.join(mydir, 'utf-16.csv')
+utf_16_csv_rel = DocutilsTestSupport.utils.relative_path(None, utf_16_csv)
+empty_txt = os.path.join(mydir, 'empty.txt')
+
+unichr_exception = DocutilsTestSupport.exception_data(
+ unichr, int("9999999999999", 16))[0]
+if isinstance(unichr_exception, OverflowError):
+ unichr_exception_string = 'code too large (%s)' % unichr_exception
+else:
+ unichr_exception_string = str(unichr_exception)
+
+# some error messages changed in Python 3.3, CPython has backported to 2.7.4,
+# PyPy has not
+csv_eod_error_str = 'unexpected end of data'
+if sys.version_info < (2,7,4) or platform.python_implementation() == 'PyPy':
+ csv_eod_error_str = 'newline inside string'
+# pypy adds a line number
+if sys.version_info >= (3, 0) and platform.python_implementation() == 'PyPy':
+ csv_eod_error_str = 'line 1: ' + csv_eod_error_str
+csv_unknown_url = "'bogus.csv'"
+if sys.version_info < (3, 0):
+ csv_unknown_url = "bogus.csv"
+
+
+def null_bytes():
+ with open(utf_16_csv, 'rb') as f:
+ csv_data = f.read()
+ csv_data = unicode(csv_data, 'latin1').splitlines()
+ reader = csv.reader([tables.CSVTable.encode_for_csv(line + '\n')
+ for line in csv_data])
+ next(reader)
+
+null_bytes_exception = DocutilsTestSupport.exception_data(null_bytes)[0]
+
+totest = {}
+
+totest['table'] = [
+["""\
+.. table:: Truth table for "not"
+ :class: custom
+ :name: tab:truth.not
+
+ ===== =====
+ A not A
+ ===== =====
+ False True
+ True False
+ ===== =====
+""",
+"""\
+<document source="test data">
+ <table classes="custom" ids="tab-truth-not" names="tab:truth.not">
+ <title>
+ Truth table for "not"
+ <tgroup cols="2">
+ <colspec colwidth="5">
+ <colspec colwidth="5">
+ <thead>
+ <row>
+ <entry>
+ <paragraph>
+ A
+ <entry>
+ <paragraph>
+ not A
+ <tbody>
+ <row>
+ <entry>
+ <paragraph>
+ False
+ <entry>
+ <paragraph>
+ True
+ <row>
+ <entry>
+ <paragraph>
+ True
+ <entry>
+ <paragraph>
+ False
+"""],
+["""\
+.. table::
+
+ ========== ==========
+ Table without
+ a title
+ ========== ==========
+""",
+"""\
+<document source="test data">
+ <table>
+ <tgroup cols="2">
+ <colspec colwidth="10">
+ <colspec colwidth="10">
+ <tbody>
+ <row>
+ <entry>
+ <paragraph>
+ Table
+ <entry>
+ <paragraph>
+ without
+ <row>
+ <entry>
+ <paragraph>
+ a
+ <entry>
+ <paragraph>
+ title
+"""],
+["""\
+.. table:: title with an *error
+
+ ====== =====
+ Simple table
+ ====== =====
+""",
+"""\
+<document source="test data">
+ <table>
+ <title>
+ title with an \n\
+ <problematic ids="id2" refid="id1">
+ *
+ error
+ <tgroup cols="2">
+ <colspec colwidth="6">
+ <colspec colwidth="5">
+ <tbody>
+ <row>
+ <entry>
+ <paragraph>
+ Simple
+ <entry>
+ <paragraph>
+ table
+ <system_message backrefs="id2" ids="id1" level="2" line="1" source="test data" type="WARNING">
+ <paragraph>
+ Inline emphasis start-string without end-string.
+"""],
+["""\
+.. table:: Not a table.
+
+ This is a paragraph.
+""",
+"""\
+<document source="test data">
+ <system_message level="3" line="1" source="test data" type="ERROR">
+ <paragraph>
+ Error parsing content block for the "table" directive: exactly one table expected.
+ <literal_block xml:space="preserve">
+ .. table:: Not a table.
+ \n\
+ This is a paragraph.
+"""],
+["""\
+.. table:: empty
+""",
+"""\
+<document source="test data">
+ <system_message level="2" line="1" source="test data" type="WARNING">
+ <paragraph>
+ Content block expected for the "table" directive; none found.
+ <literal_block xml:space="preserve">
+ .. table:: empty
+"""],
+["""\
+.. table::
+ :width: 100 %
+
+ ============ ==============
+ col 1 col 2
+ ============ ==============
+""",
+"""\
+<document source="test data">
+ <table width="100%">
+ <tgroup cols="2">
+ <colspec colwidth="12">
+ <colspec colwidth="14">
+ <tbody>
+ <row>
+ <entry>
+ <paragraph>
+ col 1
+ <entry>
+ <paragraph>
+ col 2
+"""],
+["""\
+.. table::
+ :width: 100px
+
+ ============ ==============
+ col 1 col 2
+ ============ ==============
+""",
+"""\
+<document source="test data">
+ <table width="100px">
+ <tgroup cols="2">
+ <colspec colwidth="12">
+ <colspec colwidth="14">
+ <tbody>
+ <row>
+ <entry>
+ <paragraph>
+ col 1
+ <entry>
+ <paragraph>
+ col 2
+"""],
+["""\
+.. table::
+ :width: 321
+
+ ============ ==============
+ col 1 col 2
+ ============ ==============
+""",
+"""\
+<document source="test data">
+ <table width="321">
+ <tgroup cols="2">
+ <colspec colwidth="12">
+ <colspec colwidth="14">
+ <tbody>
+ <row>
+ <entry>
+ <paragraph>
+ col 1
+ <entry>
+ <paragraph>
+ col 2
+"""],
+["""\
+.. table::
+ :widths: 15, 25
+
+ ============ ==============
+ Columns with custom widths.
+ ============ ==============
+""",
+"""\
+<document source="test data">
+ <table classes="colwidths-given">
+ <tgroup cols="2">
+ <colspec colwidth="15">
+ <colspec colwidth="25">
+ <tbody>
+ <row>
+ <entry>
+ <paragraph>
+ Columns with
+ <entry>
+ <paragraph>
+ custom widths.
+"""],
+["""\
+.. table::
+ :widths: 10, 20
+
+ +--------------+----------------+
+ | Columns with | custom widths. |
+ +--------------+----------------+
+""",
+"""\
+<document source="test data">
+ <table classes="colwidths-given">
+ <tgroup cols="2">
+ <colspec colwidth="10">
+ <colspec colwidth="20">
+ <tbody>
+ <row>
+ <entry>
+ <paragraph>
+ Columns with
+ <entry>
+ <paragraph>
+ custom widths.
+"""],
+["""\
+.. table::
+ :widths: auto
+
+ +--------------+-------------------+
+ | Columns with | automatic widths. |
+ +--------------+-------------------+
+""",
+"""\
+<document source="test data">
+ <table classes="colwidths-auto">
+ <tgroup cols="2">
+ <colspec colwidth="14">
+ <colspec colwidth="19">
+ <tbody>
+ <row>
+ <entry>
+ <paragraph>
+ Columns with
+ <entry>
+ <paragraph>
+ automatic widths.
+"""],
+["""\
+.. table::
+ :widths: grid
+
+ +--------------+-------------------+
+ | Columns with | automatic widths. |
+ +--------------+-------------------+
+""",
+"""\
+<document source="test data">
+ <table classes="colwidths-given">
+ <tgroup cols="2">
+ <colspec colwidth="14">
+ <colspec colwidth="19">
+ <tbody>
+ <row>
+ <entry>
+ <paragraph>
+ Columns with
+ <entry>
+ <paragraph>
+ automatic widths.
+"""],
+["""\
+.. table::
+ :align: center
+
+ ====== =====
+ Simple table
+ ====== =====
+""",
+"""\
+<document source="test data">
+ <table align="center">
+ <tgroup cols="2">
+ <colspec colwidth="6">
+ <colspec colwidth="5">
+ <tbody>
+ <row>
+ <entry>
+ <paragraph>
+ Simple
+ <entry>
+ <paragraph>
+ table
+"""],
+]
+
+totest['csv-table'] = [
+["""\
+.. csv-table:: inline with integral header
+ :width: 80%
+ :widths: 10, 20, 30
+ :header-rows: 1
+ :stub-columns: 1
+
+ "Treat", "Quantity", "Description"
+ "Albatross", 2.99, "On a stick!"
+ "Crunchy Frog", 1.49, "If we took the bones out, it wouldn\'t be
+ crunchy, now would it?"
+ "Gannet Ripple", 1.99, "On a stick!"
+""",
+"""\
+<document source="test data">
+ <table classes="colwidths-given" width="80%">
+ <title>
+ inline with integral header
+ <tgroup cols="3">
+ <colspec colwidth="10" stub="1">
+ <colspec colwidth="20">
+ <colspec colwidth="30">
+ <thead>
+ <row>
+ <entry>
+ <paragraph>
+ Treat
+ <entry>
+ <paragraph>
+ Quantity
+ <entry>
+ <paragraph>
+ Description
+ <tbody>
+ <row>
+ <entry>
+ <paragraph>
+ Albatross
+ <entry>
+ <paragraph>
+ 2.99
+ <entry>
+ <paragraph>
+ On a stick!
+ <row>
+ <entry>
+ <paragraph>
+ Crunchy Frog
+ <entry>
+ <paragraph>
+ 1.49
+ <entry>
+ <paragraph>
+ If we took the bones out, it wouldn't be
+ crunchy, now would it?
+ <row>
+ <entry>
+ <paragraph>
+ Gannet Ripple
+ <entry>
+ <paragraph>
+ 1.99
+ <entry>
+ <paragraph>
+ On a stick!
+"""],
+["""\
+.. csv-table:: inline with separate header
+ :header: "Treat", Quantity, "Description"
+ :widths: 10,20,30
+
+ "Albatross", 2.99, "On a stick!"
+""",
+"""\
+<document source="test data">
+ <table classes="colwidths-given">
+ <title>
+ inline with separate header
+ <tgroup cols="3">
+ <colspec colwidth="10">
+ <colspec colwidth="20">
+ <colspec colwidth="30">
+ <thead>
+ <row>
+ <entry>
+ <paragraph>
+ Treat
+ <entry>
+ <paragraph>
+ Quantity
+ <entry>
+ <paragraph>
+ Description
+ <tbody>
+ <row>
+ <entry>
+ <paragraph>
+ Albatross
+ <entry>
+ <paragraph>
+ 2.99
+ <entry>
+ <paragraph>
+ On a stick!
+"""],
+["""\
+.. csv-table:: complex internal structure
+ :header: "Treat", Quantity, "
+ * Description,
+ * Definition, or
+ * Narrative"
+
+ "
+ * Ice cream
+ * Sorbet
+ * Albatross", 2.99, "On a stick!"
+""",
+"""\
+<document source="test data">
+ <table>
+ <title>
+ complex internal structure
+ <tgroup cols="3">
+ <colspec colwidth="33">
+ <colspec colwidth="33">
+ <colspec colwidth="33">
+ <thead>
+ <row>
+ <entry>
+ <paragraph>
+ Treat
+ <entry>
+ <paragraph>
+ Quantity
+ <entry>
+ <bullet_list bullet="*">
+ <list_item>
+ <paragraph>
+ Description,
+ <list_item>
+ <paragraph>
+ Definition, or
+ <list_item>
+ <paragraph>
+ Narrative
+ <tbody>
+ <row>
+ <entry>
+ <bullet_list bullet="*">
+ <list_item>
+ <paragraph>
+ Ice cream
+ <list_item>
+ <paragraph>
+ Sorbet
+ <list_item>
+ <paragraph>
+ Albatross
+ <entry>
+ <paragraph>
+ 2.99
+ <entry>
+ <paragraph>
+ On a stick!
+"""],
+["""\
+.. csv-table:: short rows
+
+ one, 2, three
+ 4, five
+""",
+"""\
+<document source="test data">
+ <table>
+ <title>
+ short rows
+ <tgroup cols="3">
+ <colspec colwidth="33">
+ <colspec colwidth="33">
+ <colspec colwidth="33">
+ <tbody>
+ <row>
+ <entry>
+ <paragraph>
+ one
+ <entry>
+ <paragraph>
+ 2
+ <entry>
+ <paragraph>
+ three
+ <row>
+ <entry>
+ <paragraph>
+ 4
+ <entry>
+ <paragraph>
+ five
+ <entry>
+"""],
+["""\
+.. csv-table:: short rows
+ :header-rows: 1
+
+ header col 1, header col 2
+ one, 2, three
+ 4
+""",
+"""\
+<document source="test data">
+ <table>
+ <title>
+ short rows
+ <tgroup cols="3">
+ <colspec colwidth="33">
+ <colspec colwidth="33">
+ <colspec colwidth="33">
+ <thead>
+ <row>
+ <entry>
+ <paragraph>
+ header col 1
+ <entry>
+ <paragraph>
+ header col 2
+ <entry>
+ <tbody>
+ <row>
+ <entry>
+ <paragraph>
+ one
+ <entry>
+ <paragraph>
+ 2
+ <entry>
+ <paragraph>
+ three
+ <row>
+ <entry>
+ <paragraph>
+ 4
+ <entry>
+ <entry>
+"""],
+[u"""\
+.. csv-table:: non-ASCII characters
+
+ Heiz\xf6lr\xfccksto\xdfabd\xe4mpfung
+""",
+u"""\
+<document source="test data">
+ <table>
+ <title>
+ non-ASCII characters
+ <tgroup cols="1">
+ <colspec colwidth="100">
+ <tbody>
+ <row>
+ <entry>
+ <paragraph>
+ Heiz\xf6lr\xfccksto\xdfabd\xe4mpfung
+"""],
+["""\
+.. csv-table:: center aligned
+ :align: center
+
+ 11, 12
+ 21, 22
+""",
+"""\
+<document source="test data">
+ <table align="center">
+ <title>
+ center aligned
+ <tgroup cols="2">
+ <colspec colwidth="50">
+ <colspec colwidth="50">
+ <tbody>
+ <row>
+ <entry>
+ <paragraph>
+ 11
+ <entry>
+ <paragraph>
+ 12
+ <row>
+ <entry>
+ <paragraph>
+ 21
+ <entry>
+ <paragraph>
+ 22
+"""],
+["""\
+.. csv-table:: empty
+""",
+"""\
+<document source="test data">
+ <system_message level="2" line="1" source="test data" type="WARNING">
+ <paragraph>
+ The "csv-table" directive requires content; none supplied.
+ <literal_block xml:space="preserve">
+ .. csv-table:: empty
+"""],
+["""\
+.. csv-table:: insufficient header row data
+ :header-rows: 2
+
+ some, csv, data
+""",
+"""\
+<document source="test data">
+ <system_message level="3" line="1" source="test data" type="ERROR">
+ <paragraph>
+ 2 header row(s) specified but only 1 row(s) of data supplied ("csv-table" directive).
+ <literal_block xml:space="preserve">
+ .. csv-table:: insufficient header row data
+ :header-rows: 2
+ \n\
+ some, csv, data
+"""],
+["""\
+.. csv-table:: insufficient body data
+ :header-rows: 1
+
+ some, csv, data
+""",
+"""\
+<document source="test data">
+ <system_message level="3" line="1" source="test data" type="ERROR">
+ <paragraph>
+ Insufficient data supplied (1 row(s)); no data remaining for table body, required by "csv-table" directive.
+ <literal_block xml:space="preserve">
+ .. csv-table:: insufficient body data
+ :header-rows: 1
+ \n\
+ some, csv, data
+"""],
+["""\
+.. csv-table:: content and external
+ :file: bogus.csv
+
+ some, csv, data
+""",
+"""\
+<document source="test data">
+ <system_message level="3" line="1" source="test data" type="ERROR">
+ <paragraph>
+ "csv-table" directive may not both specify an external file and have content.
+ <literal_block xml:space="preserve">
+ .. csv-table:: content and external
+ :file: bogus.csv
+ \n\
+ some, csv, data
+"""],
+["""\
+.. csv-table:: external file and url
+ :file: bogus.csv
+ :url: http://example.org/bogus.csv
+""",
+"""\
+<document source="test data">
+ <system_message level="3" line="1" source="test data" type="ERROR">
+ <paragraph>
+ The "file" and "url" options may not be simultaneously specified for the "csv-table" directive.
+ <literal_block xml:space="preserve">
+ .. csv-table:: external file and url
+ :file: bogus.csv
+ :url: http://example.org/bogus.csv
+"""],
+["""\
+.. csv-table:: error in the *title
+
+ some, csv, data
+""",
+"""\
+<document source="test data">
+ <table>
+ <title>
+ error in the \n\
+ <problematic ids="id2" refid="id1">
+ *
+ title
+ <tgroup cols="3">
+ <colspec colwidth="33">
+ <colspec colwidth="33">
+ <colspec colwidth="33">
+ <tbody>
+ <row>
+ <entry>
+ <paragraph>
+ some
+ <entry>
+ <paragraph>
+ csv
+ <entry>
+ <paragraph>
+ data
+ <system_message backrefs="id2" ids="id1" level="2" line="1" source="test data" type="WARNING">
+ <paragraph>
+ Inline emphasis start-string without end-string.
+"""],
+["""\
+.. csv-table:: no such file
+ :file: bogus.csv
+""",
+"""\
+<document source="test data">
+ <system_message level="4" line="1" source="test data" type="SEVERE">
+ <paragraph>
+ Problems with "csv-table" directive path:
+ [Errno 2] No such file or directory: 'bogus.csv'.
+ <literal_block xml:space="preserve">
+ .. csv-table:: no such file
+ :file: bogus.csv
+"""],
+# note that this output is rewritten below for certain python versions
+["""\
+.. csv-table:: bad URL
+ :url: bogus.csv
+""",
+"""\
+<document source="test data">
+ <system_message level="4" line="1" source="test data" type="SEVERE">
+ <paragraph>
+ Problems with "csv-table" directive URL "bogus.csv":
+ unknown url type: %s.
+ <literal_block xml:space="preserve">
+ .. csv-table:: bad URL
+ :url: bogus.csv
+""" % csv_unknown_url],
+["""\
+.. csv-table:: column mismatch
+ :widths: 10,20
+
+ some, csv, data
+""",
+"""\
+<document source="test data">
+ <system_message level="3" line="1" source="test data" type="ERROR">
+ <paragraph>
+ "csv-table" widths do not match the number of columns in table (3).
+ <literal_block xml:space="preserve">
+ .. csv-table:: column mismatch
+ :widths: 10,20
+ \n\
+ some, csv, data
+"""],
+["""\
+.. csv-table:: bad column widths
+ :widths: 10,y,z
+
+ some, csv, data
+
+.. csv-table:: bad column widths
+ :widths: 0 0 0
+
+ some, csv, data
+""",
+"""\
+<document source="test data">
+ <system_message level="3" line="1" source="test data" type="ERROR">
+ <paragraph>
+ Error in "csv-table" directive:
+ invalid option value: (option: "widths"; value: '10,y,z')
+ %s.
+ <literal_block xml:space="preserve">
+ .. csv-table:: bad column widths
+ :widths: 10,y,z
+ \n\
+ some, csv, data
+ <system_message level="3" line="6" source="test data" type="ERROR">
+ <paragraph>
+ Error in "csv-table" directive:
+ invalid option value: (option: "widths"; value: '0 0 0')
+ negative or zero value; must be positive.
+ <literal_block xml:space="preserve">
+ .. csv-table:: bad column widths
+ :widths: 0 0 0
+ \n\
+ some, csv, data
+""" % DocutilsTestSupport.exception_data(int, u"y")[1][0]],
+["""\
+.. csv-table:: good delimiter
+ :delim: /
+
+ some/csv/data
+
+.. csv-table:: good delimiter
+ :delim: \\
+
+ some\\csv\\data
+
+.. csv-table:: good delimiter
+ :delim: 0x5c
+
+ some\\csv\\data
+
+.. csv-table:: good delimiter
+ :delim: space
+
+ some csv data
+""",
+"""\
+<document source="test data">
+ <table>
+ <title>
+ good delimiter
+ <tgroup cols="3">
+ <colspec colwidth="33">
+ <colspec colwidth="33">
+ <colspec colwidth="33">
+ <tbody>
+ <row>
+ <entry>
+ <paragraph>
+ some
+ <entry>
+ <paragraph>
+ csv
+ <entry>
+ <paragraph>
+ data
+ <table>
+ <title>
+ good delimiter
+ <tgroup cols="3">
+ <colspec colwidth="33">
+ <colspec colwidth="33">
+ <colspec colwidth="33">
+ <tbody>
+ <row>
+ <entry>
+ <paragraph>
+ some
+ <entry>
+ <paragraph>
+ csv
+ <entry>
+ <paragraph>
+ data
+ <table>
+ <title>
+ good delimiter
+ <tgroup cols="3">
+ <colspec colwidth="33">
+ <colspec colwidth="33">
+ <colspec colwidth="33">
+ <tbody>
+ <row>
+ <entry>
+ <paragraph>
+ some
+ <entry>
+ <paragraph>
+ csv
+ <entry>
+ <paragraph>
+ data
+ <table>
+ <title>
+ good delimiter
+ <tgroup cols="3">
+ <colspec colwidth="33">
+ <colspec colwidth="33">
+ <colspec colwidth="33">
+ <tbody>
+ <row>
+ <entry>
+ <paragraph>
+ some
+ <entry>
+ <paragraph>
+ csv
+ <entry>
+ <paragraph>
+ data
+"""],
+["""\
+.. csv-table:: bad delimiter
+ :delim: multiple
+
+.. csv-table:: bad delimiter
+ :delim: U+9999999999999
+""",
+"""\
+<document source="test data">
+ <system_message level="3" line="1" source="test data" type="ERROR">
+ <paragraph>
+ Error in "csv-table" directive:
+ invalid option value: (option: "delim"; value: 'multiple')
+ 'multiple' invalid; must be a single character or a Unicode code.
+ <literal_block xml:space="preserve">
+ .. csv-table:: bad delimiter
+ :delim: multiple
+ <system_message level="3" line="4" source="test data" type="ERROR">
+ <paragraph>
+ Error in "csv-table" directive:
+ invalid option value: (option: "delim"; value: 'U+9999999999999')
+ %s.
+ <literal_block xml:space="preserve">
+ .. csv-table:: bad delimiter
+ :delim: U+9999999999999
+""" % unichr_exception_string],
+["""\
+.. csv-table:: bad CSV data
+
+ "bad", \"csv, data
+""",
+"""\
+<document source="test data">
+ <system_message level="3" line="1" source="test data" type="ERROR">
+ <paragraph>
+ Error with CSV data in "csv-table" directive:
+ %s
+ <literal_block xml:space="preserve">
+ .. csv-table:: bad CSV data
+ \n\
+ "bad", \"csv, data
+""" % csv_eod_error_str],
+["""\
+.. csv-table:: bad CSV header data
+ :header: "bad", \"csv, data
+
+ good, csv, data
+""",
+"""\
+<document source="test data">
+ <system_message level="3" line="1" source="test data" type="ERROR">
+ <paragraph>
+ Error with CSV data in "csv-table" directive:
+ %s
+ <literal_block xml:space="preserve">
+ .. csv-table:: bad CSV header data
+ :header: "bad", \"csv, data
+ \n\
+ good, csv, data
+""" % csv_eod_error_str],
+["""\
+.. csv-table:: bad encoding
+ :file: %s
+ :encoding: latin-1
+
+(7- and 8-bit text encoded as UTF-16 has lots of null/zero bytes.)
+""" % utf_16_csv,
+"""\
+<document source="test data">
+ <system_message level="3" line="1" source="test data" type="ERROR">
+ <paragraph>
+ Error with CSV data in "csv-table" directive:
+ %s
+ <literal_block xml:space="preserve">
+ .. csv-table:: bad encoding
+ :file: %s
+ :encoding: latin-1
+ <paragraph>
+ (7- and 8-bit text encoded as UTF-16 has lots of null/zero bytes.)
+""" % (null_bytes_exception, utf_16_csv)],
+["""\
+.. csv-table:: good encoding
+ :file: %s
+ :encoding: utf-16
+ :header-rows: 1
+""" % utf_16_csv,
+u"""\
+<document source="test data">
+ <table>
+ <title>
+ good encoding
+ <tgroup cols="3">
+ <colspec colwidth="33">
+ <colspec colwidth="33">
+ <colspec colwidth="33">
+ <thead>
+ <row>
+ <entry>
+ <paragraph>
+ Treat
+ <entry>
+ <paragraph>
+ Quantity
+ <entry>
+ <paragraph>
+ Description
+ <tbody>
+ <row>
+ <entry>
+ <paragraph>
+ Albatr\u00b0\u00df
+ <entry>
+ <paragraph>
+ 2.99
+ <entry>
+ <paragraph>
+ \u00a1On a \u03c3\u03c4\u03b9\u03ba!
+ <row>
+ <entry>
+ <paragraph>
+ Crunchy Frog
+ <entry>
+ <paragraph>
+ 1.49
+ <entry>
+ <paragraph>
+ If we took the b\u00f6nes out, it wouldn\u2019t be
+ crunchy, now would it?
+ <row>
+ <entry>
+ <paragraph>
+ Gannet Ripple
+ <entry>
+ <paragraph>
+ 1.99
+ <entry>
+ <paragraph>
+ \u00bfOn a \u03c3\u03c4\u03b9\u03ba?
+"""],
+["""\
+.. csv-table:: no CSV data
+ :file: %s
+""" % empty_txt,
+"""\
+<document source="test data">
+ <system_message level="3" line="1" source="test data" type="ERROR">
+ <paragraph>
+ No table data detected in CSV file.
+ <literal_block xml:space="preserve">
+ .. csv-table:: no CSV data
+ :file: %s
+""" % empty_txt],
+]
+
+totest['list-table'] = [
+["""\
+.. list-table:: list table with integral header
+ :widths: 10 20 30
+ :header-rows: 1
+ :stub-columns: 1
+
+ * - Treat
+ - Quantity
+ - Description
+ * - Albatross
+ - 2.99
+ - On a stick!
+ * - Crunchy Frog
+ - 1.49
+ - If we took the bones out, it wouldn\'t be
+ crunchy, now would it?
+ * - Gannet Ripple
+ - 1.99
+ - On a stick!
+""",
+"""\
+<document source="test data">
+ <table classes="colwidths-given">
+ <title>
+ list table with integral header
+ <tgroup cols="3">
+ <colspec colwidth="10" stub="1">
+ <colspec colwidth="20">
+ <colspec colwidth="30">
+ <thead>
+ <row>
+ <entry>
+ <paragraph>
+ Treat
+ <entry>
+ <paragraph>
+ Quantity
+ <entry>
+ <paragraph>
+ Description
+ <tbody>
+ <row>
+ <entry>
+ <paragraph>
+ Albatross
+ <entry>
+ <paragraph>
+ 2.99
+ <entry>
+ <paragraph>
+ On a stick!
+ <row>
+ <entry>
+ <paragraph>
+ Crunchy Frog
+ <entry>
+ <paragraph>
+ 1.49
+ <entry>
+ <paragraph>
+ If we took the bones out, it wouldn\'t be
+ crunchy, now would it?
+ <row>
+ <entry>
+ <paragraph>
+ Gannet Ripple
+ <entry>
+ <paragraph>
+ 1.99
+ <entry>
+ <paragraph>
+ On a stick!
+"""],
+["""\
+.. list-table:: list table with integral header
+ :widths: auto
+ :header-rows: 1
+ :stub-columns: 1
+
+ * - Treat
+ - Quantity
+ - Description
+ * - Albatross
+ - 2.99
+ - On a stick!
+""",
+"""\
+<document source="test data">
+ <table classes="colwidths-auto">
+ <title>
+ list table with integral header
+ <tgroup cols="3">
+ <colspec colwidth="33" stub="1">
+ <colspec colwidth="33">
+ <colspec colwidth="33">
+ <thead>
+ <row>
+ <entry>
+ <paragraph>
+ Treat
+ <entry>
+ <paragraph>
+ Quantity
+ <entry>
+ <paragraph>
+ Description
+ <tbody>
+ <row>
+ <entry>
+ <paragraph>
+ Albatross
+ <entry>
+ <paragraph>
+ 2.99
+ <entry>
+ <paragraph>
+ On a stick!
+"""],
+["""\
+.. list-table:: list table with integral header
+ :header-rows: 1
+ :stub-columns: 1
+
+ * - Treat
+ - Quantity
+ - Description
+ * - Albatross
+ - 2.99
+ - On a stick!
+ * - Crunchy Frog
+ - 1.49
+ - If we took the bones out, it wouldn\'t be
+ crunchy, now would it?
+ * - Gannet Ripple
+ - 1.99
+ - On a stick!
+""",
+"""\
+<document source="test data">
+ <table>
+ <title>
+ list table with integral header
+ <tgroup cols="3">
+ <colspec colwidth="33" stub="1">
+ <colspec colwidth="33">
+ <colspec colwidth="33">
+ <thead>
+ <row>
+ <entry>
+ <paragraph>
+ Treat
+ <entry>
+ <paragraph>
+ Quantity
+ <entry>
+ <paragraph>
+ Description
+ <tbody>
+ <row>
+ <entry>
+ <paragraph>
+ Albatross
+ <entry>
+ <paragraph>
+ 2.99
+ <entry>
+ <paragraph>
+ On a stick!
+ <row>
+ <entry>
+ <paragraph>
+ Crunchy Frog
+ <entry>
+ <paragraph>
+ 1.49
+ <entry>
+ <paragraph>
+ If we took the bones out, it wouldn\'t be
+ crunchy, now would it?
+ <row>
+ <entry>
+ <paragraph>
+ Gannet Ripple
+ <entry>
+ <paragraph>
+ 1.99
+ <entry>
+ <paragraph>
+ On a stick!
+"""],
+["""\
+.. list-table:: center aligned
+ :align: center
+
+ * - 11
+ - 12
+ * - 21
+ - 22
+""",
+"""\
+<document source="test data">
+ <table align="center">
+ <title>
+ center aligned
+ <tgroup cols="2">
+ <colspec colwidth="50">
+ <colspec colwidth="50">
+ <tbody>
+ <row>
+ <entry>
+ <paragraph>
+ 11
+ <entry>
+ <paragraph>
+ 12
+ <row>
+ <entry>
+ <paragraph>
+ 21
+ <entry>
+ <paragraph>
+ 22
+"""],
+["""\
+.. list-table::
+
+ not a bullet list
+""",
+"""\
+<document source="test data">
+ <system_message level="3" line="1" source="test data" type="ERROR">
+ <paragraph>
+ Error parsing content block for the "list-table" directive: exactly one bullet list expected.
+ <literal_block xml:space="preserve">
+ .. list-table::
+ \n\
+ not a bullet list
+"""],
+["""\
+.. list-table::
+
+ * not a second-level bullet list
+""",
+"""\
+<document source="test data">
+ <system_message level="3" line="1" source="test data" type="ERROR">
+ <paragraph>
+ Error parsing content block for the "list-table" directive: two-level bullet list expected, but row 1 does not contain a second-level bullet list.
+ <literal_block xml:space="preserve">
+ .. list-table::
+ \n\
+ * not a second-level bullet list
+"""],
+["""\
+.. list-table::
+
+ * - columns not uniform
+ * - first row has one,
+ - second row has two
+""",
+"""\
+<document source="test data">
+ <system_message level="3" line="1" source="test data" type="ERROR">
+ <paragraph>
+ Error parsing content block for the "list-table" directive: uniform two-level bullet list expected, but row 2 does not contain the same number of items as row 1 (2 vs 1).
+ <literal_block xml:space="preserve">
+ .. list-table::
+ \n\
+ * - columns not uniform
+ * - first row has one,
+ - second row has two
+"""],
+["""\
+.. list-table::
+ :widths: 10 20
+
+ * - ":widths:" option doesn't match columns
+""",
+"""\
+<document source="test data">
+ <system_message level="3" line="1" source="test data" type="ERROR">
+ <paragraph>
+ "list-table" widths do not match the number of columns in table (1).
+ <literal_block xml:space="preserve">
+ .. list-table::
+ :widths: 10 20
+ \n\
+ * - ":widths:" option doesn\'t match columns
+"""],
+["""\
+.. list-table::
+ :stub-columns: 3
+
+ * - column 1
+ - column 2
+""",
+"""\
+<document source="test data">
+ <system_message level="3" line="1" source="test data" type="ERROR">
+ <paragraph>
+ 3 stub column(s) specified but only 2 columns(s) of data supplied ("list-table" directive).
+ <literal_block xml:space="preserve">
+ .. list-table::
+ :stub-columns: 3
+ \n\
+ * - column 1
+ - column 2
+"""],
+["""\
+.. list-table::
+ :stub-columns: 2
+
+ * - column 1
+ - column 2
+""",
+"""\
+<document source="test data">
+ <system_message level="3" line="1" source="test data" type="ERROR">
+ <paragraph>
+ Insufficient data supplied (2 columns(s)); no data remaining for table body, required by "list-table" directive.
+ <literal_block xml:space="preserve">
+ .. list-table::
+ :stub-columns: 2
+ \n\
+ * - column 1
+ - column 2
+"""],
+["""\
+.. list-table:: empty
+""",
+"""\
+<document source="test data">
+ <system_message level="3" line="1" source="test data" type="ERROR">
+ <paragraph>
+ The "list-table" directive is empty; content required.
+ <literal_block xml:space="preserve">
+ .. list-table:: empty
+"""],
+]
+
+
+if __name__ == '__main__':
+ import unittest
+ unittest.main(defaultTest='suite')
--- /dev/null
+#! /usr/bin/env python
+
+# $Id: test_target_notes.py 8356 2019-08-26 16:44:19Z milde $
+# Author: David Goodger <goodger@python.org>
+# Copyright: This module has been placed in the public domain.
+
+"""
+Tests for the target-notes directives.
+"""
+from __future__ import absolute_import
+
+from . import DocutilsTestSupport
+
+
+def suite():
+ s = DocutilsTestSupport.ParserTestSuite()
+ s.generateTests(totest)
+ return s
+
+totest = {}
+
+totest['target-notes'] = [
+["""\
+.. target-notes::
+""",
+"""\
+<document source="test data">
+ <pending>
+ .. internal attributes:
+ .transform: docutils.transforms.references.TargetNotes
+ .details:
+"""],
+["""\
+.. target-notes:: :class: custom
+""",
+"""\
+<document source="test data">
+ <pending>
+ .. internal attributes:
+ .transform: docutils.transforms.references.TargetNotes
+ .details:
+ class: ['custom']
+"""],
+["""\
+.. target-notes::
+ :class: custom
+ :name: targets
+""",
+"""\
+<document source="test data">
+ <pending ids="targets" names="targets">
+ .. internal attributes:
+ .transform: docutils.transforms.references.TargetNotes
+ .details:
+ class: ['custom']
+"""],
+["""\
+.. target-notes::
+ :class:
+""",
+"""\
+<document source="test data">
+ <system_message level="3" line="1" source="test data" type="ERROR">
+ <paragraph>
+ Error in "target-notes" directive:
+ invalid option value: (option: "class"; value: None)
+ argument required but none supplied.
+ <literal_block xml:space="preserve">
+ .. target-notes::
+ :class:
+"""],
+]
+
+
+if __name__ == '__main__':
+ import unittest
+ unittest.main(defaultTest='suite')
--- /dev/null
+#! /usr/bin/env python
+
+# $Id: test_test_directives.py 8356 2019-08-26 16:44:19Z milde $
+# Author: David Goodger <goodger@python.org>
+# Copyright: This module has been placed in the public domain.
+
+"""
+Tests for misc.py test directives.
+"""
+from __future__ import absolute_import
+
+from . import DocutilsTestSupport
+
+
+def suite():
+ s = DocutilsTestSupport.ParserTestSuite()
+ s.generateTests(totest)
+ return s
+
+totest = {}
+
+totest['test_directives'] = [
+["""\
+.. reStructuredText-test-directive::
+
+Paragraph.
+""",
+"""\
+<document source="test data">
+ <system_message level="1" line="1" source="test data" type="INFO">
+ <paragraph>
+ Directive processed. Type="reStructuredText-test-directive", arguments=[], options={}, content: None
+ <paragraph>
+ Paragraph.
+"""],
+["""\
+.. reStructuredText-test-directive ::
+
+An optional space before the "::".
+""",
+"""\
+<document source="test data">
+ <system_message level="1" line="1" source="test data" type="INFO">
+ <paragraph>
+ Directive processed. Type="reStructuredText-test-directive", arguments=[], options={}, content: None
+ <paragraph>
+ An optional space before the "::".
+"""],
+["""\
+.. reStructuredText-test-directive:: argument
+
+Paragraph.
+""",
+"""\
+<document source="test data">
+ <system_message level="1" line="1" source="test data" type="INFO">
+ <paragraph>
+ Directive processed. Type="reStructuredText-test-directive", arguments=['argument'], options={}, content: None
+ <paragraph>
+ Paragraph.
+"""],
+["""\
+.. reStructuredText-test-directive:: argument
+ :option: value
+
+Paragraph.
+""",
+"""\
+<document source="test data">
+ <system_message level="1" line="1" source="test data" type="INFO">
+ <paragraph>
+ Directive processed. Type="reStructuredText-test-directive", arguments=['argument'], options={'option': 'value'}, content: None
+ <paragraph>
+ Paragraph.
+"""],
+["""\
+.. reStructuredText-test-directive:: :option: value
+
+Paragraph.
+""",
+"""\
+<document source="test data">
+ <system_message level="1" line="1" source="test data" type="INFO">
+ <paragraph>
+ Directive processed. Type="reStructuredText-test-directive", arguments=[], options={'option': 'value'}, content: None
+ <paragraph>
+ Paragraph.
+"""],
+["""\
+.. reStructuredText-test-directive:: :option:
+
+Paragraph.
+""",
+"""\
+<document source="test data">
+ <system_message level="3" line="1" source="test data" type="ERROR">
+ <paragraph>
+ Error in "reStructuredText-test-directive" directive:
+ invalid option value: (option: "option"; value: None)
+ argument required but none supplied.
+ <literal_block xml:space="preserve">
+ .. reStructuredText-test-directive:: :option:
+ <paragraph>
+ Paragraph.
+"""],
+["""\
+.. reStructuredText-test-directive::
+
+ Directive block contains one paragraph, with a blank line before.
+
+Paragraph.
+""",
+"""\
+<document source="test data">
+ <system_message level="1" line="1" source="test data" type="INFO">
+ <paragraph>
+ Directive processed. Type="reStructuredText-test-directive", arguments=[], options={}, content:
+ <literal_block xml:space="preserve">
+ Directive block contains one paragraph, with a blank line before.
+ <paragraph>
+ Paragraph.
+"""],
+["""\
+.. reStructuredText-test-directive::
+
+
+ Directive block contains one paragraph, with two blank lines before.
+
+Paragraph.
+""",
+"""\
+<document source="test data">
+ <system_message level="1" line="1" source="test data" type="INFO">
+ <paragraph>
+ Directive processed. Type="reStructuredText-test-directive", arguments=[], options={}, content:
+ <literal_block xml:space="preserve">
+ Directive block contains one paragraph, with two blank lines before.
+ <paragraph>
+ Paragraph.
+"""],
+["""\
+.. reStructuredText-test-directive::
+ Directive block contains one paragraph, no blank line before.
+
+Paragraph.
+""",
+"""\
+<document source="test data">
+ <system_message level="1" line="1" source="test data" type="INFO">
+ <paragraph>
+ Directive processed. Type="reStructuredText-test-directive", arguments=['Directive block contains one paragraph, no blank line before.'], options={}, content: None
+ <paragraph>
+ Paragraph.
+"""],
+["""\
+.. reStructuredText-test-directive::
+ block
+no blank line.
+
+Paragraph.
+""",
+"""\
+<document source="test data">
+ <system_message level="1" line="1" source="test data" type="INFO">
+ <paragraph>
+ Directive processed. Type="reStructuredText-test-directive", arguments=['block'], options={}, content: None
+ <system_message level="2" line="3" source="test data" type="WARNING">
+ <paragraph>
+ Explicit markup ends without a blank line; unexpected unindent.
+ <paragraph>
+ no blank line.
+ <paragraph>
+ Paragraph.
+"""],
+["""\
+.. reStructuredText-test-directive:: argument
+ :option: * value1
+ * value2
+
+Paragraph.
+""",
+"""\
+<document source="test data">
+ <system_message level="1" line="1" source="test data" type="INFO">
+ <paragraph>
+ Directive processed. Type="reStructuredText-test-directive", arguments=['argument'], options={'option': '* value1\\n* value2'}, content: None
+ <paragraph>
+ Paragraph.
+"""],
+["""\
+.. reStructuredText-test-directive::
+
+ Directive \\block \\*contains* \\\\backslashes.
+""",
+"""\
+<document source="test data">
+ <system_message level="1" line="1" source="test data" type="INFO">
+ <paragraph>
+ Directive processed. Type="reStructuredText-test-directive", arguments=[], options={}, content:
+ <literal_block xml:space="preserve">
+ Directive \\block \\*contains* \\\\backslashes.
+"""],
+]
+
+
+if __name__ == '__main__':
+ import unittest
+ unittest.main(defaultTest='suite')
--- /dev/null
+#! /usr/bin/env python
+
+# $Id: test_title.py 8356 2019-08-26 16:44:19Z milde $
+# Author: Lea Wiemann <LeWiemann@gmail.com>
+# Copyright: This module has been placed in the public domain.
+
+"""
+Tests for the 'title' directive.
+"""
+from __future__ import absolute_import
+
+from . import DocutilsTestSupport
+
+
+def suite():
+ s = DocutilsTestSupport.ParserTestSuite()
+ s.generateTests(totest)
+ return s
+
+totest = {}
+
+totest['title'] = [
+["""\
+.. title:: This is the document title.
+""",
+"""\
+<document source="test data" title="This is the document title.">
+"""],
+]
+
+
+if __name__ == '__main__':
+ import unittest
+ unittest.main(defaultTest='suite')
--- /dev/null
+#! /usr/bin/env python
+
+# $Id: test_topics.py 8356 2019-08-26 16:44:19Z milde $
+# Author: David Goodger <goodger@python.org>
+# Copyright: This module has been placed in the public domain.
+
+"""
+Tests for the "topic" directive.
+"""
+from __future__ import absolute_import
+
+from . import DocutilsTestSupport
+
+
+def suite():
+ s = DocutilsTestSupport.ParserTestSuite()
+ s.generateTests(totest)
+ return s
+
+totest = {}
+
+totest['topics'] = [
+["""\
+.. topic::
+""",
+"""\
+<document source="test data">
+ <system_message level="3" line="1" source="test data" type="ERROR">
+ <paragraph>
+ Error in "topic" directive:
+ 1 argument(s) required, 0 supplied.
+ <literal_block xml:space="preserve">
+ .. topic::
+"""],
+["""\
+.. topic:: Title
+""",
+"""\
+<document source="test data">
+ <system_message level="3" line="1" source="test data" type="ERROR">
+ <paragraph>
+ Content block expected for the "topic" directive; none found.
+ <literal_block xml:space="preserve">
+ .. topic:: Title
+"""],
+["""\
+.. topic:: Title
+
+ Body.
+""",
+"""\
+<document source="test data">
+ <topic>
+ <title>
+ Title
+ <paragraph>
+ Body.
+"""],
+["""\
+.. topic:: With Options
+ :class: custom
+ :name: my point
+
+ Body.
+""",
+"""\
+<document source="test data">
+ <topic classes="custom" ids="my-point" names="my\\ point">
+ <title>
+ With Options
+ <paragraph>
+ Body.
+"""],
+["""\
+.. topic::
+
+ Title
+
+ Body.
+""",
+"""\
+<document source="test data">
+ <system_message level="3" line="1" source="test data" type="ERROR">
+ <paragraph>
+ Error in "topic" directive:
+ 1 argument(s) required, 0 supplied.
+ <literal_block xml:space="preserve">
+ .. topic::
+ \n\
+ Title
+ \n\
+ Body.
+"""],
+["""\
+.. topic:: Title
+ Body.
+""",
+"""\
+<document source="test data">
+ <system_message level="3" line="1" source="test data" type="ERROR">
+ <paragraph>
+ Content block expected for the "topic" directive; none found.
+ <literal_block xml:space="preserve">
+ .. topic:: Title
+ Body.
+"""],
+["""\
+.. topic::
+
+ Title
+ Body.
+""",
+"""\
+<document source="test data">
+ <system_message level="3" line="1" source="test data" type="ERROR">
+ <paragraph>
+ Error in "topic" directive:
+ 1 argument(s) required, 0 supplied.
+ <literal_block xml:space="preserve">
+ .. topic::
+ \n\
+ Title
+ Body.
+"""],
+["""\
+.. topic:: Title
+
+ .. topic:: Nested
+
+ Body.
+""",
+"""\
+<document source="test data">
+ <topic>
+ <title>
+ Title
+ <system_message level="3" line="3" source="test data" type="ERROR">
+ <paragraph>
+ The "topic" directive may not be used within topics or body elements.
+ <literal_block xml:space="preserve">
+ .. topic:: Nested
+ \n\
+ Body.
+"""],
+["""\
+.. topic:: Title
+
+ .. topic:: Nested
+
+ Body.
+ More.
+""",
+"""\
+<document source="test data">
+ <topic>
+ <title>
+ Title
+ <system_message level="3" line="3" source="test data" type="ERROR">
+ <paragraph>
+ The "topic" directive may not be used within topics or body elements.
+ <literal_block xml:space="preserve">
+ .. topic:: Nested
+ \n\
+ Body.
+ <system_message level="2" line="6" source="test data" type="WARNING">
+ <paragraph>
+ Explicit markup ends without a blank line; unexpected unindent.
+ <paragraph>
+ More.
+"""],
+["""\
+.. topic:: Title
+
+ .. topic:: Nested
+
+ Body.
+
+ More.
+
+More.
+""",
+"""\
+<document source="test data">
+ <topic>
+ <title>
+ Title
+ <system_message level="3" line="3" source="test data" type="ERROR">
+ <paragraph>
+ The "topic" directive may not be used within topics or body elements.
+ <literal_block xml:space="preserve">
+ .. topic:: Nested
+ \n\
+ Body.
+ <paragraph>
+ More.
+ <paragraph>
+ More.
+"""],
+["""\
+.. topic:: First
+
+ Body
+
+.. topic:: Second
+
+ Body.
+""",
+"""\
+<document source="test data">
+ <topic>
+ <title>
+ First
+ <paragraph>
+ Body
+ <topic>
+ <title>
+ Second
+ <paragraph>
+ Body.
+"""],
+["""\
+.. sidebar:: Title
+ :subtitle: Outer
+
+ .. topic:: Nested
+
+ Body.
+
+ More.
+
+More.
+""",
+"""\
+<document source="test data">
+ <sidebar>
+ <title>
+ Title
+ <subtitle>
+ Outer
+ <topic>
+ <title>
+ Nested
+ <paragraph>
+ Body.
+ <paragraph>
+ More.
+ <paragraph>
+ More.
+"""],
+]
+
+
+if __name__ == '__main__':
+ import unittest
+ unittest.main(defaultTest='suite')
--- /dev/null
+#! /usr/bin/env python
+
+# $Id: test_unicode.py 8367 2019-08-27 12:09:56Z milde $
+# Author: David Goodger <goodger@python.org>
+# Copyright: This module has been placed in the public domain.
+
+"""
+Tests for misc.py "unicode" directive.
+"""
+from __future__ import absolute_import
+
+import sys
+
+from . import DocutilsTestSupport
+
+
+if sys.version_info >= (3, 0):
+ unichr = chr # noqa
+
+
+def suite():
+ s = DocutilsTestSupport.ParserTestSuite()
+ s.generateTests(totest)
+ return s
+
+unichr_exception = DocutilsTestSupport.exception_data(
+ unichr, int("111111111111111111", 16))[0]
+if isinstance(unichr_exception, OverflowError):
+ unichr_exception_string = 'code too large (%s)' % unichr_exception
+else:
+ unichr_exception_string = str(unichr_exception)
+
+totest = {}
+
+totest['unicode'] = [
+["""
+Insert an em-dash (|mdash|), a copyright symbol (|copy|), a non-breaking
+space (|nbsp|), a backwards-not-equals (|bne|), and a captial omega (|Omega|).
+
+.. |mdash| unicode:: 0x02014
+.. |copy| unicode:: \\u00A9
+.. |nbsp| unicode::  
+.. |bne| unicode:: U0003D U020E5
+.. |Omega| unicode:: U+003A9
+""",
+u"""\
+<document source="test data">
+ <paragraph>
+ Insert an em-dash (
+ <substitution_reference refname="mdash">
+ mdash
+ ), a copyright symbol (
+ <substitution_reference refname="copy">
+ copy
+ ), a non-breaking
+ space (
+ <substitution_reference refname="nbsp">
+ nbsp
+ ), a backwards-not-equals (
+ <substitution_reference refname="bne">
+ bne
+ ), and a captial omega (
+ <substitution_reference refname="Omega">
+ Omega
+ ).
+ <substitution_definition names="mdash">
+ \u2014
+ <substitution_definition names="copy">
+ \u00A9
+ <substitution_definition names="nbsp">
+ \u00A0
+ <substitution_definition names="bne">
+ =
+ \u20e5
+ <substitution_definition names="Omega">
+ \u03a9
+"""],
+["""
+Bad input:
+
+.. |empty| unicode::
+.. |empty too| unicode:: .. comment doesn't count as content
+.. |not hex| unicode:: 0xHEX
+.. |not all hex| unicode:: UABCX
+.. unicode:: not in a substitution definition
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ Bad input:
+ <system_message level="3" line="4" source="test data" type="ERROR">
+ <paragraph>
+ Error in "unicode" directive:
+ 1 argument(s) required, 0 supplied.
+ <literal_block xml:space="preserve">
+ unicode::
+ <system_message level="2" line="4" source="test data" type="WARNING">
+ <paragraph>
+ Substitution definition "empty" empty or invalid.
+ <literal_block xml:space="preserve">
+ .. |empty| unicode::
+ <system_message level="2" line="5" source="test data" type="WARNING">
+ <paragraph>
+ Substitution definition "empty too" empty or invalid.
+ <literal_block xml:space="preserve">
+ .. |empty too| unicode:: .. comment doesn't count as content
+ <substitution_definition names="not\\ hex">
+ 0xHEX
+ <substitution_definition names="not\\ all\\ hex">
+ UABCX
+ <system_message level="3" line="8" source="test data" type="ERROR">
+ <paragraph>
+ Invalid context: the "unicode" directive can only be used within a substitution definition.
+ <literal_block xml:space="preserve">
+ .. unicode:: not in a substitution definition
+"""],
+["""
+Testing comments and extra text.
+
+Copyright |copy| 2003, |BogusMegaCorp (TM)|.
+
+.. |copy| unicode:: 0xA9 .. copyright sign
+.. |BogusMegaCorp (TM)| unicode:: BogusMegaCorp U+2122
+ .. with trademark sign
+""",
+u"""\
+<document source="test data">
+ <paragraph>
+ Testing comments and extra text.
+ <paragraph>
+ Copyright
+ <substitution_reference refname="copy">
+ copy
+ 2003,
+ <substitution_reference refname="BogusMegaCorp (TM)">
+ BogusMegaCorp (TM)
+ .
+ <substitution_definition names="copy">
+ \u00A9
+ <substitution_definition names="BogusMegaCorp\\ (TM)">
+ BogusMegaCorp
+ \u2122
+"""],
+["""
+.. |too big for int| unicode:: 0x111111111111111111
+.. |too big for unicode| unicode:: 0x11111111
+""",
+"""\
+<document source="test data">
+ <system_message level="3" line="2" source="test data" type="ERROR">
+ <paragraph>
+ Invalid character code: 0x111111111111111111
+ ValueError: %s
+ <literal_block xml:space="preserve">
+ unicode:: 0x111111111111111111
+ <system_message level="2" line="2" source="test data" type="WARNING">
+ <paragraph>
+ Substitution definition "too big for int" empty or invalid.
+ <literal_block xml:space="preserve">
+ .. |too big for int| unicode:: 0x111111111111111111
+ <system_message level="3" line="3" source="test data" type="ERROR">
+ <paragraph>
+ Invalid character code: 0x11111111
+ %s
+ <literal_block xml:space="preserve">
+ unicode:: 0x11111111
+ <system_message level="2" line="3" source="test data" type="WARNING">
+ <paragraph>
+ Substitution definition "too big for unicode" empty or invalid.
+ <literal_block xml:space="preserve">
+ .. |too big for unicode| unicode:: 0x11111111
+""" % (unichr_exception_string,
+ DocutilsTestSupport.exception_data(unichr, int("11111111", 16))[2])]
+]
+
+
+if __name__ == '__main__':
+ import unittest
+ unittest.main(defaultTest='suite')
--- /dev/null
+#! /usr/bin/env python
+
+# $Id: test_unknown.py 8356 2019-08-26 16:44:19Z milde $
+# Author: David Goodger <goodger@python.org>
+# Copyright: This module has been placed in the public domain.
+
+"""
+Tests for unknown directives.
+"""
+from __future__ import absolute_import
+
+from . import DocutilsTestSupport
+
+
+def suite():
+ s = DocutilsTestSupport.ParserTestSuite()
+ s.generateTests(totest)
+ return s
+
+totest = {}
+
+totest['unknown'] = [
+["""\
+.. reStructuredText-unknown-directive::
+
+.. reStructuredText-unknown-directive:: argument
+
+.. reStructuredText-unknown-directive::
+ block
+""",
+"""\
+<document source="test data">
+ <system_message level="1" line="1" source="test data" type="INFO">
+ <paragraph>
+ No directive entry for "reStructuredText-unknown-directive" in module "docutils.parsers.rst.languages.en".
+ Trying "reStructuredText-unknown-directive" as canonical directive name.
+ <system_message level="3" line="1" source="test data" type="ERROR">
+ <paragraph>
+ Unknown directive type "reStructuredText-unknown-directive".
+ <literal_block xml:space="preserve">
+ .. reStructuredText-unknown-directive::
+ <system_message level="1" line="3" source="test data" type="INFO">
+ <paragraph>
+ No directive entry for "reStructuredText-unknown-directive" in module "docutils.parsers.rst.languages.en".
+ Trying "reStructuredText-unknown-directive" as canonical directive name.
+ <system_message level="3" line="3" source="test data" type="ERROR">
+ <paragraph>
+ Unknown directive type "reStructuredText-unknown-directive".
+ <literal_block xml:space="preserve">
+ .. reStructuredText-unknown-directive:: argument
+ <system_message level="1" line="5" source="test data" type="INFO">
+ <paragraph>
+ No directive entry for "reStructuredText-unknown-directive" in module "docutils.parsers.rst.languages.en".
+ Trying "reStructuredText-unknown-directive" as canonical directive name.
+ <system_message level="3" line="5" source="test data" type="ERROR">
+ <paragraph>
+ Unknown directive type "reStructuredText-unknown-directive".
+ <literal_block xml:space="preserve">
+ .. reStructuredText-unknown-directive::
+ block
+"""],
+]
+
+
+if __name__ == '__main__':
+ import unittest
+ unittest.main(defaultTest='suite')
--- /dev/null
+#! /usr/bin/env python
+
+# $Id: test_doctest_blocks.py 8356 2019-08-26 16:44:19Z milde $
+# Author: David Goodger <goodger@python.org>
+# Copyright: This module has been placed in the public domain.
+
+"""
+Tests for states.py.
+"""
+from __future__ import absolute_import
+
+from . import DocutilsTestSupport
+
+
+def suite():
+ s = DocutilsTestSupport.ParserTestSuite()
+ s.generateTests(totest)
+ return s
+
+totest = {}
+
+totest['doctest_blocks'] = [
+["""\
+Paragraph.
+
+>>> print("Doctest block.")
+Doctest block.
+
+Paragraph.
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ Paragraph.
+ <doctest_block xml:space="preserve">
+ >>> print("Doctest block.")
+ Doctest block.
+ <paragraph>
+ Paragraph.
+"""],
+["""\
+Paragraph.
+
+>>> print(" Indented output.")
+ Indented output.
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ Paragraph.
+ <doctest_block xml:space="preserve">
+ >>> print(" Indented output.")
+ Indented output.
+"""],
+["""\
+Paragraph.
+
+ >>> print(" Indented block & output.")
+ Indented block & output.
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ Paragraph.
+ <block_quote>
+ <doctest_block xml:space="preserve">
+ >>> print(" Indented block & output.")
+ Indented block & output.
+"""],
+]
+
+if __name__ == '__main__':
+ import unittest
+ unittest.main(defaultTest='suite')
--- /dev/null
+#! /usr/bin/env python
+# -*- coding: utf-8 -*-
+
+# $Id: test_east_asian_text.py 8366 2019-08-27 12:09:19Z milde $
+# Author: David Goodger <goodger@python.org>
+# Copyright: This module has been placed in the public domain.
+
+"""
+Tests for East Asian text with double-width characters.
+"""
+from __future__ import absolute_import
+
+from . import DocutilsTestSupport
+
+import unicodedata
+
+try:
+ east_asian_width = unicodedata.east_asian_width
+except AttributeError:
+ east_asian_width = None
+
+
+def suite():
+ s = DocutilsTestSupport.ParserTestSuite()
+ s.generateTests(totest)
+ return s
+
+totest = {}
+
+totest['double-width'] = [
+[u"""\
+タイトル1
+=========
+
+タイトル2
+========
+""",
+u"""\
+<document source="test data">
+ <section ids="id1" names="タイトル1">
+ <title>
+ タイトル1
+ <section ids="id2" names="タイトル2">
+ <title>
+ タイトル2
+ <system_message level="2" line="5" source="test data" type="WARNING">
+ <paragraph>
+ Title underline too short.
+ <literal_block xml:space="preserve">
+ タイトル2
+ ========
+"""],
+[u"""
++-----------------------+
+| * ヒョウ:ダイ1ギョウ |
+| * ダイ2ギョウ |
++-----------------------+
+| \\* ダイ1ギョウ |
+| * ダイ2ギョウ |
++-----------------------+
+""",
+u"""\
+<document source="test data">
+ <table>
+ <tgroup cols="1">
+ <colspec colwidth="23">
+ <tbody>
+ <row>
+ <entry>
+ <bullet_list bullet="*">
+ <list_item>
+ <paragraph>
+ ヒョウ:ダイ1ギョウ
+ <list_item>
+ <paragraph>
+ ダイ2ギョウ
+ <row>
+ <entry>
+ <paragraph>
+ * ダイ1ギョウ
+ * ダイ2ギョウ
+"""],
+[u"""\
+Complex spanning pattern (no edge knows all rows/cols):
+
++--------+---------------------+
+| 北西・ | 北・北東セル |
+| 西セル +--------------+------+
+| | 真ん中のセル | 東・ |
++--------+--------------+ 南東 |
+| 南西・南セル | セル |
++-----------------------+------+
+""",
+u"""\
+<document source="test data">
+ <paragraph>
+ Complex spanning pattern (no edge knows all rows/cols):
+ <table>
+ <tgroup cols="3">
+ <colspec colwidth="8">
+ <colspec colwidth="14">
+ <colspec colwidth="6">
+ <tbody>
+ <row>
+ <entry morerows="1">
+ <paragraph>
+ 北西・
+ 西セル
+ <entry morecols="1">
+ <paragraph>
+ 北・北東セル
+ <row>
+ <entry>
+ <paragraph>
+ 真ん中のセル
+ <entry morerows="1">
+ <paragraph>
+ 東・
+ 南東
+ セル
+ <row>
+ <entry morecols="1">
+ <paragraph>
+ 南西・南セル
+"""],
+[u"""\
+========= =========
+ダイ1ラン ダイ2ラン
+========= =========
+
+======== =========
+ダイ1ラン ダイ2ラン
+======== =========
+""",
+u"""\
+<document source="test data">
+ <table>
+ <tgroup cols="2">
+ <colspec colwidth="9">
+ <colspec colwidth="9">
+ <tbody>
+ <row>
+ <entry>
+ <paragraph>
+ ダイ1ラン
+ <entry>
+ <paragraph>
+ ダイ2ラン
+ <system_message level="3" line="6" source="test data" type="ERROR">
+ <paragraph>
+ Malformed table.
+ Text in column margin in table line 2.
+ <literal_block xml:space="preserve">
+ ======== =========
+ ダイ1ラン ダイ2ラン
+ ======== =========
+"""],
+[u"""\
+Some ambiguous-width characters:
+
+= ===================================
+© copyright sign
+® registered sign
+« left pointing guillemet
+» right pointing guillemet
+– en-dash
+— em-dash
+‘ single turned comma quotation mark
+’ single comma quotation mark
+‚ low single comma quotation mark
+“ double turned comma quotation mark
+” double comma quotation mark
+„ low double comma quotation mark
+† dagger
+‡ double dagger
+… ellipsis
+™ trade mark sign
+⇔ left-right double arrow
+= ===================================
+""",
+b"""\
+<document source="test data">
+ <paragraph>
+ Some ambiguous-width characters:
+ <table>
+ <tgroup cols="2">
+ <colspec colwidth="1">
+ <colspec colwidth="35">
+ <tbody>
+ <row>
+ <entry>
+ <paragraph>
+ \xa9
+ <entry>
+ <paragraph>
+ copyright sign
+ <row>
+ <entry>
+ <paragraph>
+ \xae
+ <entry>
+ <paragraph>
+ registered sign
+ <row>
+ <entry>
+ <paragraph>
+ \xab
+ <entry>
+ <paragraph>
+ left pointing guillemet
+ <row>
+ <entry>
+ <paragraph>
+ \xbb
+ <entry>
+ <paragraph>
+ right pointing guillemet
+ <row>
+ <entry>
+ <paragraph>
+ \\u2013
+ <entry>
+ <paragraph>
+ en-dash
+ <row>
+ <entry>
+ <paragraph>
+ \\u2014
+ <entry>
+ <paragraph>
+ em-dash
+ <row>
+ <entry>
+ <paragraph>
+ \\u2018
+ <entry>
+ <paragraph>
+ single turned comma quotation mark
+ <row>
+ <entry>
+ <paragraph>
+ \\u2019
+ <entry>
+ <paragraph>
+ single comma quotation mark
+ <row>
+ <entry>
+ <paragraph>
+ \\u201a
+ <entry>
+ <paragraph>
+ low single comma quotation mark
+ <row>
+ <entry>
+ <paragraph>
+ \\u201c
+ <entry>
+ <paragraph>
+ double turned comma quotation mark
+ <row>
+ <entry>
+ <paragraph>
+ \\u201d
+ <entry>
+ <paragraph>
+ double comma quotation mark
+ <row>
+ <entry>
+ <paragraph>
+ \\u201e
+ <entry>
+ <paragraph>
+ low double comma quotation mark
+ <row>
+ <entry>
+ <paragraph>
+ \\u2020
+ <entry>
+ <paragraph>
+ dagger
+ <row>
+ <entry>
+ <paragraph>
+ \\u2021
+ <entry>
+ <paragraph>
+ double dagger
+ <row>
+ <entry>
+ <paragraph>
+ \\u2026
+ <entry>
+ <paragraph>
+ ellipsis
+ <row>
+ <entry>
+ <paragraph>
+ \\u2122
+ <entry>
+ <paragraph>
+ trade mark sign
+ <row>
+ <entry>
+ <paragraph>
+ \\u21d4
+ <entry>
+ <paragraph>
+ left-right double arrow
+""".decode('raw_unicode_escape')],
+]
+'''
+[u"""\
+""",
+u"""\
+"""],
+'''
+
+
+if __name__ == '__main__':
+ import unittest
+ unittest.main(defaultTest='suite')
--- /dev/null
+#! /usr/bin/env python
+
+# $Id: test_enumerated_lists.py 8356 2019-08-26 16:44:19Z milde $
+# Author: David Goodger <goodger@python.org>
+# Copyright: This module has been placed in the public domain.
+
+"""
+Tests for states.py.
+"""
+from __future__ import absolute_import
+
+from . import DocutilsTestSupport
+
+
+def suite():
+ s = DocutilsTestSupport.ParserTestSuite()
+ s.generateTests(totest)
+ return s
+
+totest = {}
+
+totest['enumerated_lists'] = [
+["""\
+1. Item one.
+
+2. Item two.
+
+3. Item three.
+""",
+"""\
+<document source="test data">
+ <enumerated_list enumtype="arabic" prefix="" suffix=".">
+ <list_item>
+ <paragraph>
+ Item one.
+ <list_item>
+ <paragraph>
+ Item two.
+ <list_item>
+ <paragraph>
+ Item three.
+"""],
+["""\
+No blank lines betwen items:
+
+1. Item one.
+2. Item two.
+3. Item three.
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ No blank lines betwen items:
+ <enumerated_list enumtype="arabic" prefix="" suffix=".">
+ <list_item>
+ <paragraph>
+ Item one.
+ <list_item>
+ <paragraph>
+ Item two.
+ <list_item>
+ <paragraph>
+ Item three.
+"""],
+["""\
+1.
+empty item above, no blank line
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ 1.
+ empty item above, no blank line
+"""],
+["""\
+Scrambled:
+
+3. Item three.
+
+2. Item two.
+
+1. Item one.
+
+3. Item three.
+2. Item two.
+1. Item one.
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ Scrambled:
+ <enumerated_list enumtype="arabic" prefix="" start="3" suffix=".">
+ <list_item>
+ <paragraph>
+ Item three.
+ <system_message level="1" line="3" source="test data" type="INFO">
+ <paragraph>
+ Enumerated list start value not ordinal-1: "3" (ordinal 3)
+ <enumerated_list enumtype="arabic" prefix="" start="2" suffix=".">
+ <list_item>
+ <paragraph>
+ Item two.
+ <system_message level="1" line="5" source="test data" type="INFO">
+ <paragraph>
+ Enumerated list start value not ordinal-1: "2" (ordinal 2)
+ <enumerated_list enumtype="arabic" prefix="" suffix=".">
+ <list_item>
+ <paragraph>
+ Item one.
+ <paragraph>
+ 3. Item three.
+ 2. Item two.
+ 1. Item one.
+"""],
+["""\
+Skipping item 3:
+
+1. Item 1.
+2. Item 2.
+4. Item 4.
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ Skipping item 3:
+ <enumerated_list enumtype="arabic" prefix="" suffix=".">
+ <list_item>
+ <paragraph>
+ Item 1.
+ <system_message level="2" line="4" source="test data" type="WARNING">
+ <paragraph>
+ Enumerated list ends without a blank line; unexpected unindent.
+ <paragraph>
+ 2. Item 2.
+ 4. Item 4.
+"""],
+["""\
+Start with non-ordinal-1:
+
+0. Item zero.
+1. Item one.
+2. Item two.
+3. Item three.
+
+And again:
+
+2. Item two.
+3. Item three.
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ Start with non-ordinal-1:
+ <enumerated_list enumtype="arabic" prefix="" start="0" suffix=".">
+ <list_item>
+ <paragraph>
+ Item zero.
+ <list_item>
+ <paragraph>
+ Item one.
+ <list_item>
+ <paragraph>
+ Item two.
+ <list_item>
+ <paragraph>
+ Item three.
+ <system_message level="1" line="3" source="test data" type="INFO">
+ <paragraph>
+ Enumerated list start value not ordinal-1: "0" (ordinal 0)
+ <paragraph>
+ And again:
+ <enumerated_list enumtype="arabic" prefix="" start="2" suffix=".">
+ <list_item>
+ <paragraph>
+ Item two.
+ <list_item>
+ <paragraph>
+ Item three.
+ <system_message level="1" line="10" source="test data" type="INFO">
+ <paragraph>
+ Enumerated list start value not ordinal-1: "2" (ordinal 2)
+"""],
+["""\
+1. Item one: line 1,
+ line 2.
+2. Item two: line 1,
+ line 2.
+3. Item three: paragraph 1, line 1,
+ line 2.
+
+ Paragraph 2.
+""",
+"""\
+<document source="test data">
+ <enumerated_list enumtype="arabic" prefix="" suffix=".">
+ <list_item>
+ <paragraph>
+ Item one: line 1,
+ line 2.
+ <list_item>
+ <paragraph>
+ Item two: line 1,
+ line 2.
+ <list_item>
+ <paragraph>
+ Item three: paragraph 1, line 1,
+ line 2.
+ <paragraph>
+ Paragraph 2.
+"""],
+["""\
+Different enumeration sequences:
+
+1. Item 1.
+2. Item 2.
+3. Item 3.
+
+A. Item A.
+B. Item B.
+C. Item C.
+
+a. Item a.
+b. Item b.
+c. Item c.
+
+I. Item I.
+II. Item II.
+III. Item III.
+
+i. Item i.
+ii. Item ii.
+iii. Item iii.
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ Different enumeration sequences:
+ <enumerated_list enumtype="arabic" prefix="" suffix=".">
+ <list_item>
+ <paragraph>
+ Item 1.
+ <list_item>
+ <paragraph>
+ Item 2.
+ <list_item>
+ <paragraph>
+ Item 3.
+ <enumerated_list enumtype="upperalpha" prefix="" suffix=".">
+ <list_item>
+ <paragraph>
+ Item A.
+ <list_item>
+ <paragraph>
+ Item B.
+ <list_item>
+ <paragraph>
+ Item C.
+ <enumerated_list enumtype="loweralpha" prefix="" suffix=".">
+ <list_item>
+ <paragraph>
+ Item a.
+ <list_item>
+ <paragraph>
+ Item b.
+ <list_item>
+ <paragraph>
+ Item c.
+ <enumerated_list enumtype="upperroman" prefix="" suffix=".">
+ <list_item>
+ <paragraph>
+ Item I.
+ <list_item>
+ <paragraph>
+ Item II.
+ <list_item>
+ <paragraph>
+ Item III.
+ <enumerated_list enumtype="lowerroman" prefix="" suffix=".">
+ <list_item>
+ <paragraph>
+ Item i.
+ <list_item>
+ <paragraph>
+ Item ii.
+ <list_item>
+ <paragraph>
+ Item iii.
+"""],
+["""\
+Bad Roman numerals:
+
+i. i
+
+ii. ii
+
+iii. iii
+
+iiii. iiii
+ second line
+
+(LCD) is an acronym made up of Roman numerals
+
+(livid) is a word made up of Roman numerals
+
+(CIVIL) is another such word
+
+(I) I
+
+(IVXLCDM) IVXLCDM
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ Bad Roman numerals:
+ <enumerated_list enumtype="lowerroman" prefix="" suffix=".">
+ <list_item>
+ <paragraph>
+ i
+ <list_item>
+ <paragraph>
+ ii
+ <list_item>
+ <paragraph>
+ iii
+ <definition_list>
+ <definition_list_item>
+ <term>
+ iiii. iiii
+ <definition>
+ <paragraph>
+ second line
+ <paragraph>
+ (LCD) is an acronym made up of Roman numerals
+ <paragraph>
+ (livid) is a word made up of Roman numerals
+ <paragraph>
+ (CIVIL) is another such word
+ <enumerated_list enumtype="upperroman" prefix="(" suffix=")">
+ <list_item>
+ <paragraph>
+ I
+ <paragraph>
+ (IVXLCDM) IVXLCDM
+"""],
+["""\
+Potentially ambiguous cases:
+
+A. Item A.
+B. Item B.
+C. Item C.
+
+I. Item I.
+II. Item II.
+III. Item III.
+
+a. Item a.
+b. Item b.
+c. Item c.
+
+i. Item i.
+ii. Item ii.
+iii. Item iii.
+
+Phew! Safe!
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ Potentially ambiguous cases:
+ <enumerated_list enumtype="upperalpha" prefix="" suffix=".">
+ <list_item>
+ <paragraph>
+ Item A.
+ <list_item>
+ <paragraph>
+ Item B.
+ <list_item>
+ <paragraph>
+ Item C.
+ <enumerated_list enumtype="upperroman" prefix="" suffix=".">
+ <list_item>
+ <paragraph>
+ Item I.
+ <list_item>
+ <paragraph>
+ Item II.
+ <list_item>
+ <paragraph>
+ Item III.
+ <enumerated_list enumtype="loweralpha" prefix="" suffix=".">
+ <list_item>
+ <paragraph>
+ Item a.
+ <list_item>
+ <paragraph>
+ Item b.
+ <list_item>
+ <paragraph>
+ Item c.
+ <enumerated_list enumtype="lowerroman" prefix="" suffix=".">
+ <list_item>
+ <paragraph>
+ Item i.
+ <list_item>
+ <paragraph>
+ Item ii.
+ <list_item>
+ <paragraph>
+ Item iii.
+ <paragraph>
+ Phew! Safe!
+"""],
+["""\
+Definitely ambiguous:
+
+A. Item A.
+B. Item B.
+C. Item C.
+D. Item D.
+E. Item E.
+F. Item F.
+G. Item G.
+H. Item H.
+I. Item I.
+II. Item II.
+III. Item III.
+
+a. Item a.
+b. Item b.
+c. Item c.
+d. Item d.
+e. Item e.
+f. Item f.
+g. Item g.
+h. Item h.
+i. Item i.
+ii. Item ii.
+iii. Item iii.
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ Definitely ambiguous:
+ <enumerated_list enumtype="upperalpha" prefix="" suffix=".">
+ <list_item>
+ <paragraph>
+ Item A.
+ <list_item>
+ <paragraph>
+ Item B.
+ <list_item>
+ <paragraph>
+ Item C.
+ <list_item>
+ <paragraph>
+ Item D.
+ <list_item>
+ <paragraph>
+ Item E.
+ <list_item>
+ <paragraph>
+ Item F.
+ <list_item>
+ <paragraph>
+ Item G.
+ <list_item>
+ <paragraph>
+ Item H.
+ <system_message level="2" line="11" source="test data" type="WARNING">
+ <paragraph>
+ Enumerated list ends without a blank line; unexpected unindent.
+ <enumerated_list enumtype="upperroman" prefix="" suffix=".">
+ <list_item>
+ <paragraph>
+ Item I.
+ <list_item>
+ <paragraph>
+ Item II.
+ <list_item>
+ <paragraph>
+ Item III.
+ <enumerated_list enumtype="loweralpha" prefix="" suffix=".">
+ <list_item>
+ <paragraph>
+ Item a.
+ <list_item>
+ <paragraph>
+ Item b.
+ <list_item>
+ <paragraph>
+ Item c.
+ <list_item>
+ <paragraph>
+ Item d.
+ <list_item>
+ <paragraph>
+ Item e.
+ <list_item>
+ <paragraph>
+ Item f.
+ <list_item>
+ <paragraph>
+ Item g.
+ <list_item>
+ <paragraph>
+ Item h.
+ <system_message level="2" line="23" source="test data" type="WARNING">
+ <paragraph>
+ Enumerated list ends without a blank line; unexpected unindent.
+ <enumerated_list enumtype="lowerroman" prefix="" suffix=".">
+ <list_item>
+ <paragraph>
+ Item i.
+ <list_item>
+ <paragraph>
+ Item ii.
+ <list_item>
+ <paragraph>
+ Item iii.
+"""],
+["""\
+Different enumeration formats:
+
+1. Item 1.
+2. Item 2.
+3. Item 3.
+
+1) Item 1).
+2) Item 2).
+3) Item 3).
+
+(1) Item (1).
+(2) Item (2).
+(3) Item (3).
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ Different enumeration formats:
+ <enumerated_list enumtype="arabic" prefix="" suffix=".">
+ <list_item>
+ <paragraph>
+ Item 1.
+ <list_item>
+ <paragraph>
+ Item 2.
+ <list_item>
+ <paragraph>
+ Item 3.
+ <enumerated_list enumtype="arabic" prefix="" suffix=")">
+ <list_item>
+ <paragraph>
+ Item 1).
+ <list_item>
+ <paragraph>
+ Item 2).
+ <list_item>
+ <paragraph>
+ Item 3).
+ <enumerated_list enumtype="arabic" prefix="(" suffix=")">
+ <list_item>
+ <paragraph>
+ Item (1).
+ <list_item>
+ <paragraph>
+ Item (2).
+ <list_item>
+ <paragraph>
+ Item (3).
+"""],
+["""\
+Nested enumerated lists:
+
+1. Item 1.
+
+ A) Item A).
+ B) Item B).
+ C) Item C).
+
+2. Item 2.
+
+ (a) Item (a).
+
+ I) Item I).
+ II) Item II).
+ III) Item III).
+
+ (b) Item (b).
+
+ (c) Item (c).
+
+ (i) Item (i).
+ (ii) Item (ii).
+ (iii) Item (iii).
+
+3. Item 3.
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ Nested enumerated lists:
+ <enumerated_list enumtype="arabic" prefix="" suffix=".">
+ <list_item>
+ <paragraph>
+ Item 1.
+ <enumerated_list enumtype="upperalpha" prefix="" suffix=")">
+ <list_item>
+ <paragraph>
+ Item A).
+ <list_item>
+ <paragraph>
+ Item B).
+ <list_item>
+ <paragraph>
+ Item C).
+ <list_item>
+ <paragraph>
+ Item 2.
+ <enumerated_list enumtype="loweralpha" prefix="(" suffix=")">
+ <list_item>
+ <paragraph>
+ Item (a).
+ <enumerated_list enumtype="upperroman" prefix="" suffix=")">
+ <list_item>
+ <paragraph>
+ Item I).
+ <list_item>
+ <paragraph>
+ Item II).
+ <list_item>
+ <paragraph>
+ Item III).
+ <list_item>
+ <paragraph>
+ Item (b).
+ <list_item>
+ <paragraph>
+ Item (c).
+ <enumerated_list enumtype="lowerroman" prefix="(" suffix=")">
+ <list_item>
+ <paragraph>
+ Item (i).
+ <list_item>
+ <paragraph>
+ Item (ii).
+ <list_item>
+ <paragraph>
+ Item (iii).
+ <list_item>
+ <paragraph>
+ Item 3.
+"""],
+[u"""\
+A. Einstein was a great influence on
+B. Physicist, who was a colleague of
+C. Chemist. They all worked in
+Princeton, NJ.
+
+Using a non-breaking space as a workaround:
+
+A.\u00a0Einstein was a great influence on
+B. Physicist, who was a colleague of
+C. Chemist. They all worked in
+Princeton, NJ.
+""",
+"""\
+<document source="test data">
+ <enumerated_list enumtype="upperalpha" prefix="" suffix=".">
+ <list_item>
+ <paragraph>
+ Einstein was a great influence on
+ <list_item>
+ <paragraph>
+ Physicist, who was a colleague of
+ <system_message level="2" line="3" source="test data" type="WARNING">
+ <paragraph>
+ Enumerated list ends without a blank line; unexpected unindent.
+ <paragraph>
+ C. Chemist. They all worked in
+ Princeton, NJ.
+ <paragraph>
+ Using a non-breaking space as a workaround:
+ <paragraph>
+ A.\xa0Einstein was a great influence on
+ B. Physicist, who was a colleague of
+ C. Chemist. They all worked in
+ Princeton, NJ.
+"""],
+["""\
+1. Item one: line 1,
+ line 2.
+2. Item two: line 1,
+ line 2.
+3. Item three: paragraph 1, line 1,
+ line 2.
+
+ Paragraph 2.
+""",
+"""\
+<document source="test data">
+ <enumerated_list enumtype="arabic" prefix="" suffix=".">
+ <list_item>
+ <paragraph>
+ Item one: line 1,
+ line 2.
+ <list_item>
+ <paragraph>
+ Item two: line 1,
+ <system_message level="2" line="4" source="test data" type="WARNING">
+ <paragraph>
+ Enumerated list ends without a blank line; unexpected unindent.
+ <block_quote>
+ <paragraph>
+ line 2.
+ <system_message level="2" line="5" source="test data" type="WARNING">
+ <paragraph>
+ Block quote ends without a blank line; unexpected unindent.
+ <enumerated_list enumtype="arabic" prefix="" start="3" suffix=".">
+ <list_item>
+ <paragraph>
+ Item three: paragraph 1, line 1,
+ <system_message level="1" line="5" source="test data" type="INFO">
+ <paragraph>
+ Enumerated list start value not ordinal-1: "3" (ordinal 3)
+ <system_message level="2" line="6" source="test data" type="WARNING">
+ <paragraph>
+ Enumerated list ends without a blank line; unexpected unindent.
+ <block_quote>
+ <paragraph>
+ line 2.
+ <block_quote>
+ <paragraph>
+ Paragraph 2.
+"""],
+["""\
+1. Item one.
+
+#. Item two.
+
+#. Item three.
+""",
+"""\
+<document source="test data">
+ <enumerated_list enumtype="arabic" prefix="" suffix=".">
+ <list_item>
+ <paragraph>
+ Item one.
+ <list_item>
+ <paragraph>
+ Item two.
+ <list_item>
+ <paragraph>
+ Item three.
+"""],
+["""\
+a. Item one.
+#. Item two.
+#. Item three.
+""",
+"""\
+<document source="test data">
+ <enumerated_list enumtype="loweralpha" prefix="" suffix=".">
+ <list_item>
+ <paragraph>
+ Item one.
+ <list_item>
+ <paragraph>
+ Item two.
+ <list_item>
+ <paragraph>
+ Item three.
+"""],
+["""\
+i. Item one.
+ii. Item two.
+#. Item three.
+""",
+"""\
+<document source="test data">
+ <enumerated_list enumtype="lowerroman" prefix="" suffix=".">
+ <list_item>
+ <paragraph>
+ Item one.
+ <list_item>
+ <paragraph>
+ Item two.
+ <list_item>
+ <paragraph>
+ Item three.
+"""],
+["""\
+#. Item one.
+#. Item two.
+#. Item three.
+""",
+"""\
+<document source="test data">
+ <enumerated_list enumtype="arabic" prefix="" suffix=".">
+ <list_item>
+ <paragraph>
+ Item one.
+ <list_item>
+ <paragraph>
+ Item two.
+ <list_item>
+ <paragraph>
+ Item three.
+"""],
+["""\
+1. Item one.
+#. Item two.
+3. Item three.
+""",
+"""\
+<document source="test data">
+ <enumerated_list enumtype="arabic" prefix="" suffix=".">
+ <list_item>
+ <paragraph>
+ Item one.
+ <system_message level="2" line="2" source="test data" type="WARNING">
+ <paragraph>
+ Enumerated list ends without a blank line; unexpected unindent.
+ <paragraph>
+ #. Item two.
+ 3. Item three.
+"""],
+["""\
+z.
+x
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ z.
+ x
+"""],
+["""\
+3-space indent, with a trailing space:
+
+1. \n\
+ foo
+
+3-space indent, no trailing space:
+
+1.
+ foo
+
+2-space indent:
+
+1.
+ foo
+
+1-space indent:
+
+1.
+ foo
+
+0-space indent, not a list item:
+
+1.
+foo
+
+No item content:
+
+1.
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ 3-space indent, with a trailing space:
+ <enumerated_list enumtype="arabic" prefix="" suffix=".">
+ <list_item>
+ <paragraph>
+ foo
+ <paragraph>
+ 3-space indent, no trailing space:
+ <enumerated_list enumtype="arabic" prefix="" suffix=".">
+ <list_item>
+ <paragraph>
+ foo
+ <paragraph>
+ 2-space indent:
+ <enumerated_list enumtype="arabic" prefix="" suffix=".">
+ <list_item>
+ <paragraph>
+ foo
+ <paragraph>
+ 1-space indent:
+ <enumerated_list enumtype="arabic" prefix="" suffix=".">
+ <list_item>
+ <paragraph>
+ foo
+ <paragraph>
+ 0-space indent, not a list item:
+ <paragraph>
+ 1.
+ foo
+ <paragraph>
+ No item content:
+ <enumerated_list enumtype="arabic" prefix="" suffix=".">
+ <list_item>
+"""],
+]
+
+
+if __name__ == '__main__':
+ import unittest
+ unittest.main(defaultTest='suite')
--- /dev/null
+#! /usr/bin/env python
+
+# $Id: test_field_lists.py 8356 2019-08-26 16:44:19Z milde $
+# Author: David Goodger <goodger@python.org>
+# Copyright: This module has been placed in the public domain.
+
+"""
+Tests for states.py.
+"""
+from __future__ import absolute_import
+
+from . import DocutilsTestSupport
+
+
+def suite():
+ s = DocutilsTestSupport.ParserTestSuite()
+ s.generateTests(totest)
+ return s
+
+totest = {}
+
+totest['field_lists'] = [
+["""\
+One-liners:
+
+:Author: Me
+
+:Version: 1
+
+:Date: 2001-08-11
+
+:Parameter i: integer
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ One-liners:
+ <field_list>
+ <field>
+ <field_name>
+ Author
+ <field_body>
+ <paragraph>
+ Me
+ <field>
+ <field_name>
+ Version
+ <field_body>
+ <paragraph>
+ 1
+ <field>
+ <field_name>
+ Date
+ <field_body>
+ <paragraph>
+ 2001-08-11
+ <field>
+ <field_name>
+ Parameter i
+ <field_body>
+ <paragraph>
+ integer
+"""],
+["""\
+One-liners, no blank lines:
+
+:Author: Me
+:Version: 1
+:Date: 2001-08-11
+:Parameter i: integer
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ One-liners, no blank lines:
+ <field_list>
+ <field>
+ <field_name>
+ Author
+ <field_body>
+ <paragraph>
+ Me
+ <field>
+ <field_name>
+ Version
+ <field_body>
+ <paragraph>
+ 1
+ <field>
+ <field_name>
+ Date
+ <field_body>
+ <paragraph>
+ 2001-08-11
+ <field>
+ <field_name>
+ Parameter i
+ <field_body>
+ <paragraph>
+ integer
+"""],
+["""\
+:field:
+empty item above, no blank line
+""",
+"""\
+<document source="test data">
+ <field_list>
+ <field>
+ <field_name>
+ field
+ <field_body>
+ <system_message level="2" line="2" source="test data" type="WARNING">
+ <paragraph>
+ Field list ends without a blank line; unexpected unindent.
+ <paragraph>
+ empty item above, no blank line
+"""],
+["""\
+Field bodies starting on the next line:
+
+:Author:
+ Me
+:Version:
+ 1
+:Date:
+ 2001-08-11
+:Parameter i:
+ integer
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ Field bodies starting on the next line:
+ <field_list>
+ <field>
+ <field_name>
+ Author
+ <field_body>
+ <paragraph>
+ Me
+ <field>
+ <field_name>
+ Version
+ <field_body>
+ <paragraph>
+ 1
+ <field>
+ <field_name>
+ Date
+ <field_body>
+ <paragraph>
+ 2001-08-11
+ <field>
+ <field_name>
+ Parameter i
+ <field_body>
+ <paragraph>
+ integer
+"""],
+["""\
+One-paragraph, multi-liners:
+
+:Authors: Me,
+ Myself,
+ and I
+:Version: 1
+ or so
+:Date: 2001-08-11
+ (Saturday)
+:Parameter i: counter
+ (integer)
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ One-paragraph, multi-liners:
+ <field_list>
+ <field>
+ <field_name>
+ Authors
+ <field_body>
+ <paragraph>
+ Me,
+ Myself,
+ and I
+ <field>
+ <field_name>
+ Version
+ <field_body>
+ <paragraph>
+ 1
+ or so
+ <field>
+ <field_name>
+ Date
+ <field_body>
+ <paragraph>
+ 2001-08-11
+ (Saturday)
+ <field>
+ <field_name>
+ Parameter i
+ <field_body>
+ <paragraph>
+ counter
+ (integer)
+"""],
+["""\
+One-paragraph, multi-liners, not lined up:
+
+:Authors: Me,
+ Myself,
+ and I
+:Version: 1
+ or so
+:Date: 2001-08-11
+ (Saturday)
+:Parameter i: counter
+ (integer)
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ One-paragraph, multi-liners, not lined up:
+ <field_list>
+ <field>
+ <field_name>
+ Authors
+ <field_body>
+ <paragraph>
+ Me,
+ Myself,
+ and I
+ <field>
+ <field_name>
+ Version
+ <field_body>
+ <paragraph>
+ 1
+ or so
+ <field>
+ <field_name>
+ Date
+ <field_body>
+ <paragraph>
+ 2001-08-11
+ (Saturday)
+ <field>
+ <field_name>
+ Parameter i
+ <field_body>
+ <paragraph>
+ counter
+ (integer)
+"""],
+["""\
+Multiple body elements:
+
+:Authors: - Me
+ - Myself
+ - I
+
+:Abstract:
+ This is a field list item's body,
+ containing multiple elements.
+
+ Here's a literal block::
+
+ def f(x):
+ return x**2 + x
+
+ Even nested field lists are possible:
+
+ :Date: 2001-08-11
+ :Day: Saturday
+ :Time: 15:07
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ Multiple body elements:
+ <field_list>
+ <field>
+ <field_name>
+ Authors
+ <field_body>
+ <bullet_list bullet="-">
+ <list_item>
+ <paragraph>
+ Me
+ <list_item>
+ <paragraph>
+ Myself
+ <list_item>
+ <paragraph>
+ I
+ <field>
+ <field_name>
+ Abstract
+ <field_body>
+ <paragraph>
+ This is a field list item's body,
+ containing multiple elements.
+ <paragraph>
+ Here's a literal block:
+ <literal_block xml:space="preserve">
+ def f(x):
+ return x**2 + x
+ <paragraph>
+ Even nested field lists are possible:
+ <field_list>
+ <field>
+ <field_name>
+ Date
+ <field_body>
+ <paragraph>
+ 2001-08-11
+ <field>
+ <field_name>
+ Day
+ <field_body>
+ <paragraph>
+ Saturday
+ <field>
+ <field_name>
+ Time
+ <field_body>
+ <paragraph>
+ 15:07
+"""],
+["""\
+Nested field lists on one line:
+
+:field1: :field2: :field3: body
+:field4: :field5: :field6: body
+ :field7: body
+ :field8: body
+ :field9: body line 1
+ body line 2
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ Nested field lists on one line:
+ <field_list>
+ <field>
+ <field_name>
+ field1
+ <field_body>
+ <field_list>
+ <field>
+ <field_name>
+ field2
+ <field_body>
+ <field_list>
+ <field>
+ <field_name>
+ field3
+ <field_body>
+ <paragraph>
+ body
+ <field>
+ <field_name>
+ field4
+ <field_body>
+ <field_list>
+ <field>
+ <field_name>
+ field5
+ <field_body>
+ <field_list>
+ <field>
+ <field_name>
+ field6
+ <field_body>
+ <paragraph>
+ body
+ <field>
+ <field_name>
+ field7
+ <field_body>
+ <paragraph>
+ body
+ <field>
+ <field_name>
+ field8
+ <field_body>
+ <paragraph>
+ body
+ <field>
+ <field_name>
+ field9
+ <field_body>
+ <paragraph>
+ body line 1
+ body line 2
+"""],
+["""\
+:Parameter i j k: multiple arguments
+""",
+"""\
+<document source="test data">
+ <field_list>
+ <field>
+ <field_name>
+ Parameter i j k
+ <field_body>
+ <paragraph>
+ multiple arguments
+"""],
+["""\
+:Field *name* `with` **inline** ``markup``: inline markup in
+ field name is parsed.
+""",
+"""\
+<document source="test data">
+ <field_list>
+ <field>
+ <field_name>
+ Field \n\
+ <emphasis>
+ name
+ \n\
+ <title_reference>
+ with
+ \n\
+ <strong>
+ inline
+ \n\
+ <literal>
+ markup
+ <field_body>
+ <paragraph>
+ inline markup in
+ field name is parsed.
+"""],
+["""\
+:Field name with *bad inline markup: should generate warning.
+""",
+"""\
+<document source="test data">
+ <field_list>
+ <field>
+ <field_name>
+ Field name with \n\
+ <problematic ids="id2" refid="id1">
+ *
+ bad inline markup
+ <field_body>
+ <system_message backrefs="id2" ids="id1" level="2" line="1" source="test data" type="WARNING">
+ <paragraph>
+ Inline emphasis start-string without end-string.
+ <paragraph>
+ should generate warning.
+"""],
+[r"""Some edge cases:
+
+:Empty:
+:Author: Me
+No blank line before this paragraph.
+
+: Field: marker must not begin with whitespace.
+
+:Field : marker must not end with whitespace.
+
+Field: marker is missing its open-colon.
+
+:Field marker is missing its close-colon.
+
+:Field\: names\: with\: colons\:: are possible.
+
+:\\Field\ names with backslashes\\: are possible, too.
+
+:\\: A backslash.
+
+:Not a\\\: field list.
+
+:Not a \: field list either.
+
+:\: Not a field list either.
+
+:\:
+ A definition list, not a field list.
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ Some edge cases:
+ <field_list>
+ <field>
+ <field_name>
+ Empty
+ <field_body>
+ <field>
+ <field_name>
+ Author
+ <field_body>
+ <paragraph>
+ Me
+ <system_message level="2" line="5" source="test data" type="WARNING">
+ <paragraph>
+ Field list ends without a blank line; unexpected unindent.
+ <paragraph>
+ No blank line before this paragraph.
+ <paragraph>
+ : Field: marker must not begin with whitespace.
+ <paragraph>
+ :Field : marker must not end with whitespace.
+ <paragraph>
+ Field: marker is missing its open-colon.
+ <paragraph>
+ :Field marker is missing its close-colon.
+ <field_list>
+ <field>
+ <field_name>
+ Field: names: with: colons:
+ <field_body>
+ <paragraph>
+ are possible.
+ <field>
+ <field_name>
+ \\Field names with backslashes\\
+ <field_body>
+ <paragraph>
+ are possible, too.
+ <field>
+ <field_name>
+ \\
+ <field_body>
+ <paragraph>
+ A backslash.
+ <paragraph>
+ :Not a\\: field list.
+ <paragraph>
+ :Not a : field list either.
+ <paragraph>
+ :: Not a field list either.
+ <definition_list>
+ <definition_list_item>
+ <term>
+ ::
+ <definition>
+ <paragraph>
+ A definition list, not a field list.
+"""],
+[r"""
+:first: field
+:field:name:with:embedded:colons: unambiguous, no need for escapes
+
+..
+
+:embedded:colons: in first field name
+:field:\`:name: not interpreted text
+:field:\`name: not interpreted text
+""",
+"""\
+<document source="test data">
+ <field_list>
+ <field>
+ <field_name>
+ first
+ <field_body>
+ <paragraph>
+ field
+ <field>
+ <field_name>
+ field:name:with:embedded:colons
+ <field_body>
+ <paragraph>
+ unambiguous, no need for escapes
+ <comment xml:space="preserve">
+ <field_list>
+ <field>
+ <field_name>
+ embedded:colons
+ <field_body>
+ <paragraph>
+ in first field name
+ <field>
+ <field_name>
+ field:`:name
+ <field_body>
+ <paragraph>
+ not interpreted text
+ <field>
+ <field_name>
+ field:`name
+ <field_body>
+ <paragraph>
+ not interpreted text
+"""],
+[r"""
+Edge cases involving embedded colons and interpreted text.
+
+Recognized as field list items:
+
+:field\:`name`: interpreted text (standard role) requires
+ escaping a leading colon in a field name
+
+:field:name: unambiguous, no need for escapes
+
+:field::name: double colons are OK, too
+
+:field:\`name`: not interpreted text
+
+:`field name`:code:: interpreted text with role in the field name
+ works only when the role follows the text
+
+:a `complex`:code:\ field name: field body
+
+Not recognized as field list items:
+
+::code:`not a field name`: paragraph with interpreted text
+
+:code:`not a field name`: paragraph with interpreted text
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ Edge cases involving embedded colons and interpreted text.
+ <paragraph>
+ Recognized as field list items:
+ <field_list>
+ <field>
+ <field_name>
+ field:
+ <title_reference>
+ name
+ <field_body>
+ <paragraph>
+ interpreted text (standard role) requires
+ escaping a leading colon in a field name
+ <field>
+ <field_name>
+ field:name
+ <field_body>
+ <paragraph>
+ unambiguous, no need for escapes
+ <field>
+ <field_name>
+ field::name
+ <field_body>
+ <paragraph>
+ double colons are OK, too
+ <field>
+ <field_name>
+ field:`name`
+ <field_body>
+ <paragraph>
+ not interpreted text
+ <field>
+ <field_name>
+ <literal classes="code">
+ field name
+ <field_body>
+ <paragraph>
+ interpreted text with role in the field name
+ works only when the role follows the text
+ <field>
+ <field_name>
+ a
+ <literal classes="code">
+ complex
+ field name
+ <field_body>
+ <paragraph>
+ field body
+ <paragraph>
+ Not recognized as field list items:
+ <paragraph>
+ :
+ <literal classes="code">
+ not a field name
+ : paragraph with interpreted text
+ <paragraph>
+ <literal classes="code">
+ not a field name
+ : paragraph with interpreted text
+"""],
+]
+
+if __name__ == '__main__':
+ import unittest
+ unittest.main(defaultTest='suite')
--- /dev/null
+#! /usr/bin/env python
+
+# $Id: test_footnotes.py 8356 2019-08-26 16:44:19Z milde $
+# Author: David Goodger <goodger@python.org>
+# Copyright: This module has been placed in the public domain.
+
+"""
+Tests for states.py.
+"""
+from __future__ import absolute_import
+
+from . import DocutilsTestSupport
+
+
+def suite():
+ s = DocutilsTestSupport.ParserTestSuite()
+ s.generateTests(totest)
+ return s
+
+totest = {}
+
+totest['footnotes'] = [
+["""\
+.. [1] This is a footnote.
+""",
+"""\
+<document source="test data">
+ <footnote ids="id1" names="1">
+ <label>
+ 1
+ <paragraph>
+ This is a footnote.
+"""],
+["""\
+.. [1] This is a footnote
+ on multiple lines.
+""",
+"""\
+<document source="test data">
+ <footnote ids="id1" names="1">
+ <label>
+ 1
+ <paragraph>
+ This is a footnote
+ on multiple lines.
+"""],
+["""\
+.. [1] This is a footnote
+ on multiple lines with more space.
+
+.. [2] This is a footnote
+ on multiple lines with less space.
+""",
+"""\
+<document source="test data">
+ <footnote ids="id1" names="1">
+ <label>
+ 1
+ <paragraph>
+ This is a footnote
+ on multiple lines with more space.
+ <footnote ids="id2" names="2">
+ <label>
+ 2
+ <paragraph>
+ This is a footnote
+ on multiple lines with less space.
+"""],
+["""\
+.. [1]
+ This is a footnote on multiple lines
+ whose block starts on line 2.
+""",
+"""\
+<document source="test data">
+ <footnote ids="id1" names="1">
+ <label>
+ 1
+ <paragraph>
+ This is a footnote on multiple lines
+ whose block starts on line 2.
+"""],
+["""\
+.. [1]
+
+That was an empty footnote.
+""",
+"""\
+<document source="test data">
+ <footnote ids="id1" names="1">
+ <label>
+ 1
+ <paragraph>
+ That was an empty footnote.
+"""],
+["""\
+.. [1]
+No blank line.
+""",
+"""\
+<document source="test data">
+ <footnote ids="id1" names="1">
+ <label>
+ 1
+ <system_message level="2" line="2" source="test data" type="WARNING">
+ <paragraph>
+ Explicit markup ends without a blank line; unexpected unindent.
+ <paragraph>
+ No blank line.
+"""],
+]
+
+totest['auto_numbered_footnotes'] = [
+["""\
+[#]_ is the first auto-numbered footnote reference.
+[#]_ is the second auto-numbered footnote reference.
+
+.. [#] Auto-numbered footnote 1.
+.. [#] Auto-numbered footnote 2.
+.. [#] Auto-numbered footnote 3.
+
+[#]_ is the third auto-numbered footnote reference.
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ <footnote_reference auto="1" ids="id1">
+ is the first auto-numbered footnote reference.
+ <footnote_reference auto="1" ids="id2">
+ is the second auto-numbered footnote reference.
+ <footnote auto="1" ids="id3">
+ <paragraph>
+ Auto-numbered footnote 1.
+ <footnote auto="1" ids="id4">
+ <paragraph>
+ Auto-numbered footnote 2.
+ <footnote auto="1" ids="id5">
+ <paragraph>
+ Auto-numbered footnote 3.
+ <paragraph>
+ <footnote_reference auto="1" ids="id6">
+ is the third auto-numbered footnote reference.
+"""],
+["""\
+[#third]_ is a reference to the third auto-numbered footnote.
+
+.. [#first] First auto-numbered footnote.
+.. [#second] Second auto-numbered footnote.
+.. [#third] Third auto-numbered footnote.
+
+[#second]_ is a reference to the second auto-numbered footnote.
+[#first]_ is a reference to the first auto-numbered footnote.
+[#third]_ is another reference to the third auto-numbered footnote.
+
+Here are some internal cross-references to the targets generated by
+the footnotes: first_, second_, third_.
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ <footnote_reference auto="1" ids="id1" refname="third">
+ is a reference to the third auto-numbered footnote.
+ <footnote auto="1" ids="first" names="first">
+ <paragraph>
+ First auto-numbered footnote.
+ <footnote auto="1" ids="second" names="second">
+ <paragraph>
+ Second auto-numbered footnote.
+ <footnote auto="1" ids="third" names="third">
+ <paragraph>
+ Third auto-numbered footnote.
+ <paragraph>
+ <footnote_reference auto="1" ids="id2" refname="second">
+ is a reference to the second auto-numbered footnote.
+ <footnote_reference auto="1" ids="id3" refname="first">
+ is a reference to the first auto-numbered footnote.
+ <footnote_reference auto="1" ids="id4" refname="third">
+ is another reference to the third auto-numbered footnote.
+ <paragraph>
+ Here are some internal cross-references to the targets generated by
+ the footnotes: \n\
+ <reference name="first" refname="first">
+ first
+ , \n\
+ <reference name="second" refname="second">
+ second
+ , \n\
+ <reference name="third" refname="third">
+ third
+ .
+"""],
+["""\
+Mixed anonymous and labelled auto-numbered footnotes:
+
+[#four]_ should be 4, [#]_ should be 1,
+[#]_ should be 3, [#]_ is one too many,
+[#two]_ should be 2, and [#six]_ doesn't exist.
+
+.. [#] Auto-numbered footnote 1.
+.. [#two] Auto-numbered footnote 2.
+.. [#] Auto-numbered footnote 3.
+.. [#four] Auto-numbered footnote 4.
+.. [#five] Auto-numbered footnote 5.
+.. [#five] Auto-numbered footnote 5 again (duplicate).
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ Mixed anonymous and labelled auto-numbered footnotes:
+ <paragraph>
+ <footnote_reference auto="1" ids="id1" refname="four">
+ should be 4, \n\
+ <footnote_reference auto="1" ids="id2">
+ should be 1,
+ <footnote_reference auto="1" ids="id3">
+ should be 3, \n\
+ <footnote_reference auto="1" ids="id4">
+ is one too many,
+ <footnote_reference auto="1" ids="id5" refname="two">
+ should be 2, and \n\
+ <footnote_reference auto="1" ids="id6" refname="six">
+ doesn't exist.
+ <footnote auto="1" ids="id7">
+ <paragraph>
+ Auto-numbered footnote 1.
+ <footnote auto="1" ids="two" names="two">
+ <paragraph>
+ Auto-numbered footnote 2.
+ <footnote auto="1" ids="id8">
+ <paragraph>
+ Auto-numbered footnote 3.
+ <footnote auto="1" ids="four" names="four">
+ <paragraph>
+ Auto-numbered footnote 4.
+ <footnote auto="1" dupnames="five" ids="five">
+ <paragraph>
+ Auto-numbered footnote 5.
+ <footnote auto="1" dupnames="five" ids="id9">
+ <system_message backrefs="id9" level="2" line="12" source="test data" type="WARNING">
+ <paragraph>
+ Duplicate explicit target name: "five".
+ <paragraph>
+ Auto-numbered footnote 5 again (duplicate).
+"""],
+["""\
+Mixed manually-numbered, anonymous auto-numbered,
+and labelled auto-numbered footnotes:
+
+[#four]_ should be 4, [#]_ should be 2,
+[1]_ is 1, [3]_ is 3,
+[#]_ should be 6, [#]_ is one too many,
+[#five]_ should be 5, and [#six]_ doesn't exist.
+
+.. [1] Manually-numbered footnote 1.
+.. [#] Auto-numbered footnote 2.
+.. [#four] Auto-numbered footnote 4.
+.. [3] Manually-numbered footnote 3
+.. [#five] Auto-numbered footnote 5.
+.. [#five] Auto-numbered footnote 5 again (duplicate).
+.. [#] Auto-numbered footnote 6.
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ Mixed manually-numbered, anonymous auto-numbered,
+ and labelled auto-numbered footnotes:
+ <paragraph>
+ <footnote_reference auto="1" ids="id1" refname="four">
+ should be 4, \n\
+ <footnote_reference auto="1" ids="id2">
+ should be 2,
+ <footnote_reference ids="id3" refname="1">
+ 1
+ is 1, \n\
+ <footnote_reference ids="id4" refname="3">
+ 3
+ is 3,
+ <footnote_reference auto="1" ids="id5">
+ should be 6, \n\
+ <footnote_reference auto="1" ids="id6">
+ is one too many,
+ <footnote_reference auto="1" ids="id7" refname="five">
+ should be 5, and \n\
+ <footnote_reference auto="1" ids="id8" refname="six">
+ doesn't exist.
+ <footnote ids="id9" names="1">
+ <label>
+ 1
+ <paragraph>
+ Manually-numbered footnote 1.
+ <footnote auto="1" ids="id10">
+ <paragraph>
+ Auto-numbered footnote 2.
+ <footnote auto="1" ids="four" names="four">
+ <paragraph>
+ Auto-numbered footnote 4.
+ <footnote ids="id11" names="3">
+ <label>
+ 3
+ <paragraph>
+ Manually-numbered footnote 3
+ <footnote auto="1" dupnames="five" ids="five">
+ <paragraph>
+ Auto-numbered footnote 5.
+ <footnote auto="1" dupnames="five" ids="id12">
+ <system_message backrefs="id12" level="2" line="14" source="test data" type="WARNING">
+ <paragraph>
+ Duplicate explicit target name: "five".
+ <paragraph>
+ Auto-numbered footnote 5 again (duplicate).
+ <footnote auto="1" ids="id13">
+ <paragraph>
+ Auto-numbered footnote 6.
+"""],
+]
+
+totest['auto_symbol_footnotes'] = [
+["""\
+.. [*] This is an auto-symbol footnote.
+""",
+"""\
+<document source="test data">
+ <footnote auto="*" ids="id1">
+ <paragraph>
+ This is an auto-symbol footnote.
+"""],
+]
+
+
+if __name__ == '__main__':
+ import unittest
+ unittest.main(defaultTest='suite')
--- /dev/null
+#! /usr/bin/env python
+# -*- coding: utf-8 -*-
+
+# $Id: test_inline_markup.py 8356 2019-08-26 16:44:19Z milde $
+# Author: David Goodger <goodger@python.org>
+# Copyright: This module has been placed in the public domain.
+
+"""
+Tests for inline markup in docutils/parsers/rst/states.py.
+Interpreted text tests are in a separate module, test_interpreted.py.
+"""
+from __future__ import absolute_import
+
+from . import DocutilsTestSupport
+
+
+def suite():
+ s = DocutilsTestSupport.ParserTestSuite()
+ s.generateTests(totest)
+ return s
+
+totest = {}
+
+totest['emphasis'] = [
+["""\
+*emphasis*
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ <emphasis>
+ emphasis
+"""],
+[u"""\
+l'*emphasis* with the *emphasis*' apostrophe.
+l\u2019*emphasis* with the *emphasis*\u2019 apostrophe.
+""",
+u"""\
+<document source="test data">
+ <paragraph>
+ l\'
+ <emphasis>
+ emphasis
+ with the \n\
+ <emphasis>
+ emphasis
+ \' apostrophe.
+ l\u2019
+ <emphasis>
+ emphasis
+ with the \n\
+ <emphasis>
+ emphasis
+ \u2019 apostrophe.
+"""],
+["""\
+*emphasized sentence
+across lines*
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ <emphasis>
+ emphasized sentence
+ across lines
+"""],
+["""\
+*emphasis without closing asterisk
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ <problematic ids="id2" refid="id1">
+ *
+ emphasis without closing asterisk
+ <system_message backrefs="id2" ids="id1" level="2" line="1" source="test data" type="WARNING">
+ <paragraph>
+ Inline emphasis start-string without end-string.
+"""],
+[r"""some punctuation is allowed around inline markup, e.g.
+/*emphasis*/, -*emphasis*-, and :*emphasis*: (delimiters),
+(*emphasis*), [*emphasis*], <*emphasis*>, {*emphasis*} (open/close pairs)
+*emphasis*., *emphasis*,, *emphasis*!, and *emphasis*\ (closing delimiters),
+
+but not
+)*emphasis*(, ]*emphasis*[, >*emphasis*>, }*emphasis*{ (close/open pairs),
+(*), [*], '*' or '"*"' ("quoted" start-string),
+x*2* or 2*x* (alphanumeric char before),
+\*args or * (escaped, whitespace behind start-string),
+or *the\* *stars\* *inside* (escaped, whitespace before end-string).
+
+However, '*args' will trigger a warning and may be problematic.
+
+what about *this**?
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ some punctuation is allowed around inline markup, e.g.
+ /
+ <emphasis>
+ emphasis
+ /, -
+ <emphasis>
+ emphasis
+ -, and :
+ <emphasis>
+ emphasis
+ : (delimiters),
+ (
+ <emphasis>
+ emphasis
+ ), [
+ <emphasis>
+ emphasis
+ ], <
+ <emphasis>
+ emphasis
+ >, {
+ <emphasis>
+ emphasis
+ } (open/close pairs)
+ <emphasis>
+ emphasis
+ ., \n\
+ <emphasis>
+ emphasis
+ ,, \n\
+ <emphasis>
+ emphasis
+ !, and \n\
+ <emphasis>
+ emphasis
+ (closing delimiters),
+ <paragraph>
+ but not
+ )*emphasis*(, ]*emphasis*[, >*emphasis*>, }*emphasis*{ (close/open pairs),
+ (*), [*], '*' or '"*"' ("quoted" start-string),
+ x*2* or 2*x* (alphanumeric char before),
+ *args or * (escaped, whitespace behind start-string),
+ or \n\
+ <emphasis>
+ the* *stars* *inside
+ (escaped, whitespace before end-string).
+ <paragraph>
+ However, '
+ <problematic ids="id2" refid="id1">
+ *
+ args' will trigger a warning and may be problematic.
+ <system_message backrefs="id2" ids="id1" level="2" line="13" source="test data" type="WARNING">
+ <paragraph>
+ Inline emphasis start-string without end-string.
+ <paragraph>
+ what about \n\
+ <emphasis>
+ this*
+ ?
+"""],
+[u"""\
+Quotes around inline markup:
+
+'*emphasis*' "*emphasis*" Straight,
+‘*emphasis*’ “*emphasis*” English, ...,
+« *emphasis* » ‹ *emphasis* › « *emphasis* » ‹ *emphasis* ›
+« *emphasis* » ‹ *emphasis* › French,
+„*emphasis*“ ‚*emphasis*‘ »*emphasis*« ›*emphasis*‹ German, Czech, ...,
+„*emphasis*” «*emphasis*» Romanian,
+“*emphasis*„ ‘*emphasis*‚ Greek,
+「*emphasis*」 『*emphasis*』traditional Chinese,
+”*emphasis*” ’*emphasis*’ »*emphasis*» ›*emphasis*› Swedish, Finnish,
+„*emphasis*” ‚*emphasis*’ Polish,
+„*emphasis*” »*emphasis*« ’*emphasis*’ Hungarian,
+""",
+u"""\
+<document source="test data">
+ <paragraph>
+ Quotes around inline markup:
+ <paragraph>
+ \'
+ <emphasis>
+ emphasis
+ \' "
+ <emphasis>
+ emphasis
+ " Straight,
+ \u2018
+ <emphasis>
+ emphasis
+ \u2019 \u201c
+ <emphasis>
+ emphasis
+ \u201d English, ...,
+ \xab\u202f
+ <emphasis>
+ emphasis
+ \u202f\xbb \u2039\u202f
+ <emphasis>
+ emphasis
+ \u202f\u203a \xab\xa0
+ <emphasis>
+ emphasis
+ \xa0\xbb \u2039\xa0
+ <emphasis>
+ emphasis
+ \xa0\u203a
+ \xab\u2005
+ <emphasis>
+ emphasis
+ \u2005\xbb \u2039\u2005
+ <emphasis>
+ emphasis
+ \u2005\u203a French,
+ \u201e
+ <emphasis>
+ emphasis
+ \u201c \u201a
+ <emphasis>
+ emphasis
+ \u2018 \xbb
+ <emphasis>
+ emphasis
+ \xab \u203a
+ <emphasis>
+ emphasis
+ \u2039 German, Czech, ...,
+ \u201e
+ <emphasis>
+ emphasis
+ \u201d \xab
+ <emphasis>
+ emphasis
+ \xbb Romanian,
+ \u201c
+ <emphasis>
+ emphasis
+ \u201e \u2018
+ <emphasis>
+ emphasis
+ \u201a Greek,
+ \u300c
+ <emphasis>
+ emphasis
+ \u300d \u300e
+ <emphasis>
+ emphasis
+ \u300ftraditional Chinese,
+ \u201d
+ <emphasis>
+ emphasis
+ \u201d \u2019
+ <emphasis>
+ emphasis
+ \u2019 \xbb
+ <emphasis>
+ emphasis
+ \xbb \u203a
+ <emphasis>
+ emphasis
+ \u203a Swedish, Finnish,
+ \u201e
+ <emphasis>
+ emphasis
+ \u201d \u201a
+ <emphasis>
+ emphasis
+ \u2019 Polish,
+ \u201e
+ <emphasis>
+ emphasis
+ \u201d \xbb
+ <emphasis>
+ emphasis
+ \xab \u2019
+ <emphasis>
+ emphasis
+ \u2019 Hungarian,
+"""],
+[r"""
+Emphasized asterisk: *\**
+
+Emphasized double asterisk: *\***
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ Emphasized asterisk: \n\
+ <emphasis>
+ *
+ <paragraph>
+ Emphasized double asterisk: \n\
+ <emphasis>
+ **
+"""],
+]
+
+totest['strong'] = [
+["""\
+**strong**
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ <strong>
+ strong
+"""],
+[u"""\
+l'**strong** and l\u2019**strong** with apostrophe
+""",
+u"""\
+<document source="test data">
+ <paragraph>
+ l'
+ <strong>
+ strong
+ and l\u2019
+ <strong>
+ strong
+ with apostrophe
+"""],
+[u"""\
+quoted '**strong**', quoted "**strong**",
+quoted \u2018**strong**\u2019, quoted \u201c**strong**\u201d,
+quoted \xab**strong**\xbb
+""",
+u"""\
+<document source="test data">
+ <paragraph>
+ quoted '
+ <strong>
+ strong
+ ', quoted "
+ <strong>
+ strong
+ ",
+ quoted \u2018
+ <strong>
+ strong
+ \u2019, quoted \u201c
+ <strong>
+ strong
+ \u201d,
+ quoted \xab
+ <strong>
+ strong
+ \xbb
+"""],
+[r"""
+(**strong**) but not (**) or '(** ' or x**2 or \**kwargs or **
+
+(however, '**kwargs' will trigger a warning and may be problematic)
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ (
+ <strong>
+ strong
+ ) but not (**) or '(** ' or x**2 or **kwargs or **
+ <paragraph>
+ (however, '
+ <problematic ids="id2" refid="id1">
+ **
+ kwargs' will trigger a warning and may be problematic)
+ <system_message backrefs="id2" ids="id1" level="2" line="4" source="test data" type="WARNING">
+ <paragraph>
+ Inline strong start-string without end-string.
+"""],
+["""\
+Strong asterisk: *****
+
+Strong double asterisk: ******
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ Strong asterisk: \n\
+ <strong>
+ *
+ <paragraph>
+ Strong double asterisk: \n\
+ <strong>
+ **
+"""],
+["""\
+**strong without closing asterisks
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ <problematic ids="id2" refid="id1">
+ **
+ strong without closing asterisks
+ <system_message backrefs="id2" ids="id1" level="2" line="1" source="test data" type="WARNING">
+ <paragraph>
+ Inline strong start-string without end-string.
+"""],
+]
+
+totest['literal'] = [
+["""\
+``literal``
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ <literal>
+ literal
+"""],
+[r"""
+``\literal``
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ <literal>
+ \\literal
+"""],
+[r"""
+``lite\ral``
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ <literal>
+ lite\\ral
+"""],
+[r"""
+``literal\``
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ <literal>
+ literal\\
+"""],
+[u"""\
+l'``literal`` and l\u2019``literal`` with apostrophe
+""",
+u"""\
+<document source="test data">
+ <paragraph>
+ l'
+ <literal>
+ literal
+ and l\u2019
+ <literal>
+ literal
+ with apostrophe
+"""],
+[u"""\
+quoted '``literal``', quoted "``literal``",
+quoted \u2018``literal``\u2019, quoted \u201c``literal``\u201d,
+quoted \xab``literal``\xbb
+""",
+u"""\
+<document source="test data">
+ <paragraph>
+ quoted '
+ <literal>
+ literal
+ ', quoted "
+ <literal>
+ literal
+ ",
+ quoted \u2018
+ <literal>
+ literal
+ \u2019, quoted \u201c
+ <literal>
+ literal
+ \u201d,
+ quoted \xab
+ <literal>
+ literal
+ \xbb
+"""],
+[u"""\
+``'literal'`` with quotes, ``"literal"`` with quotes,
+``\u2018literal\u2019`` with quotes, ``\u201cliteral\u201d`` with quotes,
+``\xabliteral\xbb`` with quotes
+""",
+u"""\
+<document source="test data">
+ <paragraph>
+ <literal>
+ 'literal'
+ with quotes, \n\
+ <literal>
+ "literal"
+ with quotes,
+ <literal>
+ \u2018literal\u2019
+ with quotes, \n\
+ <literal>
+ \u201cliteral\u201d
+ with quotes,
+ <literal>
+ \xabliteral\xbb
+ with quotes
+"""],
+[r"""
+``literal ``TeX quotes'' & \backslash`` but not "``" or ``
+
+(however, ``standalone TeX quotes'' will trigger a warning
+and may be problematic)
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ <literal>
+ literal ``TeX quotes'' & \\backslash
+ but not "``" or ``
+ <paragraph>
+ (however, \n\
+ <problematic ids="id2" refid="id1">
+ ``
+ standalone TeX quotes'' will trigger a warning
+ and may be problematic)
+ <system_message backrefs="id2" ids="id1" level="2" line="4" source="test data" type="WARNING">
+ <paragraph>
+ Inline literal start-string without end-string.
+"""],
+["""\
+Find the ```interpreted text``` in this paragraph!
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ Find the \n\
+ <literal>
+ `interpreted text`
+ in this paragraph!
+"""],
+["""\
+``literal without closing backquotes
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ <problematic ids="id2" refid="id1">
+ ``
+ literal without closing backquotes
+ <system_message backrefs="id2" ids="id1" level="2" line="1" source="test data" type="WARNING">
+ <paragraph>
+ Inline literal start-string without end-string.
+"""],
+[r"""
+Python ``list``\s use square bracket syntax.
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ Python \n\
+ <literal>
+ list
+ s use square bracket syntax.
+"""],
+[r"""
+Blank after opening `` not allowed.
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ Blank after opening `` not allowed.
+"""],
+[r"""
+no blank ``after closing``continues`` literal.
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ no blank \n\
+ <literal>
+ after closing``continues
+ literal.
+"""],
+[r"""
+dot ``after closing``. is possible.
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ dot \n\
+ <literal>
+ after closing
+ . is possible.
+"""],
+]
+
+totest['references'] = [
+["""\
+ref_
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ <reference name="ref" refname="ref">
+ ref
+"""],
+[u"""\
+l'ref_ and l\u2019ref_ with apostrophe
+""",
+u"""\
+<document source="test data">
+ <paragraph>
+ l'
+ <reference name="ref" refname="ref">
+ ref
+ and l\u2019
+ <reference name="ref" refname="ref">
+ ref
+ with apostrophe
+"""],
+[u"""\
+quoted 'ref_', quoted "ref_",
+quoted \u2018ref_\u2019, quoted \u201cref_\u201d,
+quoted \xabref_\xbb,
+but not 'ref ref'_, "ref ref"_, \u2018ref ref\u2019_,
+\u201cref ref\u201d_, or \xabref ref\xbb_
+""",
+u"""\
+<document source="test data">
+ <paragraph>
+ quoted '
+ <reference name="ref" refname="ref">
+ ref
+ ', quoted "
+ <reference name="ref" refname="ref">
+ ref
+ ",
+ quoted \u2018
+ <reference name="ref" refname="ref">
+ ref
+ \u2019, quoted \u201c
+ <reference name="ref" refname="ref">
+ ref
+ \u201d,
+ quoted \xab
+ <reference name="ref" refname="ref">
+ ref
+ \xbb,
+ but not 'ref ref'_, "ref ref"_, \u2018ref ref\u2019_,
+ \u201cref ref\u201d_, or \xabref ref\xbb_
+"""],
+["""\
+ref__
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ <reference anonymous="1" name="ref">
+ ref
+"""],
+[u"""\
+l'ref__ and l\u2019ref__ with apostrophe
+""",
+u"""\
+<document source="test data">
+ <paragraph>
+ l'
+ <reference anonymous="1" name="ref">
+ ref
+ and l\u2019
+ <reference anonymous="1" name="ref">
+ ref
+ with apostrophe
+"""],
+[u"""\
+quoted 'ref__', quoted "ref__",
+quoted \u2018ref__\u2019, quoted \u201cref__\u201d,
+quoted \xabref__\xbb,
+but not 'ref ref'__, "ref ref"__, \u2018ref ref\u2019__,
+\u201cref ref\u201d__, or \xabref ref\xbb__
+""",
+u"""\
+<document source="test data">
+ <paragraph>
+ quoted '
+ <reference anonymous="1" name="ref">
+ ref
+ ', quoted "
+ <reference anonymous="1" name="ref">
+ ref
+ ",
+ quoted \u2018
+ <reference anonymous="1" name="ref">
+ ref
+ \u2019, quoted \u201c
+ <reference anonymous="1" name="ref">
+ ref
+ \u201d,
+ quoted \xab
+ <reference anonymous="1" name="ref">
+ ref
+ \xbb,
+ but not 'ref ref'__, "ref ref"__, \u2018ref ref\u2019__,
+ \u201cref ref\u201d__, or \xabref ref\xbb__
+"""],
+["""\
+ref_, r_, r_e-f_, -ref_, and anonymousref__,
+but not _ref_ or __attr__ or object.__attr__
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ <reference name="ref" refname="ref">
+ ref
+ , \n\
+ <reference name="r" refname="r">
+ r
+ , \n\
+ <reference name="r_e-f" refname="r_e-f">
+ r_e-f
+ , -
+ <reference name="ref" refname="ref">
+ ref
+ , and \n\
+ <reference anonymous="1" name="anonymousref">
+ anonymousref
+ ,
+ but not _ref_ or __attr__ or object.__attr__
+"""],
+]
+
+totest['phrase_references'] = [
+["""\
+`phrase reference`_
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ <reference name="phrase reference" refname="phrase reference">
+ phrase reference
+"""],
+[u"""\
+l'`phrase reference`_ and l\u2019`phrase reference`_ with apostrophe
+""",
+u"""\
+<document source="test data">
+ <paragraph>
+ l'
+ <reference name="phrase reference" refname="phrase reference">
+ phrase reference
+ and l\u2019
+ <reference name="phrase reference" refname="phrase reference">
+ phrase reference
+ with apostrophe
+"""],
+[u"""\
+quoted '`phrase reference`_', quoted "`phrase reference`_",
+quoted \u2018`phrase reference`_\u2019,
+quoted \u201c`phrase reference`_\u201d,
+quoted \xab`phrase reference`_\xbb
+""",
+u"""\
+<document source="test data">
+ <paragraph>
+ quoted '
+ <reference name="phrase reference" refname="phrase reference">
+ phrase reference
+ ', quoted "
+ <reference name="phrase reference" refname="phrase reference">
+ phrase reference
+ ",
+ quoted \u2018
+ <reference name="phrase reference" refname="phrase reference">
+ phrase reference
+ \u2019,
+ quoted \u201c
+ <reference name="phrase reference" refname="phrase reference">
+ phrase reference
+ \u201d,
+ quoted \xab
+ <reference name="phrase reference" refname="phrase reference">
+ phrase reference
+ \xbb
+"""],
+[u"""\
+`'phrase reference'`_ with quotes, `"phrase reference"`_ with quotes,
+`\u2018phrase reference\u2019`_ with quotes,
+`\u201cphrase reference\u201d`_ with quotes,
+`\xabphrase reference\xbb`_ with quotes
+""",
+u"""\
+<document source="test data">
+ <paragraph>
+ <reference name="'phrase reference'" refname="'phrase reference'">
+ 'phrase reference'
+ with quotes, \n\
+ <reference name=""phrase reference"" refname=""phrase reference"">
+ "phrase reference"
+ with quotes,
+ <reference name="\u2018phrase reference\u2019" refname="\u2018phrase reference\u2019">
+ \u2018phrase reference\u2019
+ with quotes,
+ <reference name="\u201cphrase reference\u201d" refname="\u201cphrase reference\u201d">
+ \u201cphrase reference\u201d
+ with quotes,
+ <reference name="\xabphrase reference\xbb" refname="\xabphrase reference\xbb">
+ \xabphrase reference\xbb
+ with quotes
+"""],
+["""\
+`anonymous reference`__
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ <reference anonymous="1" name="anonymous reference">
+ anonymous reference
+"""],
+[u"""\
+l'`anonymous reference`__ and l\u2019`anonymous reference`__ with apostrophe
+""",
+u"""\
+<document source="test data">
+ <paragraph>
+ l'
+ <reference anonymous="1" name="anonymous reference">
+ anonymous reference
+ and l\u2019
+ <reference anonymous="1" name="anonymous reference">
+ anonymous reference
+ with apostrophe
+"""],
+[u"""\
+quoted '`anonymous reference`__', quoted "`anonymous reference`__",
+quoted \u2018`anonymous reference`__\u2019,
+quoted \u201c`anonymous reference`__\u201d,
+quoted \xab`anonymous reference`__\xbb
+""",
+u"""\
+<document source="test data">
+ <paragraph>
+ quoted '
+ <reference anonymous="1" name="anonymous reference">
+ anonymous reference
+ ', quoted "
+ <reference anonymous="1" name="anonymous reference">
+ anonymous reference
+ ",
+ quoted \u2018
+ <reference anonymous="1" name="anonymous reference">
+ anonymous reference
+ \u2019,
+ quoted \u201c
+ <reference anonymous="1" name="anonymous reference">
+ anonymous reference
+ \u201d,
+ quoted \xab
+ <reference anonymous="1" name="anonymous reference">
+ anonymous reference
+ \xbb
+"""],
+[u"""\
+`'anonymous reference'`__ with quotes, `"anonymous reference"`__ with quotes,
+`\u2018anonymous reference\u2019`__ with quotes,
+`\u201canonymous reference\u201d`__ with quotes,
+`\xabanonymous reference\xbb`__ with quotes
+""",
+u"""\
+<document source="test data">
+ <paragraph>
+ <reference anonymous="1" name="'anonymous reference'">
+ 'anonymous reference'
+ with quotes, \n\
+ <reference anonymous="1" name=""anonymous reference"">
+ "anonymous reference"
+ with quotes,
+ <reference anonymous="1" name="\u2018anonymous reference\u2019">
+ \u2018anonymous reference\u2019
+ with quotes,
+ <reference anonymous="1" name="\u201canonymous reference\u201d">
+ \u201canonymous reference\u201d
+ with quotes,
+ <reference anonymous="1" name="\xabanonymous reference\xbb">
+ \xabanonymous reference\xbb
+ with quotes
+"""],
+["""\
+`phrase reference
+across lines`_
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ <reference name="phrase reference across lines" refname="phrase reference across lines">
+ phrase reference
+ across lines
+"""],
+["""\
+`phrase\\`_ reference`_
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ <reference name="phrase`_ reference" refname="phrase`_ reference">
+ phrase`_ reference
+"""],
+["""\
+Invalid phrase reference:
+
+:role:`phrase reference`_
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ Invalid phrase reference:
+ <paragraph>
+ <problematic ids="id2" refid="id1">
+ :role:`phrase reference`_
+ <system_message backrefs="id2" ids="id1" level="2" line="3" source="test data" type="WARNING">
+ <paragraph>
+ Mismatch: both interpreted text role prefix and reference suffix.
+"""],
+["""\
+Invalid phrase reference:
+
+`phrase reference`:role:_
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ Invalid phrase reference:
+ <paragraph>
+ <problematic ids="id2" refid="id1">
+ `phrase reference`:role:_
+ <system_message backrefs="id2" ids="id1" level="2" line="3" source="test data" type="WARNING">
+ <paragraph>
+ Mismatch: both interpreted text role suffix and reference suffix.
+"""],
+["""\
+`phrase reference_ without closing backquote
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ <problematic ids="id2" refid="id1">
+ `
+ phrase \n\
+ <reference name="reference" refname="reference">
+ reference
+ without closing backquote
+ <system_message backrefs="id2" ids="id1" level="2" line="1" source="test data" type="WARNING">
+ <paragraph>
+ Inline interpreted text or phrase reference start-string without end-string.
+"""],
+["""\
+`anonymous phrase reference__ without closing backquote
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ <problematic ids="id2" refid="id1">
+ `
+ anonymous phrase \n\
+ <reference anonymous="1" name="reference">
+ reference
+ without closing backquote
+ <system_message backrefs="id2" ids="id1" level="2" line="1" source="test data" type="WARNING">
+ <paragraph>
+ Inline interpreted text or phrase reference start-string without end-string.
+"""],
+]
+
+totest['embedded_URIs'] = [
+["""\
+`phrase reference <http://example.com>`_
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ <reference name="phrase reference" refuri="http://example.com">
+ phrase reference
+ <target ids="phrase-reference" names="phrase\\ reference" refuri="http://example.com">
+"""],
+["""\
+`anonymous reference <http://example.com>`__
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ <reference name="anonymous reference" refuri="http://example.com">
+ anonymous reference
+"""],
+["""\
+`embedded URI on next line
+<http://example.com>`__
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ <reference name="embedded URI on next line" refuri="http://example.com">
+ embedded URI on next line
+"""],
+["""\
+`embedded URI across lines <http://example.com/
+long/path>`__
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ <reference name="embedded URI across lines" refuri="http://example.com/long/path">
+ embedded URI across lines
+"""],
+["""\
+`embedded URI with whitespace <http://example.com/
+long/path /and /whitespace>`__
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ <reference name="embedded URI with whitespace" refuri="http://example.com/long/path/and/whitespace">
+ embedded URI with whitespace
+"""],
+[r"""
+`embedded URI with escaped whitespace <http://example.com/a\
+long/path\ and/some\ escaped\ whitespace>`__
+
+`<omitted\ reference\ text\ with\ escaped\ whitespace>`__
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ <reference name="embedded URI with escaped whitespace" refuri="http://example.com/a long/path and/some escaped whitespace">
+ embedded URI with escaped whitespace
+ <paragraph>
+ <reference name="omitted reference text with escaped whitespace" refuri="omitted reference text with escaped whitespace">
+ omitted reference text with escaped whitespace
+"""],
+["""\
+`embedded email address <jdoe@example.com>`__
+
+`embedded email address broken across lines <jdoe
+@example.com>`__
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ <reference name="embedded email address" refuri="mailto:jdoe@example.com">
+ embedded email address
+ <paragraph>
+ <reference name="embedded email address broken across lines" refuri="mailto:jdoe@example.com">
+ embedded email address broken across lines
+"""],
+[r"""
+`embedded URI with too much whitespace < http://example.com/
+long/path /and /whitespace >`__
+
+`embedded URI with too much whitespace at end <http://example.com/
+long/path /and /whitespace >`__
+
+`embedded URI with no preceding whitespace<http://example.com>`__
+
+`escaped URI \<http://example.com>`__
+
+See `HTML Anchors: \<a>`_.
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ <reference anonymous="1" name="embedded URI with too much whitespace < http://example.com/ long/path /and /whitespace >">
+ embedded URI with too much whitespace < http://example.com/
+ long/path /and /whitespace >
+ <paragraph>
+ <reference anonymous="1" name="embedded URI with too much whitespace at end <http://example.com/ long/path /and /whitespace >">
+ embedded URI with too much whitespace at end <http://example.com/
+ long/path /and /whitespace >
+ <paragraph>
+ <reference anonymous="1" name="embedded URI with no preceding whitespace<http://example.com>">
+ embedded URI with no preceding whitespace<http://example.com>
+ <paragraph>
+ <reference anonymous="1" name="escaped URI <http://example.com>">
+ escaped URI <http://example.com>
+ <paragraph>
+ See \n\
+ <reference name="HTML Anchors: <a>" refname="html anchors: <a>">
+ HTML Anchors: <a>
+ .
+"""],
+["""\
+Relative URIs' reference text can be omitted:
+
+`<reference>`_
+
+`<anonymous>`__
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ Relative URIs' reference text can be omitted:
+ <paragraph>
+ <reference name="reference" refuri="reference">
+ reference
+ <target ids="reference" names="reference" refuri="reference">
+ <paragraph>
+ <reference name="anonymous" refuri="anonymous">
+ anonymous
+"""],
+[r"""
+Escape trailing low-line char in URIs:
+
+`<reference\_>`_
+
+`<anonymous\_>`__
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ Escape trailing low-line char in URIs:
+ <paragraph>
+ <reference name="reference_" refuri="reference_">
+ reference_
+ <target ids="reference" names="reference_" refuri="reference_">
+ <paragraph>
+ <reference name="anonymous_" refuri="anonymous_">
+ anonymous_
+"""],
+["""\
+Escape other char in URIs:
+
+`<reference\\:1>`_
+
+`<anonymous\\call>`__
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ Escape other char in URIs:
+ <paragraph>
+ <reference name="reference:1" refuri="reference:1">
+ reference:1
+ <target ids="reference-1" names="reference:1" refuri="reference:1">
+ <paragraph>
+ <reference name="anonymouscall" refuri="anonymouscall">
+ anonymouscall
+"""],
+]
+
+totest['embedded_aliases'] = [
+["""\
+`phrase reference <alias_>`_
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ <reference name="phrase reference" refname="alias">
+ phrase reference
+ <target names="phrase\\ reference" refname="alias">
+"""],
+["""\
+`anonymous reference <alias_>`__
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ <reference name="anonymous reference" refname="alias">
+ anonymous reference
+"""],
+["""\
+`embedded alias on next line
+<alias_>`__
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ <reference name="embedded alias on next line" refname="alias">
+ embedded alias on next line
+"""],
+["""\
+`embedded alias across lines <alias
+phrase_>`__
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ <reference name="embedded alias across lines" refname="alias phrase">
+ embedded alias across lines
+"""],
+["""\
+`embedded alias with whitespace <alias
+long phrase_>`__
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ <reference name="embedded alias with whitespace" refname="alias long phrase">
+ embedded alias with whitespace
+"""],
+["""\
+`<embedded alias with whitespace_>`__
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ <reference name="embedded alias with whitespace" refname="embedded alias with whitespace">
+ embedded alias with whitespace
+"""],
+[r"""
+`no embedded alias (whitespace inside bracket) < alias_ >`__
+
+`no embedded alias (no preceding whitespace)<alias_>`__
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ <reference anonymous="1" name="no embedded alias (whitespace inside bracket) < alias_ >">
+ no embedded alias (whitespace inside bracket) < alias_ >
+ <paragraph>
+ <reference anonymous="1" name="no embedded alias (no preceding whitespace)<alias_>">
+ no embedded alias (no preceding whitespace)<alias_>
+"""],
+[r"""
+`anonymous reference <alias\ with\\ escaped \:characters_>`__
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ <reference name="anonymous reference" refname="aliaswith\\ escaped :characters">
+ anonymous reference
+"""],
+[r"""
+`anonymous reference <alias\ with\\ escaped \:characters_>`__
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ <reference name="anonymous reference" refname="aliaswith\\ escaped :characters">
+ anonymous reference
+"""],
+]
+
+totest['inline_targets'] = [
+["""\
+_`target`
+
+Here is _`another target` in some text. And _`yet
+another target`, spanning lines.
+
+_`Here is a TaRgeT` with case and spacial difficulties.
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ <target ids="target" names="target">
+ target
+ <paragraph>
+ Here is \n\
+ <target ids="another-target" names="another\\ target">
+ another target
+ in some text. And \n\
+ <target ids="yet-another-target" names="yet\\ another\\ target">
+ yet
+ another target
+ , spanning lines.
+ <paragraph>
+ <target ids="here-is-a-target" names="here\\ is\\ a\\ target">
+ Here is a TaRgeT
+ with case and spacial difficulties.
+"""],
+[u"""\
+l'_`target1` and l\u2019_`target2` with apostrophe
+""",
+u"""\
+<document source="test data">
+ <paragraph>
+ l'
+ <target ids="target1" names="target1">
+ target1
+ and l\u2019
+ <target ids="target2" names="target2">
+ target2
+ with apostrophe
+"""],
+[u"""\
+quoted '_`target1`', quoted "_`target2`",
+quoted \u2018_`target3`\u2019, quoted \u201c_`target4`\u201d,
+quoted \xab_`target5`\xbb
+""",
+u"""\
+<document source="test data">
+ <paragraph>
+ quoted '
+ <target ids="target1" names="target1">
+ target1
+ ', quoted "
+ <target ids="target2" names="target2">
+ target2
+ ",
+ quoted \u2018
+ <target ids="target3" names="target3">
+ target3
+ \u2019, quoted \u201c
+ <target ids="target4" names="target4">
+ target4
+ \u201d,
+ quoted \xab
+ <target ids="target5" names="target5">
+ target5
+ \xbb
+"""],
+[u"""\
+_`'target1'` with quotes, _`"target2"` with quotes,
+_`\u2018target3\u2019` with quotes, _`\u201ctarget4\u201d` with quotes,
+_`\xabtarget5\xbb` with quotes
+""",
+u"""\
+<document source="test data">
+ <paragraph>
+ <target ids="target1" names="'target1'">
+ 'target1'
+ with quotes, \n\
+ <target ids="target2" names=""target2"">
+ "target2"
+ with quotes,
+ <target ids="target3" names="\u2018target3\u2019">
+ \u2018target3\u2019
+ with quotes, \n\
+ <target ids="target4" names="\u201ctarget4\u201d">
+ \u201ctarget4\u201d
+ with quotes,
+ <target ids="target5" names="\xabtarget5\xbb">
+ \xabtarget5\xbb
+ with quotes
+"""],
+["""\
+But this isn't a _target; targets require backquotes.
+
+And _`this`_ is just plain confusing.
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ But this isn't a _target; targets require backquotes.
+ <paragraph>
+ And \n\
+ <problematic ids="id2" refid="id1">
+ _`
+ this`_ is just plain confusing.
+ <system_message backrefs="id2" ids="id1" level="2" line="3" source="test data" type="WARNING">
+ <paragraph>
+ Inline target start-string without end-string.
+"""],
+["""\
+_`inline target without closing backquote
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ <problematic ids="id2" refid="id1">
+ _`
+ inline target without closing backquote
+ <system_message backrefs="id2" ids="id1" level="2" line="1" source="test data" type="WARNING">
+ <paragraph>
+ Inline target start-string without end-string.
+"""],
+]
+
+totest['footnote_reference'] = [
+["""\
+[1]_
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ <footnote_reference ids="id1" refname="1">
+ 1
+"""],
+["""\
+[#]_
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ <footnote_reference auto="1" ids="id1">
+"""],
+["""\
+[#label]_
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ <footnote_reference auto="1" ids="id1" refname="label">
+"""],
+["""\
+[*]_
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ <footnote_reference auto="*" ids="id1">
+"""],
+["""\
+Adjacent footnote refs are not possible: [*]_[#label]_ [#]_[2]_ [1]_[*]_
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ Adjacent footnote refs are not possible: [*]_[#label]_ [#]_[2]_ [1]_[*]_
+"""],
+]
+
+totest['citation_reference'] = [
+["""\
+[citation]_
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ <citation_reference ids="id1" refname="citation">
+ citation
+"""],
+["""\
+[citation]_ and [cit-ation]_ and [cit.ation]_ and [CIT1]_ but not [CIT 1]_
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ <citation_reference ids="id1" refname="citation">
+ citation
+ and \n\
+ <citation_reference ids="id2" refname="cit-ation">
+ cit-ation
+ and \n\
+ <citation_reference ids="id3" refname="cit.ation">
+ cit.ation
+ and \n\
+ <citation_reference ids="id4" refname="cit1">
+ CIT1
+ but not [CIT 1]_
+"""],
+["""\
+Adjacent citation refs are not possible: [citation]_[CIT1]_
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ Adjacent citation refs are not possible: [citation]_[CIT1]_
+"""],
+]
+
+totest['substitution_references'] = [
+["""\
+|subref|
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ <substitution_reference refname="subref">
+ subref
+"""],
+["""\
+|subref|_ and |subref|__
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ <reference refname="subref">
+ <substitution_reference refname="subref">
+ subref
+ and \n\
+ <reference anonymous="1">
+ <substitution_reference refname="subref">
+ subref
+"""],
+["""\
+|substitution reference|
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ <substitution_reference refname="substitution reference">
+ substitution reference
+"""],
+["""\
+|substitution
+reference|
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ <substitution_reference refname="substitution reference">
+ substitution
+ reference
+"""],
+["""\
+|substitution reference without closing verbar
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ <problematic ids="id2" refid="id1">
+ |
+ substitution reference without closing verbar
+ <system_message backrefs="id2" ids="id1" level="2" line="1" source="test data" type="WARNING">
+ <paragraph>
+ Inline substitution_reference start-string without end-string.
+"""],
+["""\
+first | then || and finally |||
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ first | then || and finally |||
+"""],
+]
+
+totest['standalone_hyperlink'] = [
+["""\
+http://www.standalone.hyperlink.com
+
+http:/one-slash-only.absolute.path
+
+[http://example.com]
+
+(http://example.com)
+
+<http://example.com>
+
+http://[1080:0:0:0:8:800:200C:417A]/IPv6address.html
+
+http://[3ffe:2a00:100:7031::1] (the final "]" is ambiguous in text)
+
+http://[3ffe:2a00:100:7031::1]/
+
+mailto:someone@somewhere.com
+
+news:comp.lang.python
+
+An email address in a sentence: someone@somewhere.com.
+
+ftp://ends.with.a.period.
+
+(a.question.mark@end?)
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ <reference refuri="http://www.standalone.hyperlink.com">
+ http://www.standalone.hyperlink.com
+ <paragraph>
+ <reference refuri="http:/one-slash-only.absolute.path">
+ http:/one-slash-only.absolute.path
+ <paragraph>
+ [
+ <reference refuri="http://example.com">
+ http://example.com
+ ]
+ <paragraph>
+ (
+ <reference refuri="http://example.com">
+ http://example.com
+ )
+ <paragraph>
+ <
+ <reference refuri="http://example.com">
+ http://example.com
+ >
+ <paragraph>
+ <reference refuri="http://[1080:0:0:0:8:800:200C:417A]/IPv6address.html">
+ http://[1080:0:0:0:8:800:200C:417A]/IPv6address.html
+ <paragraph>
+ <reference refuri="http://[3ffe:2a00:100:7031::1">
+ http://[3ffe:2a00:100:7031::1
+ ] (the final "]" is ambiguous in text)
+ <paragraph>
+ <reference refuri="http://[3ffe:2a00:100:7031::1]/">
+ http://[3ffe:2a00:100:7031::1]/
+ <paragraph>
+ <reference refuri="mailto:someone@somewhere.com">
+ mailto:someone@somewhere.com
+ <paragraph>
+ <reference refuri="news:comp.lang.python">
+ news:comp.lang.python
+ <paragraph>
+ An email address in a sentence: \n\
+ <reference refuri="mailto:someone@somewhere.com">
+ someone@somewhere.com
+ .
+ <paragraph>
+ <reference refuri="ftp://ends.with.a.period">
+ ftp://ends.with.a.period
+ .
+ <paragraph>
+ (
+ <reference refuri="mailto:a.question.mark@end">
+ a.question.mark@end
+ ?)
+"""],
+[r"""
+Valid URLs with escaped markup characters:
+
+http://example.com/\*content\*/whatever
+
+http://example.com/\*content*/whatever
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ Valid URLs with escaped markup characters:
+ <paragraph>
+ <reference refuri="http://example.com/*content*/whatever">
+ http://example.com/*content*/whatever
+ <paragraph>
+ <reference refuri="http://example.com/*content*/whatever">
+ http://example.com/*content*/whatever
+"""],
+["""\
+Valid URLs may end with punctuation inside "<>":
+
+<http://example.org/ends-with-dot.>
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ Valid URLs may end with punctuation inside "<>":
+ <paragraph>
+ <
+ <reference refuri="http://example.org/ends-with-dot.">
+ http://example.org/ends-with-dot.
+ >
+"""],
+["""\
+Valid URLs with interesting endings:
+
+http://example.org/ends-with-pluses++
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ Valid URLs with interesting endings:
+ <paragraph>
+ <reference refuri="http://example.org/ends-with-pluses++">
+ http://example.org/ends-with-pluses++
+"""],
+["""\
+None of these are standalone hyperlinks (their "schemes"
+are not recognized): signal:noise, a:b.
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ None of these are standalone hyperlinks (their "schemes"
+ are not recognized): signal:noise, a:b.
+"""],
+["""\
+Escaped email addresses are not recognized: test\\@example.org
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ Escaped email addresses are not recognized: test@example.org
+"""],
+]
+
+totest['markup recognition rules'] = [
+["""\
+__This__ should be left alone.
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ __This__ should be left alone.
+"""],
+[r"""
+Character-level m\ *a*\ **r**\ ``k``\ `u`:title:\p
+with backslash-escaped whitespace, including new\
+lines.
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ Character-level m
+ <emphasis>
+ a
+ <strong>
+ r
+ <literal>
+ k
+ <title_reference>
+ u
+ p
+ with backslash-escaped whitespace, including newlines.
+"""],
+[u"""\
+text-*separated*\u2010*by*\u2011*various*\u2012*dashes*\u2013*and*\u2014*hyphens*.
+\u00bf*punctuation*? \u00a1*examples*!\u00a0*no-break-space*\u00a0.
+""",
+u"""\
+<document source="test data">
+ <paragraph>
+ text-
+ <emphasis>
+ separated
+ \u2010
+ <emphasis>
+ by
+ \u2011
+ <emphasis>
+ various
+ \u2012
+ <emphasis>
+ dashes
+ \u2013
+ <emphasis>
+ and
+ \u2014
+ <emphasis>
+ hyphens
+ .
+ \xbf
+ <emphasis>
+ punctuation
+ ? \xa1
+ <emphasis>
+ examples
+ !\xa0
+ <emphasis>
+ no-break-space
+ \u00a0.
+"""],
+# Whitespace characters:
+# \u180e*MONGOLIAN VOWEL SEPARATOR*\u180e, fails in Python 2.6
+[u"""\
+text separated by
+*newline*
+or *space* or one of
+\xa0*NO-BREAK SPACE*\xa0,
+\u1680*OGHAM SPACE MARK*\u1680,
+\u2000*EN QUAD*\u2000,
+\u2001*EM QUAD*\u2001,
+\u2002*EN SPACE*\u2002,
+\u2003*EM SPACE*\u2003,
+\u2004*THREE-PER-EM SPACE*\u2004,
+\u2005*FOUR-PER-EM SPACE*\u2005,
+\u2006*SIX-PER-EM SPACE*\u2006,
+\u2007*FIGURE SPACE*\u2007,
+\u2008*PUNCTUATION SPACE*\u2008,
+\u2009*THIN SPACE*\u2009,
+\u200a*HAIR SPACE*\u200a,
+\u202f*NARROW NO-BREAK SPACE*\u202f,
+\u205f*MEDIUM MATHEMATICAL SPACE*\u205f,
+\u3000*IDEOGRAPHIC SPACE*\u3000,
+\u2028*LINE SEPARATOR*\u2028
+""",
+u"""\
+<document source="test data">
+ <paragraph>
+ text separated by
+ <emphasis>
+ newline
+ \n\
+ or \n\
+ <emphasis>
+ space
+ or one of
+ \xa0
+ <emphasis>
+ NO-BREAK SPACE
+ \xa0,
+ \u1680
+ <emphasis>
+ OGHAM SPACE MARK
+ \u1680,
+ \u2000
+ <emphasis>
+ EN QUAD
+ \u2000,
+ \u2001
+ <emphasis>
+ EM QUAD
+ \u2001,
+ \u2002
+ <emphasis>
+ EN SPACE
+ \u2002,
+ \u2003
+ <emphasis>
+ EM SPACE
+ \u2003,
+ \u2004
+ <emphasis>
+ THREE-PER-EM SPACE
+ \u2004,
+ \u2005
+ <emphasis>
+ FOUR-PER-EM SPACE
+ \u2005,
+ \u2006
+ <emphasis>
+ SIX-PER-EM SPACE
+ \u2006,
+ \u2007
+ <emphasis>
+ FIGURE SPACE
+ \u2007,
+ \u2008
+ <emphasis>
+ PUNCTUATION SPACE
+ \u2008,
+ \u2009
+ <emphasis>
+ THIN SPACE
+ \u2009,
+ \u200a
+ <emphasis>
+ HAIR SPACE
+ \u200a,
+ \u202f
+ <emphasis>
+ NARROW NO-BREAK SPACE
+ \u202f,
+ \u205f
+ <emphasis>
+ MEDIUM MATHEMATICAL SPACE
+ \u205f,
+ \u3000
+ <emphasis>
+ IDEOGRAPHIC SPACE
+ \u3000,
+ <paragraph>
+ <emphasis>
+ LINE SEPARATOR
+"""],
+[u"""\
+inline markup separated by non-ASCII whitespace
+\xa0**NO-BREAK SPACE**\xa0, \xa0``NO-BREAK SPACE``\xa0, \xa0`NO-BREAK SPACE`\xa0,
+\u2000**EN QUAD**\u2000, \u2000``EN QUAD``\u2000, \u2000`EN QUAD`\u2000,
+\u202f**NARROW NBSP**\u202f, \u202f``NARROW NBSP``\u202f, \u202f`NARROW NBSP`\u202f,
+""",
+u"""\
+<document source="test data">
+ <paragraph>
+ inline markup separated by non-ASCII whitespace
+ \xa0
+ <strong>
+ NO-BREAK SPACE
+ \xa0, \xa0
+ <literal>
+ NO-BREAK SPACE
+ \xa0, \xa0
+ <title_reference>
+ NO-BREAK SPACE
+ \xa0,
+ \u2000
+ <strong>
+ EN QUAD
+ \u2000, \u2000
+ <literal>
+ EN QUAD
+ \u2000, \u2000
+ <title_reference>
+ EN QUAD
+ \u2000,
+ \u202f
+ <strong>
+ NARROW NBSP
+ \u202f, \u202f
+ <literal>
+ NARROW NBSP
+ \u202f, \u202f
+ <title_reference>
+ NARROW NBSP
+ \u202f,
+"""],
+[u"""\
+no inline markup due to whitespace inside and behind: *
+newline
+*
+* space * or one of
+*\xa0NO-BREAK SPACE\xa0*
+*\u1680OGHAM SPACE MARK\u1680*
+*\u2000EN QUAD\u2000*
+*\u2001EM QUAD\u2001*
+*\u2002EN SPACE\u2002*
+*\u2003EM SPACE\u2003*
+*\u2004THREE-PER-EM SPACE\u2004*
+*\u2005FOUR-PER-EM SPACE\u2005*
+*\u2006SIX-PER-EM SPACE\u2006*
+*\u2007FIGURE SPACE\u2007*
+*\u2008PUNCTUATION SPACE\u2008*
+*\u2009THIN SPACE\u2009*
+*\u200aHAIR SPACE\u200a*
+*\u202fNARROW NO-BREAK SPACE\u202f*
+*\u205fMEDIUM MATHEMATICAL SPACE\u205f*
+*\u3000IDEOGRAPHIC SPACE\u3000*
+*\u2028LINE SEPARATOR\u2028*
+""",
+u"""\
+<document source="test data">
+ <paragraph>
+ no inline markup due to whitespace inside and behind: *
+ newline
+ *
+ * space * or one of
+ *\xa0NO-BREAK SPACE\xa0*
+ *\u1680OGHAM SPACE MARK\u1680*
+ *\u2000EN QUAD\u2000*
+ *\u2001EM QUAD\u2001*
+ *\u2002EN SPACE\u2002*
+ *\u2003EM SPACE\u2003*
+ *\u2004THREE-PER-EM SPACE\u2004*
+ *\u2005FOUR-PER-EM SPACE\u2005*
+ *\u2006SIX-PER-EM SPACE\u2006*
+ *\u2007FIGURE SPACE\u2007*
+ *\u2008PUNCTUATION SPACE\u2008*
+ *\u2009THIN SPACE\u2009*
+ *\u200aHAIR SPACE\u200a*
+ *\u202fNARROW NO-BREAK SPACE\u202f*
+ *\u205fMEDIUM MATHEMATICAL SPACE\u205f*
+ *\u3000IDEOGRAPHIC SPACE\u3000*
+ *
+ LINE SEPARATOR
+ *"""],
+[u"""\
+no inline markup because of non-ASCII whitespace following /preceding the markup
+**\xa0NO-BREAK SPACE\xa0** ``\xa0NO-BREAK SPACE\xa0`` `\xa0NO-BREAK SPACE\xa0`
+**\u2000EN QUAD\u2000** ``\u2000EN QUAD\u2000`` `\u2000EN QUAD\u2000`
+**\u202fNARROW NBSP\u202f** ``\u202fNARROW NBSP\u202f`` `\u202fNARROW NBSP\u202f`
+""",
+u"""\
+<document source="test data">
+ <paragraph>
+ no inline markup because of non-ASCII whitespace following /preceding the markup
+ **\xa0NO-BREAK SPACE\xa0** ``\xa0NO-BREAK SPACE\xa0`` `\xa0NO-BREAK SPACE\xa0`
+ **\u2000EN QUAD\u2000** ``\u2000EN QUAD\u2000`` `\u2000EN QUAD\u2000`
+ **\u202fNARROW NBSP\u202f** ``\u202fNARROW NBSP\u202f`` `\u202fNARROW NBSP\u202f`\
+"""],
+# « * » ‹ * › « * » ‹ * › « * » ‹ * › French,
+[u"""\
+"Quoted" markup start-string (matched openers & closers) -> no markup:
+
+'*' "*" (*) <*> [*] {*}
+⁅*⁆
+
+Some international quoting styles:
+‘*’ “*” English, ...,
+„*“ ‚*‘ »*« ›*‹ German, Czech, ...,
+„*” «*» Romanian,
+“*„ ‘*‚ Greek,
+「*」 『*』traditional Chinese,
+”*” ’*’ »*» ›*› Swedish, Finnish,
+„*” ‚*’ Polish,
+„*” »*« ’*’ Hungarian,
+
+But this is „*’ emphasized »*‹.
+""",
+u"""\
+<document source="test data">
+ <paragraph>
+ "Quoted" markup start-string (matched openers & closers) -> no markup:
+ <paragraph>
+ '*' "*" (*) <*> [*] {*}
+ ⁅*⁆
+ <paragraph>
+ Some international quoting styles:
+ ‘*’ “*” English, ...,
+ „*“ ‚*‘ »*« ›*‹ German, Czech, ...,
+ „*” «*» Romanian,
+ “*„ ‘*‚ Greek,
+ 「*」 『*』traditional Chinese,
+ ”*” ’*’ »*» ›*› Swedish, Finnish,
+ „*” ‚*’ Polish,
+ „*” »*« ’*’ Hungarian,
+ <paragraph>
+ But this is „
+ <emphasis>
+ ’ emphasized »
+ ‹.
+"""],
+]
+
+
+if __name__ == '__main__':
+ import unittest
+ unittest.main(defaultTest='suite')
--- /dev/null
+#! /usr/bin/env python
+
+# $Id: test_interpreted.py 8356 2019-08-26 16:44:19Z milde $
+# Author: David Goodger <goodger@python.org>
+# Copyright: This module has been placed in the public domain.
+
+"""
+Tests for interpreted text in docutils/parsers/rst/states.py.
+"""
+from __future__ import absolute_import
+
+from . import DocutilsTestSupport
+from docutils.utils.code_analyzer import with_pygments
+
+
+def suite():
+ s = DocutilsTestSupport.ParserTestSuite()
+ if not with_pygments:
+ del(totest['code-parsing'])
+ s.generateTests(totest)
+ return s
+
+totest = {}
+
+totest['basics'] = [
+["""\
+`interpreted`
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ <title_reference>
+ interpreted
+"""],
+["""\
+:title:`interpreted`
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ <title_reference>
+ interpreted
+"""],
+["""\
+`interpreted`:title:
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ <title_reference>
+ interpreted
+"""],
+["""\
+`interpreted \\`title``
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ <title_reference>
+ interpreted `title`
+"""],
+["""\
+:title:`:not-role: interpreted`
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ <title_reference>
+ :not-role: interpreted
+"""],
+["""\
+`interpreted` but not \\`interpreted` [`] or ({[`] or [`]}) or `
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ <title_reference>
+ interpreted
+ but not `interpreted` [`] or ({[`] or [`]}) or `
+"""],
+["""\
+`interpreted`-text `interpreted`: text `interpreted`:text `text`'s interpreted
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ <title_reference>
+ interpreted
+ -text \n\
+ <title_reference>
+ interpreted
+ : text \n\
+ <title_reference>
+ interpreted
+ :text \n\
+ <title_reference>
+ text
+ 's interpreted
+"""],
+["""\
+`interpreted without closing backquote
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ <problematic ids="id2" refid="id1">
+ `
+ interpreted without closing backquote
+ <system_message backrefs="id2" ids="id1" level="2" line="1" source="test data" type="WARNING">
+ <paragraph>
+ Inline interpreted text or phrase reference start-string without end-string.
+"""],
+["""\
+`interpreted`:not a role if it contains whitespace:
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ <title_reference>
+ interpreted
+ :not a role if it contains whitespace:
+"""],
+["""\
+:title:`` (empty interpreted text not recognized)
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ :title:`` (empty interpreted text not recognized)
+"""],
+["""\
+:title:`\\ ` (interpreted text containing empty string)
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ <title_reference>
+ (interpreted text containing empty string)
+"""],
+["""\
+`\\ `:title: (interpreted text containing empty string (postfix))
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ <title_reference>
+ (interpreted text containing empty string (postfix))
+"""],
+["""\
+:title:`\\ non-empty`
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ <title_reference>
+ non-empty
+"""],
+["""\
+:title:`\\ ` (trailing unquoted space)
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ :title:
+ <problematic ids="id2" refid="id1">
+ `
+ ` (trailing unquoted space)
+ <system_message backrefs="id2" ids="id1" level="2" line="1" source="test data" type="WARNING">
+ <paragraph>
+ Inline interpreted text or phrase reference start-string without end-string.
+"""],
+["""\
+Explicit roles for standard inline markup:
+:emphasis:`emphasis`,
+:strong:`strong`,
+:literal:`inline literal text`.
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ Explicit roles for standard inline markup:
+ <emphasis>
+ emphasis
+ ,
+ <strong>
+ strong
+ ,
+ <literal>
+ inline literal text
+ .
+"""],
+["""\
+Simple explicit roles:
+:ab:`abbreviation`,
+:ac:`acronym`,
+:sup:`superscript`,
+:sub:`subscript`,
+:title:`title reference`.
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ Simple explicit roles:
+ <abbreviation>
+ abbreviation
+ ,
+ <acronym>
+ acronym
+ ,
+ <superscript>
+ superscript
+ ,
+ <subscript>
+ subscript
+ ,
+ <title_reference>
+ title reference
+ .
+"""],
+]
+
+totest['code'] = [
+["""\
+Code role for inline code snippets:
+:code:`$\alpha = \\int_0^\\infty f(x) dx$`.
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ Code role for inline code snippets:
+ <literal classes="code">
+ $\x07lpha = \\int_0^\\infty f(x) dx$
+ .
+"""],
+]
+
+totest['code-parsing'] = [
+["""\
+.. role:: tex(code)
+ :language: latex
+
+Custom role based on code role:
+:tex:`$\alpha = f(x)$`.
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ Custom role based on code role:
+ <literal classes="code tex latex">
+ <inline classes="literal string">
+ $
+ <inline classes="name builtin">
+ \x07lpha \n\
+ <inline classes="operator">
+ =
+ <inline classes="name builtin">
+ f
+ <inline classes="operator">
+ (
+ <inline classes="name builtin">
+ x
+ <inline classes="operator">
+ )
+ <inline classes="literal string">
+ $
+ .
+"""],
+["""\
+Custom role based on code role:
+
+.. role:: python(code)
+ :language: python
+ :class: testclass
+
+Python code :python:`print("The end")`.
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ Custom role based on code role:
+ <paragraph>
+ Python code \n\
+ <literal classes="code testclass python">
+ <inline classes="keyword">
+ print
+ <inline classes="punctuation">
+ (
+ <inline classes="literal string double">
+ "The end"
+ <inline classes="punctuation">
+ )
+ .
+"""],
+]
+
+totest['references'] = [
+["""\
+:PEP:`0`
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ <reference refuri="http://www.python.org/dev/peps/pep-0000">
+ PEP 0
+"""],
+["""\
+:PEP:`-1`
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ <problematic ids="id2" refid="id1">
+ :PEP:`-1`
+ <system_message backrefs="id2" ids="id1" level="3" line="1" source="test data" type="ERROR">
+ <paragraph>
+ PEP number must be a number from 0 to 9999; "-1" is invalid.
+"""],
+["""\
+:RFC:`2822`
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ <reference refuri="http://tools.ietf.org/html/rfc2822.html">
+ RFC 2822
+"""],
+["""\
+:RFC:`0`
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ <problematic ids="id2" refid="id1">
+ :RFC:`0`
+ <system_message backrefs="id2" ids="id1" level="3" line="1" source="test data" type="ERROR">
+ <paragraph>
+ RFC number must be a number greater than or equal to 1; "0" is invalid.
+"""],
+["""\
+:RFC:`2822#section1`
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ <reference refuri="http://tools.ietf.org/html/rfc2822.html#section1">
+ RFC 2822
+"""],
+]
+
+totest['unknown_roles'] = [
+["""\
+:role:`interpreted`
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ <problematic ids="id2" refid="id1">
+ :role:`interpreted`
+ <system_message level="1" line="1" source="test data" type="INFO">
+ <paragraph>
+ No role entry for "role" in module "docutils.parsers.rst.languages.en".
+ Trying "role" as canonical role name.
+ <system_message backrefs="id2" ids="id1" level="3" line="1" source="test data" type="ERROR">
+ <paragraph>
+ Unknown interpreted text role "role".
+"""],
+["""\
+`interpreted`:role:
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ <problematic ids="id2" refid="id1">
+ `interpreted`:role:
+ <system_message level="1" line="1" source="test data" type="INFO">
+ <paragraph>
+ No role entry for "role" in module "docutils.parsers.rst.languages.en".
+ Trying "role" as canonical role name.
+ <system_message backrefs="id2" ids="id1" level="3" line="1" source="test data" type="ERROR">
+ <paragraph>
+ Unknown interpreted text role "role".
+"""],
+["""\
+:role:`interpreted`:role:
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ <problematic ids="id2" refid="id1">
+ :role:`interpreted`:role:
+ <system_message backrefs="id2" ids="id1" level="2" line="1" source="test data" type="WARNING">
+ <paragraph>
+ Multiple roles in interpreted text (both prefix and suffix present; only one allowed).
+"""],
+["""\
+:very.long-role_name:`interpreted`
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ <problematic ids="id2" refid="id1">
+ :very.long-role_name:`interpreted`
+ <system_message level="1" line="1" source="test data" type="INFO">
+ <paragraph>
+ No role entry for "very.long-role_name" in module "docutils.parsers.rst.languages.en".
+ Trying "very.long-role_name" as canonical role name.
+ <system_message backrefs="id2" ids="id1" level="3" line="1" source="test data" type="ERROR">
+ <paragraph>
+ Unknown interpreted text role "very.long-role_name".
+"""],
+["""\
+:restructuredtext-unimplemented-role:`interpreted`
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ <problematic ids="id2" refid="id1">
+ :restructuredtext-unimplemented-role:`interpreted`
+ <system_message level="1" line="1" source="test data" type="INFO">
+ <paragraph>
+ No role entry for "restructuredtext-unimplemented-role" in module "docutils.parsers.rst.languages.en".
+ Trying "restructuredtext-unimplemented-role" as canonical role name.
+ <system_message backrefs="id2" ids="id1" level="3" line="1" source="test data" type="ERROR">
+ <paragraph>
+ Interpreted text role "restructuredtext-unimplemented-role" not implemented.
+"""],
+]
+
+
+if __name__ == '__main__':
+ import unittest
+ unittest.main(defaultTest='suite')
--- /dev/null
+#! /usr/bin/env python
+
+# $Id: test_interpreted.py 6424 2010-09-18 10:43:52Z smerten $
+# Author: David Goodger <goodger@python.org>
+# Copyright: This module has been placed in the public domain.
+
+"""
+Tests for interpreted text in docutils/parsers/rst/states.py.
+Test not default/fallback language french.
+"""
+from __future__ import absolute_import
+
+from . import DocutilsTestSupport
+
+
+def suite():
+ s = DocutilsTestSupport.ParserTestSuite(suite_settings={'language_code':'fr'})
+ s.generateTests(totest)
+ return s
+
+totest = {}
+
+totest['basics'] = [
+["""\
+Simple explicit roles and english fallbacks:
+:acronym:`acronym`,
+:exp:`superscript`,
+:ind:`subscript`,
+:titre:`title reference`.
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ Simple explicit roles and english fallbacks:
+ <acronym>
+ acronym
+ ,
+ <superscript>
+ superscript
+ ,
+ <subscript>
+ subscript
+ ,
+ <title_reference>
+ title reference
+ .
+ <system_message level="1" line="1" source="test data" type="INFO">
+ <paragraph>
+ No role entry for "acronym" in module "docutils.parsers.rst.languages.fr".
+ Using English fallback for role "acronym".
+"""],
+]
+
+if __name__ == '__main__':
+ import unittest
+ unittest.main(defaultTest='suite')
--- /dev/null
+#! /usr/bin/env python
+
+# $Id: test_line_blocks.py 8356 2019-08-26 16:44:19Z milde $
+# Author: David Goodger <goodger@python.org>
+# Copyright: This module has been placed in the public domain.
+
+"""
+Tests for states.py.
+"""
+from __future__ import absolute_import
+
+from . import DocutilsTestSupport
+
+
+def suite():
+ s = DocutilsTestSupport.ParserTestSuite()
+ s.generateTests(totest)
+ return s
+
+totest = {}
+
+totest['line_blocks'] = [
+["""\
+| This is a line block.
+| Line breaks are *preserved*.
+
+| This is a second line block.
+
+| This is a third.
+""",
+"""\
+<document source="test data">
+ <line_block>
+ <line>
+ This is a line block.
+ <line>
+ Line breaks are \n\
+ <emphasis>
+ preserved
+ .
+ <line_block>
+ <line>
+ This is a second line block.
+ <line_block>
+ <line>
+ This is a third.
+"""],
+["""\
+| In line blocks,
+| Initial indentation is *also* preserved.
+""",
+"""\
+<document source="test data">
+ <line_block>
+ <line>
+ In line blocks,
+ <line_block>
+ <line>
+ Initial indentation is \n\
+ <emphasis>
+ also
+ preserved.
+"""],
+["""\
+| Individual lines in line blocks
+ *may* wrap, as indicated by the lack of a vertical bar prefix.
+| These are called "continuation lines".
+""",
+"""\
+<document source="test data">
+ <line_block>
+ <line>
+ Individual lines in line blocks
+ <emphasis>
+ may
+ wrap, as indicated by the lack of a vertical bar prefix.
+ <line>
+ These are called "continuation lines".
+"""],
+["""\
+| Inline markup in line blocks may also wrap *to
+ continuation lines*.
+| But not to following lines.
+""",
+"""\
+<document source="test data">
+ <line_block>
+ <line>
+ Inline markup in line blocks may also wrap \n\
+ <emphasis>
+ to
+ continuation lines
+ .
+ <line>
+ But not to following lines.
+"""],
+["""\
+\\| This is not a line block.
+The vertical bar is simply part of a paragraph.
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ | This is not a line block.
+ The vertical bar is simply part of a paragraph.
+"""],
+["""\
+| This line block is incomplete.
+There should be a blank line before this paragraph.
+""",
+"""\
+<document source="test data">
+ <line_block>
+ <line>
+ This line block is incomplete.
+ <system_message level="2" line="2" source="test data" type="WARNING">
+ <paragraph>
+ Line block ends without a blank line.
+ <paragraph>
+ There should be a blank line before this paragraph.
+"""],
+["""\
+| This line block contains
+|
+| blank lines.
+""",
+"""\
+<document source="test data">
+ <line_block>
+ <line>
+ This line block contains
+ <line>
+ <line>
+ blank lines.
+"""],
+["""\
+| The blank lines in this block
+| \n\
+| \n\
+| have bogus spaces.
+""",
+"""\
+<document source="test data">
+ <line_block>
+ <line>
+ The blank lines in this block
+ <line>
+ <line>
+ <line>
+ have bogus spaces.
+"""],
+["""\
+| Initial indentation is also significant and preserved:
+|
+| Indented 4 spaces
+| Not indented
+| Indented 2 spaces
+| Indented 4 spaces
+| Only one space
+|
+| Continuation lines may be indented less
+ than their base lines.
+""",
+"""\
+<document source="test data">
+ <line_block>
+ <line>
+ Initial indentation is also significant and preserved:
+ <line>
+ <line_block>
+ <line>
+ Indented 4 spaces
+ <line>
+ Not indented
+ <line_block>
+ <line_block>
+ <line>
+ Indented 2 spaces
+ <line_block>
+ <line>
+ Indented 4 spaces
+ <line>
+ Only one space
+ <line>
+ <line_block>
+ <line>
+ Continuation lines may be indented less
+ than their base lines.
+"""],
+["""\
+|
+| This block begins and ends with blank lines.
+|
+""",
+"""\
+<document source="test data">
+ <line_block>
+ <line>
+ <line>
+ This block begins and ends with blank lines.
+ <line>
+"""],
+["""\
+This is not
+| a line block.
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ This is not
+ | a line block.
+"""],
+["""\
+| The first line is indented.
+| The second line is more indented.
+""",
+"""\
+<document source="test data">
+ <line_block>
+ <line>
+ The first line is indented.
+ <line_block>
+ <line>
+ The second line is more indented.
+"""],
+["""\
+| The first line is indented.
+| The second line is less indented.
+""",
+"""\
+<document source="test data">
+ <line_block>
+ <line_block>
+ <line>
+ The first line is indented.
+ <line>
+ The second line is less indented.
+"""],
+["""\
+|This is not
+|a line block
+
+| This is an
+|incomplete line block.
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ <problematic ids="id2" refid="id1">
+ |
+ This is not
+ <problematic ids="id4" refid="id3">
+ |
+ a line block
+ <system_message backrefs="id2" ids="id1" level="2" line="1" source="test data" type="WARNING">
+ <paragraph>
+ Inline substitution_reference start-string without end-string.
+ <system_message backrefs="id4" ids="id3" level="2" line="1" source="test data" type="WARNING">
+ <paragraph>
+ Inline substitution_reference start-string without end-string.
+ <line_block>
+ <line>
+ This is an
+ <system_message level="2" line="5" source="test data" type="WARNING">
+ <paragraph>
+ Line block ends without a blank line.
+ <paragraph>
+ <problematic ids="id6" refid="id5">
+ |
+ incomplete line block.
+ <system_message backrefs="id6" ids="id5" level="2" line="5" source="test data" type="WARNING">
+ <paragraph>
+ Inline substitution_reference start-string without end-string.
+"""],
+["""\
+| Inline markup *may not
+| wrap* over several lines.
+""",
+"""\
+<document source="test data">
+ <line_block>
+ <line>
+ Inline markup \n\
+ <problematic ids="id2" refid="id1">
+ *
+ may not
+ <line>
+ wrap* over several lines.
+ <system_message backrefs="id2" ids="id1" level="2" line="1" source="test data" type="WARNING">
+ <paragraph>
+ Inline emphasis start-string without end-string.
+"""],
+["""\
+| * Block level markup
+| * is not recognized.
+""",
+"""\
+<document source="test data">
+ <line_block>
+ <line>
+ * Block level markup
+ <line>
+ * is not recognized.
+"""],
+["""\
+System messages can appear in place of lines:
+
+| `uff <test1>`_
+| `uff <test2>`_
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ System messages can appear in place of lines:
+ <line_block>
+ <line>
+ <reference name="uff" refuri="test1">
+ uff
+ <target dupnames="uff" ids="uff" refuri="test1">
+ <system_message backrefs="id1" level="2" line="3" source="test data" type="WARNING">
+ <paragraph>
+ Duplicate explicit target name: "uff".
+ <line>
+ <reference name="uff" refuri="test2">
+ uff
+ <target dupnames="uff" ids="id1" refuri="test2">
+"""],
+]
+
+
+if __name__ == '__main__':
+ import unittest
+ unittest.main(defaultTest='suite')
--- /dev/null
+#! /usr/bin/env python
+
+# $Id: test_literal_blocks.py 8356 2019-08-26 16:44:19Z milde $
+# Author: David Goodger <goodger@python.org>
+# Copyright: This module has been placed in the public domain.
+
+"""
+Tests for states.py.
+"""
+from __future__ import absolute_import
+
+from . import DocutilsTestSupport
+
+
+def suite():
+ s = DocutilsTestSupport.ParserTestSuite()
+ s.generateTests(totest)
+ return s
+
+totest = {}
+
+totest['indented_literal_blocks'] = [
+["""\
+A paragraph::
+
+ A literal block.
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ A paragraph:
+ <literal_block xml:space="preserve">
+ A literal block.
+"""],
+["""\
+A paragraph with a space after the colons:: \n\
+
+ A literal block.
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ A paragraph with a space after the colons:
+ <literal_block xml:space="preserve">
+ A literal block.
+"""],
+["""\
+A paragraph::
+
+ A literal block.
+
+Another paragraph::
+
+ Another literal block.
+ With two blank lines following.
+
+
+A final paragraph.
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ A paragraph:
+ <literal_block xml:space="preserve">
+ A literal block.
+ <paragraph>
+ Another paragraph:
+ <literal_block xml:space="preserve">
+ Another literal block.
+ With two blank lines following.
+ <paragraph>
+ A final paragraph.
+"""],
+["""\
+A paragraph
+on more than
+one line::
+
+ A literal block.
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ A paragraph
+ on more than
+ one line:
+ <literal_block xml:space="preserve">
+ A literal block.
+"""],
+["""\
+A paragraph
+on more than
+one line::
+ A literal block
+ with no blank line above.
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ A paragraph
+ on more than
+ one line:
+ <system_message level="3" line="4" source="test data" type="ERROR">
+ <paragraph>
+ Unexpected indentation.
+ <literal_block xml:space="preserve">
+ A literal block
+ with no blank line above.
+"""],
+["""\
+A paragraph::
+
+ A literal block.
+no blank line
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ A paragraph:
+ <literal_block xml:space="preserve">
+ A literal block.
+ <system_message level="2" line="4" source="test data" type="WARNING">
+ <paragraph>
+ Literal block ends without a blank line; unexpected unindent.
+ <paragraph>
+ no blank line
+"""],
+[r"""
+A paragraph\\::
+
+ A literal block.
+
+A paragraph\::
+
+ Not a literal block.
+""",
+r"""<document source="test data">
+ <paragraph>
+ A paragraph\:
+ <literal_block xml:space="preserve">
+ A literal block.
+ <paragraph>
+ A paragraph::
+ <block_quote>
+ <paragraph>
+ Not a literal block.
+"""],
+[r"""
+\\::
+
+ A literal block.
+
+\::
+
+ Not a literal block.
+""",
+r"""<document source="test data">
+ <paragraph>
+ \:
+ <literal_block xml:space="preserve">
+ A literal block.
+ <paragraph>
+ ::
+ <block_quote>
+ <paragraph>
+ Not a literal block.
+"""],
+["""\
+A paragraph: ::
+
+ A literal block.
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ A paragraph:
+ <literal_block xml:space="preserve">
+ A literal block.
+"""],
+["""\
+A paragraph:
+
+::
+
+ A literal block.
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ A paragraph:
+ <literal_block xml:space="preserve">
+ A literal block.
+"""],
+["""\
+A paragraph:
+::
+
+ A literal block.
+""",
+"""\
+<document source="test data">
+ <system_message level="1" line="2" source="test data" type="INFO">
+ <paragraph>
+ Possible title underline, too short for the title.
+ Treating it as ordinary text because it's so short.
+ <paragraph>
+ A paragraph:
+ <literal_block xml:space="preserve">
+ A literal block.
+"""],
+["""\
+A paragraph:
+
+::
+
+ A literal block.
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ A paragraph:
+ <literal_block xml:space="preserve">
+ A literal block.
+"""],
+["""\
+A paragraph::
+
+Not a literal block.
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ A paragraph:
+ <system_message level="2" line="3" source="test data" type="WARNING">
+ <paragraph>
+ Literal block expected; none found.
+ <paragraph>
+ Not a literal block.
+"""],
+["""\
+A paragraph::
+
+ A wonky literal block.
+ Literal line 2.
+
+ Literal line 3.
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ A paragraph:
+ <literal_block xml:space="preserve">
+ A wonky literal block.
+ Literal line 2.
+ \n\
+ Literal line 3.
+"""],
+["""\
+EOF, even though a literal block is indicated::
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ EOF, even though a literal block is indicated:
+ <system_message level="2" line="2" source="test data" type="WARNING">
+ <paragraph>
+ Literal block expected; none found.
+"""],
+]
+
+totest['quoted_literal_blocks'] = [
+["""\
+A paragraph::
+
+> A literal block.
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ A paragraph:
+ <literal_block xml:space="preserve">
+ > A literal block.
+"""],
+["""\
+A paragraph::
+
+
+> A literal block.
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ A paragraph:
+ <literal_block xml:space="preserve">
+ > A literal block.
+"""],
+["""\
+A paragraph::
+
+> A literal block.
+> Line 2.
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ A paragraph:
+ <literal_block xml:space="preserve">
+ > A literal block.
+ > Line 2.
+"""],
+["""\
+A paragraph::
+
+> A literal block.
+ Indented line.
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ A paragraph:
+ <literal_block xml:space="preserve">
+ > A literal block.
+ <system_message level="3" line="4" source="test data" type="ERROR">
+ <paragraph>
+ Unexpected indentation.
+ <block_quote>
+ <paragraph>
+ Indented line.
+"""],
+["""\
+A paragraph::
+
+> A literal block.
+Text.
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ A paragraph:
+ <literal_block xml:space="preserve">
+ > A literal block.
+ <system_message level="3" line="4" source="test data" type="ERROR">
+ <paragraph>
+ Inconsistent literal block quoting.
+ <paragraph>
+ Text.
+"""],
+["""\
+A paragraph::
+
+> A literal block.
+$ Inconsistent line.
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ A paragraph:
+ <literal_block xml:space="preserve">
+ > A literal block.
+ <system_message level="3" line="4" source="test data" type="ERROR">
+ <paragraph>
+ Inconsistent literal block quoting.
+ <paragraph>
+ $ Inconsistent line.
+"""],
+]
+
+
+if __name__ == '__main__':
+ import unittest
+ unittest.main(defaultTest='suite')
--- /dev/null
+#! /usr/bin/env python
+
+# $Id: test_option_lists.py 8356 2019-08-26 16:44:19Z milde $
+# Author: David Goodger <goodger@python.org>
+# Copyright: This module has been placed in the public domain.
+
+"""
+Tests for states.py.
+"""
+from __future__ import absolute_import
+
+from . import DocutilsTestSupport
+
+
+def suite():
+ s = DocutilsTestSupport.ParserTestSuite()
+ s.generateTests(totest)
+ return s
+
+totest = {}
+
+totest['option_lists'] = [
+["""\
+Short options:
+
+-a option -a
+
+-b file option -b
+
+-c name option -c
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ Short options:
+ <option_list>
+ <option_list_item>
+ <option_group>
+ <option>
+ <option_string>
+ -a
+ <description>
+ <paragraph>
+ option -a
+ <option_list_item>
+ <option_group>
+ <option>
+ <option_string>
+ -b
+ <option_argument delimiter=" ">
+ file
+ <description>
+ <paragraph>
+ option -b
+ <option_list_item>
+ <option_group>
+ <option>
+ <option_string>
+ -c
+ <option_argument delimiter=" ">
+ name
+ <description>
+ <paragraph>
+ option -c
+"""],
+["""\
+Long options:
+
+--aaaa option --aaaa
+--bbbb=file option --bbbb
+--cccc name option --cccc
+--d-e-f-g option --d-e-f-g
+--h_i_j_k option --h_i_j_k
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ Long options:
+ <option_list>
+ <option_list_item>
+ <option_group>
+ <option>
+ <option_string>
+ --aaaa
+ <description>
+ <paragraph>
+ option --aaaa
+ <option_list_item>
+ <option_group>
+ <option>
+ <option_string>
+ --bbbb
+ <option_argument delimiter="=">
+ file
+ <description>
+ <paragraph>
+ option --bbbb
+ <option_list_item>
+ <option_group>
+ <option>
+ <option_string>
+ --cccc
+ <option_argument delimiter=" ">
+ name
+ <description>
+ <paragraph>
+ option --cccc
+ <option_list_item>
+ <option_group>
+ <option>
+ <option_string>
+ --d-e-f-g
+ <description>
+ <paragraph>
+ option --d-e-f-g
+ <option_list_item>
+ <option_group>
+ <option>
+ <option_string>
+ --h_i_j_k
+ <description>
+ <paragraph>
+ option --h_i_j_k
+"""],
+["""\
+Old GNU-style options:
+
++a option +a
+
++b file option +b
+
++c name option +c
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ Old GNU-style options:
+ <option_list>
+ <option_list_item>
+ <option_group>
+ <option>
+ <option_string>
+ +a
+ <description>
+ <paragraph>
+ option +a
+ <option_list_item>
+ <option_group>
+ <option>
+ <option_string>
+ +b
+ <option_argument delimiter=" ">
+ file
+ <description>
+ <paragraph>
+ option +b
+ <option_list_item>
+ <option_group>
+ <option>
+ <option_string>
+ +c
+ <option_argument delimiter=" ">
+ name
+ <description>
+ <paragraph>
+ option +c
+"""],
+["""\
+VMS/DOS-style options:
+
+/A option /A
+/B file option /B
+/CCC option /CCC
+/DDD string option /DDD
+/EEE=int option /EEE
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ VMS/DOS-style options:
+ <option_list>
+ <option_list_item>
+ <option_group>
+ <option>
+ <option_string>
+ /A
+ <description>
+ <paragraph>
+ option /A
+ <option_list_item>
+ <option_group>
+ <option>
+ <option_string>
+ /B
+ <option_argument delimiter=" ">
+ file
+ <description>
+ <paragraph>
+ option /B
+ <option_list_item>
+ <option_group>
+ <option>
+ <option_string>
+ /CCC
+ <description>
+ <paragraph>
+ option /CCC
+ <option_list_item>
+ <option_group>
+ <option>
+ <option_string>
+ /DDD
+ <option_argument delimiter=" ">
+ string
+ <description>
+ <paragraph>
+ option /DDD
+ <option_list_item>
+ <option_group>
+ <option>
+ <option_string>
+ /EEE
+ <option_argument delimiter="=">
+ int
+ <description>
+ <paragraph>
+ option /EEE
+"""],
+["""\
+Mixed short, long, and VMS/DOS options:
+
+-a option -a
+--bbbb=file option -bbbb
+/C option /C
+--dddd name option --dddd
+-e string option -e
+/F file option /F
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ Mixed short, long, and VMS/DOS options:
+ <option_list>
+ <option_list_item>
+ <option_group>
+ <option>
+ <option_string>
+ -a
+ <description>
+ <paragraph>
+ option -a
+ <option_list_item>
+ <option_group>
+ <option>
+ <option_string>
+ --bbbb
+ <option_argument delimiter="=">
+ file
+ <description>
+ <paragraph>
+ option -bbbb
+ <option_list_item>
+ <option_group>
+ <option>
+ <option_string>
+ /C
+ <description>
+ <paragraph>
+ option /C
+ <option_list_item>
+ <option_group>
+ <option>
+ <option_string>
+ --dddd
+ <option_argument delimiter=" ">
+ name
+ <description>
+ <paragraph>
+ option --dddd
+ <option_list_item>
+ <option_group>
+ <option>
+ <option_string>
+ -e
+ <option_argument delimiter=" ">
+ string
+ <description>
+ <paragraph>
+ option -e
+ <option_list_item>
+ <option_group>
+ <option>
+ <option_string>
+ /F
+ <option_argument delimiter=" ">
+ file
+ <description>
+ <paragraph>
+ option /F
+"""],
+["""\
+Aliased options:
+
+-a, --aaaa, /A option -a, --aaaa, /A
+-b file, --bbbb=file, /B file option -b, --bbbb, /B
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ Aliased options:
+ <option_list>
+ <option_list_item>
+ <option_group>
+ <option>
+ <option_string>
+ -a
+ <option>
+ <option_string>
+ --aaaa
+ <option>
+ <option_string>
+ /A
+ <description>
+ <paragraph>
+ option -a, --aaaa, /A
+ <option_list_item>
+ <option_group>
+ <option>
+ <option_string>
+ -b
+ <option_argument delimiter=" ">
+ file
+ <option>
+ <option_string>
+ --bbbb
+ <option_argument delimiter="=">
+ file
+ <option>
+ <option_string>
+ /B
+ <option_argument delimiter=" ">
+ file
+ <description>
+ <paragraph>
+ option -b, --bbbb, /B
+"""],
+["""\
+Multiple lines in descriptions, aligned:
+
+-a option -a, line 1
+ line 2
+-b file option -b, line 1
+ line 2
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ Multiple lines in descriptions, aligned:
+ <option_list>
+ <option_list_item>
+ <option_group>
+ <option>
+ <option_string>
+ -a
+ <description>
+ <paragraph>
+ option -a, line 1
+ line 2
+ <option_list_item>
+ <option_group>
+ <option>
+ <option_string>
+ -b
+ <option_argument delimiter=" ">
+ file
+ <description>
+ <paragraph>
+ option -b, line 1
+ line 2
+"""],
+["""\
+Multiple lines in descriptions, not aligned:
+
+-a option -a, line 1
+ line 2
+-b file option -b, line 1
+ line 2
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ Multiple lines in descriptions, not aligned:
+ <option_list>
+ <option_list_item>
+ <option_group>
+ <option>
+ <option_string>
+ -a
+ <description>
+ <paragraph>
+ option -a, line 1
+ line 2
+ <option_list_item>
+ <option_group>
+ <option>
+ <option_string>
+ -b
+ <option_argument delimiter=" ">
+ file
+ <description>
+ <paragraph>
+ option -b, line 1
+ line 2
+"""],
+["""\
+Descriptions begin on next line:
+
+-a
+ option -a, line 1
+ line 2
+-b file
+ option -b, line 1
+ line 2
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ Descriptions begin on next line:
+ <option_list>
+ <option_list_item>
+ <option_group>
+ <option>
+ <option_string>
+ -a
+ <description>
+ <paragraph>
+ option -a, line 1
+ line 2
+ <option_list_item>
+ <option_group>
+ <option>
+ <option_string>
+ -b
+ <option_argument delimiter=" ">
+ file
+ <description>
+ <paragraph>
+ option -b, line 1
+ line 2
+"""],
+["""\
+Multiple body elements in descriptions:
+
+-a option -a, para 1
+
+ para 2
+-b file
+ option -b, para 1
+
+ para 2
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ Multiple body elements in descriptions:
+ <option_list>
+ <option_list_item>
+ <option_group>
+ <option>
+ <option_string>
+ -a
+ <description>
+ <paragraph>
+ option -a, para 1
+ <paragraph>
+ para 2
+ <option_list_item>
+ <option_group>
+ <option>
+ <option_string>
+ -b
+ <option_argument delimiter=" ">
+ file
+ <description>
+ <paragraph>
+ option -b, para 1
+ <paragraph>
+ para 2
+"""],
+["""\
+--option
+empty item above, no blank line
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ --option
+ empty item above, no blank line
+"""],
+["""\
+An option list using equals:
+
+--long1=arg1 Description 1
+--long2=arg2 Description 2
+
+An option list using spaces:
+
+--long1 arg1 Description 1
+--long2 arg2 Description 2
+
+An option list using mixed delimiters:
+
+--long1=arg1 Description 1
+--long2 arg2 Description 2
+
+An option list using mixed delimiters in one line:
+
+--long1=arg1, --long2 arg2 Description
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ An option list using equals:
+ <option_list>
+ <option_list_item>
+ <option_group>
+ <option>
+ <option_string>
+ --long1
+ <option_argument delimiter="=">
+ arg1
+ <description>
+ <paragraph>
+ Description 1
+ <option_list_item>
+ <option_group>
+ <option>
+ <option_string>
+ --long2
+ <option_argument delimiter="=">
+ arg2
+ <description>
+ <paragraph>
+ Description 2
+ <paragraph>
+ An option list using spaces:
+ <option_list>
+ <option_list_item>
+ <option_group>
+ <option>
+ <option_string>
+ --long1
+ <option_argument delimiter=" ">
+ arg1
+ <description>
+ <paragraph>
+ Description 1
+ <option_list_item>
+ <option_group>
+ <option>
+ <option_string>
+ --long2
+ <option_argument delimiter=" ">
+ arg2
+ <description>
+ <paragraph>
+ Description 2
+ <paragraph>
+ An option list using mixed delimiters:
+ <option_list>
+ <option_list_item>
+ <option_group>
+ <option>
+ <option_string>
+ --long1
+ <option_argument delimiter="=">
+ arg1
+ <description>
+ <paragraph>
+ Description 1
+ <option_list_item>
+ <option_group>
+ <option>
+ <option_string>
+ --long2
+ <option_argument delimiter=" ">
+ arg2
+ <description>
+ <paragraph>
+ Description 2
+ <paragraph>
+ An option list using mixed delimiters in one line:
+ <option_list>
+ <option_list_item>
+ <option_group>
+ <option>
+ <option_string>
+ --long1
+ <option_argument delimiter="=">
+ arg1
+ <option>
+ <option_string>
+ --long2
+ <option_argument delimiter=" ">
+ arg2
+ <description>
+ <paragraph>
+ Description
+"""],
+["""\
+Some edge cases:
+
+--option=arg arg too many arguments
+
+--option=arg,arg not supported (yet?)
+
+--option=arg=arg too many arguments
+
+--option arg arg too many arguments
+
+-a letter arg2 too many arguments
+
+/A letter arg2 too many arguments
+
+--option= argument missing
+
+--=argument option missing
+
+-- everything missing
+
+- this should be a bullet list item
+
+These next ones should be simple paragraphs:
+
+-1
+
+--option
+
+--1
+
+-1 and this one too.
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ Some edge cases:
+ <paragraph>
+ --option=arg arg too many arguments
+ <paragraph>
+ --option=arg,arg not supported (yet?)
+ <paragraph>
+ --option=arg=arg too many arguments
+ <paragraph>
+ --option arg arg too many arguments
+ <paragraph>
+ -a letter arg2 too many arguments
+ <paragraph>
+ /A letter arg2 too many arguments
+ <paragraph>
+ --option= argument missing
+ <paragraph>
+ --=argument option missing
+ <paragraph>
+ -- everything missing
+ <bullet_list bullet="-">
+ <list_item>
+ <paragraph>
+ this should be a bullet list item
+ <paragraph>
+ These next ones should be simple paragraphs:
+ <paragraph>
+ -1
+ <paragraph>
+ --option
+ <paragraph>
+ --1
+ <paragraph>
+ -1 and this one too.
+"""],
+["""\
+Complex optargs:
+
+--source-url=<URL> Use the supplied <URL> verbatim.
+--output-encoding=<name[:handler]>, -o<name[:handler]>
+ Specify the text encoding for output.
+--af=<filter1[=parameter1:parameter2:...],filter2,...>
+ Setup a chain of audio filters.
+ Option argument containing delimiter ``=``.
+-f <[path]filename> Send output to file.
+-d <src dest> Use diff from <src> to <dest>.
+--bogus=<x y z> Bogus 3D coordinates.
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ Complex optargs:
+ <option_list>
+ <option_list_item>
+ <option_group>
+ <option>
+ <option_string>
+ --source-url
+ <option_argument delimiter="=">
+ <URL>
+ <description>
+ <paragraph>
+ Use the supplied <URL> verbatim.
+ <option_list_item>
+ <option_group>
+ <option>
+ <option_string>
+ --output-encoding
+ <option_argument delimiter="=">
+ <name[:handler]>
+ <option>
+ <option_string>
+ -o
+ <option_argument delimiter="">
+ <name[:handler]>
+ <description>
+ <paragraph>
+ Specify the text encoding for output.
+ <option_list_item>
+ <option_group>
+ <option>
+ <option_string>
+ --af
+ <option_argument delimiter="=">
+ <filter1[=parameter1:parameter2:...],filter2,...>
+ <description>
+ <paragraph>
+ Setup a chain of audio filters.
+ Option argument containing delimiter \n\
+ <literal>
+ =
+ .
+ <option_list_item>
+ <option_group>
+ <option>
+ <option_string>
+ -f
+ <option_argument delimiter=" ">
+ <[path]filename>
+ <description>
+ <paragraph>
+ Send output to file.
+ <option_list_item>
+ <option_group>
+ <option>
+ <option_string>
+ -d
+ <option_argument delimiter=" ">
+ <src dest>
+ <description>
+ <paragraph>
+ Use diff from <src> to <dest>.
+ <option_list_item>
+ <option_group>
+ <option>
+ <option_string>
+ --bogus
+ <option_argument delimiter="=">
+ <x y z>
+ <description>
+ <paragraph>
+ Bogus 3D coordinates.
+"""],
+]
+
+
+if __name__ == '__main__':
+ import unittest
+ unittest.main(defaultTest='suite')
--- /dev/null
+#! /usr/bin/env python
+
+# $Id: test_outdenting.py 8356 2019-08-26 16:44:19Z milde $
+# Author: David Goodger <goodger@python.org>
+# Copyright: This module has been placed in the public domain.
+
+"""
+Tests for states.py.
+"""
+from __future__ import absolute_import
+
+from . import DocutilsTestSupport
+
+
+def suite():
+ s = DocutilsTestSupport.ParserTestSuite()
+ s.generateTests(totest)
+ return s
+
+totest = {}
+
+totest['outdenting'] = [
+["""\
+Anywhere a paragraph would have an effect on the current
+indentation level, a comment or list item should also.
+
++ bullet
+
+This paragraph ends the bullet list item before a block quote.
+
+ Block quote.
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ Anywhere a paragraph would have an effect on the current
+ indentation level, a comment or list item should also.
+ <bullet_list bullet="+">
+ <list_item>
+ <paragraph>
+ bullet
+ <paragraph>
+ This paragraph ends the bullet list item before a block quote.
+ <block_quote>
+ <paragraph>
+ Block quote.
+"""],
+["""\
++ bullet
+
+.. Comments swallow up all indented text following.
+
+ (Therefore this is not a) block quote.
+
+- bullet
+
+ If we want a block quote after this bullet list item,
+ we need to use an empty comment:
+
+..
+
+ Block quote.
+""",
+"""\
+<document source="test data">
+ <bullet_list bullet="+">
+ <list_item>
+ <paragraph>
+ bullet
+ <comment xml:space="preserve">
+ Comments swallow up all indented text following.
+ \n\
+ (Therefore this is not a) block quote.
+ <bullet_list bullet="-">
+ <list_item>
+ <paragraph>
+ bullet
+ <paragraph>
+ If we want a block quote after this bullet list item,
+ we need to use an empty comment:
+ <comment xml:space="preserve">
+ <block_quote>
+ <paragraph>
+ Block quote.
+"""],
+]
+
+if __name__ == '__main__':
+ import unittest
+ unittest.main(defaultTest='suite')
--- /dev/null
+#! /usr/bin/env python
+
+# $Id: test_paragraphs.py 8356 2019-08-26 16:44:19Z milde $
+# Author: David Goodger <goodger@python.org>
+# Copyright: This module has been placed in the public domain.
+
+"""
+Tests for states.py.
+"""
+from __future__ import absolute_import
+
+from . import DocutilsTestSupport
+
+
+def suite():
+ s = DocutilsTestSupport.ParserTestSuite()
+ s.generateTests(totest)
+ return s
+
+totest = {}
+
+totest['paragraphs'] = [
+["""\
+A paragraph.
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ A paragraph.
+"""],
+["""\
+Paragraph 1.
+
+Paragraph 2.
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ Paragraph 1.
+ <paragraph>
+ Paragraph 2.
+"""],
+["""\
+Line 1.
+Line 2.
+Line 3.
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ Line 1.
+ Line 2.
+ Line 3.
+"""],
+["""\
+Paragraph 1, Line 1.
+Line 2.
+Line 3.
+
+Paragraph 2, Line 1.
+Line 2.
+Line 3.
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ Paragraph 1, Line 1.
+ Line 2.
+ Line 3.
+ <paragraph>
+ Paragraph 2, Line 1.
+ Line 2.
+ Line 3.
+"""],
+["""\
+A. Einstein was a really
+smart dude.
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ A. Einstein was a really
+ smart dude.
+"""],
+]
+
+if __name__ == '__main__':
+ import unittest
+ unittest.main(defaultTest='suite')
--- /dev/null
+# -*- coding: utf-8 -*-
+#! /usr/bin/env python
+
+# $Id: test_section_headers.py 8356 2019-08-26 16:44:19Z milde $
+# Author: David Goodger <goodger@python.org>
+# Copyright: This module has been placed in the public domain.
+
+"""
+Tests for states.py.
+"""
+from __future__ import absolute_import
+
+from . import DocutilsTestSupport
+
+
+def suite():
+ s = DocutilsTestSupport.ParserTestSuite()
+ s.generateTests(totest)
+ return s
+
+totest = {}
+
+totest['section_headers'] = [
+["""\
+Title
+=====
+
+Paragraph.
+""",
+"""\
+<document source="test data">
+ <section ids="title" names="title">
+ <title>
+ Title
+ <paragraph>
+ Paragraph.
+"""],
+["""\
+Title
+=====
+Paragraph (no blank line).
+""",
+"""\
+<document source="test data">
+ <section ids="title" names="title">
+ <title>
+ Title
+ <paragraph>
+ Paragraph (no blank line).
+"""],
+["""\
+Paragraph.
+
+Title
+=====
+
+Paragraph.
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ Paragraph.
+ <section ids="title" names="title">
+ <title>
+ Title
+ <paragraph>
+ Paragraph.
+"""],
+["""\
+Test unexpected section titles.
+
+ Title
+ =====
+ Paragraph.
+
+ -----
+ Title
+ -----
+ Paragraph.
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ Test unexpected section titles.
+ <block_quote>
+ <system_message level="4" line="4" source="test data" type="SEVERE">
+ <paragraph>
+ Unexpected section title.
+ <literal_block xml:space="preserve">
+ Title
+ =====
+ <paragraph>
+ Paragraph.
+ <system_message level="4" line="7" source="test data" type="SEVERE">
+ <paragraph>
+ Unexpected section title or transition.
+ <literal_block xml:space="preserve">
+ -----
+ <system_message level="4" line="9" source="test data" type="SEVERE">
+ <paragraph>
+ Unexpected section title.
+ <literal_block xml:space="preserve">
+ Title
+ -----
+ <paragraph>
+ Paragraph.
+"""],
+["""\
+Title
+====
+
+Test short underline.
+""",
+"""\
+<document source="test data">
+ <section ids="title" names="title">
+ <title>
+ Title
+ <system_message level="2" line="2" source="test data" type="WARNING">
+ <paragraph>
+ Title underline too short.
+ <literal_block xml:space="preserve">
+ Title
+ ====
+ <paragraph>
+ Test short underline.
+"""],
+[u"""\
+à with combining varia
+======================
+
+Do not count combining chars in title column width.
+""",
+u"""\
+<document source="test data">
+ <section ids="a-with-combining-varia" names="a\u0300\\ with\\ combining\\ varia">
+ <title>
+ à with combining varia
+ <paragraph>
+ Do not count combining chars in title column width.
+"""],
+["""\
+=====
+Title
+=====
+
+Test overline title.
+""",
+"""\
+<document source="test data">
+ <section ids="title" names="title">
+ <title>
+ Title
+ <paragraph>
+ Test overline title.
+"""],
+["""\
+=======
+ Title
+=======
+
+Test overline title with inset.
+""",
+"""\
+<document source="test data">
+ <section ids="title" names="title">
+ <title>
+ Title
+ <paragraph>
+ Test overline title with inset.
+"""],
+["""\
+========================
+ Test Missing Underline
+""",
+"""\
+<document source="test data">
+ <system_message level="4" line="1" source="test data" type="SEVERE">
+ <paragraph>
+ Incomplete section title.
+ <literal_block xml:space="preserve">
+ ========================
+ Test Missing Underline
+"""],
+["""\
+========================
+ Test Missing Underline
+
+""",
+"""\
+<document source="test data">
+ <system_message level="4" line="1" source="test data" type="SEVERE">
+ <paragraph>
+ Missing matching underline for section title overline.
+ <literal_block xml:space="preserve">
+ ========================
+ Test Missing Underline
+"""],
+["""\
+=======
+ Title
+
+Test missing underline, with paragraph.
+""",
+"""\
+<document source="test data">
+ <system_message level="4" line="1" source="test data" type="SEVERE">
+ <paragraph>
+ Missing matching underline for section title overline.
+ <literal_block xml:space="preserve">
+ =======
+ Title
+ <paragraph>
+ Test missing underline, with paragraph.
+"""],
+["""\
+=======
+ Long Title
+=======
+
+Test long title and space normalization.
+""",
+"""\
+<document source="test data">
+ <section ids="long-title" names="long\\ title">
+ <title>
+ Long Title
+ <system_message level="2" line="1" source="test data" type="WARNING">
+ <paragraph>
+ Title overline too short.
+ <literal_block xml:space="preserve">
+ =======
+ Long Title
+ =======
+ <paragraph>
+ Test long title and space normalization.
+"""],
+["""\
+=======
+ Title
+-------
+
+Paragraph.
+""",
+"""\
+<document source="test data">
+ <system_message level="4" line="1" source="test data" type="SEVERE">
+ <paragraph>
+ Title overline & underline mismatch.
+ <literal_block xml:space="preserve">
+ =======
+ Title
+ -------
+ <paragraph>
+ Paragraph.
+"""],
+["""\
+========================
+
+========================
+
+Test missing titles; blank line in-between.
+
+========================
+
+========================
+""",
+"""\
+<document source="test data">
+ <transition>
+ <transition>
+ <paragraph>
+ Test missing titles; blank line in-between.
+ <transition>
+ <transition>
+"""],
+["""\
+========================
+========================
+
+Test missing titles; nothing in-between.
+
+========================
+========================
+""",
+"""\
+<document source="test data">
+ <system_message level="3" line="1" source="test data" type="ERROR">
+ <paragraph>
+ Invalid section title or transition marker.
+ <literal_block xml:space="preserve">
+ ========================
+ ========================
+ <paragraph>
+ Test missing titles; nothing in-between.
+ <system_message level="3" line="6" source="test data" type="ERROR">
+ <paragraph>
+ Invalid section title or transition marker.
+ <literal_block xml:space="preserve">
+ ========================
+ ========================
+"""],
+["""\
+.. Test return to existing, highest-level section (Title 3).
+
+Title 1
+=======
+Paragraph 1.
+
+Title 2
+-------
+Paragraph 2.
+
+Title 3
+=======
+Paragraph 3.
+
+Title 4
+-------
+Paragraph 4.
+""",
+"""\
+<document source="test data">
+ <comment xml:space="preserve">
+ Test return to existing, highest-level section (Title 3).
+ <section ids="title-1" names="title\\ 1">
+ <title>
+ Title 1
+ <paragraph>
+ Paragraph 1.
+ <section ids="title-2" names="title\\ 2">
+ <title>
+ Title 2
+ <paragraph>
+ Paragraph 2.
+ <section ids="title-3" names="title\\ 3">
+ <title>
+ Title 3
+ <paragraph>
+ Paragraph 3.
+ <section ids="title-4" names="title\\ 4">
+ <title>
+ Title 4
+ <paragraph>
+ Paragraph 4.
+"""],
+["""\
+Test return to existing, highest-level section (Title 3, with overlines).
+
+=======
+Title 1
+=======
+Paragraph 1.
+
+-------
+Title 2
+-------
+Paragraph 2.
+
+=======
+Title 3
+=======
+Paragraph 3.
+
+-------
+Title 4
+-------
+Paragraph 4.
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ Test return to existing, highest-level section (Title 3, with overlines).
+ <section ids="title-1" names="title\\ 1">
+ <title>
+ Title 1
+ <paragraph>
+ Paragraph 1.
+ <section ids="title-2" names="title\\ 2">
+ <title>
+ Title 2
+ <paragraph>
+ Paragraph 2.
+ <section ids="title-3" names="title\\ 3">
+ <title>
+ Title 3
+ <paragraph>
+ Paragraph 3.
+ <section ids="title-4" names="title\\ 4">
+ <title>
+ Title 4
+ <paragraph>
+ Paragraph 4.
+"""],
+["""\
+Test return to existing, higher-level section (Title 4).
+
+Title 1
+=======
+Paragraph 1.
+
+Title 2
+-------
+Paragraph 2.
+
+Title 3
+```````
+Paragraph 3.
+
+Title 4
+-------
+Paragraph 4.
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ Test return to existing, higher-level section (Title 4).
+ <section ids="title-1" names="title\\ 1">
+ <title>
+ Title 1
+ <paragraph>
+ Paragraph 1.
+ <section ids="title-2" names="title\\ 2">
+ <title>
+ Title 2
+ <paragraph>
+ Paragraph 2.
+ <section ids="title-3" names="title\\ 3">
+ <title>
+ Title 3
+ <paragraph>
+ Paragraph 3.
+ <section ids="title-4" names="title\\ 4">
+ <title>
+ Title 4
+ <paragraph>
+ Paragraph 4.
+"""],
+["""\
+Test bad subsection order (Title 4).
+
+Title 1
+=======
+Paragraph 1.
+
+Title 2
+-------
+Paragraph 2.
+
+Title 3
+=======
+Paragraph 3.
+
+Title 4
+```````
+Paragraph 4.
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ Test bad subsection order (Title 4).
+ <section ids="title-1" names="title\\ 1">
+ <title>
+ Title 1
+ <paragraph>
+ Paragraph 1.
+ <section ids="title-2" names="title\\ 2">
+ <title>
+ Title 2
+ <paragraph>
+ Paragraph 2.
+ <section ids="title-3" names="title\\ 3">
+ <title>
+ Title 3
+ <paragraph>
+ Paragraph 3.
+ <system_message level="4" line="15" source="test data" type="SEVERE">
+ <paragraph>
+ Title level inconsistent:
+ <literal_block xml:space="preserve">
+ Title 4
+ ```````
+ <paragraph>
+ Paragraph 4.
+"""],
+["""\
+Test bad subsection order (Title 4, with overlines).
+
+=======
+Title 1
+=======
+Paragraph 1.
+
+-------
+Title 2
+-------
+Paragraph 2.
+
+=======
+Title 3
+=======
+Paragraph 3.
+
+```````
+Title 4
+```````
+Paragraph 4.
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ Test bad subsection order (Title 4, with overlines).
+ <section ids="title-1" names="title\\ 1">
+ <title>
+ Title 1
+ <paragraph>
+ Paragraph 1.
+ <section ids="title-2" names="title\\ 2">
+ <title>
+ Title 2
+ <paragraph>
+ Paragraph 2.
+ <section ids="title-3" names="title\\ 3">
+ <title>
+ Title 3
+ <paragraph>
+ Paragraph 3.
+ <system_message level="4" line="19" source="test data" type="SEVERE">
+ <paragraph>
+ Title level inconsistent:
+ <literal_block xml:space="preserve">
+ ```````
+ Title 4
+ ```````
+ <paragraph>
+ Paragraph 4.
+"""],
+["""\
+Title containing *inline* ``markup``
+====================================
+
+Paragraph.
+""",
+"""\
+<document source="test data">
+ <section ids="title-containing-inline-markup" names="title\\ containing\\ inline\\ markup">
+ <title>
+ Title containing \n\
+ <emphasis>
+ inline
+ \n\
+ <literal>
+ markup
+ <paragraph>
+ Paragraph.
+"""],
+["""\
+1. Numbered Title
+=================
+
+Paragraph.
+""",
+"""\
+<document source="test data">
+ <section ids="numbered-title" names="1.\\ numbered\\ title">
+ <title>
+ 1. Numbered Title
+ <paragraph>
+ Paragraph.
+"""],
+["""\
+1. Item 1.
+2. Item 2.
+3. Numbered Title
+=================
+
+Paragraph.
+""",
+"""\
+<document source="test data">
+ <enumerated_list enumtype="arabic" prefix="" suffix=".">
+ <list_item>
+ <paragraph>
+ Item 1.
+ <list_item>
+ <paragraph>
+ Item 2.
+ <system_message level="2" line="3" source="test data" type="WARNING">
+ <paragraph>
+ Enumerated list ends without a blank line; unexpected unindent.
+ <section ids="numbered-title" names="3.\\ numbered\\ title">
+ <title>
+ 3. Numbered Title
+ <paragraph>
+ Paragraph.
+"""],
+["""\
+ABC
+===
+
+Short title.
+""",
+"""\
+<document source="test data">
+ <section ids="abc" names="abc">
+ <title>
+ ABC
+ <paragraph>
+ Short title.
+"""],
+["""\
+ABC
+==
+
+Underline too short.
+""",
+"""\
+<document source="test data">
+ <system_message level="1" line="2" source="test data" type="INFO">
+ <paragraph>
+ Possible title underline, too short for the title.
+ Treating it as ordinary text because it's so short.
+ <paragraph>
+ ABC
+ ==
+ <paragraph>
+ Underline too short.
+"""],
+["""\
+==
+ABC
+==
+
+Over & underline too short.
+""",
+"""\
+<document source="test data">
+ <system_message level="1" line="1" source="test data" type="INFO">
+ <paragraph>
+ Possible incomplete section title.
+ Treating the overline as ordinary text because it's so short.
+ <paragraph>
+ ==
+ ABC
+ ==
+ <paragraph>
+ Over & underline too short.
+"""],
+["""\
+==
+ABC
+
+Overline too short, no underline.
+""",
+"""\
+<document source="test data">
+ <system_message level="1" line="1" source="test data" type="INFO">
+ <paragraph>
+ Possible incomplete section title.
+ Treating the overline as ordinary text because it's so short.
+ <paragraph>
+ ==
+ ABC
+ <paragraph>
+ Overline too short, no underline.
+"""],
+["""\
+==
+ABC
+""",
+"""\
+<document source="test data">
+ <system_message level="1" line="1" source="test data" type="INFO">
+ <paragraph>
+ Possible incomplete section title.
+ Treating the overline as ordinary text because it's so short.
+ <paragraph>
+ ==
+ ABC
+"""],
+["""\
+==
+ Not a title: a definition list item.
+""",
+"""\
+<document source="test data">
+ <system_message level="1" line="1" source="test data" type="INFO">
+ <paragraph>
+ Possible incomplete section title.
+ Treating the overline as ordinary text because it's so short.
+ <definition_list>
+ <definition_list_item>
+ <term>
+ ==
+ <definition>
+ <paragraph>
+ Not a title: a definition list item.
+"""],
+["""\
+==
+ Not a title: a definition list item.
+--
+ Another definition list item. It's in a different list,
+ but that's an acceptable limitation given that this will
+ probably never happen in real life.
+
+ The next line will trigger a warning:
+==
+""",
+"""\
+<document source="test data">
+ <system_message level="1" line="1" source="test data" type="INFO">
+ <paragraph>
+ Possible incomplete section title.
+ Treating the overline as ordinary text because it's so short.
+ <definition_list>
+ <definition_list_item>
+ <term>
+ ==
+ <definition>
+ <paragraph>
+ Not a title: a definition list item.
+ <system_message level="2" line="3" source="test data" type="WARNING">
+ <paragraph>
+ Definition list ends without a blank line; unexpected unindent.
+ <system_message level="1" line="3" source="test data" type="INFO">
+ <paragraph>
+ Possible incomplete section title.
+ Treating the overline as ordinary text because it's so short.
+ <definition_list>
+ <definition_list_item>
+ <term>
+ --
+ <definition>
+ <paragraph>
+ Another definition list item. It's in a different list,
+ but that's an acceptable limitation given that this will
+ probably never happen in real life.
+ <paragraph>
+ The next line will trigger a warning:
+ <system_message level="2" line="9" source="test data" type="WARNING">
+ <paragraph>
+ Definition list ends without a blank line; unexpected unindent.
+ <paragraph>
+ ==
+"""],
+["""\
+Paragraph
+
+ ==
+ ABC
+ ==
+
+ Over & underline too short.
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ Paragraph
+ <block_quote>
+ <system_message level="1" line="3" source="test data" type="INFO">
+ <paragraph>
+ Unexpected possible title overline or transition.
+ Treating it as ordinary text because it's so short.
+ <paragraph>
+ ==
+ ABC
+ ==
+ <paragraph>
+ Over & underline too short.
+"""],
+["""\
+Paragraph
+
+ ABC
+ ==
+
+ Underline too short.
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ Paragraph
+ <block_quote>
+ <paragraph>
+ ABC
+ ==
+ <paragraph>
+ Underline too short.
+"""],
+["""\
+...
+...
+
+...
+---
+
+...
+...
+...
+""",
+"""\
+<document source="test data">
+ <system_message level="1" line="1" source="test data" type="INFO">
+ <paragraph>
+ Possible incomplete section title.
+ Treating the overline as ordinary text because it's so short.
+ <section dupnames="..." ids="id1">
+ <title>
+ ...
+ <system_message level="1" line="4" source="test data" type="INFO">
+ <paragraph>
+ Possible incomplete section title.
+ Treating the overline as ordinary text because it's so short.
+ <section dupnames="..." ids="id2">
+ <title>
+ ...
+ <system_message backrefs="id2" level="1" line="5" source="test data" type="INFO">
+ <paragraph>
+ Duplicate implicit target name: "...".
+ <system_message level="1" line="7" source="test data" type="INFO">
+ <paragraph>
+ Possible incomplete section title.
+ Treating the overline as ordinary text because it's so short.
+ <system_message level="1" line="7" source="test data" type="INFO">
+ <paragraph>
+ Possible incomplete section title.
+ Treating the overline as ordinary text because it's so short.
+ <section dupnames="..." ids="id3">
+ <title>
+ ...
+ <system_message backrefs="id3" level="1" line="8" source="test data" type="INFO">
+ <paragraph>
+ Duplicate implicit target name: "...".
+ <paragraph>
+ ...
+"""],
+["""\
+..
+Hi
+..
+
+...
+Yo
+...
+
+Ho
+""",
+"""\
+<document source="test data">
+ <comment xml:space="preserve">
+ <system_message level="2" line="2" source="test data" type="WARNING">
+ <paragraph>
+ Explicit markup ends without a blank line; unexpected unindent.
+ <section ids="hi" names="hi">
+ <title>
+ Hi
+ <section ids="yo" names="yo">
+ <title>
+ Yo
+ <paragraph>
+ Ho
+"""],
+["""\
+Empty Section
+=============
+""",
+"""\
+<document source="test data">
+ <section ids="empty-section" names="empty\\ section">
+ <title>
+ Empty Section
+"""],
+["""\
+===
+One
+===
+
+The bubble-up parser strategy conflicts with short titles
+(<= 3 char-long over- & underlines).
+
+===
+Two
+===
+
+The parser currently contains a work-around kludge.
+Without it, the parser ends up in an infinite loop.
+""",
+"""\
+<document source="test data">
+ <section ids="one" names="one">
+ <title>
+ One
+ <paragraph>
+ The bubble-up parser strategy conflicts with short titles
+ (<= 3 char-long over- & underlines).
+ <section ids="two" names="two">
+ <title>
+ Two
+ <paragraph>
+ The parser currently contains a work-around kludge.
+ Without it, the parser ends up in an infinite loop.
+"""],
+["""\
+""",
+"""\
+<document source="test data">
+"""],
+]
+
+
+if __name__ == '__main__':
+ import unittest
+ unittest.main(defaultTest='suite')
--- /dev/null
+#! /usr/bin/env python
+
+# $Id: test_substitutions.py 8356 2019-08-26 16:44:19Z milde $
+# Author: David Goodger <goodger@python.org>
+# Copyright: This module has been placed in the public domain.
+
+"""
+Tests for states.py.
+"""
+from __future__ import absolute_import
+
+from . import DocutilsTestSupport
+
+
+def suite():
+ s = DocutilsTestSupport.ParserTestSuite()
+ s.generateTests(totest)
+ return s
+
+totest = {}
+
+totest['substitution_definitions'] = [
+["""\
+Here's an image substitution definition:
+
+.. |symbol| image:: symbol.png
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ Here's an image substitution definition:
+ <substitution_definition names="symbol">
+ <image alt="symbol" uri="symbol.png">
+"""],
+["""\
+Embedded directive starts on the next line:
+
+.. |symbol|
+ image:: symbol.png
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ Embedded directive starts on the next line:
+ <substitution_definition names="symbol">
+ <image alt="symbol" uri="symbol.png">
+"""],
+["""\
+Trailing spaces should not be significant:
+
+.. |symbol| image:: \n\
+ symbol.png
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ Trailing spaces should not be significant:
+ <substitution_definition names="symbol">
+ <image alt="symbol" uri="symbol.png">
+"""],
+["""\
+Here's a series of substitution definitions:
+
+.. |symbol 1| image:: symbol1.png
+.. |SYMBOL 2| image:: symbol2.png
+ :height: 50
+ :width: 100
+.. |symbol 3| image:: symbol3.png
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ Here's a series of substitution definitions:
+ <substitution_definition names="symbol\\ 1">
+ <image alt="symbol 1" uri="symbol1.png">
+ <substitution_definition names="SYMBOL\\ 2">
+ <image alt="SYMBOL 2" height="50" uri="symbol2.png" width="100">
+ <substitution_definition names="symbol\\ 3">
+ <image alt="symbol 3" uri="symbol3.png">
+"""],
+["""\
+.. |very long substitution text,
+ split across lines| image:: symbol.png
+""",
+"""\
+<document source="test data">
+ <substitution_definition names="very\\ long\\ substitution\\ text,\\ split\\ across\\ lines">
+ <image alt="very long substitution text, split across lines" uri="symbol.png">
+"""],
+["""\
+.. |symbol 1| image:: symbol.png
+
+ Followed by a block quote.
+""",
+"""\
+<document source="test data">
+ <system_message level="3" line="1" source="test data" type="ERROR">
+ <paragraph>
+ Error in "image" directive:
+ no content permitted.
+ <literal_block xml:space="preserve">
+ image:: symbol.png
+ \n\
+ Followed by a block quote.
+ <system_message level="2" line="1" source="test data" type="WARNING">
+ <paragraph>
+ Substitution definition "symbol 1" empty or invalid.
+ <literal_block xml:space="preserve">
+ .. |symbol 1| image:: symbol.png
+ \n\
+ Followed by a block quote.
+"""],
+["""\
+.. |symbol 1| image:: symbol.png
+
+Followed by a paragraph.
+
+.. |symbol 2| image:: symbol.png
+
+..
+
+ Followed by a block quote.
+""",
+"""\
+<document source="test data">
+ <substitution_definition names="symbol\\ 1">
+ <image alt="symbol 1" uri="symbol.png">
+ <paragraph>
+ Followed by a paragraph.
+ <substitution_definition names="symbol\\ 2">
+ <image alt="symbol 2" uri="symbol.png">
+ <comment xml:space="preserve">
+ <block_quote>
+ <paragraph>
+ Followed by a block quote.
+"""],
+[u"""\
+Substitutions support case differences:
+
+.. |eacute| replace:: \u00E9
+.. |Eacute| replace:: \u00C9
+""",
+u"""\
+<document source="test data">
+ <paragraph>
+ Substitutions support case differences:
+ <substitution_definition names="eacute">
+ \u00E9
+ <substitution_definition names="Eacute">
+ \u00C9
+"""],
+["""\
+Raw substitution, backslashes should be preserved:
+
+.. |alpha| raw:: latex
+
+ $\\\\alpha$
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ Raw substitution, backslashes should be preserved:
+ <substitution_definition names="alpha">
+ <raw format="latex" xml:space="preserve">
+ $\\\\alpha$
+"""],
+["""\
+Here are some duplicate substitution definitions:
+
+.. |symbol| image:: symbol.png
+.. |symbol| image:: symbol.png
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ Here are some duplicate substitution definitions:
+ <substitution_definition dupnames="symbol">
+ <image alt="symbol" uri="symbol.png">
+ <system_message level="3" line="4" source="test data" type="ERROR">
+ <paragraph>
+ Duplicate substitution definition name: "symbol".
+ <substitution_definition names="symbol">
+ <image alt="symbol" uri="symbol.png">
+"""],
+["""\
+Here are some bad cases:
+
+.. |symbol| image:: symbol.png
+No blank line after.
+
+.. |empty|
+
+.. |unknown| directive:: symbol.png
+
+.. |invalid 1| there's no directive here
+.. |invalid 2| there's no directive here
+ With some block quote text, line 1.
+ And some more, line 2.
+
+.. |invalid 3| there's no directive here
+
+.. | bad name | bad data
+
+.. |
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ Here are some bad cases:
+ <substitution_definition names="symbol">
+ <image alt="symbol" uri="symbol.png">
+ <system_message level="2" line="4" source="test data" type="WARNING">
+ <paragraph>
+ Explicit markup ends without a blank line; unexpected unindent.
+ <paragraph>
+ No blank line after.
+ <system_message level="2" line="6" source="test data" type="WARNING">
+ <paragraph>
+ Substitution definition "empty" missing contents.
+ <literal_block xml:space="preserve">
+ .. |empty|
+ <system_message level="1" line="8" source="test data" type="INFO">
+ <paragraph>
+ No directive entry for "directive" in module "docutils.parsers.rst.languages.en".
+ Trying "directive" as canonical directive name.
+ <system_message level="3" line="8" source="test data" type="ERROR">
+ <paragraph>
+ Unknown directive type "directive".
+ <literal_block xml:space="preserve">
+ directive:: symbol.png
+ <system_message level="2" line="8" source="test data" type="WARNING">
+ <paragraph>
+ Substitution definition "unknown" empty or invalid.
+ <literal_block xml:space="preserve">
+ .. |unknown| directive:: symbol.png
+ <system_message level="2" line="10" source="test data" type="WARNING">
+ <paragraph>
+ Substitution definition "invalid 1" empty or invalid.
+ <literal_block xml:space="preserve">
+ .. |invalid 1| there's no directive here
+ <system_message level="2" line="11" source="test data" type="WARNING">
+ <paragraph>
+ Substitution definition "invalid 2" empty or invalid.
+ <literal_block xml:space="preserve">
+ .. |invalid 2| there's no directive here
+ With some block quote text, line 1.
+ And some more, line 2.
+ <system_message level="2" line="15" source="test data" type="WARNING">
+ <paragraph>
+ Substitution definition "invalid 3" empty or invalid.
+ <literal_block xml:space="preserve">
+ .. |invalid 3| there's no directive here
+ <comment xml:space="preserve">
+ | bad name | bad data
+ <comment xml:space="preserve">
+ |
+"""],
+["""\
+Elements that are prohibited inside of substitution definitions:
+
+.. |target| replace:: _`target`
+.. |reference| replace:: anonymous__
+.. |auto-numbered footnote| replace:: [#]_
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ Elements that are prohibited inside of substitution definitions:
+ <system_message level="3" line="3" source="test data" type="ERROR">
+ <paragraph>
+ Substitution definition contains illegal element <target>:
+ <literal_block xml:space="preserve">
+ <target ids="target" names="target">
+ target
+ <literal_block xml:space="preserve">
+ .. |target| replace:: _`target`
+ <system_message level="3" line="4" source="test data" type="ERROR">
+ <paragraph>
+ Substitution definition contains illegal element <reference>:
+ <literal_block xml:space="preserve">
+ <reference anonymous="1" name="anonymous">
+ anonymous
+ <literal_block xml:space="preserve">
+ .. |reference| replace:: anonymous__
+ <system_message level="3" line="5" source="test data" type="ERROR">
+ <paragraph>
+ Substitution definition contains illegal element <footnote_reference>:
+ <literal_block xml:space="preserve">
+ <footnote_reference auto="1" ids="id1">
+ <literal_block xml:space="preserve">
+ .. |auto-numbered footnote| replace:: [#]_
+"""],
+]
+
+
+if __name__ == '__main__':
+ import unittest
+ unittest.main(defaultTest='suite')
--- /dev/null
+#! /usr/bin/env python
+
+# $Id: test_tables.py 8356 2019-08-26 16:44:19Z milde $
+# Author: David Goodger <goodger@python.org>
+# Copyright: This module has been placed in the public domain.
+
+"""
+Tests for states.py.
+"""
+from __future__ import absolute_import
+
+import os
+
+from . import DocutilsTestSupport
+
+
+def suite():
+ s = DocutilsTestSupport.ParserTestSuite()
+ s.generateTests(totest)
+ return s
+
+mydir = 'test_parsers/test_rst/'
+include2 = os.path.join(mydir, 'test_directives/include2.txt')
+
+totest = {}
+
+totest['grid_tables'] = [
+["""\
++-------------------------------------+
+| A table with one cell and one line. |
++-------------------------------------+
+""",
+"""\
+<document source="test data">
+ <table>
+ <tgroup cols="1">
+ <colspec colwidth="37">
+ <tbody>
+ <row>
+ <entry>
+ <paragraph>
+ A table with one cell and one line.
+"""],
+["""\
++-----------------------+
+| A table with one cell |
+| and two lines. |
++-----------------------+
+""",
+"""\
+<document source="test data">
+ <table>
+ <tgroup cols="1">
+ <colspec colwidth="23">
+ <tbody>
+ <row>
+ <entry>
+ <paragraph>
+ A table with one cell
+ and two lines.
+"""],
+["""\
++-----------------------+
+| A malformed table. |
++-----------------------+
+""",
+"""\
+<document source="test data">
+ <system_message level="3" line="1" source="test data" type="ERROR">
+ <paragraph>
+ Malformed table.
+ <literal_block xml:space="preserve">
+ +-----------------------+
+ | A malformed table. |
+ +-----------------------+
+"""],
+["""\
++------------------------+
+| A well-formed | table. |
++------------------------+
+
++------------------------+
+| This +----------+ too! |
++------------------------+
+""",
+"""\
+<document source="test data">
+ <table>
+ <tgroup cols="1">
+ <colspec colwidth="24">
+ <tbody>
+ <row>
+ <entry>
+ <paragraph>
+ A well-formed | table.
+ <table>
+ <tgroup cols="1">
+ <colspec colwidth="24">
+ <tbody>
+ <row>
+ <entry>
+ <paragraph>
+ This +----------+ too!
+"""],
+["""\
++--------------+--------------+
+| A table with | two columns. |
++--------------+--------------+
+""",
+"""\
+<document source="test data">
+ <table>
+ <tgroup cols="2">
+ <colspec colwidth="14">
+ <colspec colwidth="14">
+ <tbody>
+ <row>
+ <entry>
+ <paragraph>
+ A table with
+ <entry>
+ <paragraph>
+ two columns.
+"""],
+["""\
++--------------+
+| A table with |
++--------------+
+| two rows. |
++--------------+
+""",
+"""\
+<document source="test data">
+ <table>
+ <tgroup cols="1">
+ <colspec colwidth="14">
+ <tbody>
+ <row>
+ <entry>
+ <paragraph>
+ A table with
+ <row>
+ <entry>
+ <paragraph>
+ two rows.
+"""],
+["""\
++--------------+-------------+
+| A table with | two columns |
++--------------+-------------+
+| and | two rows. |
++--------------+-------------+
+""",
+"""\
+<document source="test data">
+ <table>
+ <tgroup cols="2">
+ <colspec colwidth="14">
+ <colspec colwidth="13">
+ <tbody>
+ <row>
+ <entry>
+ <paragraph>
+ A table with
+ <entry>
+ <paragraph>
+ two columns
+ <row>
+ <entry>
+ <paragraph>
+ and
+ <entry>
+ <paragraph>
+ two rows.
+"""],
+["""\
++--------------+---------------+
+| A table with | two columns, |
++--------------+---------------+
+| two rows, and a column span. |
++------------------------------+
+""",
+"""\
+<document source="test data">
+ <table>
+ <tgroup cols="2">
+ <colspec colwidth="14">
+ <colspec colwidth="15">
+ <tbody>
+ <row>
+ <entry>
+ <paragraph>
+ A table with
+ <entry>
+ <paragraph>
+ two columns,
+ <row>
+ <entry morecols="1">
+ <paragraph>
+ two rows, and a column span.
+"""],
+["""\
++--------------------------+
+| A table with three rows, |
++------------+-------------+
+| and two | columns. |
++------------+-------------+
+| First and last rows |
+| contains column spans. |
++--------------------------+
+""",
+"""\
+<document source="test data">
+ <table>
+ <tgroup cols="2">
+ <colspec colwidth="12">
+ <colspec colwidth="13">
+ <tbody>
+ <row>
+ <entry morecols="1">
+ <paragraph>
+ A table with three rows,
+ <row>
+ <entry>
+ <paragraph>
+ and two
+ <entry>
+ <paragraph>
+ columns.
+ <row>
+ <entry morecols="1">
+ <paragraph>
+ First and last rows
+ contains column spans.
+"""],
+["""\
++--------------+--------------+
+| A table with | two columns, |
++--------------+ and a row |
+| two rows, | span. |
++--------------+--------------+
+""",
+"""\
+<document source="test data">
+ <table>
+ <tgroup cols="2">
+ <colspec colwidth="14">
+ <colspec colwidth="14">
+ <tbody>
+ <row>
+ <entry>
+ <paragraph>
+ A table with
+ <entry morerows="1">
+ <paragraph>
+ two columns,
+ and a row
+ span.
+ <row>
+ <entry>
+ <paragraph>
+ two rows,
+"""],
+["""\
++------------+-------------+---------------+
+| A table | two rows in | and row spans |
+| with three +-------------+ to left and |
+| columns, | the middle, | right. |
++------------+-------------+---------------+
+""",
+"""\
+<document source="test data">
+ <table>
+ <tgroup cols="3">
+ <colspec colwidth="12">
+ <colspec colwidth="13">
+ <colspec colwidth="15">
+ <tbody>
+ <row>
+ <entry morerows="1">
+ <paragraph>
+ A table
+ with three
+ columns,
+ <entry>
+ <paragraph>
+ two rows in
+ <entry morerows="1">
+ <paragraph>
+ and row spans
+ to left and
+ right.
+ <row>
+ <entry>
+ <paragraph>
+ the middle,
+"""],
+["""\
+Complex spanning pattern (no edge knows all rows/cols):
+
++-----------+-------------------------+
+| W/NW cell | N/NE cell |
+| +-------------+-----------+
+| | Middle cell | E/SE cell |
++-----------+-------------+ |
+| S/SE cell | |
++-------------------------+-----------+
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ Complex spanning pattern (no edge knows all rows/cols):
+ <table>
+ <tgroup cols="3">
+ <colspec colwidth="11">
+ <colspec colwidth="13">
+ <colspec colwidth="11">
+ <tbody>
+ <row>
+ <entry morerows="1">
+ <paragraph>
+ W/NW cell
+ <entry morecols="1">
+ <paragraph>
+ N/NE cell
+ <row>
+ <entry>
+ <paragraph>
+ Middle cell
+ <entry morerows="1">
+ <paragraph>
+ E/SE cell
+ <row>
+ <entry morecols="1">
+ <paragraph>
+ S/SE cell
+"""],
+["""\
++------------------------+------------+----------+----------+
+| Header row, column 1 | Header 2 | Header 3 | Header 4 |
++========================+============+==========+==========+
+| body row 1, column 1 | column 2 | column 3 | column 4 |
++------------------------+------------+----------+----------+
+| body row 2 | Cells may span columns. |
++------------------------+------------+---------------------+
+| body row 3 | Cells may | - Table cells |
++------------------------+ span rows. | - contain |
+| body row 4 | | - body elements. |
++------------------------+------------+---------------------+
+""",
+"""\
+<document source="test data">
+ <table>
+ <tgroup cols="4">
+ <colspec colwidth="24">
+ <colspec colwidth="12">
+ <colspec colwidth="10">
+ <colspec colwidth="10">
+ <thead>
+ <row>
+ <entry>
+ <paragraph>
+ Header row, column 1
+ <entry>
+ <paragraph>
+ Header 2
+ <entry>
+ <paragraph>
+ Header 3
+ <entry>
+ <paragraph>
+ Header 4
+ <tbody>
+ <row>
+ <entry>
+ <paragraph>
+ body row 1, column 1
+ <entry>
+ <paragraph>
+ column 2
+ <entry>
+ <paragraph>
+ column 3
+ <entry>
+ <paragraph>
+ column 4
+ <row>
+ <entry>
+ <paragraph>
+ body row 2
+ <entry morecols="2">
+ <paragraph>
+ Cells may span columns.
+ <row>
+ <entry>
+ <paragraph>
+ body row 3
+ <entry morerows="1">
+ <paragraph>
+ Cells may
+ span rows.
+ <entry morecols="1" morerows="1">
+ <bullet_list bullet="-">
+ <list_item>
+ <paragraph>
+ Table cells
+ <list_item>
+ <paragraph>
+ contain
+ <list_item>
+ <paragraph>
+ body elements.
+ <row>
+ <entry>
+ <paragraph>
+ body row 4
+"""],
+["""\
++-----------------+--------+
+| A simple table | cell 2 |
++-----------------+--------+
+| cell 3 | cell 4 |
++-----------------+--------+
+No blank line after table.
+""",
+"""\
+<document source="test data">
+ <table>
+ <tgroup cols="2">
+ <colspec colwidth="17">
+ <colspec colwidth="8">
+ <tbody>
+ <row>
+ <entry>
+ <paragraph>
+ A simple table
+ <entry>
+ <paragraph>
+ cell 2
+ <row>
+ <entry>
+ <paragraph>
+ cell 3
+ <entry>
+ <paragraph>
+ cell 4
+ <system_message level="2" line="6" source="test data" type="WARNING">
+ <paragraph>
+ Blank line required after table.
+ <paragraph>
+ No blank line after table.
+"""],
+["""\
++-----------------+--------+
+| A simple table | cell 2 |
++-----------------+--------+
+| cell 3 | cell 4 |
++-----------------+--------+
+ Unexpected indent and no blank line after table.
+""",
+"""\
+<document source="test data">
+ <table>
+ <tgroup cols="2">
+ <colspec colwidth="17">
+ <colspec colwidth="8">
+ <tbody>
+ <row>
+ <entry>
+ <paragraph>
+ A simple table
+ <entry>
+ <paragraph>
+ cell 2
+ <row>
+ <entry>
+ <paragraph>
+ cell 3
+ <entry>
+ <paragraph>
+ cell 4
+ <system_message level="3" line="6" source="test data" type="ERROR">
+ <paragraph>
+ Unexpected indentation.
+ <system_message level="2" line="6" source="test data" type="WARNING">
+ <paragraph>
+ Blank line required after table.
+ <block_quote>
+ <paragraph>
+ Unexpected indent and no blank line after table.
+"""],
+["""\
++--------------+-------------+
+| A bad table. | |
++--------------+ |
+| Cells must be rectangles. |
++----------------------------+
+""",
+"""\
+<document source="test data">
+ <system_message level="3" line="1" source="test data" type="ERROR">
+ <paragraph>
+ Malformed table.
+ Malformed table; parse incomplete.
+ <literal_block xml:space="preserve">
+ +--------------+-------------+
+ | A bad table. | |
+ +--------------+ |
+ | Cells must be rectangles. |
+ +----------------------------+
+"""],
+["""\
++------------------------------+
+| This table contains another. |
+| |
+| +-------------------------+ |
+| | A table within a table. | |
+| +-------------------------+ |
++------------------------------+
+""",
+"""\
+<document source="test data">
+ <table>
+ <tgroup cols="1">
+ <colspec colwidth="30">
+ <tbody>
+ <row>
+ <entry>
+ <paragraph>
+ This table contains another.
+ <table>
+ <tgroup cols="1">
+ <colspec colwidth="25">
+ <tbody>
+ <row>
+ <entry>
+ <paragraph>
+ A table within a table.
+"""],
+["""\
++------------------+--------+
+| A simple table | |
++------------------+--------+
+| with empty cells | |
++------------------+--------+
+""",
+"""\
+<document source="test data">
+ <table>
+ <tgroup cols="2">
+ <colspec colwidth="18">
+ <colspec colwidth="8">
+ <tbody>
+ <row>
+ <entry>
+ <paragraph>
+ A simple table
+ <entry>
+ <row>
+ <entry>
+ <paragraph>
+ with empty cells
+ <entry>
+"""],
+[("""\
++------------------------------------------------------------------------------+
+| .. include:: |
+%s
++------------------------------------------------------------------------------+
+| (The first cell of this table may expand |
+| to accommodate long filesystem paths.) |
++------------------------------------------------------------------------------+
+""") % ('\n'.join(['| %-70s |' % include2[part * 70 : (part + 1) * 70]
+ for part in range(len(include2) // 70 + 1)])),
+"""\
+<document source="test data">
+ <table>
+ <tgroup cols="1">
+ <colspec colwidth="78">
+ <tbody>
+ <row>
+ <entry>
+ <paragraph>
+ Here are some paragraphs
+ that can appear at any level.
+ <paragraph>
+ This file (include2.txt) is used by
+ <literal>
+ test_include.py
+ .
+ <row>
+ <entry>
+ <paragraph>
+ (The first cell of this table may expand
+ to accommodate long filesystem paths.)
+"""],
+[("""\
+Something before.
+
++------------------------------------------------------------------------------+
+| .. include:: |
+%s
++------------------------------------------------------------------------------+
+
+Something afterwards.
+
+And more.
+""") % ('\n'.join(['| %-70s |' % include2[part * 70 : (part + 1) * 70]
+ for part in range(len(include2) // 70 + 1)])),
+"""\
+<document source="test data">
+ <paragraph>
+ Something before.
+ <table>
+ <tgroup cols="1">
+ <colspec colwidth="78">
+ <tbody>
+ <row>
+ <entry>
+ <paragraph>
+ Here are some paragraphs
+ that can appear at any level.
+ <paragraph>
+ This file (include2.txt) is used by
+ <literal>
+ test_include.py
+ .
+ <paragraph>
+ Something afterwards.
+ <paragraph>
+ And more.
+"""],
+]
+
+totest['simple_tables'] = [
+["""\
+============ ============
+A table with two columns.
+============ ============
+
+Paragraph.
+""",
+"""\
+<document source="test data">
+ <table>
+ <tgroup cols="2">
+ <colspec colwidth="12">
+ <colspec colwidth="12">
+ <tbody>
+ <row>
+ <entry>
+ <paragraph>
+ A table with
+ <entry>
+ <paragraph>
+ two columns.
+ <paragraph>
+ Paragraph.
+"""],
+["""\
+============ ============
+A table with two columns
+and two rows.
+============ ============
+""",
+"""\
+<document source="test data">
+ <table>
+ <tgroup cols="2">
+ <colspec colwidth="12">
+ <colspec colwidth="12">
+ <tbody>
+ <row>
+ <entry>
+ <paragraph>
+ A table with
+ <entry>
+ <paragraph>
+ two columns
+ <row>
+ <entry>
+ <paragraph>
+ and
+ <entry>
+ <paragraph>
+ two rows.
+"""],
+["""\
+============ ==============
+A table with two columns,
+two rows, and a column span.
+============================
+""",
+"""\
+<document source="test data">
+ <table>
+ <tgroup cols="2">
+ <colspec colwidth="12">
+ <colspec colwidth="14">
+ <tbody>
+ <row>
+ <entry>
+ <paragraph>
+ A table with
+ <entry>
+ <paragraph>
+ two columns,
+ <row>
+ <entry morecols="1">
+ <paragraph>
+ two rows, and a column span.
+"""],
+["""\
+== =========== ===========
+1 A table with three rows,
+-- ------------------------
+2 and three columns.
+3 First and third rows
+ contain column spans.
+
+ This row is a multi-line row, and overflows to the right.
+-- ------------------------
+4 One last row.
+== =========== ===========
+""",
+"""\
+<document source="test data">
+ <table>
+ <tgroup cols="3">
+ <colspec colwidth="2">
+ <colspec colwidth="11">
+ <colspec colwidth="44">
+ <tbody>
+ <row>
+ <entry>
+ <paragraph>
+ 1
+ <entry morecols="1">
+ <paragraph>
+ A table with three rows,
+ <row>
+ <entry>
+ <paragraph>
+ 2
+ <entry>
+ <paragraph>
+ and three
+ <entry>
+ <paragraph>
+ columns.
+ <row>
+ <entry>
+ <paragraph>
+ 3
+ <entry morecols="1">
+ <paragraph>
+ First and third rows
+ contain column spans.
+ <paragraph>
+ This row is a multi-line row, and overflows to the right.
+ <row>
+ <entry>
+ <paragraph>
+ 4
+ <entry>
+ <paragraph>
+ One last
+ <entry>
+ <paragraph>
+ row.
+"""],
+["""\
+======= ========= ========
+A table with three columns.
+================== ========
+""",
+"""\
+<document source="test data">
+ <table>
+ <tgroup cols="3">
+ <colspec colwidth="7">
+ <colspec colwidth="9">
+ <colspec colwidth="8">
+ <tbody>
+ <row>
+ <entry morecols="1">
+ <paragraph>
+ A table with three
+ <entry>
+ <paragraph>
+ columns.
+"""],
+["""\
+============== ======
+A simple table this text extends to the right
+cell 3 as does this text
+============== ======
+""",
+"""\
+<document source="test data">
+ <table>
+ <tgroup cols="2">
+ <colspec colwidth="14">
+ <colspec colwidth="30">
+ <tbody>
+ <row>
+ <entry>
+ <paragraph>
+ A simple table
+ <entry>
+ <paragraph>
+ this text extends to the right
+ <row>
+ <entry>
+ <paragraph>
+ cell 3
+ <entry>
+ <paragraph>
+ as does this text
+"""],
+["""\
+============== ======
+A simple table this text extends to the right
+ continuation of cell 2
+============== ======
+""",
+"""\
+<document source="test data">
+ <table>
+ <tgroup cols="2">
+ <colspec colwidth="14">
+ <colspec colwidth="30">
+ <tbody>
+ <row>
+ <entry>
+ <paragraph>
+ A simple table
+ <entry>
+ <paragraph>
+ this text extends to the right
+ continuation of cell 2
+"""],
+["""\
+============== ======
+A simple table with
+no bottom border
+""",
+"""\
+<document source="test data">
+ <system_message level="3" line="1" source="test data" type="ERROR">
+ <paragraph>
+ Malformed table.
+ No bottom table border found.
+ <literal_block xml:space="preserve">
+ ============== ======
+ A simple table with
+ no bottom border
+"""],
+["""\
+============== ======
+A simple table cell 2
+cell 3 cell 4
+============== ======
+No blank line after table.
+""",
+"""\
+<document source="test data">
+ <system_message level="3" line="1" source="test data" type="ERROR">
+ <paragraph>
+ Malformed table.
+ No bottom table border found or no blank line after table bottom.
+ <literal_block xml:space="preserve">
+ ============== ======
+ A simple table cell 2
+ cell 3 cell 4
+ ============== ======
+ <system_message level="2" line="5" source="test data" type="WARNING">
+ <paragraph>
+ Blank line required after table.
+ <paragraph>
+ No blank line after table.
+"""],
+["""\
+============== ======
+A simple table cell 2
+============== ======
+cell 3 cell 4
+============== ======
+No blank line after table.
+""",
+"""\
+<document source="test data">
+ <table>
+ <tgroup cols="2">
+ <colspec colwidth="14">
+ <colspec colwidth="6">
+ <thead>
+ <row>
+ <entry>
+ <paragraph>
+ A simple table
+ <entry>
+ <paragraph>
+ cell 2
+ <tbody>
+ <row>
+ <entry>
+ <paragraph>
+ cell 3
+ <entry>
+ <paragraph>
+ cell 4
+ <system_message level="2" line="6" source="test data" type="WARNING">
+ <paragraph>
+ Blank line required after table.
+ <paragraph>
+ No blank line after table.
+"""],
+["""\
+============== ======
+A simple table cell 2
+cell 3 cell 4
+============== ======
+ Unexpected indent and no blank line after table.
+""",
+"""\
+<document source="test data">
+ <system_message level="3" line="1" source="test data" type="ERROR">
+ <paragraph>
+ Malformed table.
+ No bottom table border found or no blank line after table bottom.
+ <literal_block xml:space="preserve">
+ ============== ======
+ A simple table cell 2
+ cell 3 cell 4
+ ============== ======
+ <system_message level="2" line="5" source="test data" type="WARNING">
+ <paragraph>
+ Blank line required after table.
+ <block_quote>
+ <paragraph>
+ Unexpected indent and no blank line after table.
+"""],
+["""\
+============== ======
+A bad table cell 2
+cell 3 cell 4
+============ ========
+""",
+"""\
+<document source="test data">
+ <system_message level="3" line="4" source="test data" type="ERROR">
+ <paragraph>
+ Malformed table.
+ Column span alignment problem in table line 4.
+ <literal_block xml:space="preserve">
+ ============== ======
+ A bad table cell 2
+ cell 3 cell 4
+ ============ ========
+"""],
+["""\
+======== =========
+A bad table cell 2
+cell 3 cell 4
+======== =========
+""",
+"""\
+<document source="test data">
+ <system_message level="3" line="2" source="test data" type="ERROR">
+ <paragraph>
+ Malformed table.
+ Text in column margin in table line 2.
+ <literal_block xml:space="preserve">
+ ======== =========
+ A bad table cell 2
+ cell 3 cell 4
+ ======== =========
+"""],
+["""\
+== ============================
+1 This table contains another.
+2 ======= ====== ========
+ A table within a table.
+ ======= ====== ========
+
+ The outer table does have to
+ have at least two columns
+ though.
+== ============================
+""",
+"""\
+<document source="test data">
+ <table>
+ <tgroup cols="2">
+ <colspec colwidth="2">
+ <colspec colwidth="28">
+ <tbody>
+ <row>
+ <entry>
+ <paragraph>
+ 1
+ <entry>
+ <paragraph>
+ This table contains another.
+ <row>
+ <entry>
+ <paragraph>
+ 2
+ <entry>
+ <table>
+ <tgroup cols="3">
+ <colspec colwidth="7">
+ <colspec colwidth="6">
+ <colspec colwidth="8">
+ <tbody>
+ <row>
+ <entry>
+ <paragraph>
+ A table
+ <entry>
+ <paragraph>
+ within
+ <entry>
+ <paragraph>
+ a table.
+ <paragraph>
+ The outer table does have to
+ have at least two columns
+ though.
+"""],
+["""\
+================ ======
+A simple table
+with empty cells
+================ ======
+""",
+"""\
+<document source="test data">
+ <table>
+ <tgroup cols="2">
+ <colspec colwidth="16">
+ <colspec colwidth="6">
+ <tbody>
+ <row>
+ <entry>
+ <paragraph>
+ A simple table
+ <entry>
+ <row>
+ <entry>
+ <paragraph>
+ with empty cells
+ <entry>
+"""],
+["""\
+============== ========
+ A table with
+============== ========
+ centered cells.
+
+============== ========
+""",
+"""\
+<document source="test data">
+ <table>
+ <tgroup cols="2">
+ <colspec colwidth="14">
+ <colspec colwidth="8">
+ <thead>
+ <row>
+ <entry>
+ <paragraph>
+ A table
+ <entry>
+ <paragraph>
+ with
+ <tbody>
+ <row>
+ <entry>
+ <paragraph>
+ centered
+ <entry>
+ <paragraph>
+ cells.
+"""],
+["""\
+============== ======
+A simple table this text extends to the right
+cell 3 the bottom border below is too long
+============== ========
+""",
+"""\
+<document source="test data">
+ <system_message level="3" line="1" source="test data" type="ERROR">
+ <paragraph>
+ Malformed table.
+ Bottom/header table border does not match top border.
+ <literal_block xml:space="preserve">
+ ============== ======
+ A simple table this text extends to the right
+ cell 3 the bottom border below is too long
+ ============== ========
+"""],
+["""\
+============ =================
+A table with row separators.
+------------ -----------------
+
+Blank line before.
+------------ -----------------
+
+Blank lines before and after.
+
+------------ -----------------
+Blank line after.
+
+============ =================
+""",
+"""\
+<document source="test data">
+ <table>
+ <tgroup cols="2">
+ <colspec colwidth="12">
+ <colspec colwidth="17">
+ <tbody>
+ <row>
+ <entry>
+ <paragraph>
+ A table with
+ <entry>
+ <paragraph>
+ row separators.
+ <row>
+ <entry>
+ <paragraph>
+ Blank line
+ <entry>
+ <paragraph>
+ before.
+ <row>
+ <entry>
+ <paragraph>
+ Blank lines
+ <entry>
+ <paragraph>
+ before and after.
+ <row>
+ <entry>
+ <paragraph>
+ Blank line
+ <entry>
+ <paragraph>
+ after.
+"""],
+["""\
+============ ====================
+A table with many row separators.
+------------ --------------------
+------------ --------------------
+
+------------ --------------------
+============ ====================
+""",
+"""\
+<document source="test data">
+ <table>
+ <tgroup cols="2">
+ <colspec colwidth="12">
+ <colspec colwidth="20">
+ <tbody>
+ <row>
+ <entry>
+ <paragraph>
+ A table with
+ <entry>
+ <paragraph>
+ many row separators.
+ <row>
+ <entry>
+ <entry>
+ <row>
+ <entry>
+ <entry>
+ <row>
+ <entry>
+ <entry>
+"""],
+["""\
+== =========== ===========
+1 Span columns 2 & 3
+-- ------------------------
+2 Span columns 2 & 3
+ ------------------------
+3
+== =========== ===========
+
+== =========== ===========
+1 Span cols 1&2 but not 3
+--------------- -----------
+2 Span cols 1&2 but not 3
+---------------
+3 no spans here
+== =========== ===========
+
+== =========== ===========
+1 Not a span Not a span
+ ----------- -----------
+2
+== =========== ===========
+""",
+"""\
+<document source="test data">
+ <system_message level="3" line="4" source="test data" type="ERROR">
+ <paragraph>
+ Malformed table.
+ Text in column margin in table line 4.
+ <literal_block xml:space="preserve">
+ == =========== ===========
+ 1 Span columns 2 & 3
+ -- ------------------------
+ 2 Span columns 2 & 3
+ ------------------------
+ 3
+ == =========== ===========
+ <system_message level="3" line="13" source="test data" type="ERROR">
+ <paragraph>
+ Malformed table.
+ Column span incomplete in table line 5.
+ <literal_block xml:space="preserve">
+ == =========== ===========
+ 1 Span cols 1&2 but not 3
+ --------------- -----------
+ 2 Span cols 1&2 but not 3
+ ---------------
+ 3 no spans here
+ == =========== ===========
+ <table>
+ <tgroup cols="3">
+ <colspec colwidth="2">
+ <colspec colwidth="11">
+ <colspec colwidth="11">
+ <tbody>
+ <row>
+ <entry>
+ <paragraph>
+ 1
+ <entry>
+ <system_message level="4" line="19" source="test data" type="SEVERE">
+ <paragraph>
+ Unexpected section title.
+ <literal_block xml:space="preserve">
+ Not a span
+ -----------
+ <entry>
+ <system_message level="4" line="19" source="test data" type="SEVERE">
+ <paragraph>
+ Unexpected section title.
+ <literal_block xml:space="preserve">
+ Not a span
+ -----------
+ <row>
+ <entry>
+ <paragraph>
+ 2
+ <entry>
+ <entry>
+"""],
+["""\
+========= =====================================================================
+Inclusion .. include::
+%s
+Note The first row of this table may expand
+ to accommodate long filesystem paths.
+========= =====================================================================
+""" % ('\n'.join([' %-65s' % include2[part * 65 : (part + 1) * 65]
+ for part in range(len(include2) // 65 + 1)])),
+"""\
+<document source="test data">
+ <table>
+ <tgroup cols="2">
+ <colspec colwidth="9">
+ <colspec colwidth="69">
+ <tbody>
+ <row>
+ <entry>
+ <paragraph>
+ Inclusion
+ <entry>
+ <paragraph>
+ Here are some paragraphs
+ that can appear at any level.
+ <paragraph>
+ This file (include2.txt) is used by
+ <literal>
+ test_include.py
+ .
+ <row>
+ <entry>
+ <paragraph>
+ Note
+ <entry>
+ <paragraph>
+ The first row of this table may expand
+ to accommodate long filesystem paths.
+"""],
+]
+
+
+if __name__ == '__main__':
+ import unittest
+ unittest.main(defaultTest='suite')
--- /dev/null
+#! /usr/bin/env python
+
+# $Id: test_targets.py 8356 2019-08-26 16:44:19Z milde $
+# Author: David Goodger <goodger@python.org>
+# Copyright: This module has been placed in the public domain.
+
+"""
+Tests for states.py.
+"""
+from __future__ import absolute_import
+
+from . import DocutilsTestSupport
+
+
+def suite():
+ s = DocutilsTestSupport.ParserTestSuite()
+ s.generateTests(totest)
+ return s
+
+totest = {}
+
+totest['targets'] = [
+["""\
+.. _target:
+
+(Internal hyperlink target.)
+""",
+"""\
+<document source="test data">
+ <target ids="target" names="target">
+ <paragraph>
+ (Internal hyperlink target.)
+"""],
+["""\
+.. _optional space before colon :
+""",
+"""\
+<document source="test data">
+ <target ids="optional-space-before-colon" names="optional\\ space\\ before\\ colon">
+"""],
+[r"""
+External hyperlink targets:
+
+.. _one-liner: http://structuredtext.sourceforge.net
+
+.. _starts-on-this-line: http://
+ structuredtext.
+ sourceforge.net
+
+.. _entirely-below:
+ http://structuredtext.
+ sourceforge.net
+
+.. _escaped-whitespace: http://example.org/a\ path\ with\
+ spaces.html
+
+.. _not-indirect: uri\_
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ External hyperlink targets:
+ <target ids="one-liner" names="one-liner" refuri="http://structuredtext.sourceforge.net">
+ <target ids="starts-on-this-line" names="starts-on-this-line" refuri="http://structuredtext.sourceforge.net">
+ <target ids="entirely-below" names="entirely-below" refuri="http://structuredtext.sourceforge.net">
+ <target ids="escaped-whitespace" names="escaped-whitespace" refuri="http://example.org/a path with spaces.html">
+ <target ids="not-indirect" names="not-indirect" refuri="uri_">
+"""],
+["""\
+Indirect hyperlink targets:
+
+.. _target1: reference_
+
+.. _target2: `phrase-link reference`_
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ Indirect hyperlink targets:
+ <target ids="target1" names="target1" refname="reference">
+ <target ids="target2" names="target2" refname="phrase-link reference">
+"""],
+["""\
+.. _a long target name:
+
+.. _`a target name: including a colon (quoted)`:
+
+.. _a target name\\: including a colon (escaped):
+""",
+"""\
+<document source="test data">
+ <target ids="a-long-target-name" names="a\\ long\\ target\\ name">
+ <target ids="a-target-name-including-a-colon-quoted" names="a\\ target\\ name:\\ including\\ a\\ colon\\ (quoted)">
+ <target ids="a-target-name-including-a-colon-escaped" names="a\\ target\\ name:\\ including\\ a\\ colon\\ (escaped)">
+"""],
+["""\
+.. _`target: No matching backquote.
+.. _`: No matching backquote either.
+""",
+"""\
+<document source="test data">
+ <comment xml:space="preserve">
+ _`target: No matching backquote.
+ <system_message level="2" line="1" source="test data" type="WARNING">
+ <paragraph>
+ malformed hyperlink target.
+ <comment xml:space="preserve">
+ _`: No matching backquote either.
+ <system_message level="2" line="2" source="test data" type="WARNING">
+ <paragraph>
+ malformed hyperlink target.
+"""],
+["""\
+.. _a very long target name,
+ split across lines:
+.. _`and another,
+ with backquotes`:
+""",
+"""\
+<document source="test data">
+ <target ids="a-very-long-target-name-split-across-lines" names="a\\ very\\ long\\ target\\ name,\\ split\\ across\\ lines">
+ <target ids="and-another-with-backquotes" names="and\\ another,\\ with\\ backquotes">
+"""],
+["""\
+External hyperlink:
+
+.. _target: http://www.python.org/
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ External hyperlink:
+ <target ids="target" names="target" refuri="http://www.python.org/">
+"""],
+["""\
+.. _email: jdoe@example.com
+
+.. _multi-line email: jdoe
+ @example.com
+""",
+"""\
+<document source="test data">
+ <target ids="email" names="email" refuri="mailto:jdoe@example.com">
+ <target ids="multi-line-email" names="multi-line\\ email" refuri="mailto:jdoe@example.com">
+"""],
+["""\
+Malformed target:
+
+.. __malformed: no good
+
+Target beginning with an underscore:
+
+.. _`_target`: OK
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ Malformed target:
+ <comment xml:space="preserve">
+ __malformed: no good
+ <system_message level="2" line="3" source="test data" type="WARNING">
+ <paragraph>
+ malformed hyperlink target.
+ <paragraph>
+ Target beginning with an underscore:
+ <target ids="target" names="_target" refuri="OK">
+"""],
+["""\
+Duplicate external targets (different URIs):
+
+.. _target: first
+
+.. _target: second
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ Duplicate external targets (different URIs):
+ <target dupnames="target" ids="target" refuri="first">
+ <system_message backrefs="id1" level="2" line="5" source="test data" type="WARNING">
+ <paragraph>
+ Duplicate explicit target name: "target".
+ <target dupnames="target" ids="id1" refuri="second">
+"""],
+["""\
+Duplicate external targets (same URIs):
+
+.. _target: first
+
+.. _target: first
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ Duplicate external targets (same URIs):
+ <target ids="target" names="target" refuri="first">
+ <system_message backrefs="id1" level="1" line="5" source="test data" type="INFO">
+ <paragraph>
+ Duplicate explicit target name: "target".
+ <target dupnames="target" ids="id1" refuri="first">
+"""],
+["""\
+Duplicate implicit targets.
+
+Title
+=====
+
+Paragraph.
+
+Title
+=====
+
+Paragraph.
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ Duplicate implicit targets.
+ <section dupnames="title" ids="title">
+ <title>
+ Title
+ <paragraph>
+ Paragraph.
+ <section dupnames="title" ids="id1">
+ <title>
+ Title
+ <system_message backrefs="id1" level="1" line="9" source="test data" type="INFO">
+ <paragraph>
+ Duplicate implicit target name: "title".
+ <paragraph>
+ Paragraph.
+"""],
+["""\
+Duplicate implicit/explicit targets.
+
+Title
+=====
+
+.. _title:
+
+Paragraph.
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ Duplicate implicit/explicit targets.
+ <section dupnames="title" ids="title">
+ <title>
+ Title
+ <system_message backrefs="id1" level="1" line="6" source="test data" type="INFO">
+ <paragraph>
+ Duplicate implicit target name: "title".
+ <target ids="id1" names="title">
+ <paragraph>
+ Paragraph.
+"""],
+["""\
+Duplicate implicit/directive targets.
+
+Title
+=====
+
+.. target-notes::
+ :name: title
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ Duplicate implicit/directive targets.
+ <section dupnames="title" ids="title">
+ <title>
+ Title
+ <pending ids="id1" names="title">
+ <system_message backrefs="id1" level="1" line="4" source="test data" type="INFO">
+ <paragraph>
+ Duplicate implicit target name: "title".
+ .. internal attributes:
+ .transform: docutils.transforms.references.TargetNotes
+ .details:
+"""],
+["""\
+Duplicate explicit targets.
+
+.. _title:
+
+First.
+
+.. _title:
+
+Second.
+
+.. _title:
+
+Third.
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ Duplicate explicit targets.
+ <target dupnames="title" ids="title">
+ <paragraph>
+ First.
+ <system_message backrefs="id1" level="2" line="7" source="test data" type="WARNING">
+ <paragraph>
+ Duplicate explicit target name: "title".
+ <target dupnames="title" ids="id1">
+ <paragraph>
+ Second.
+ <system_message backrefs="id2" level="2" line="11" source="test data" type="WARNING">
+ <paragraph>
+ Duplicate explicit target name: "title".
+ <target dupnames="title" ids="id2">
+ <paragraph>
+ Third.
+"""],
+["""\
+Duplicate explicit/directive targets.
+
+.. _title:
+
+First.
+
+.. rubric:: this is a title too
+ :name: title
+
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ Duplicate explicit/directive targets.
+ <target dupnames="title" ids="title">
+ <paragraph>
+ First.
+ <rubric dupnames="title" ids="id1">
+ this is a title too
+ <system_message backrefs="id1" level="2" line="9" source="test data" type="WARNING">
+ <paragraph>
+ Duplicate explicit target name: "title".
+"""],
+["""\
+Duplicate targets:
+
+Target
+======
+
+Implicit section header target.
+
+.. [TARGET] Citation target.
+
+.. [#target] Autonumber-labeled footnote target.
+
+.. _target:
+
+Explicit internal target.
+
+.. _target: Explicit_external_target
+
+.. rubric:: directive with target
+ :name: Target
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ Duplicate targets:
+ <section dupnames="target" ids="target">
+ <title>
+ Target
+ <paragraph>
+ Implicit section header target.
+ <citation dupnames="target" ids="id1">
+ <label>
+ TARGET
+ <system_message backrefs="id1" level="1" line="8" source="test data" type="INFO">
+ <paragraph>
+ Duplicate implicit target name: "target".
+ <paragraph>
+ Citation target.
+ <footnote auto="1" dupnames="target" ids="id2">
+ <system_message backrefs="id2" level="2" line="10" source="test data" type="WARNING">
+ <paragraph>
+ Duplicate explicit target name: "target".
+ <paragraph>
+ Autonumber-labeled footnote target.
+ <system_message backrefs="id3" level="2" line="12" source="test data" type="WARNING">
+ <paragraph>
+ Duplicate explicit target name: "target".
+ <target dupnames="target" ids="id3">
+ <paragraph>
+ Explicit internal target.
+ <system_message backrefs="id4" level="2" line="16" source="test data" type="WARNING">
+ <paragraph>
+ Duplicate explicit target name: "target".
+ <target dupnames="target" ids="id4" refuri="Explicit_external_target">
+ <rubric dupnames="target" ids="id5">
+ directive with target
+ <system_message backrefs="id5" level="2" line="4" source="test data" type="WARNING">
+ <paragraph>
+ Duplicate explicit target name: "target".
+"""],
+["""\
+.. _unescaped colon at end:: no good
+
+.. _:: no good either
+
+.. _escaped colon\\:: OK
+
+.. _`unescaped colon, quoted:`: OK
+""",
+"""\
+<document source="test data">
+ <comment xml:space="preserve">
+ _unescaped colon at end:: no good
+ <system_message level="2" line="1" source="test data" type="WARNING">
+ <paragraph>
+ malformed hyperlink target.
+ <comment xml:space="preserve">
+ _:: no good either
+ <system_message level="2" line="3" source="test data" type="WARNING">
+ <paragraph>
+ malformed hyperlink target.
+ <target ids="escaped-colon" names="escaped\\ colon:" refuri="OK">
+ <target ids="unescaped-colon-quoted" names="unescaped\\ colon,\\ quoted:" refuri="OK">
+"""],
+]
+
+totest['anonymous_targets'] = [
+["""\
+Anonymous external hyperlink target:
+
+.. __: http://w3c.org/
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ Anonymous external hyperlink target:
+ <target anonymous="1" ids="id1" refuri="http://w3c.org/">
+"""],
+["""\
+Anonymous external hyperlink target:
+
+__ http://w3c.org/
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ Anonymous external hyperlink target:
+ <target anonymous="1" ids="id1" refuri="http://w3c.org/">
+"""],
+["""\
+Anonymous indirect hyperlink target:
+
+.. __: reference_
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ Anonymous indirect hyperlink target:
+ <target anonymous="1" ids="id1" refname="reference">
+"""],
+["""\
+Anonymous external hyperlink target, not indirect:
+
+__ uri\\_
+
+__ this URI ends with an underscore_
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ Anonymous external hyperlink target, not indirect:
+ <target anonymous="1" ids="id1" refuri="uri_">
+ <target anonymous="1" ids="id2" refuri="thisURIendswithanunderscore_">
+"""],
+["""\
+Anonymous indirect hyperlink targets:
+
+__ reference_
+__ `a very long
+ reference`_
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ Anonymous indirect hyperlink targets:
+ <target anonymous="1" ids="id1" refname="reference">
+ <target anonymous="1" ids="id2" refname="a very long reference">
+"""],
+["""\
+Mixed anonymous & named indirect hyperlink targets:
+
+__ reference_
+.. __: reference_
+__ reference_
+.. _target1: reference_
+no blank line
+
+.. _target2: reference_
+__ reference_
+.. __: reference_
+__ reference_
+no blank line
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ Mixed anonymous & named indirect hyperlink targets:
+ <target anonymous="1" ids="id1" refname="reference">
+ <target anonymous="1" ids="id2" refname="reference">
+ <target anonymous="1" ids="id3" refname="reference">
+ <target ids="target1" names="target1" refname="reference">
+ <system_message level="2" line="7" source="test data" type="WARNING">
+ <paragraph>
+ Explicit markup ends without a blank line; unexpected unindent.
+ <paragraph>
+ no blank line
+ <target ids="target2" names="target2" refname="reference">
+ <target anonymous="1" ids="id4" refname="reference">
+ <target anonymous="1" ids="id5" refname="reference">
+ <target anonymous="1" ids="id6" refname="reference">
+ <system_message level="2" line="13" source="test data" type="WARNING">
+ <paragraph>
+ Explicit markup ends without a blank line; unexpected unindent.
+ <paragraph>
+ no blank line
+"""],
+["""\
+.. _
+""",
+"""\
+<document source="test data">
+ <comment xml:space="preserve">
+ _
+"""],
+]
+
+
+if __name__ == '__main__':
+ import unittest
+ unittest.main(defaultTest='suite')
--- /dev/null
+#! /usr/bin/env python
+
+# $Id: test_transitions.py 8356 2019-08-26 16:44:19Z milde $
+# Author: David Goodger <goodger@python.org>
+# Copyright: This module has been placed in the public domain.
+
+"""
+Tests for transition markers.
+"""
+from __future__ import absolute_import
+
+from . import DocutilsTestSupport
+
+
+def suite():
+ s = DocutilsTestSupport.ParserTestSuite()
+ s.generateTests(totest)
+ return s
+
+totest = {}
+
+# See DocutilsTestSupport.ParserTestSuite.generateTests for a
+# description of the 'totest' data structure.
+totest['transitions'] = [
+["""\
+Test transition markers.
+
+--------
+
+Paragraph
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ Test transition markers.
+ <transition>
+ <paragraph>
+ Paragraph
+"""],
+["""\
+Section 1
+=========
+First text division of section 1.
+
+--------
+
+Second text division of section 1.
+
+Section 2
+---------
+Paragraph 2 in section 2.
+""",
+"""\
+<document source="test data">
+ <section ids="section-1" names="section\\ 1">
+ <title>
+ Section 1
+ <paragraph>
+ First text division of section 1.
+ <transition>
+ <paragraph>
+ Second text division of section 1.
+ <section ids="section-2" names="section\\ 2">
+ <title>
+ Section 2
+ <paragraph>
+ Paragraph 2 in section 2.
+"""],
+["""\
+--------
+
+A section or document may not begin with a transition.
+
+The DTD specifies that two transitions may not
+be adjacent:
+
+--------
+
+--------
+
+--------
+
+The DTD also specifies that a section or document
+may not end with a transition.
+
+--------
+""",
+"""\
+<document source="test data">
+ <transition>
+ <paragraph>
+ A section or document may not begin with a transition.
+ <paragraph>
+ The DTD specifies that two transitions may not
+ be adjacent:
+ <transition>
+ <transition>
+ <transition>
+ <paragraph>
+ The DTD also specifies that a section or document
+ may not end with a transition.
+ <transition>
+"""],
+["""\
+Test unexpected transition markers.
+
+ Block quote.
+
+ --------
+
+ Paragraph.
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ Test unexpected transition markers.
+ <block_quote>
+ <paragraph>
+ Block quote.
+ <system_message level="4" line="5" source="test data" type="SEVERE">
+ <paragraph>
+ Unexpected section title or transition.
+ <literal_block xml:space="preserve">
+ --------
+ <paragraph>
+ Paragraph.
+"""],
+["""\
+Short transition marker.
+
+---
+
+Paragraph
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ Short transition marker.
+ <paragraph>
+ ---
+ <paragraph>
+ Paragraph
+"""],
+["""\
+Sections with transitions at beginning and end.
+
+Section 1
+=========
+
+----------
+
+The next transition is legal:
+
+----------
+
+Section 2
+=========
+
+----------
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ Sections with transitions at beginning and end.
+ <section ids="section-1" names="section\\ 1">
+ <title>
+ Section 1
+ <transition>
+ <paragraph>
+ The next transition is legal:
+ <transition>
+ <section ids="section-2" names="section\\ 2">
+ <title>
+ Section 2
+ <transition>
+"""],
+["""\
+A paragraph, two transitions, and a blank line.
+
+----------
+
+----------
+
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ A paragraph, two transitions, and a blank line.
+ <transition>
+ <transition>
+"""],
+["""\
+A paragraph and two transitions.
+
+----------
+
+----------
+""", # the same:
+"""\
+<document source="test data">
+ <paragraph>
+ A paragraph and two transitions.
+ <transition>
+ <transition>
+"""],
+["""\
+----------
+
+Document beginning with a transition.
+""",
+"""\
+<document source="test data">
+ <transition>
+ <paragraph>
+ Document beginning with a transition.
+"""],
+["""\
+Section 1
+=========
+
+Subsection 1
+------------
+
+Some text.
+
+----------
+
+Section 2
+=========
+
+Some text.
+""",
+"""\
+<document source="test data">
+ <section ids="section-1" names="section\\ 1">
+ <title>
+ Section 1
+ <section ids="subsection-1" names="subsection\\ 1">
+ <title>
+ Subsection 1
+ <paragraph>
+ Some text.
+ <transition>
+ <section ids="section-2" names="section\\ 2">
+ <title>
+ Section 2
+ <paragraph>
+ Some text.
+"""],
+["""\
+Section 1
+=========
+
+----------
+
+----------
+
+----------
+
+Section 2
+=========
+
+Some text.
+""",
+"""\
+<document source="test data">
+ <section ids="section-1" names="section\\ 1">
+ <title>
+ Section 1
+ <transition>
+ <transition>
+ <transition>
+ <section ids="section-2" names="section\\ 2">
+ <title>
+ Section 2
+ <paragraph>
+ Some text.
+"""],
+["""\
+----------
+
+----------
+
+----------
+""",
+"""\
+<document source="test data">
+ <transition>
+ <transition>
+ <transition>
+"""],
+["""\
+A paragraph.
+
+----------
+
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ A paragraph.
+ <transition>
+"""],
+]
+
+
+if __name__ == '__main__':
+ import unittest
+ unittest.main(defaultTest='suite')
--- /dev/null
+#! /usr/bin/env python
+# $Id: test_pickle.py 7539 2012-11-26 13:50:06Z milde $
+# Author: David Goodger <goodger@python.org>
+# Copyright: This module has been placed in the public domain.
+
+"""
+Tests of document tree pickling.
+"""
+
+import unittest
+import DocutilsTestSupport # must be imported before docutils
+import pickle
+from docutils import core
+
+
+class PickleTests(unittest.TestCase):
+
+ def test_pickle(self):
+ doctree = core.publish_doctree(
+ source='Title\n=====\n\nparagraph\n',
+ settings_overrides={'_disable_config': True})
+ dill = pickle.dumps(doctree)
+ reconstituted = pickle.loads(dill)
+ self.assertEqual(doctree.pformat(), reconstituted.pformat())
+
+
+if __name__ == '__main__':
+ unittest.main()
--- /dev/null
+#!/usr/bin/env python
+
+# $Id: test_publisher.py 8369 2019-08-27 12:10:26Z milde $
+# Author: Martin Blais <blais@furius.ca>
+# Copyright: This module has been placed in the public domain.
+
+"""
+Test the `Publisher` facade and the ``publish_*`` convenience functions.
+"""
+
+import pickle
+import sys
+
+import DocutilsTestSupport # must be imported before docutils
+import docutils
+from docutils import core, nodes, io
+
+if sys.version_info < (3, 0):
+ u_prefix = 'u'
+else:
+ u_prefix = b''
+
+
+test_document = """\
+Test Document
+=============
+
+This is a test document with a broken reference: nonexistent_
+"""
+pseudoxml_output = b"""\
+<document ids="test-document" names="test\\ document" source="<string>" title="Test Document">
+ <title>
+ Test Document
+ <paragraph>
+ This is a test document with a broken reference: \n\
+ <problematic ids="id2" refid="id1">
+ nonexistent_
+ <section classes="system-messages">
+ <title>
+ Docutils System Messages
+ <system_message backrefs="id2" ids="id1" level="3" line="4" source="<string>" type="ERROR">
+ <paragraph>
+ Unknown target name: "nonexistent".
+"""
+exposed_pseudoxml_output = (b"""\
+<document ids="test-document" internal:refnames="{"""
++ u_prefix
++ b"""\'nonexistent\': [<reference: <#text: \'nonexistent\'>>]}" names="test\\ document" source="<string>" title="Test Document">
+ <title>
+ Test Document
+ <paragraph>
+ This is a test document with a broken reference: \n\
+ <problematic ids="id2" refid="id1">
+ nonexistent_
+ <section classes="system-messages">
+ <title>
+ Docutils System Messages
+ <system_message backrefs="id2" ids="id1" level="3" line="4" source="<string>" type="ERROR">
+ <paragraph>
+ Unknown target name: "nonexistent".
+""") # % u_prefix # %-expansion not supported in bytes in 3.3 and 3.4
+
+
+class PublisherTests(DocutilsTestSupport.StandardTestCase):
+
+ def test_input_error_handling(self):
+ # core.publish_cmdline(argv=['nonexisting/path'])
+ # exits with a short message, if `traceback` is False,
+
+ # pass IOErrors to calling application if `traceback` is True
+ try:
+ core.publish_cmdline(argv=['nonexisting/path'],
+ settings_overrides={'traceback': True})
+ except IOError as e:
+ self.assertTrue(isinstance(e, io.InputError))
+
+
+ def test_output_error_handling(self):
+ # pass IOErrors to calling application if `traceback` is True
+ try:
+ core.publish_cmdline(argv=['data/include.txt', 'nonexisting/path'],
+ settings_overrides={'traceback': True})
+ except IOError as e:
+ self.assertTrue(isinstance(e, io.OutputError))
+
+
+class PublishDoctreeTestCase(DocutilsTestSupport.StandardTestCase, docutils.SettingsSpec):
+
+ settings_default_overrides = {
+ '_disable_config': True,
+ 'warning_stream': io.NullOutput()}
+
+ def test_publish_doctree(self):
+ # Test `publish_doctree` and `publish_from_doctree`.
+
+ # Produce the document tree.
+ doctree = core.publish_doctree(
+ source=test_document, reader_name='standalone',
+ parser_name='restructuredtext', settings_spec=self,
+ settings_overrides={'expose_internals':
+ ['refnames', 'do_not_expose'],
+ 'report_level': 5})
+ self.assertTrue(isinstance(doctree, nodes.document))
+
+ # Confirm that transforms have been applied (in this case, the
+ # DocTitle transform):
+ self.assertTrue(isinstance(doctree[0], nodes.title))
+ self.assertTrue(isinstance(doctree[1], nodes.paragraph))
+ # Confirm that the Messages transform has not yet been applied:
+ self.assertEqual(len(doctree), 2)
+
+ # The `do_not_expose` attribute may not show up in the
+ # pseudoxml output because the expose_internals transform may
+ # not be applied twice.
+ doctree.do_not_expose = 'test'
+ # Write out the document:
+ output = core.publish_from_doctree(
+ doctree, writer_name='pseudoxml',
+ settings_spec=self,
+ settings_overrides={'expose_internals':
+ ['refnames', 'do_not_expose'],
+ 'report_level': 1})
+ self.assertEqual(output, exposed_pseudoxml_output)
+
+ # Test publishing parts using document as the source.
+ parts = core.publish_parts(
+ reader_name='doctree', source_class=io.DocTreeInput,
+ source=doctree, source_path='test', writer_name='html',
+ settings_spec=self)
+ self.assertTrue(isinstance(parts, dict))
+
+ def test_publish_pickle(self):
+ # Test publishing a document tree with pickling and unpickling.
+
+ # Produce the document tree.
+ doctree = core.publish_doctree(
+ source=test_document,
+ reader_name='standalone',
+ parser_name='restructuredtext',
+ settings_spec=self)
+ self.assertTrue(isinstance(doctree, nodes.document))
+
+ # Pickle the document. Note: if this fails, some unpickleable
+ # reference has been added somewhere within the document tree.
+ # If so, you need to fix that.
+ #
+ # Note: Please do not remove this test, this is an important
+ # requirement, applications will be built on the assumption
+ # that we can pickle the document.
+
+ # Remove the reporter and the transformer before pickling.
+ doctree.reporter = None
+ doctree.transformer = None
+
+ doctree_pickled = pickle.dumps(doctree)
+ self.assertTrue(isinstance(doctree_pickled, bytes))
+ del doctree
+
+ # Unpickle the document.
+ doctree_zombie = pickle.loads(doctree_pickled)
+ self.assertTrue(isinstance(doctree_zombie, nodes.document))
+
+ # Write out the document:
+ output = core.publish_from_doctree(
+ doctree_zombie, writer_name='pseudoxml',
+ settings_spec=self)
+ self.assertEqual(output, pseudoxml_output)
+
+
+if __name__ == '__main__':
+ import unittest
+ unittest.main()
--- /dev/null
+import os
+import os.path
+import sys
+
+sys.path.insert(0, os.path.abspath(os.path.dirname(__file__)))
+prev = ''
+while sys.path[0] != prev:
+ try:
+ import DocutilsTestSupport
+ break
+ except ImportError:
+ prev = sys.path[0]
+ sys.path[0] = os.path.dirname(prev)
+sys.path.pop(0)
--- /dev/null
+#! /usr/bin/env python
+
+# $Id: test_get_reader_class.py 8356 2019-08-26 16:44:19Z milde $
+# Author: grubert abadger1999
+# Maintainer: docutils-develop@lists.sourceforge.net
+# Copyright: This module has been placed in the public domain.
+
+"""
+test get_reader_class
+"""
+from __future__ import absolute_import
+
+from . import DocutilsTestSupport
+from docutils.readers import get_reader_class
+
+
+class GetReaderClassTestCase(DocutilsTestSupport.StandardTestCase):
+
+ def test_registered_reader(self):
+ rdr = get_reader_class('pep')
+ # raises ImportError on failure
+
+ def test_bogus_reader(self):
+ self.assertRaises(ImportError,
+ get_reader_class, 'nope')
+
+ def test_local_reader(self):
+ # requires local-reader.py in test directory (testroot)
+ wr = get_reader_class('local-reader')
+
+if __name__ == '__main__':
+ import unittest
+ unittest.main()
--- /dev/null
+import os
+import os.path
+import sys
+
+sys.path.insert(0, os.path.abspath(os.path.dirname(__file__)))
+prev = ''
+while sys.path[0] != prev:
+ try:
+ import DocutilsTestSupport
+ break
+ except ImportError:
+ prev = sys.path[0]
+ sys.path[0] = os.path.dirname(prev)
+sys.path.pop(0)
--- /dev/null
+#! /usr/bin/env python
+
+# $Id: test_inline_markup.py 8356 2019-08-26 16:44:19Z milde $
+# Author: David Goodger <goodger@python.org>
+# Copyright: This module has been placed in the public domain.
+
+"""
+Tests for inline markup in PEPs (readers/pep.py).
+"""
+from __future__ import absolute_import
+
+from . import DocutilsTestSupport
+
+
+def suite():
+ s = DocutilsTestSupport.PEPParserTestSuite()
+ s.generateTests(totest)
+ return s
+
+
+totest = {}
+
+totest['standalone_references'] = [
+["""\
+See PEP 287 (pep-0287.txt),
+and RFC 2822 (which obsoletes RFC822 and RFC-733).
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ See \n\
+ <reference refuri="http://www.python.org/dev/peps/pep-0287">
+ PEP 287
+ (
+ <reference refuri="http://www.python.org/dev/peps/pep-0287">
+ pep-0287.txt
+ ),
+ and \n\
+ <reference refuri="http://tools.ietf.org/html/rfc2822.html">
+ RFC 2822
+ (which obsoletes \n\
+ <reference refuri="http://tools.ietf.org/html/rfc822.html">
+ RFC822
+ and \n\
+ <reference refuri="http://tools.ietf.org/html/rfc733.html">
+ RFC-733
+ ).
+"""],
+["""\
+References split across lines:
+
+PEP
+287
+
+RFC
+2822
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ References split across lines:
+ <paragraph>
+ <reference refuri="http://www.python.org/dev/peps/pep-0287">
+ PEP
+ 287
+ <paragraph>
+ <reference refuri="http://tools.ietf.org/html/rfc2822.html">
+ RFC
+ 2822
+"""],
+["""\
+Test PEP-specific implicit references before a URL:
+
+PEP 287 (http://www.python.org/dev/peps/pep-0287), RFC 2822.
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ Test PEP-specific implicit references before a URL:
+ <paragraph>
+ <reference refuri="http://www.python.org/dev/peps/pep-0287">
+ PEP 287
+ (
+ <reference refuri="http://www.python.org/dev/peps/pep-0287">
+ http://www.python.org/dev/peps/pep-0287
+ ), \n\
+ <reference refuri="http://tools.ietf.org/html/rfc2822.html">
+ RFC 2822
+ .
+"""],
+]
+
+totest['miscellaneous'] = [
+["""\
+For *completeness*, _`let's` ``test`` **other** forms_
+|of| `inline markup` [*]_.
+
+.. [*] See http://docutils.sf.net/docs/ref/rst/restructuredtext.html.
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ For \n\
+ <emphasis>
+ completeness
+ , \n\
+ <target ids="let-s" names="let's">
+ let's
+ \n\
+ <literal>
+ test
+ \n\
+ <strong>
+ other
+ \n\
+ <reference name="forms" refname="forms">
+ forms
+ \n\
+ <substitution_reference refname="of">
+ of
+ \n\
+ <title_reference>
+ inline markup
+ \n\
+ <footnote_reference auto="*" ids="id1">
+ .
+ <footnote auto="*" ids="id2">
+ <paragraph>
+ See \n\
+ <reference refuri="http://docutils.sf.net/docs/ref/rst/restructuredtext.html">
+ http://docutils.sf.net/docs/ref/rst/restructuredtext.html
+ .
+"""],
+]
+
+
+if __name__ == '__main__':
+ import unittest
+ unittest.main(defaultTest='suite')
--- /dev/null
+#! /usr/bin/env python
+
+# $Id: test_rfc2822.py 8356 2019-08-26 16:44:19Z milde $
+# Author: David Goodger <goodger@python.org>
+# Copyright: This module has been placed in the public domain.
+
+"""
+Tests for RFC-2822 headers in PEPs (readers/pep.py).
+"""
+from __future__ import absolute_import
+
+from . import DocutilsTestSupport
+
+
+def suite():
+ s = DocutilsTestSupport.PEPParserTestSuite()
+ s.generateTests(totest)
+ return s
+
+totest = {}
+
+totest['rfc2822'] = [
+["""\
+Author: Me
+Version: 1
+Date: 2002-04-23
+""",
+"""\
+<document source="test data">
+ <field_list classes="rfc2822">
+ <field>
+ <field_name>
+ Author
+ <field_body>
+ <paragraph>
+ Me
+ <field>
+ <field_name>
+ Version
+ <field_body>
+ <paragraph>
+ 1
+ <field>
+ <field_name>
+ Date
+ <field_body>
+ <paragraph>
+ 2002-04-23
+"""],
+["""\
+
+
+Author: Me
+Version: 1
+Date: 2002-04-23
+
+.. Leading blank lines don't affect RFC-2822 header parsing.
+""",
+"""\
+<document source="test data">
+ <field_list classes="rfc2822">
+ <field>
+ <field_name>
+ Author
+ <field_body>
+ <paragraph>
+ Me
+ <field>
+ <field_name>
+ Version
+ <field_body>
+ <paragraph>
+ 1
+ <field>
+ <field_name>
+ Date
+ <field_body>
+ <paragraph>
+ 2002-04-23
+ <comment xml:space="preserve">
+ Leading blank lines don't affect RFC-2822 header parsing.
+"""],
+["""\
+.. A comment should prevent RFC-2822 header parsing.
+
+Author: Me
+Version: 1
+Date: 2002-04-23
+""",
+"""\
+<document source="test data">
+ <comment xml:space="preserve">
+ A comment should prevent RFC-2822 header parsing.
+ <paragraph>
+ Author: Me
+ Version: 1
+ Date: 2002-04-23
+"""],
+["""\
+Author: Me
+
+Version: 1
+Date: 2002-04-23
+""",
+"""\
+<document source="test data">
+ <field_list classes="rfc2822">
+ <field>
+ <field_name>
+ Author
+ <field_body>
+ <paragraph>
+ Me
+ <paragraph>
+ Version: 1
+ Date: 2002-04-23
+"""],
+["""\
+field:
+empty item above, no blank line
+""",
+"""\
+<document source="test data">
+ <field_list classes="rfc2822">
+ <field>
+ <field_name>
+ field
+ <field_body>
+ <system_message level="2" line="2" source="test data" type="WARNING">
+ <paragraph>
+ RFC2822-style field list ends without a blank line; unexpected unindent.
+ <paragraph>
+ empty item above, no blank line
+"""],
+["""\
+Author:
+ Me
+Version:
+ 1
+Date:
+ 2002-04-23
+""",
+"""\
+<document source="test data">
+ <field_list classes="rfc2822">
+ <field>
+ <field_name>
+ Author
+ <field_body>
+ <paragraph>
+ Me
+ <field>
+ <field_name>
+ Version
+ <field_body>
+ <paragraph>
+ 1
+ <field>
+ <field_name>
+ Date
+ <field_body>
+ <paragraph>
+ 2002-04-23
+"""],
+["""\
+Authors: Me,
+ Myself,
+ and I
+Version: 1
+ or so
+Date: 2002-04-23
+ (Tuesday)
+""",
+"""\
+<document source="test data">
+ <field_list classes="rfc2822">
+ <field>
+ <field_name>
+ Authors
+ <field_body>
+ <paragraph>
+ Me,
+ Myself,
+ and I
+ <field>
+ <field_name>
+ Version
+ <field_body>
+ <paragraph>
+ 1
+ or so
+ <field>
+ <field_name>
+ Date
+ <field_body>
+ <paragraph>
+ 2002-04-23
+ (Tuesday)
+"""],
+["""\
+Authors: Me,
+ Myself,
+ and I
+Version: 1
+ or so
+Date: 2002-04-23
+ (Tuesday)
+""",
+"""\
+<document source="test data">
+ <field_list classes="rfc2822">
+ <field>
+ <field_name>
+ Authors
+ <field_body>
+ <paragraph>
+ Me,
+ Myself,
+ and I
+ <field>
+ <field_name>
+ Version
+ <field_body>
+ <paragraph>
+ 1
+ or so
+ <field>
+ <field_name>
+ Date
+ <field_body>
+ <paragraph>
+ 2002-04-23
+ (Tuesday)
+"""],
+["""\
+Authors: - Me
+ - Myself
+ - I
+Version:
+""",
+"""\
+<document source="test data">
+ <field_list classes="rfc2822">
+ <field>
+ <field_name>
+ Authors
+ <field_body>
+ <bullet_list bullet="-">
+ <list_item>
+ <paragraph>
+ Me
+ <list_item>
+ <paragraph>
+ Myself
+ <list_item>
+ <paragraph>
+ I
+ <field>
+ <field_name>
+ Version
+ <field_body>
+"""],
+["""\
+Authors: Me
+
+ Myself and I
+Version:
+""",
+"""\
+<document source="test data">
+ <field_list classes="rfc2822">
+ <field>
+ <field_name>
+ Authors
+ <field_body>
+ <paragraph>
+ Me
+ <block_quote>
+ <paragraph>
+ Myself and I
+ <system_message level="2" line="4" source="test data" type="WARNING">
+ <paragraph>
+ Block quote ends without a blank line; unexpected unindent.
+ <paragraph>
+ Version:
+"""],
+]
+
+if __name__ == '__main__':
+ import unittest
+ unittest.main(defaultTest='suite')
--- /dev/null
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+# $Id: test_settings.py 8346 2019-08-26 12:11:32Z milde $
+# Author: David Goodger <goodger@python.org>
+# Copyright: This module has been placed in the public domain.
+
+"""
+Tests of runtime settings.
+"""
+from __future__ import print_function
+
+import sys
+import os
+import difflib
+import pprint
+import warnings
+import unittest
+import DocutilsTestSupport # must be imported before docutils
+from docutils import frontend, utils
+from docutils.writers import html4css1, pep_html
+from docutils.parsers import rst
+
+
+warnings.filterwarnings(action='ignore',
+ category=frontend.ConfigDeprecationWarning)
+
+
+def fixpath(path):
+ return os.path.abspath(os.path.join(*(path.split('/'))))
+
+
+class ConfigFileTests(unittest.TestCase):
+
+ config_files = {'old': fixpath('data/config_old.txt'),
+ 'one': fixpath('data/config_1.txt'),
+ 'two': fixpath('data/config_2.txt'),
+ 'list': fixpath('data/config_list.txt'),
+ 'list2': fixpath('data/config_list_2.txt'),
+ 'error': fixpath('data/config_error_handler.txt')}
+
+ settings = {
+ 'old': {u'datestamp': u'%Y-%m-%d %H:%M UTC',
+ u'generator': True,
+ u'no_random': True,
+ u'python_home': u'http://www.python.org',
+ u'source_link': True,
+ 'stylesheet': None,
+ u'stylesheet_path': [u'stylesheets/pep.css'],
+ 'template': fixpath(u'data/pep-html-template')},
+ 'one': {u'datestamp': u'%Y-%m-%d %H:%M UTC',
+ u'generator': True,
+ u'no_random': True,
+ u'python_home': u'http://www.python.org',
+ u'raw_enabled': False,
+ 'record_dependencies': utils.DependencyList(),
+ u'source_link': True,
+ 'stylesheet': None,
+ u'stylesheet_path': [u'stylesheets/pep.css'],
+ u'tab_width': 8,
+ u'template': fixpath(u'data/pep-html-template'),
+ u'trim_footnote_reference_space': True,
+ },
+ 'two': {u'footnote_references': u'superscript',
+ u'generator': False,
+ 'record_dependencies': utils.DependencyList(),
+ u'stylesheet': None,
+ u'stylesheet_path': [u'test.css'],
+ 'trim_footnote_reference_space': None},
+ 'list': {u'expose_internals': [u'a', u'b', u'c', u'd', u'e'],
+ u'strip_classes': [u'spam', u'pan', u'fun', u'parrot'],
+ u'strip_elements_with_classes': [u'sugar', u'flour', u'milk',
+ u'safran']},
+ 'list2': {u'expose_internals': [u'a', u'b', u'c', u'd', u'e', u'f'],
+ u'strip_classes': [u'spam', u'pan', u'fun', u'parrot',
+ u'ham', u'eggs'],
+ u'strip_elements_with_classes': [u'sugar', u'flour',
+ u'milk', u'safran',
+ u'eggs', u'salt']},
+ 'error': {u'error_encoding': u'ascii',
+ u'error_encoding_error_handler': u'strict'},
+ }
+
+ compare = difflib.Differ().compare
+ """Comparison method shared by all tests."""
+
+ def setUp(self):
+ self.option_parser = frontend.OptionParser(
+ components=(pep_html.Writer, rst.Parser), read_config_files=None)
+
+ def files_settings(self, *names):
+ settings = frontend.Values()
+ for name in names:
+ settings.update(self.option_parser.get_config_file_settings(
+ self.config_files[name]), self.option_parser)
+ return settings.__dict__
+
+ def expected_settings(self, *names):
+ expected = {}
+ for name in names:
+ expected.update(self.settings[name])
+ return expected
+
+ def compare_output(self, result, expected):
+ """`result` and `expected` should both be dicts."""
+ self.assertTrue('record_dependencies' in result)
+ if 'record_dependencies' not in expected:
+ # Delete it if we don't want to test it.
+ del result['record_dependencies']
+ result = pprint.pformat(result) + '\n'
+ expected = pprint.pformat(expected) + '\n'
+ try:
+ self.assertEqual(result, expected)
+ except AssertionError:
+ print('\n%s\n' % (self,), file=sys.stderr)
+ print('-: expected\n+: result', file=sys.stderr)
+ print(''.join(self.compare(expected.splitlines(1),
+ result.splitlines(1))), file=sys.stderr)
+ raise
+
+ def test_nofiles(self):
+ self.compare_output(self.files_settings(),
+ self.expected_settings())
+
+ def test_old(self):
+ self.compare_output(self.files_settings('old'),
+ self.expected_settings('old'))
+
+ def test_one(self):
+ self.compare_output(self.files_settings('one'),
+ self.expected_settings('one'))
+
+ def test_multiple(self):
+ self.compare_output(self.files_settings('one', 'two'),
+ self.expected_settings('one', 'two'))
+
+ def test_old_and_new(self):
+ self.compare_output(self.files_settings('old', 'two'),
+ self.expected_settings('old', 'two'))
+
+ def test_list(self):
+ self.compare_output(self.files_settings('list'),
+ self.expected_settings('list'))
+
+ def test_list2(self):
+ self.compare_output(self.files_settings('list', 'list2'),
+ self.expected_settings('list2'))
+
+ def test_error_handler(self):
+ self.compare_output(self.files_settings('error'),
+ self.expected_settings('error'))
+
+
+class ConfigEnvVarFileTests(ConfigFileTests):
+
+ """
+ Repeats the tests of `ConfigFileTests` using the ``DOCUTILSCONFIG``
+ environment variable and the standard Docutils config file mechanism.
+ """
+
+ def setUp(self):
+ ConfigFileTests.setUp(self)
+ self.orig_environ = os.environ
+ os.environ = os.environ.copy()
+
+ def files_settings(self, *names):
+ files = [self.config_files[name] for name in names]
+ os.environ['DOCUTILSCONFIG'] = os.pathsep.join(files)
+ settings = self.option_parser.get_standard_config_settings()
+ return settings.__dict__
+
+ def tearDown(self):
+ os.environ = self.orig_environ
+
+
+class HelperFunctionsTests(unittest.TestCase):
+
+ pathdict = {'foo': 'hallo', 'ham': u'h\xE4m', 'spam': u'spam'}
+ keys = ['foo', 'ham']
+
+ def setUp(self):
+ self.option_parser = frontend.OptionParser(
+ components=(rst.Parser,), read_config_files=None)
+
+ def test_make_paths_absolute(self):
+ pathdict = self.pathdict.copy()
+ frontend.make_paths_absolute(pathdict, self.keys, base_path='base')
+ self.assertEqual(pathdict['foo'], os.path.abspath('base/hallo'))
+ self.assertEqual(pathdict['ham'], os.path.abspath(u'base/h\xE4m'))
+ # not touched, because key not in keys:
+ self.assertEqual(pathdict['spam'], u'spam')
+
+ def test_make_paths_absolute_cwd(self):
+ # With base_path None, the cwd is used as base path.
+ # Settings values may-be `unicode` instances, therefore
+ # os.getcwdu() is used and the converted path is a unicode instance:
+ pathdict = self.pathdict.copy()
+ frontend.make_paths_absolute(pathdict, self.keys)
+ self.assertEqual(pathdict['foo'], os.path.abspath(u'hallo'))
+ self.assertEqual(pathdict['ham'], os.path.abspath(u'h\xE4m'))
+ # not touched, because key not in keys:
+ self.assertEqual(pathdict['spam'], u'spam')
+
+ boolean_settings = (
+ (True, True ),
+ ('1', True ),
+ (u'on', True ),
+ ('yes', True ),
+ (u'true', True ),
+ (u'0', False ),
+ ('off', False ),
+ (u'no', False ),
+ ('false', False ),
+ )
+ def test_validate_boolean(self):
+ for t in self.boolean_settings:
+ self.assertEqual(
+ frontend.validate_boolean(None, t[0], self.option_parser),
+ t[1])
+
+ def test_validate_ternary(self):
+ tests = (
+ ('500V', '500V'),
+ (u'parrot', u'parrot'),
+ )
+ for t in self.boolean_settings + tests:
+ self.assertEqual(
+ frontend.validate_ternary(None, t[0], self.option_parser),
+ t[1])
+
+ def test_validate_colon_separated_string_list(self):
+ tests = (
+ (u'a', ['a',] ),
+ ('a', ['a',] ),
+ (u'a:b', ['a', 'b'] ),
+ ('a:b', ['a', 'b'] ),
+ ([u'a',], ['a',] ),
+ ([u'a', u'b:c'], ['a', 'b', 'c'] ),
+ )
+ for t in tests:
+ self.assertEqual(
+ frontend.validate_colon_separated_string_list(None, t[0], None),
+ t[1])
+
+ def test_validate_comma_separated_list(self):
+ tests = (
+ (u'a', ['a',] ),
+ ('a', ['a',] ),
+ (u'a,b', ['a', 'b'] ),
+ ('a,b', ['a', 'b'] ),
+ ([u'a',], ['a',] ),
+ ([u'a', u'b,c'], ['a', 'b', 'c'] ),
+ (['a', 'b,c'], ['a', 'b', 'c'] ),
+ )
+ for t in tests:
+ self.assertEqual(
+ frontend.validate_comma_separated_list(None, t[0], None),
+ t[1])
+
+ def test_validate_url_trailing_slash(self):
+ tests = (
+ ('', './' ),
+ (None, './' ),
+ (u'http://example.org', u'http://example.org/' ),
+ ('http://example.org/', 'http://example.org/' ),
+ )
+ for t in tests:
+ self.assertEqual(
+ frontend.validate_url_trailing_slash(None, t[0], None),
+ t[1])
+
+ def test_validate_smartquotes_locales(self):
+ tests = (
+ ('en:ssvv', [('en', 'ssvv')]),
+ (u'sd:«»°°', [(u'sd', u'«»°°')]),
+ ([('sd', u'«»°°'), u'ds:°°«»'], [('sd', u'«»°°'),
+ ('ds', u'°°«»')]),
+ (u'frs:« : »:((:))', [(u'frs', [u'« ', u' »',
+ u'((', u'))'])]),
+ )
+ for t in tests:
+ self.assertEqual(
+ frontend.validate_smartquotes_locales(None, t[0], None),
+ t[1])
+
+
+
+if __name__ == '__main__':
+ unittest.main()
--- /dev/null
+#! /usr/bin/env python
+
+# $Id: test_statemachine.py 8372 2019-08-27 12:11:15Z milde $
+# Author: David Goodger <goodger@python.org>
+# Copyright: This module has been placed in the public domain.
+
+"""
+Test module for statemachine.py.
+"""
+from __future__ import print_function
+
+import unittest
+import sys
+import re
+from DocutilsTestSupport import statemachine
+
+
+debug = False
+testtext = statemachine.string2lines("""\
+First paragraph.
+
+- This is a bullet list. First list item.
+ Second line of first para.
+
+ Second para.
+
+ block quote
+
+- Second list item. Example::
+
+ a
+ literal
+ block
+
+Last paragraph.""")
+expected = ('StateMachine1 text1 blank1 bullet1 known_indent1 '
+ 'StateMachine2 text2 text2 blank2 text2 blank2 indent2 '
+ 'StateMachine3 text3 blank3 finished3 finished2 '
+ 'bullet1 known_indent1 '
+ 'StateMachine2 text2 blank2 literalblock2(4) finished2 '
+ 'text1 finished1').split()
+para1 = testtext[:2]
+item1 = [line[2:] for line in testtext[2:9]]
+item2 = [line[2:] for line in testtext[9:-1]]
+lbindent = 6
+literalblock = [line[lbindent:] for line in testtext[11:-1]]
+para2 = testtext[-1]
+
+
+class MockState(statemachine.StateWS):
+
+ patterns = {'bullet': re.compile(r'- '),
+ 'text': ''}
+ initial_transitions = ['bullet', ['text']]
+ levelholder = [0]
+
+ def bof(self, context):
+ self.levelholder[0] += 1
+ self.level = self.levelholder[0]
+ if self.debug: print('StateMachine%s' % self.level, file=sys.stderr)
+ return [], ['StateMachine%s' % self.level]
+
+ def blank(self, match, context, next_state):
+ result = ['blank%s' % self.level]
+ if self.debug: print('blank%s' % self.level, file=sys.stderr)
+ if context and context[-1] and context[-1][-2:] == '::':
+ result.extend(self.literalblock())
+ return [], None, result
+
+ def indent(self, match, context, next_state):
+ if self.debug: print('indent%s' % self.level, file=sys.stderr)
+ context, next_state, result = statemachine.StateWS.indent(
+ self, match, context, next_state)
+ return context, next_state, ['indent%s' % self.level] + result
+
+ def known_indent(self, match, context, next_state):
+ if self.debug: print('known_indent%s' % self.level, file=sys.stderr)
+ context, next_state, result = statemachine.StateWS.known_indent(
+ self, match, context, next_state)
+ return context, next_state, ['known_indent%s' % self.level] + result
+
+ def bullet(self, match, context, next_state):
+ if self.debug: print('bullet%s' % self.level, file=sys.stderr)
+ context, next_state, result \
+ = self.known_indent(match, context, next_state)
+ return [], next_state, ['bullet%s' % self.level] + result
+
+ def text(self, match, context, next_state):
+ if self.debug: print('text%s' % self.level, file=sys.stderr)
+ return [match.string], next_state, ['text%s' % self.level]
+
+ def literalblock(self):
+ indented, indent, offset, good = self.state_machine.get_indented()
+ if self.debug: print('literalblock%s(%s)' % (self.level,
+ indent), file=sys.stderr)
+ return ['literalblock%s(%s)' % (self.level, indent)]
+
+ def eof(self, context):
+ self.levelholder[0] -= 1
+ if self.debug: print('finished%s' % self.level, file=sys.stderr)
+ return ['finished%s' % self.level]
+
+
+class EmptySMTests(unittest.TestCase):
+
+ def setUp(self):
+ self.sm = statemachine.StateMachine(
+ state_classes=[], initial_state='State')
+ self.sm.debug = debug
+
+ def test_add_state(self):
+ self.sm.add_state(statemachine.State)
+ self.assertTrue(len(self.sm.states) == 1)
+ self.assertRaises(statemachine.DuplicateStateError, self.sm.add_state,
+ statemachine.State)
+ self.sm.add_state(statemachine.StateWS)
+ self.assertTrue(len(self.sm.states) == 2)
+
+ def test_add_states(self):
+ self.sm.add_states((statemachine.State, statemachine.StateWS))
+ self.assertEqual(len(self.sm.states), 2)
+
+ def test_get_state(self):
+ self.assertRaises(statemachine.UnknownStateError, self.sm.get_state)
+ self.sm.add_states((statemachine.State, statemachine.StateWS))
+ self.assertRaises(statemachine.UnknownStateError, self.sm.get_state,
+ 'unknownState')
+ self.assertTrue(isinstance(self.sm.get_state('State'),
+ statemachine.State))
+ self.assertTrue(isinstance(self.sm.get_state('StateWS'),
+ statemachine.State))
+ self.assertEqual(self.sm.current_state, 'StateWS')
+
+
+class EmptySMWSTests(EmptySMTests):
+
+ def setUp(self):
+ self.sm = statemachine.StateMachineWS(
+ state_classes=[], initial_state='State')
+ self.sm.debug = debug
+
+
+class SMWSTests(unittest.TestCase):
+
+ def setUp(self):
+ self.sm = statemachine.StateMachineWS([MockState], 'MockState',
+ debug=debug)
+ self.sm.debug = debug
+ self.sm.states['MockState'].levelholder[0] = 0
+
+ def tearDown(self):
+ self.sm.unlink()
+
+ def test___init__(self):
+ self.assertEqual(list(self.sm.states.keys()), ['MockState'])
+ self.assertEqual(len(self.sm.states['MockState'].transitions), 4)
+
+ def test_get_indented(self):
+ self.sm.input_lines = statemachine.StringList(testtext)
+ self.sm.line_offset = -1
+ self.sm.next_line(3)
+ indented, offset, good = self.sm.get_known_indented(2)
+ self.assertEqual(indented, item1)
+ self.assertEqual(offset, len(para1))
+ self.assertTrue(good)
+ self.sm.next_line()
+ indented, offset, good = self.sm.get_known_indented(2)
+ self.assertEqual(indented, item2)
+ self.assertEqual(offset, len(para1) + len(item1))
+ self.assertTrue(good)
+ self.sm.previous_line(3)
+ if self.sm.debug:
+ print('\ntest_get_indented: self.sm.line:\n', self.sm.line)
+ indented, indent, offset, good = self.sm.get_indented()
+ if self.sm.debug:
+ print('\ntest_get_indented: indented:\n', indented)
+ self.assertEqual(indent, lbindent)
+ self.assertEqual(indented, literalblock)
+ self.assertEqual(offset, (len(para1) + len(item1) + len(item2)
+ - len(literalblock)))
+ self.assertTrue(good)
+
+ def test_get_text_block(self):
+ self.sm.input_lines = statemachine.StringList(testtext)
+ self.sm.line_offset = -1
+ self.sm.next_line()
+ textblock = self.sm.get_text_block()
+ self.assertEqual(textblock, testtext[:1])
+ self.sm.next_line(2)
+ textblock = self.sm.get_text_block()
+ self.assertEqual(textblock, testtext[2:4])
+
+ def test_get_text_block_flush_left(self):
+ self.sm.input_lines = statemachine.StringList(testtext)
+ self.sm.line_offset = -1
+ self.sm.next_line()
+ textblock = self.sm.get_text_block(flush_left=1)
+ self.assertEqual(textblock, testtext[:1])
+ self.sm.next_line(2)
+ self.assertRaises(statemachine.UnexpectedIndentationError,
+ self.sm.get_text_block, flush_left=1)
+
+ def test_run(self):
+ self.assertEqual(self.sm.run(testtext), expected)
+
+
+class EmptyClass(object):
+ pass
+
+
+class EmptyStateTests(unittest.TestCase):
+
+ def setUp(self):
+ self.state = statemachine.State(EmptyClass(), debug=debug)
+ self.state.patterns = {'nop': 'dummy',
+ 'nop2': 'dummy',
+ 'nop3': 'dummy',
+ 'bogus': 'dummy'}
+ self.state.nop2 = self.state.nop3 = self.state.nop
+
+ def test_add_transitions(self):
+ self.assertEqual(len(self.state.transitions), 0)
+ self.state.add_transitions(['None'], {'None': None})
+ self.assertEqual(len(self.state.transitions), 1)
+ self.assertRaises(statemachine.UnknownTransitionError,
+ self.state.add_transitions, ['bogus'], {})
+ self.assertRaises(statemachine.DuplicateTransitionError,
+ self.state.add_transitions, ['None'],
+ {'None': None})
+
+ def test_add_transition(self):
+ self.assertEqual(len(self.state.transitions), 0)
+ self.state.add_transition('None', None)
+ self.assertEqual(len(self.state.transitions), 1)
+ self.assertRaises(statemachine.DuplicateTransitionError,
+ self.state.add_transition, 'None', None)
+
+ def test_remove_transition(self):
+ self.assertEqual(len(self.state.transitions), 0)
+ self.state.add_transition('None', None)
+ self.assertEqual(len(self.state.transitions), 1)
+ self.state.remove_transition('None')
+ self.assertEqual(len(self.state.transitions), 0)
+ self.assertRaises(statemachine.UnknownTransitionError,
+ self.state.remove_transition, 'None')
+
+ def test_make_transition(self):
+ dummy = re.compile('dummy')
+ self.assertEqual(self.state.make_transition('nop', 'bogus'),
+ (dummy, self.state.nop, 'bogus'))
+ self.assertEqual(self.state.make_transition('nop'),
+ (dummy, self.state.nop,
+ self.state.__class__.__name__))
+ self.assertRaises(statemachine.TransitionPatternNotFound,
+ self.state.make_transition, 'None')
+ self.assertRaises(statemachine.TransitionMethodNotFound,
+ self.state.make_transition, 'bogus')
+
+ def test_make_transitions(self):
+ dummy = re.compile('dummy')
+ self.assertEqual(self.state.make_transitions(('nop', ['nop2'],
+ ('nop3', 'bogus'))),
+ (['nop', 'nop2', 'nop3'],
+ {'nop': (dummy, self.state.nop,
+ self.state.__class__.__name__),
+ 'nop2': (dummy, self.state.nop2,
+ self.state.__class__.__name__),
+ 'nop3': (dummy, self.state.nop3, 'bogus')}))
+
+
+class MiscTests(unittest.TestCase):
+
+ s2l_string = "hello\tthere\thow are\tyou?\n\tI'm fine\tthanks.\n"
+ s2l_expected = ['hello there how are you?',
+ " I'm fine thanks."]
+ def test_string2lines(self):
+ self.assertEqual(statemachine.string2lines(self.s2l_string),
+ self.s2l_expected)
+
+
+if __name__ == '__main__':
+ unittest.main()
--- /dev/null
+import os
+import os.path
+import sys
+
+sys.path.insert(0, os.path.abspath(os.path.dirname(__file__)))
+prev = ''
+while sys.path[0] != prev:
+ try:
+ import DocutilsTestSupport
+ break
+ except ImportError:
+ prev = sys.path[0]
+ sys.path[0] = os.path.dirname(prev)
+sys.path.pop(0)
--- /dev/null
+#! /usr/bin/env python
+
+# $Id: test___init__.py 8356 2019-08-26 16:44:19Z milde $
+# Author: Lea Wiemann <LeWiemann@gmail.com>
+# Copyright: This module has been placed in the public domain.
+
+"""
+Test module for transforms/__init__.py.
+"""
+from __future__ import absolute_import
+
+import unittest
+
+from . import DocutilsTestSupport # must be imported before docutils
+from docutils import transforms, utils
+
+
+class TestTransform(transforms.Transform):
+
+ default_priority = 100
+
+ applied = 0
+
+ def apply(self, **kwargs):
+ self.applied += 1
+ assert kwargs == {'foo': 42}
+
+
+class KwargsTestCase(unittest.TestCase):
+
+ def test_kwargs(self):
+ transformer = transforms.Transformer(utils.new_document('test data'))
+ transformer.add_transform(TestTransform, foo=42)
+ transformer.apply_transforms()
+ self.assertEqual(len(transformer.applied), 1)
+ self.assertEqual(len(transformer.applied[0]), 4)
+ transform_record = transformer.applied[0]
+ self.assertEqual(transform_record[1], TestTransform)
+ self.assertEqual(transform_record[3], {'foo': 42})
+
+
+if __name__ == '__main__':
+ unittest.main()
--- /dev/null
+#! /usr/bin/env python
+
+# $Id: test_class.py 8356 2019-08-26 16:44:19Z milde $
+# Author: David Goodger <goodger@python.org>
+# Copyright: This module has been placed in the public domain.
+
+"""
+Tests for `docutils.transforms.misc.ClassAttribute`.
+"""
+from __future__ import absolute_import
+
+from . import DocutilsTestSupport
+from docutils.parsers.rst import Parser
+
+
+def suite():
+ parser = Parser()
+ s = DocutilsTestSupport.TransformTestSuite(parser)
+ s.generateTests(totest)
+ return s
+
+totest = {}
+
+totest['class'] = ((), [
+["""\
+.. class:: one
+
+paragraph
+""",
+"""\
+<document source="test data">
+ <paragraph classes="one">
+ paragraph
+"""],
+["""\
+.. class:: two
+..
+
+ Block quote
+""",
+"""\
+<document source="test data">
+ <comment xml:space="preserve">
+ <block_quote classes="two">
+ <paragraph>
+ Block quote
+"""],
+["""\
+ Block quote
+
+ .. class:: three
+
+Paragraph
+""",
+"""\
+<document source="test data">
+ <block_quote>
+ <paragraph>
+ Block quote
+ <paragraph classes="three">
+ Paragraph
+"""],
+["""\
+.. class:: four
+
+Section Title
+=============
+
+Paragraph
+""",
+"""\
+<document source="test data">
+ <section classes="four" ids="section-title" names="section\\ title">
+ <title>
+ Section Title
+ <paragraph>
+ Paragraph
+"""],
+["""\
+.. class:: multiple
+
+ paragraph 1
+
+ paragraph 2
+""",
+"""\
+<document source="test data">
+ <paragraph classes="multiple">
+ paragraph 1
+ <paragraph classes="multiple">
+ paragraph 2
+"""],
+["""\
+.. class:: multiple
+
+ .. Just a comment. It's silly, but possible
+""",
+"""\
+<document source="test data">
+ <comment classes="multiple" xml:space="preserve">
+ Just a comment. It's silly, but possible
+"""],
+["""\
+.. class::
+
+.. class:: 99
+""",
+"""\
+<document source="test data">
+ <system_message level="3" line="1" source="test data" type="ERROR">
+ <paragraph>
+ Error in "class" directive:
+ 1 argument(s) required, 0 supplied.
+ <literal_block xml:space="preserve">
+ .. class::
+ <system_message level="3" line="3" source="test data" type="ERROR">
+ <paragraph>
+ Invalid class attribute value for "class" directive: "99".
+ <literal_block xml:space="preserve">
+ .. class:: 99
+"""],
+["""\
+.. class:: one
+.. class:: two
+
+multiple class values may be assigned to one element
+""",
+"""\
+<document source="test data">
+ <paragraph classes="one two">
+ multiple class values may be assigned to one element
+"""],
+["""\
+.. class:: one two
+
+multiple class values may be assigned to one element
+""",
+"""\
+<document source="test data">
+ <paragraph classes="one two">
+ multiple class values may be assigned to one element
+"""],
+["""\
+.. class:: fancy
+
+2. List starts at 2.
+3. Class should apply to list, not to system message.
+""",
+"""\
+<document source="test data">
+ <enumerated_list classes="fancy" enumtype="arabic" prefix="" start="2" suffix=".">
+ <list_item>
+ <paragraph>
+ List starts at 2.
+ <list_item>
+ <paragraph>
+ Class should apply to list, not to system message.
+ <system_message level="1" line="3" source="test data" type="INFO">
+ <paragraph>
+ Enumerated list start value not ordinal-1: "2" (ordinal 2)
+"""],
+["""\
+2. List starts at 2.
+3. Class should apply to next paragraph, not to system message.
+
+ .. class:: fancy
+
+A paragraph.
+""",
+"""\
+<document source="test data">
+ <enumerated_list enumtype="arabic" prefix="" start="2" suffix=".">
+ <list_item>
+ <paragraph>
+ List starts at 2.
+ <list_item>
+ <paragraph>
+ Class should apply to next paragraph, not to system message.
+ <system_message level="1" line="1" source="test data" type="INFO">
+ <paragraph>
+ Enumerated list start value not ordinal-1: "2" (ordinal 2)
+ <paragraph classes="fancy">
+ A paragraph.
+"""],
+])
+
+
+if __name__ == '__main__':
+ import unittest
+ unittest.main(defaultTest='suite')
--- /dev/null
+#! /usr/bin/env python
+
+# $Id: test_contents.py 8356 2019-08-26 16:44:19Z milde $
+# Author: David Goodger <goodger@python.org>
+# Copyright: This module has been placed in the public domain.
+
+"""
+Tests for `docutils.transforms.parts.Contents` (via
+`docutils.transforms.universal.LastReaderPending`).
+"""
+from __future__ import absolute_import
+
+from . import DocutilsTestSupport
+from docutils.transforms.references import Substitutions
+from docutils.parsers.rst import Parser
+
+
+def suite():
+ parser = Parser()
+ s = DocutilsTestSupport.TransformTestSuite(parser)
+ s.generateTests(totest)
+ return s
+
+totest = {}
+
+totest['tables_of_contents'] = ((Substitutions,), [
+["""\
+.. contents::
+
+Title 1
+=======
+Paragraph 1.
+
+Title_ 2
+--------
+Paragraph 2.
+
+_`Title` 3
+``````````
+Paragraph 3.
+
+Title 4
+-------
+Paragraph 4.
+""",
+"""\
+<document source="test data">
+ <topic classes="contents" ids="contents" names="contents">
+ <title>
+ Contents
+ <bullet_list>
+ <list_item>
+ <paragraph>
+ <reference ids="id1" refid="title-1">
+ Title 1
+ <bullet_list>
+ <list_item>
+ <paragraph>
+ <reference ids="id2" refid="title-2">
+ Title
+ 2
+ <bullet_list>
+ <list_item>
+ <paragraph>
+ <reference ids="id3" refid="title-3">
+ Title
+ 3
+ <list_item>
+ <paragraph>
+ <reference ids="id4" refid="title-4">
+ Title 4
+ <section ids="title-1" names="title\\ 1">
+ <title refid="id1">
+ Title 1
+ <paragraph>
+ Paragraph 1.
+ <section ids="title-2" names="title\\ 2">
+ <title>
+ <reference name="Title" refname="title">
+ Title
+ 2
+ <paragraph>
+ Paragraph 2.
+ <section ids="title-3" names="title\\ 3">
+ <title refid="id3">
+ <target ids="title" names="title">
+ Title
+ 3
+ <paragraph>
+ Paragraph 3.
+ <section ids="title-4" names="title\\ 4">
+ <title refid="id4">
+ Title 4
+ <paragraph>
+ Paragraph 4.
+"""],
+["""\
+.. contents:: Table of Contents
+
+Title 1
+=======
+Paragraph 1.
+
+Title 2
+-------
+Paragraph 2.
+""",
+"""\
+<document source="test data">
+ <topic classes="contents" ids="table-of-contents" names="table\\ of\\ contents">
+ <title>
+ Table of Contents
+ <bullet_list>
+ <list_item>
+ <paragraph>
+ <reference ids="id1" refid="title-1">
+ Title 1
+ <bullet_list>
+ <list_item>
+ <paragraph>
+ <reference ids="id2" refid="title-2">
+ Title 2
+ <section ids="title-1" names="title\\ 1">
+ <title refid="id1">
+ Title 1
+ <paragraph>
+ Paragraph 1.
+ <section ids="title-2" names="title\\ 2">
+ <title refid="id2">
+ Title 2
+ <paragraph>
+ Paragraph 2.
+"""],
+["""\
+.. contents:: There's an image in Title 2
+
+Title 1
+=======
+Paragraph 1.
+
+|Title 2|
+=========
+Paragraph 2.
+
+.. |Title 2| image:: title2.png
+""",
+"""\
+<document source="test data">
+ <topic classes="contents" ids="there-s-an-image-in-title-2" names="there's\\ an\\ image\\ in\\ title\\ 2">
+ <title>
+ There's an image in Title 2
+ <bullet_list>
+ <list_item>
+ <paragraph>
+ <reference ids="id1" refid="title-1">
+ Title 1
+ <list_item>
+ <paragraph>
+ <reference ids="id2" refid="title-2">
+ Title 2
+ <section ids="title-1" names="title\\ 1">
+ <title refid="id1">
+ Title 1
+ <paragraph>
+ Paragraph 1.
+ <section ids="title-2" names="title\\ 2">
+ <title refid="id2">
+ <image alt="Title 2" uri="title2.png">
+ <paragraph>
+ Paragraph 2.
+ <substitution_definition names="Title\\ 2">
+ <image alt="Title 2" uri="title2.png">
+"""], # emacs cruft: "
+["""\
+.. contents::
+ :depth: 2
+
+Title 1
+=======
+Paragraph 1.
+
+Title 2
+-------
+Paragraph 2.
+
+Title 3
+```````
+Paragraph 3.
+
+Title 4
+-------
+Paragraph 4.
+""",
+"""\
+<document source="test data">
+ <topic classes="contents" ids="contents" names="contents">
+ <title>
+ Contents
+ <bullet_list>
+ <list_item>
+ <paragraph>
+ <reference ids="id1" refid="title-1">
+ Title 1
+ <bullet_list>
+ <list_item>
+ <paragraph>
+ <reference ids="id2" refid="title-2">
+ Title 2
+ <list_item>
+ <paragraph>
+ <reference ids="id3" refid="title-4">
+ Title 4
+ <section ids="title-1" names="title\\ 1">
+ <title refid="id1">
+ Title 1
+ <paragraph>
+ Paragraph 1.
+ <section ids="title-2" names="title\\ 2">
+ <title refid="id2">
+ Title 2
+ <paragraph>
+ Paragraph 2.
+ <section ids="title-3" names="title\\ 3">
+ <title>
+ Title 3
+ <paragraph>
+ Paragraph 3.
+ <section ids="title-4" names="title\\ 4">
+ <title refid="id3">
+ Title 4
+ <paragraph>
+ Paragraph 4.
+"""],
+["""\
+Title 1
+=======
+
+.. contents::
+ :local:
+
+Paragraph 1.
+
+Title 2
+-------
+Paragraph 2.
+
+Title 3
+```````
+Paragraph 3.
+
+Title 4
+-------
+Paragraph 4.
+""",
+"""\
+<document source="test data">
+ <section ids="title-1" names="title\\ 1">
+ <title>
+ Title 1
+ <topic classes="contents local" ids="contents" names="contents">
+ <bullet_list>
+ <list_item>
+ <paragraph>
+ <reference ids="id1" refid="title-2">
+ Title 2
+ <bullet_list>
+ <list_item>
+ <paragraph>
+ <reference ids="id2" refid="title-3">
+ Title 3
+ <list_item>
+ <paragraph>
+ <reference ids="id3" refid="title-4">
+ Title 4
+ <paragraph>
+ Paragraph 1.
+ <section ids="title-2" names="title\\ 2">
+ <title refid="id1">
+ Title 2
+ <paragraph>
+ Paragraph 2.
+ <section ids="title-3" names="title\\ 3">
+ <title refid="id2">
+ Title 3
+ <paragraph>
+ Paragraph 3.
+ <section ids="title-4" names="title\\ 4">
+ <title refid="id3">
+ Title 4
+ <paragraph>
+ Paragraph 4.
+"""],
+["""\
+.. contents::
+ :local:
+
+Test duplicate name "Contents".
+
+Section
+--------
+Paragraph.
+""",
+"""\
+<document source="test data">
+ <topic classes="contents local" ids="contents" names="contents">
+ <bullet_list>
+ <list_item>
+ <paragraph>
+ <reference ids="id1" refid="section">
+ Section
+ <paragraph>
+ Test duplicate name "Contents".
+ <section ids="section" names="section">
+ <title refid="id1">
+ Section
+ <paragraph>
+ Paragraph.
+"""],
+["""\
+.. contents::
+ :backlinks: top
+
+Section
+--------
+Paragraph.
+""",
+"""\
+<document source="test data">
+ <topic classes="contents" ids="contents" names="contents">
+ <title>
+ Contents
+ <bullet_list>
+ <list_item>
+ <paragraph>
+ <reference ids="id1" refid="section">
+ Section
+ <section ids="section" names="section">
+ <title refid="contents">
+ Section
+ <paragraph>
+ Paragraph.
+"""],
+["""\
+.. contents::
+ :backlinks: none
+
+Section
+--------
+Paragraph.
+""",
+"""\
+<document source="test data">
+ <topic classes="contents" ids="contents" names="contents">
+ <title>
+ Contents
+ <bullet_list>
+ <list_item>
+ <paragraph>
+ <reference ids="id1" refid="section">
+ Section
+ <section ids="section" names="section">
+ <title>
+ Section
+ <paragraph>
+ Paragraph.
+"""],
+["""\
+.. contents::
+
+Degenerate case, no table of contents generated.
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ Degenerate case, no table of contents generated.
+"""],
+["""\
+Title 1
+=======
+
+Paragraph 1.
+
+.. sidebar:: Contents
+
+ .. contents::
+ :local:
+
+Title 2
+-------
+Paragraph 2.
+
+Title 3
+```````
+Paragraph 3.
+""",
+"""\
+<document source="test data">
+ <section ids="title-1" names="title\\ 1">
+ <title>
+ Title 1
+ <paragraph>
+ Paragraph 1.
+ <sidebar>
+ <title>
+ Contents
+ <topic classes="contents local" ids="contents" names="contents">
+ <bullet_list>
+ <list_item>
+ <paragraph>
+ <reference ids="id1" refid="title-2">
+ Title 2
+ <bullet_list>
+ <list_item>
+ <paragraph>
+ <reference ids="id2" refid="title-3">
+ Title 3
+ <section ids="title-2" names="title\\ 2">
+ <title refid="id1">
+ Title 2
+ <paragraph>
+ Paragraph 2.
+ <section ids="title-3" names="title\\ 3">
+ <title refid="id2">
+ Title 3
+ <paragraph>
+ Paragraph 3.
+"""],
+])
+
+
+if __name__ == '__main__':
+ import unittest
+ unittest.main(defaultTest='suite')
--- /dev/null
+#! /usr/bin/env python
+# -*- coding: utf-8 -*-
+
+# $Id: test_docinfo.py 8356 2019-08-26 16:44:19Z milde $
+# Author: David Goodger <goodger@python.org>
+# Copyright: This module has been placed in the public domain.
+
+"""
+Tests for docutils.transforms.frontmatter.DocInfo.
+"""
+from __future__ import absolute_import
+
+from . import DocutilsTestSupport
+from docutils.transforms.frontmatter import DocInfo
+from docutils.parsers.rst import Parser
+
+
+def suite():
+ parser = Parser()
+ settings = {'language_code': 'en'}
+ s = DocutilsTestSupport.TransformTestSuite(
+ parser, suite_settings=settings)
+ s.generateTests(totest)
+ settings['language_code'] = 'de'
+ s.generateTests(totest_de)
+ settings['language_code'] = 'ru'
+ s.generateTests(totest_ru)
+ return s
+
+totest = {}
+totest_de = {}
+totest_ru = {}
+
+totest['bibliographic_field_lists'] = ((DocInfo,), [
+["""\
+.. Bibliographic element extraction.
+
+:Abstract:
+ There can only be one abstract.
+
+ It is automatically moved to the end of the other bibliographic elements.
+
+:Author: Me
+:Version: 1
+:Date: 2001-08-11
+:Parameter i: integer
+""",
+"""\
+<document source="test data">
+ <docinfo>
+ <author>
+ Me
+ <version>
+ 1
+ <date>
+ 2001-08-11
+ <field classes="parameter-i">
+ <field_name>
+ Parameter i
+ <field_body>
+ <paragraph>
+ integer
+ <topic classes="abstract">
+ <title>
+ Abstract
+ <paragraph>
+ There can only be one abstract.
+ <paragraph>
+ It is automatically moved to the end of the other bibliographic elements.
+ <comment xml:space="preserve">
+ Bibliographic element extraction.
+"""],
+["""\
+.. Bibliographic element extraction.
+
+:Abstract: Abstract 1.
+:Author: Me
+:Address: 123 My Street
+ Example, EX
+:Contact: me@my.org
+:Version: 1
+:Abstract: Abstract 2 (should generate a warning).
+:Date: 2001-08-11
+:Parameter i: integer
+""",
+"""\
+<document source="test data">
+ <docinfo>
+ <author>
+ Me
+ <address xml:space="preserve">
+ 123 My Street
+ Example, EX
+ <contact>
+ <reference refuri="mailto:me@my.org">
+ me@my.org
+ <version>
+ 1
+ <field classes="abstract">
+ <field_name>
+ Abstract
+ <field_body>
+ <paragraph>
+ Abstract 2 (should generate a warning).
+ <system_message level="2" line="9" source="test data" type="WARNING">
+ <paragraph>
+ There can only be one "Abstract" field.
+ <date>
+ 2001-08-11
+ <field classes="parameter-i">
+ <field_name>
+ Parameter i
+ <field_body>
+ <paragraph>
+ integer
+ <topic classes="abstract">
+ <title>
+ Abstract
+ <paragraph>
+ Abstract 1.
+ <comment xml:space="preserve">
+ Bibliographic element extraction.
+"""],
+["""\
+:Author: - must be a paragraph
+:Status: a *simple* paragraph
+:Date: But only one
+
+ paragraph.
+:Version:
+
+.. and not empty either
+""",
+"""\
+<document source="test data">
+ <docinfo>
+ <field classes="author">
+ <field_name>
+ Author
+ <field_body>
+ <bullet_list bullet="-">
+ <list_item>
+ <paragraph>
+ must be a paragraph
+ <system_message level="2" line="1" source="test data" type="WARNING">
+ <paragraph>
+ Cannot extract bibliographic field "Author" containing anything other than a single paragraph.
+ <status>
+ a \n\
+ <emphasis>
+ simple
+ paragraph
+ <field classes="date">
+ <field_name>
+ Date
+ <field_body>
+ <paragraph>
+ But only one
+ <paragraph>
+ paragraph.
+ <system_message level="2" line="3" source="test data" type="WARNING">
+ <paragraph>
+ Cannot extract compound bibliographic field "Date".
+ <field classes="version">
+ <field_name>
+ Version
+ <field_body>
+ <system_message level="2" line="6" source="test data" type="WARNING">
+ <paragraph>
+ Cannot extract empty bibliographic field "Version".
+ <comment xml:space="preserve">
+ and not empty either
+"""],
+["""\
+:Authors: Me, Myself, **I**
+:Authors: PacMan; Ms. PacMan; PacMan, Jr.
+:Authors:
+ Here
+
+ There
+
+ *Everywhere*
+:Authors: - First
+ - Second
+ - Third
+""",
+"""\
+<document source="test data">
+ <docinfo>
+ <authors>
+ <author>
+ Me
+ <author>
+ Myself
+ <author>
+ I
+ <authors>
+ <author>
+ PacMan
+ <author>
+ Ms. PacMan
+ <author>
+ PacMan, Jr.
+ <authors>
+ <author>
+ Here
+ <author>
+ There
+ <author>
+ <emphasis>
+ Everywhere
+ <authors>
+ <author>
+ First
+ <author>
+ Second
+ <author>
+ Third
+"""],
+["""\
+:Authors: Only One
+:Authors: One, Only;
+""",
+"""\
+<document source="test data">
+ <docinfo>
+ <authors>
+ <author>
+ Only One
+ <authors>
+ <author>
+ One, Only
+"""],
+[r""":Authors: Me\, Myself; **I**
+:Authors: Pac\;Man\\; Ms. Pac\Man; Pac\ Man, Jr.
+:Authors:
+ Here
+
+ The\re
+
+ *Every\ where*
+:Authors: - First\\
+ - Se\ cond
+ - Thir\d
+""",
+"""\
+<document source="test data">
+ <docinfo>
+ <authors>
+ <author>
+ Me, Myself
+ <author>
+ I
+ <authors>
+ <author>
+ Pac;Man\\
+ <author>
+ Ms. PacMan
+ <author>
+ PacMan, Jr.
+ <authors>
+ <author>
+ Here
+ <author>
+ There
+ <author>
+ <emphasis>
+ Everywhere
+ <authors>
+ <author>
+ First\\
+ <author>
+ Second
+ <author>
+ Third
+"""],
+["""\
+:Authors:
+
+:Authors: A. Einstein
+ B. Shaw
+
+:Authors:
+ -
+ -
+
+:Authors:
+ - One
+
+ Two
+
+:Authors:
+ - One
+
+ Two
+""",
+"""\
+<document source="test data">
+ <docinfo>
+ <field classes="authors">
+ <field_name>
+ Authors
+ <field_body>
+ <system_message level="2" line="1" source="test data" type="WARNING">
+ <paragraph>
+ Cannot extract empty bibliographic field "Authors".
+ <field classes="authors">
+ <field_name>
+ Authors
+ <field_body>
+ <enumerated_list enumtype="upperalpha" prefix="" suffix=".">
+ <list_item>
+ <paragraph>
+ Einstein
+ <list_item>
+ <paragraph>
+ Shaw
+ <system_message level="2" line="3" source="test data" type="WARNING">
+ <paragraph>
+ Bibliographic field "Authors" incompatible with extraction: it must contain either a single paragraph (with authors separated by one of ";,"), multiple paragraphs (one per author), or a bullet list with one paragraph (one author) per item.
+ <field classes="authors">
+ <field_name>
+ Authors
+ <field_body>
+ <bullet_list bullet="-">
+ <list_item>
+ <list_item>
+ <system_message level="2" line="6" source="test data" type="WARNING">
+ <paragraph>
+ Bibliographic field "Authors" incompatible with extraction: it must contain either a single paragraph (with authors separated by one of ";,"), multiple paragraphs (one per author), or a bullet list with one paragraph (one author) per item.
+ <field classes="authors">
+ <field_name>
+ Authors
+ <field_body>
+ <bullet_list bullet="-">
+ <list_item>
+ <paragraph>
+ One
+ <paragraph>
+ Two
+ <system_message level="2" line="10" source="test data" type="WARNING">
+ <paragraph>
+ Bibliographic field "Authors" incompatible with extraction: it must contain either a single paragraph (with authors separated by one of ";,"), multiple paragraphs (one per author), or a bullet list with one paragraph (one author) per item.
+ <field classes="authors">
+ <field_name>
+ Authors
+ <field_body>
+ <bullet_list bullet="-">
+ <list_item>
+ <paragraph>
+ One
+ <paragraph>
+ Two
+ <system_message level="2" line="15" source="test data" type="WARNING">
+ <paragraph>
+ Bibliographic field "Authors" incompatible with extraction: it must contain either a single paragraph (with authors separated by one of ";,"), multiple paragraphs (one per author), or a bullet list with one paragraph (one author) per item.
+"""],
+["""\
+.. RCS keyword extraction.
+
+:Status: (some text) $""" + """RCSfile: test_docinfo.py,v $ (more text)
+:Date: (some text) $""" + """Date: 2002/10/08 01:34:23 $ (more text)
+:Date: (some text) $""" + """Date: 2005-03-26T16:21:28.693201Z $ (more text)
+:Version: (some text) $""" + """Revision: 1.1 $ (more text)
+""",
+"""\
+<document source="test data">
+ <docinfo>
+ <status>
+ (some text) test_docinfo.py (more text)
+ <date>
+ (some text) 2002-10-08 (more text)
+ <date>
+ (some text) 2005-03-26 (more text)
+ <version>
+ (some text) 1.1 (more text)
+ <comment xml:space="preserve">
+ RCS keyword extraction.
+"""],
+])
+
+totest_de['bibliographic_field_lists'] = ((DocInfo,), [
+[u"""\
+.. Bibliographic element extraction for a German document.
+
+:Zusammenfassung: Abstract 1.
+:Autor: Me
+:Adresse: 123 My Street
+ Example, EX
+:Kontakt: me@my.org
+:Version: 1
+:Datum: 2001-08-11
+:Parameter i: integer
+""",
+u"""\
+<document source="test data">
+ <docinfo>
+ <author>
+ Me
+ <address xml:space="preserve">
+ 123 My Street
+ Example, EX
+ <contact>
+ <reference refuri="mailto:me@my.org">
+ me@my.org
+ <version>
+ 1
+ <date>
+ 2001-08-11
+ <field classes="parameter-i">
+ <field_name>
+ Parameter i
+ <field_body>
+ <paragraph>
+ integer
+ <topic classes="abstract">
+ <title>
+ Zusammenfassung
+ <paragraph>
+ Abstract 1.
+ <comment xml:space="preserve">
+ Bibliographic element extraction for a German document.
+"""],])
+
+totest_ru['bibliographic_field_lists'] = ((DocInfo,), [
+[u"""\
+.. Bibliographic element extraction for a Russian document.
+
+:аннотация: Abstract 1.
+:автор: Me
+:адрес: 123 My Street
+ Example, EX
+:контакт: me@my.org
+:версия: 1
+:дата: 2001-08-11
+:Parameter i: integer
+""",
+u"""\
+<document source="test data">
+ <docinfo>
+ <author>
+ Me
+ <address xml:space="preserve">
+ 123 My Street
+ Example, EX
+ <contact>
+ <reference refuri="mailto:me@my.org">
+ me@my.org
+ <version>
+ 1
+ <date>
+ 2001-08-11
+ <field classes="parameter-i">
+ <field_name>
+ Parameter i
+ <field_body>
+ <paragraph>
+ integer
+ <topic classes="abstract">
+ <title>
+ Аннотация
+ <paragraph>
+ Abstract 1.
+ <comment xml:space="preserve">
+ Bibliographic element extraction for a Russian document.
+"""],])
+
+
+if __name__ == '__main__':
+ import unittest
+ unittest.main(defaultTest='suite')
--- /dev/null
+#! /usr/bin/env python
+
+# $Id: test_doctitle.py 8356 2019-08-26 16:44:19Z milde $
+# Author: David Goodger <goodger@python.org>
+# Copyright: This module has been placed in the public domain.
+
+"""
+Tests for docutils.transforms.frontmatter.DocTitle.
+"""
+from __future__ import absolute_import
+
+from . import DocutilsTestSupport
+from docutils.transforms.frontmatter import DocTitle, SectionSubTitle
+from docutils.parsers.rst import Parser, Directive
+from docutils.parsers.rst.directives import register_directive
+
+
+# dummy directive to test attribute merging:
+class AddNameToDocumentTitle(Directive):
+ required_arguments = 0
+ optional_arguments = 0
+ final_argument_whitespace = True
+ option_spec = { }
+ has_content = False
+
+ def run(self):
+ document = self.state_machine.document
+ document['names'].append('Name')
+ return []
+
+register_directive('add-name-to-title', AddNameToDocumentTitle)
+
+def suite():
+ parser = Parser()
+ s = DocutilsTestSupport.TransformTestSuite(parser)
+ s.generateTests(totest)
+ return s
+
+totest = {}
+
+totest['section_headers'] = ((DocTitle, SectionSubTitle), [
+["""\
+.. test title promotion
+
+Title
+=====
+
+Paragraph.
+""",
+"""\
+<document ids="title" names="title" source="test data" title="Title">
+ <title>
+ Title
+ <comment xml:space="preserve">
+ test title promotion
+ <paragraph>
+ Paragraph.
+"""],
+["""\
+Title
+=====
+Paragraph (no blank line).
+""",
+"""\
+<document ids="title" names="title" source="test data" title="Title">
+ <title>
+ Title
+ <paragraph>
+ Paragraph (no blank line).
+"""],
+["""\
+Paragraph.
+
+Title
+=====
+
+Paragraph.
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ Paragraph.
+ <section ids="title" names="title">
+ <title>
+ Title
+ <paragraph>
+ Paragraph.
+"""],
+["""\
+Title
+=====
+
+Subtitle
+--------
+
+.. title:: Another Title
+
+Test title, subtitle, and title metadata.
+""",
+"""\
+<document ids="title" names="title" source="test data" title="Another Title">
+ <title>
+ Title
+ <subtitle ids="subtitle" names="subtitle">
+ Subtitle
+ <paragraph>
+ Test title, subtitle, and title metadata.
+"""],
+["""\
+Title
+====
+
+Test short underline.
+""",
+"""\
+<document ids="title" names="title" source="test data" title="Title">
+ <title>
+ Title
+ <system_message level="2" line="2" source="test data" type="WARNING">
+ <paragraph>
+ Title underline too short.
+ <literal_block xml:space="preserve">
+ Title
+ ====
+ <paragraph>
+ Test short underline.
+"""],
+["""\
+=======
+ Long Title
+=======
+
+Test long title and space normalization.
+The system_message should move after the document title
+(it was before the beginning of the section).
+""",
+"""\
+<document ids="long-title" names="long\\ title" source="test data" title="Long Title">
+ <title>
+ Long Title
+ <system_message level="2" line="1" source="test data" type="WARNING">
+ <paragraph>
+ Title overline too short.
+ <literal_block xml:space="preserve">
+ =======
+ Long Title
+ =======
+ <paragraph>
+ Test long title and space normalization.
+ The system_message should move after the document title
+ (it was before the beginning of the section).
+"""],
+["""\
+.. Test multiple second-level titles.
+
+Title 1
+=======
+Paragraph 1.
+
+Title 2
+-------
+Paragraph 2.
+
+Title 3
+-------
+Paragraph 3.
+""",
+"""\
+<document ids="title-1" names="title\\ 1" source="test data" title="Title 1">
+ <title>
+ Title 1
+ <comment xml:space="preserve">
+ Test multiple second-level titles.
+ <paragraph>
+ Paragraph 1.
+ <section ids="title-2" names="title\\ 2">
+ <title>
+ Title 2
+ <paragraph>
+ Paragraph 2.
+ <section ids="title-3" names="title\\ 3">
+ <title>
+ Title 3
+ <paragraph>
+ Paragraph 3.
+"""],
+["""\
+.. |foo| replace:: bar
+
+.. _invisible target:
+
+Title
+=====
+This title should be the document title despite the
+substitution_definition.
+""",
+"""\
+<document ids="title" names="title" source="test data" title="Title">
+ <title>
+ Title
+ <substitution_definition names="foo">
+ bar
+ <target ids="invisible-target" names="invisible\\ target">
+ <paragraph>
+ This title should be the document title despite the
+ substitution_definition.
+"""],
+["""\
+(Because of this paragraph, the following is not a doc title.)
+
+===============
+ Section Title
+===============
+
+Subtitle
+========
+
+-----------------
+ Another Section
+-----------------
+
+Another Subtitle
+----------------
+
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ (Because of this paragraph, the following is not a doc title.)
+ <section ids="section-title" names="section\\ title">
+ <title>
+ Section Title
+ <subtitle ids="subtitle" names="subtitle">
+ Subtitle
+ <section ids="another-section" names="another\\ section">
+ <title>
+ Another Section
+ <subtitle ids="another-subtitle" names="another\\ subtitle">
+ Another Subtitle
+"""],
+["""\
+-----
+Title
+-----
+
+This is a document, it flows nicely, so the attributes of it are at the
+bottom.
+
+.. add-name-to-title::
+
+""",
+"""\
+<document ids="title" names="Name title" source="test data" title="Title">
+ <title>
+ Title
+ <paragraph>
+ This is a document, it flows nicely, so the attributes of it are at the
+ bottom.
+"""]
+])
+
+
+if __name__ == '__main__':
+ import unittest
+ unittest.main(defaultTest='suite')
--- /dev/null
+#! /usr/bin/env python
+
+# $Id: test_expose_internals.py 8356 2019-08-26 16:44:19Z milde $
+# Author: Lea Wiemann <LeWiemann@gmail.com>
+# Copyright: This module has been placed in the public domain.
+
+"""
+Test module for universal.ExposeInternals transform.
+"""
+from __future__ import absolute_import
+
+
+from . import DocutilsTestSupport # must be imported before docutils
+from docutils.transforms.universal import ExposeInternals
+from docutils.parsers.rst import Parser
+
+
+def suite():
+ parser = Parser()
+ s = DocutilsTestSupport.TransformTestSuite(
+ parser, suite_settings={'expose_internals': ['rawsource', 'source']})
+ s.generateTests(totest)
+ return s
+
+
+totest = {}
+
+totest['transitions'] = ((ExposeInternals,), [
+["""\
+This is a test.
+""",
+"""\
+<document internal:rawsource="" source="test data">
+ <paragraph internal:rawsource="This is a test." internal:source="test data">
+ This is a test.
+"""],
+])
+
+
+if __name__ == '__main__':
+ import unittest
+ unittest.main(defaultTest='suite')
--- /dev/null
+#! /usr/bin/env python
+
+# $Id: test_filter.py 8356 2019-08-26 16:44:19Z milde $
+# Author: David Goodger <goodger@python.org>
+# Copyright: This module has been placed in the public domain.
+
+"""
+Tests for docutils.transforms.components.Filter.
+"""
+from __future__ import absolute_import
+
+from . import DocutilsTestSupport
+from docutils.parsers.rst import Parser
+
+
+def suite():
+ parser = Parser()
+ s = DocutilsTestSupport.TransformTestSuite(parser)
+ s.generateTests(totest)
+ return s
+
+totest = {}
+
+totest['meta'] = ((), [
+["""\
+.. meta::
+ :description: The reStructuredText plaintext markup language
+ :keywords: plaintext,markup language
+""",
+"""\
+<document source="test data">
+ <meta content="The reStructuredText plaintext markup language" name="description">
+ <meta content="plaintext,markup language" name="keywords">
+"""],
+])
+
+
+if __name__ == '__main__':
+ import unittest
+ unittest.main(defaultTest='suite')
--- /dev/null
+#! /usr/bin/env python
+
+# $Id: test_footnotes.py 8356 2019-08-26 16:44:19Z milde $
+# Author: David Goodger <goodger@python.org>
+# Copyright: This module has been placed in the public domain.
+
+"""
+Tests for docutils.transforms.references.Footnotes.
+"""
+from __future__ import absolute_import
+
+from . import DocutilsTestSupport
+from docutils.transforms.references import Footnotes
+from docutils.parsers.rst import Parser
+
+
+def suite():
+ parser = Parser()
+ s = DocutilsTestSupport.TransformTestSuite(parser)
+ s.generateTests(totest)
+ return s
+
+totest = {}
+
+totest['footnotes'] = ((Footnotes,), [
+["""\
+[#autolabel]_
+
+.. [#autolabel] text
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ <footnote_reference auto="1" ids="id1" refid="autolabel">
+ 1
+ <footnote auto="1" backrefs="id1" ids="autolabel" names="autolabel">
+ <label>
+ 1
+ <paragraph>
+ text
+"""],
+["""\
+autonumber: [#]_
+
+.. [#] text
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ autonumber: \n\
+ <footnote_reference auto="1" ids="id1" refid="id2">
+ 1
+ <footnote auto="1" backrefs="id1" ids="id2" names="1">
+ <label>
+ 1
+ <paragraph>
+ text
+"""],
+["""\
+[#]_ is the first auto-numbered footnote reference.
+[#]_ is the second auto-numbered footnote reference.
+
+.. [#] Auto-numbered footnote 1.
+.. [#] Auto-numbered footnote 2.
+.. [#] Auto-numbered footnote 3.
+
+[#]_ is the third auto-numbered footnote reference.
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ <footnote_reference auto="1" ids="id1" refid="id3">
+ 1
+ is the first auto-numbered footnote reference.
+ <footnote_reference auto="1" ids="id2" refid="id4">
+ 2
+ is the second auto-numbered footnote reference.
+ <footnote auto="1" backrefs="id1" ids="id3" names="1">
+ <label>
+ 1
+ <paragraph>
+ Auto-numbered footnote 1.
+ <footnote auto="1" backrefs="id2" ids="id4" names="2">
+ <label>
+ 2
+ <paragraph>
+ Auto-numbered footnote 2.
+ <footnote auto="1" backrefs="id6" ids="id5" names="3">
+ <label>
+ 3
+ <paragraph>
+ Auto-numbered footnote 3.
+ <paragraph>
+ <footnote_reference auto="1" ids="id6" refid="id5">
+ 3
+ is the third auto-numbered footnote reference.
+"""],
+["""\
+[#third]_ is a reference to the third auto-numbered footnote.
+
+.. [#first] First auto-numbered footnote.
+.. [#second] Second auto-numbered footnote.
+.. [#third] Third auto-numbered footnote.
+
+[#second]_ is a reference to the second auto-numbered footnote.
+[#first]_ is a reference to the first auto-numbered footnote.
+[#third]_ is another reference to the third auto-numbered footnote.
+
+Here are some internal cross-references to the implicit targets
+generated by the footnotes: first_, second_, third_.
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ <footnote_reference auto="1" ids="id1" refid="third">
+ 3
+ is a reference to the third auto-numbered footnote.
+ <footnote auto="1" backrefs="id3" ids="first" names="first">
+ <label>
+ 1
+ <paragraph>
+ First auto-numbered footnote.
+ <footnote auto="1" backrefs="id2" ids="second" names="second">
+ <label>
+ 2
+ <paragraph>
+ Second auto-numbered footnote.
+ <footnote auto="1" backrefs="id1 id4" ids="third" names="third">
+ <label>
+ 3
+ <paragraph>
+ Third auto-numbered footnote.
+ <paragraph>
+ <footnote_reference auto="1" ids="id2" refid="second">
+ 2
+ is a reference to the second auto-numbered footnote.
+ <footnote_reference auto="1" ids="id3" refid="first">
+ 1
+ is a reference to the first auto-numbered footnote.
+ <footnote_reference auto="1" ids="id4" refid="third">
+ 3
+ is another reference to the third auto-numbered footnote.
+ <paragraph>
+ Here are some internal cross-references to the implicit targets
+ generated by the footnotes: \n\
+ <reference name="first" refname="first">
+ first
+ , \n\
+ <reference name="second" refname="second">
+ second
+ , \n\
+ <reference name="third" refname="third">
+ third
+ .
+"""],
+["""\
+Mixed anonymous and labelled auto-numbered footnotes:
+
+[#four]_ should be 4, [#]_ should be 1,
+[#]_ should be 3, [#]_ is one too many,
+[#two]_ should be 2, and [#six]_ doesn't exist.
+
+.. [#] Auto-numbered footnote 1.
+.. [#two] Auto-numbered footnote 2.
+.. [#] Auto-numbered footnote 3.
+.. [#four] Auto-numbered footnote 4.
+.. [#five] Auto-numbered footnote 5.
+.. [#five] Auto-numbered footnote 5 again (duplicate).
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ Mixed anonymous and labelled auto-numbered footnotes:
+ <paragraph>
+ <footnote_reference auto="1" ids="id1" refid="four">
+ 4
+ should be 4, \n\
+ <footnote_reference auto="1" ids="id2" refid="id7">
+ 1
+ should be 1,
+ <footnote_reference auto="1" ids="id3" refid="id8">
+ 3
+ should be 3, \n\
+ <problematic ids="id11 id4" refid="id10">
+ [#]_
+ is one too many,
+ <footnote_reference auto="1" ids="id5" refid="two">
+ 2
+ should be 2, and \n\
+ <footnote_reference auto="1" ids="id6" refname="six">
+ doesn't exist.
+ <footnote auto="1" backrefs="id2" ids="id7" names="1">
+ <label>
+ 1
+ <paragraph>
+ Auto-numbered footnote 1.
+ <footnote auto="1" backrefs="id5" ids="two" names="two">
+ <label>
+ 2
+ <paragraph>
+ Auto-numbered footnote 2.
+ <footnote auto="1" backrefs="id3" ids="id8" names="3">
+ <label>
+ 3
+ <paragraph>
+ Auto-numbered footnote 3.
+ <footnote auto="1" backrefs="id1" ids="four" names="four">
+ <label>
+ 4
+ <paragraph>
+ Auto-numbered footnote 4.
+ <footnote auto="1" dupnames="five" ids="five">
+ <label>
+ 5
+ <paragraph>
+ Auto-numbered footnote 5.
+ <footnote auto="1" dupnames="five" ids="id9">
+ <label>
+ 6
+ <system_message backrefs="id9" level="2" line="12" source="test data" type="WARNING">
+ <paragraph>
+ Duplicate explicit target name: "five".
+ <paragraph>
+ Auto-numbered footnote 5 again (duplicate).
+ <system_message backrefs="id11" ids="id10" level="3" line="3" source="test data" type="ERROR">
+ <paragraph>
+ Too many autonumbered footnote references: only 2 corresponding footnotes available.
+"""],
+["""\
+Mixed auto-numbered and manual footnotes:
+
+.. [1] manually numbered
+.. [#] auto-numbered
+.. [#label] autonumber-labeled
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ Mixed auto-numbered and manual footnotes:
+ <footnote ids="id1" names="1">
+ <label>
+ 1
+ <paragraph>
+ manually numbered
+ <footnote auto="1" ids="id2" names="2">
+ <label>
+ 2
+ <paragraph>
+ auto-numbered
+ <footnote auto="1" ids="label" names="label">
+ <label>
+ 3
+ <paragraph>
+ autonumber-labeled
+"""],
+["""\
+A labeled autonumbered footnote referece: [#footnote]_.
+
+An unlabeled autonumbered footnote referece: [#]_.
+
+.. [#] Unlabeled autonumbered footnote.
+.. [#footnote] Labeled autonumbered footnote.
+ Note that the footnotes are not in the same
+ order as the references.
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ A labeled autonumbered footnote referece: \n\
+ <footnote_reference auto="1" ids="id1" refid="footnote">
+ 2
+ .
+ <paragraph>
+ An unlabeled autonumbered footnote referece: \n\
+ <footnote_reference auto="1" ids="id2" refid="id3">
+ 1
+ .
+ <footnote auto="1" backrefs="id2" ids="id3" names="1">
+ <label>
+ 1
+ <paragraph>
+ Unlabeled autonumbered footnote.
+ <footnote auto="1" backrefs="id1" ids="footnote" names="footnote">
+ <label>
+ 2
+ <paragraph>
+ Labeled autonumbered footnote.
+ Note that the footnotes are not in the same
+ order as the references.
+"""],
+["""\
+Mixed manually-numbered, anonymous auto-numbered,
+and labelled auto-numbered footnotes:
+
+[#four]_ should be 4, [#]_ should be 2,
+[1]_ is 1, [3]_ is 3,
+[#]_ should be 6, [#]_ is one too many,
+[#five]_ should be 5, and [#eight]_ doesn't exist.
+
+.. [1] Manually-numbered footnote 1.
+.. [#] Auto-numbered footnote 2.
+.. [#four] Auto-numbered footnote 4.
+.. [3] Manually-numbered footnote 3
+.. [#five] Auto-numbered footnote 5.
+.. [#] Auto-numbered footnote 6.
+.. [#five] Auto-numbered footnote 5 again (duplicate).
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ Mixed manually-numbered, anonymous auto-numbered,
+ and labelled auto-numbered footnotes:
+ <paragraph>
+ <footnote_reference auto="1" ids="id1" refid="four">
+ 4
+ should be 4, \n\
+ <footnote_reference auto="1" ids="id2" refid="id10">
+ 2
+ should be 2,
+ <footnote_reference ids="id3" refid="id9">
+ 1
+ is 1, \n\
+ <footnote_reference ids="id4" refid="id11">
+ 3
+ is 3,
+ <footnote_reference auto="1" ids="id5" refid="id12">
+ 6
+ should be 6, \n\
+ <problematic ids="id15 id6" refid="id14">
+ [#]_
+ is one too many,
+ <footnote_reference auto="1" ids="id7" refname="five">
+ should be 5, and \n\
+ <footnote_reference auto="1" ids="id8" refname="eight">
+ doesn't exist.
+ <footnote backrefs="id3" ids="id9" names="1">
+ <label>
+ 1
+ <paragraph>
+ Manually-numbered footnote 1.
+ <footnote auto="1" backrefs="id2" ids="id10" names="2">
+ <label>
+ 2
+ <paragraph>
+ Auto-numbered footnote 2.
+ <footnote auto="1" backrefs="id1" ids="four" names="four">
+ <label>
+ 4
+ <paragraph>
+ Auto-numbered footnote 4.
+ <footnote backrefs="id4" ids="id11" names="3">
+ <label>
+ 3
+ <paragraph>
+ Manually-numbered footnote 3
+ <footnote auto="1" dupnames="five" ids="five">
+ <label>
+ 5
+ <paragraph>
+ Auto-numbered footnote 5.
+ <footnote auto="1" backrefs="id5" ids="id12" names="6">
+ <label>
+ 6
+ <paragraph>
+ Auto-numbered footnote 6.
+ <footnote auto="1" dupnames="five" ids="id13">
+ <label>
+ 7
+ <system_message backrefs="id13" level="2" line="15" source="test data" type="WARNING">
+ <paragraph>
+ Duplicate explicit target name: "five".
+ <paragraph>
+ Auto-numbered footnote 5 again (duplicate).
+ <system_message backrefs="id15" ids="id14" level="3" line="4" source="test data" type="ERROR">
+ <paragraph>
+ Too many autonumbered footnote references: only 2 corresponding footnotes available.
+"""],
+["""\
+Referencing a footnote by symbol [*]_.
+
+.. [*] This is an auto-symbol footnote.
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ Referencing a footnote by symbol \n\
+ <footnote_reference auto="*" ids="id1" refid="id2">
+ *
+ .
+ <footnote auto="*" backrefs="id1" ids="id2">
+ <label>
+ *
+ <paragraph>
+ This is an auto-symbol footnote.
+"""],
+["""\
+A sequence of symbol footnote references:
+[*]_ [*]_ [*]_ [*]_ [*]_ [*]_ [*]_ [*]_ [*]_ [*]_ [*]_ [*]_.
+
+.. [*] Auto-symbol footnote 1.
+.. [*] Auto-symbol footnote 2.
+.. [*] Auto-symbol footnote 3.
+.. [*] Auto-symbol footnote 4.
+.. [*] Auto-symbol footnote 5.
+.. [*] Auto-symbol footnote 6.
+.. [*] Auto-symbol footnote 7.
+.. [*] Auto-symbol footnote 8.
+.. [*] Auto-symbol footnote 9.
+.. [*] Auto-symbol footnote 10.
+.. [*] Auto-symbol footnote 11.
+.. [*] Auto-symbol footnote 12.
+""",
+u"""\
+<document source="test data">
+ <paragraph>
+ A sequence of symbol footnote references:
+ <footnote_reference auto="*" ids="id1" refid="id13">
+ *
+ \n\
+ <footnote_reference auto="*" ids="id2" refid="id14">
+ \u2020
+ \n\
+ <footnote_reference auto="*" ids="id3" refid="id15">
+ \u2021
+ \n\
+ <footnote_reference auto="*" ids="id4" refid="id16">
+ \u00A7
+ \n\
+ <footnote_reference auto="*" ids="id5" refid="id17">
+ \u00B6
+ \n\
+ <footnote_reference auto="*" ids="id6" refid="id18">
+ #
+ \n\
+ <footnote_reference auto="*" ids="id7" refid="id19">
+ \u2660
+ \n\
+ <footnote_reference auto="*" ids="id8" refid="id20">
+ \u2665
+ \n\
+ <footnote_reference auto="*" ids="id9" refid="id21">
+ \u2666
+ \n\
+ <footnote_reference auto="*" ids="id10" refid="id22">
+ \u2663
+ \n\
+ <footnote_reference auto="*" ids="id11" refid="id23">
+ **
+ \n\
+ <footnote_reference auto="*" ids="id12" refid="id24">
+ \u2020\u2020
+ .
+ <footnote auto="*" backrefs="id1" ids="id13">
+ <label>
+ *
+ <paragraph>
+ Auto-symbol footnote 1.
+ <footnote auto="*" backrefs="id2" ids="id14">
+ <label>
+ \u2020
+ <paragraph>
+ Auto-symbol footnote 2.
+ <footnote auto="*" backrefs="id3" ids="id15">
+ <label>
+ \u2021
+ <paragraph>
+ Auto-symbol footnote 3.
+ <footnote auto="*" backrefs="id4" ids="id16">
+ <label>
+ \u00A7
+ <paragraph>
+ Auto-symbol footnote 4.
+ <footnote auto="*" backrefs="id5" ids="id17">
+ <label>
+ \u00B6
+ <paragraph>
+ Auto-symbol footnote 5.
+ <footnote auto="*" backrefs="id6" ids="id18">
+ <label>
+ #
+ <paragraph>
+ Auto-symbol footnote 6.
+ <footnote auto="*" backrefs="id7" ids="id19">
+ <label>
+ \u2660
+ <paragraph>
+ Auto-symbol footnote 7.
+ <footnote auto="*" backrefs="id8" ids="id20">
+ <label>
+ \u2665
+ <paragraph>
+ Auto-symbol footnote 8.
+ <footnote auto="*" backrefs="id9" ids="id21">
+ <label>
+ \u2666
+ <paragraph>
+ Auto-symbol footnote 9.
+ <footnote auto="*" backrefs="id10" ids="id22">
+ <label>
+ \u2663
+ <paragraph>
+ Auto-symbol footnote 10.
+ <footnote auto="*" backrefs="id11" ids="id23">
+ <label>
+ **
+ <paragraph>
+ Auto-symbol footnote 11.
+ <footnote auto="*" backrefs="id12" ids="id24">
+ <label>
+ \u2020\u2020
+ <paragraph>
+ Auto-symbol footnote 12.
+"""],
+["""\
+Duplicate manual footnote labels:
+
+.. [1] Footnote.
+
+.. [1] Footnote.
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ Duplicate manual footnote labels:
+ <footnote dupnames="1" ids="id1">
+ <label>
+ 1
+ <paragraph>
+ Footnote.
+ <footnote dupnames="1" ids="id2">
+ <label>
+ 1
+ <system_message backrefs="id2" level="2" line="5" source="test data" type="WARNING">
+ <paragraph>
+ Duplicate explicit target name: "1".
+ <paragraph>
+ Footnote.
+"""],
+])
+
+
+if __name__ == '__main__':
+ import unittest
+ unittest.main(defaultTest='suite')
--- /dev/null
+#! /usr/bin/env python
+
+# $Id: test_hyperlinks.py 8356 2019-08-26 16:44:19Z milde $
+# Author: David Goodger <goodger@python.org>
+# Copyright: This module has been placed in the public domain.
+
+"""
+Tests for docutils.transforms.references.Hyperlinks.
+"""
+from __future__ import absolute_import
+
+from . import DocutilsTestSupport
+from docutils.transforms.references import PropagateTargets, \
+ AnonymousHyperlinks, IndirectHyperlinks, ExternalTargets, \
+ InternalTargets, DanglingReferences
+from docutils.parsers.rst import Parser
+
+
+def suite():
+ parser = Parser()
+ s = DocutilsTestSupport.TransformTestSuite(parser)
+ s.generateTests(totest)
+ return s
+
+totest = {}
+
+# Exhaustive listing of hyperlink variations: every combination of
+# target/reference, direct/indirect, internal/external, and named/anonymous,
+# plus embedded URIs.
+totest['exhaustive_hyperlinks'] = ((PropagateTargets, AnonymousHyperlinks,
+ IndirectHyperlinks,
+ ExternalTargets, InternalTargets,
+ DanglingReferences), [
+["""\
+direct_ external
+
+.. _direct: http://direct
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ <reference name="direct" refuri="http://direct">
+ direct
+ external
+ <target ids="direct" names="direct" refuri="http://direct">
+"""],
+["""\
+indirect_ external
+
+.. _indirect: xtarget_
+.. _xtarget: http://indirect
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ <reference name="indirect" refuri="http://indirect">
+ indirect
+ external
+ <target ids="indirect" names="indirect" refuri="http://indirect">
+ <target ids="xtarget" names="xtarget" refuri="http://indirect">
+"""],
+["""\
+.. _direct:
+
+direct_ internal
+""",
+"""\
+<document source="test data">
+ <target refid="direct">
+ <paragraph ids="direct" names="direct">
+ <reference name="direct" refid="direct">
+ direct
+ internal
+"""],
+["""\
+.. _ztarget:
+
+indirect_ internal
+
+.. _indirect2: ztarget_
+.. _indirect: indirect2_
+""",
+"""\
+<document source="test data">
+ <target refid="ztarget">
+ <paragraph ids="ztarget" names="ztarget">
+ <reference name="indirect" refid="ztarget">
+ indirect
+ internal
+ <target ids="indirect2" names="indirect2" refid="ztarget">
+ <target ids="indirect" names="indirect" refid="ztarget">
+"""],
+["""\
+Implicit
+--------
+
+indirect_ internal
+
+.. _indirect: implicit_
+""",
+"""\
+<document source="test data">
+ <section ids="implicit" names="implicit">
+ <title>
+ Implicit
+ <paragraph>
+ <reference name="indirect" refid="implicit">
+ indirect
+ internal
+ <target ids="indirect" names="indirect" refid="implicit">
+"""],
+["""\
+Implicit
+--------
+
+`multiply-indirect`_ internal
+
+.. _multiply-indirect: indirect_
+.. _indirect: implicit_
+""",
+"""\
+<document source="test data">
+ <section ids="implicit" names="implicit">
+ <title>
+ Implicit
+ <paragraph>
+ <reference name="multiply-indirect" refid="implicit">
+ multiply-indirect
+ internal
+ <target ids="multiply-indirect" names="multiply-indirect" refid="implicit">
+ <target ids="indirect" names="indirect" refid="implicit">
+"""],
+["""\
+circular_ indirect reference
+
+.. _circular: indirect_
+.. _indirect: circular_
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ <problematic ids="id2" refid="id1">
+ circular_
+ indirect reference
+ <target ids="circular" names="circular" refid="circular">
+ <problematic ids="id3 indirect" names="indirect" refid="id1">
+ .. _indirect: circular_
+ <system_message backrefs="id2 id3" ids="id1" level="3" line="3" source="test data" type="ERROR">
+ <paragraph>
+ Indirect hyperlink target "circular" (id="circular") refers to target "indirect", forming a circular reference.
+"""],
+["""\
+Implicit
+--------
+
+Duplicate implicit targets.
+
+Implicit
+--------
+
+indirect_ internal
+
+.. _indirect: implicit_
+
+Direct internal reference: Implicit_
+""",
+"""\
+<document source="test data">
+ <section dupnames="implicit" ids="implicit">
+ <title>
+ Implicit
+ <paragraph>
+ Duplicate implicit targets.
+ <section dupnames="implicit" ids="id1">
+ <title>
+ Implicit
+ <system_message backrefs="id1" level="1" line="7" source="test data" type="INFO">
+ <paragraph>
+ Duplicate implicit target name: "implicit".
+ <paragraph>
+ <problematic ids="id3" refid="id2">
+ indirect_
+ internal
+ <target ids="indirect" names="indirect" refname="implicit">
+ <paragraph>
+ Direct internal reference:
+ <problematic ids="id5" refid="id4">
+ Implicit_
+ <system_message backrefs="id3" ids="id2" level="3" line="11" source="test data" type="ERROR">
+ <paragraph>
+ Indirect hyperlink target "indirect" (id="indirect") refers to target "implicit", which is a duplicate, and cannot be used as a unique reference.
+ <system_message backrefs="id5" ids="id4" level="3" line="13" source="test data" type="ERROR">
+ <paragraph>
+ Duplicate target name, cannot be used as a unique reference: "implicit".
+"""],
+["""\
+`direct external`__
+
+__ http://direct
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ <reference anonymous="1" name="direct external" refuri="http://direct">
+ direct external
+ <target anonymous="1" ids="id1" refuri="http://direct">
+"""],
+["""\
+`indirect external`__
+
+__ xtarget_
+.. _xtarget: http://indirect
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ <reference anonymous="1" name="indirect external" refuri="http://indirect">
+ indirect external
+ <target anonymous="1" ids="id1" refuri="http://indirect">
+ <target ids="xtarget" names="xtarget" refuri="http://indirect">
+"""],
+["""\
+__
+
+`direct internal`__
+""",
+"""\
+<document source="test data">
+ <target anonymous="1" refid="id1">
+ <paragraph ids="id1">
+ <reference anonymous="1" name="direct internal" refid="id1">
+ direct internal
+"""],
+["""\
+.. _ztarget:
+
+`indirect internal`__
+
+__ ztarget_
+""",
+"""\
+<document source="test data">
+ <target refid="ztarget">
+ <paragraph ids="ztarget" names="ztarget">
+ <reference anonymous="1" name="indirect internal" refid="ztarget">
+ indirect internal
+ <target anonymous="1" ids="id1" refid="ztarget">
+"""],
+["""\
+.. _ztarget:
+
+First
+
+.. _ztarget:
+
+Second
+
+`indirect internal`__
+
+__ ztarget_
+""",
+"""\
+<document source="test data">
+ <target dupnames="ztarget" refid="ztarget">
+ <paragraph ids="ztarget">
+ First
+ <system_message backrefs="id1" level="2" line="5" source="test data" type="WARNING">
+ <paragraph>
+ Duplicate explicit target name: "ztarget".
+ <target dupnames="ztarget" refid="id1">
+ <paragraph ids="id1">
+ Second
+ <paragraph>
+ <problematic ids="id4" refid="id3">
+ `indirect internal`__
+ <target anonymous="1" ids="id2" refname="ztarget">
+ <system_message backrefs="id4" ids="id3" level="3" line="11" source="test data" type="ERROR">
+ <paragraph>
+ Indirect hyperlink target (id="id2") refers to target "ztarget", which is a duplicate, and cannot be used as a unique reference.
+"""],
+["""\
+The next anonymous hyperlink reference is parsed (and discarded) at
+some point, but nonetheless anonymous hyperlink references and targets
+match in this snippet.
+
+.. |invalid| replace:: anonymous__
+
+hyperlink__
+
+__ URL
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ The next anonymous hyperlink reference is parsed (and discarded) at
+ some point, but nonetheless anonymous hyperlink references and targets
+ match in this snippet.
+ <system_message level="3" line="5" source="test data" type="ERROR">
+ <paragraph>
+ Substitution definition contains illegal element <reference>:
+ <literal_block xml:space="preserve">
+ <reference anonymous="1" name="anonymous">
+ anonymous
+ <literal_block xml:space="preserve">
+ .. |invalid| replace:: anonymous__
+ <paragraph>
+ <reference anonymous="1" name="hyperlink" refuri="URL">
+ hyperlink
+ <target anonymous="1" ids="id1" refuri="URL">
+"""],
+["""\
+An `embedded uri <http://direct>`_.
+
+Another reference to the same `embedded URI`_.
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ An \n\
+ <reference name="embedded uri" refuri="http://direct">
+ embedded uri
+ <target ids="embedded-uri" names="embedded\\ uri" refuri="http://direct">
+ .
+ <paragraph>
+ Another reference to the same \n\
+ <reference name="embedded URI" refuri="http://direct">
+ embedded URI
+ .
+"""],
+["""\
+An `anonymous embedded uri <http://direct>`__.
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ An \n\
+ <reference name="anonymous embedded uri" refuri="http://direct">
+ anonymous embedded uri
+ .
+"""],
+["""\
+An `embedded alias <alias_>`_.
+
+Another reference to the same `embedded alias`_.
+
+.. _alias: ham.py
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ An \n\
+ <reference name="embedded alias" refuri="ham.py">
+ embedded alias
+ <target names="embedded\\ alias" refuri="ham.py">
+ .
+ <paragraph>
+ Another reference to the same \n\
+ <reference name="embedded alias" refuri="ham.py">
+ embedded alias
+ .
+ <target ids="alias" names="alias" refuri="ham.py">
+"""],
+["""\
+An `anonymous embedded alias <redirect_>`__.
+
+.. _redirect: spam.py
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ An \n\
+ <reference name="anonymous embedded alias" refuri="spam.py">
+ anonymous embedded alias
+ .
+ <target ids="redirect" names="redirect" refuri="spam.py">
+"""],
+["""\
+An `embedded alias <alias_>`_ with unknown reference.
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ An \n\
+ <problematic ids="id3" refid="id2">
+ `embedded alias <alias_>`_
+ <target names="embedded\\ alias" refname="alias">
+ with unknown reference.
+ <system_message ids="id1" level="3" line="1" source="test data" type="ERROR">
+ <paragraph>
+ Indirect hyperlink target "embedded alias" refers to target "alias", which does not exist.
+ <system_message backrefs="id3" ids="id2" level="3" line="1" source="test data" type="ERROR">
+ <paragraph>
+ Unknown target name: "alias".
+ <system_message level="1" line="1" source="test data" type="INFO">
+ <paragraph>
+ Hyperlink target "embedded alias" is not referenced.\
+"""],
+["""\
+An embedded URI with trailing underline:
+`__init__ <http:example.py.html#__init__>`__.
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ An embedded URI with trailing underline:
+ <reference name="__init__" refuri="http:example.py.html#__init__">
+ __init__
+ .
+"""],
+["""\
+Hyperlinks with angle-bracketed text need escaping.
+
+See `Element \\<a>`_, `Element <b\\>`_, and `Element <c>\\ `_.
+
+.. _`Element <a>`:
+.. _`Element <b>`:
+.. _`Element <c>`: elements.txt
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ Hyperlinks with angle-bracketed text need escaping.
+ <paragraph>
+ See \n\
+ <reference name="Element <a>" refuri="elements.txt">
+ Element <a>
+ , \n\
+ <reference name="Element <b>" refuri="elements.txt">
+ Element <b>
+ , and \n\
+ <reference name="Element <c>" refuri="elements.txt">
+ Element <c>
+ .
+ <target refid="element-a">
+ <target refid="element-b">
+ <target ids="element-c element-b element-a" names="element\\ <c> element\\ <b> element\\ <a>" refuri="elements.txt">
+"""],
+["""\
+.. _target:
+
+.. [1] Footnote; target_
+""",
+"""\
+<document source="test data">
+ <target ids="target" names="target">
+ <footnote ids="id1" names="1">
+ <label>
+ 1
+ <paragraph>
+ Footnote; \n\
+ <reference name="target" refid="target">
+ target
+"""],
+["""\
+.. _target:
+
+.. [cit] Citation; target_
+""",
+"""\
+<document source="test data">
+ <target ids="target" names="target">
+ <citation ids="cit" names="cit">
+ <label>
+ cit
+ <paragraph>
+ Citation; \n\
+ <reference name="target" refid="target">
+ target
+"""],
+])
+
+totest['hyperlinks'] = ((PropagateTargets, AnonymousHyperlinks,
+ IndirectHyperlinks, ExternalTargets,
+ InternalTargets, DanglingReferences), [
+["""\
+.. _internal hyperlink:
+
+This paragraph referenced.
+
+By this `internal hyperlink`_ reference.
+""",
+"""\
+<document source="test data">
+ <target refid="internal-hyperlink">
+ <paragraph ids="internal-hyperlink" names="internal\\ hyperlink">
+ This paragraph referenced.
+ <paragraph>
+ By this \n\
+ <reference name="internal hyperlink" refid="internal-hyperlink">
+ internal hyperlink
+ reference.
+"""],
+["""\
+.. _chained:
+.. _internal hyperlink:
+
+This paragraph referenced.
+
+By this `internal hyperlink`_ reference
+as well as by this chained_ reference.
+
+The results of the transform are not visible at the XML level.
+""",
+"""\
+<document source="test data">
+ <target refid="chained">
+ <target refid="internal-hyperlink">
+ <paragraph ids="internal-hyperlink chained" names="internal\\ hyperlink chained">
+ This paragraph referenced.
+ <paragraph>
+ By this \n\
+ <reference name="internal hyperlink" refid="internal-hyperlink">
+ internal hyperlink
+ reference
+ as well as by this \n\
+ <reference name="chained" refid="chained">
+ chained
+ reference.
+ <paragraph>
+ The results of the transform are not visible at the XML level.
+"""],
+["""\
+.. _chained:
+__ http://anonymous
+
+Anonymous__ and chained_ both refer to the same URI.
+""",
+"""\
+<document source="test data">
+ <target refid="chained">
+ <target anonymous="1" ids="id1 chained" names="chained" refuri="http://anonymous">
+ <paragraph>
+ <reference anonymous="1" name="Anonymous" refuri="http://anonymous">
+ Anonymous
+ and \n\
+ <reference name="chained" refuri="http://anonymous">
+ chained
+ both refer to the same URI.
+"""],
+["""\
+.. _a:
+.. _b:
+
+x
+""",
+"""\
+<document source="test data">
+ <target refid="a">
+ <target refid="b">
+ <paragraph ids="b a" names="b a">
+ x
+ <system_message level="1" line="1" source="test data" type="INFO">
+ <paragraph>
+ Hyperlink target "a" is not referenced.
+ <system_message level="1" line="2" source="test data" type="INFO">
+ <paragraph>
+ Hyperlink target "b" is not referenced.
+"""],
+["""\
+.. _a:
+.. _b:
+
+a_
+""",
+"""\
+<document source="test data">
+ <target refid="a">
+ <target refid="b">
+ <paragraph ids="b a" names="b a">
+ <reference name="a" refid="a">
+ a
+ <system_message level="1" line="2" source="test data" type="INFO">
+ <paragraph>
+ Hyperlink target "b" is not referenced.
+"""],
+["""\
+.. _a:
+.. _b:
+
+b_
+""",
+"""\
+<document source="test data">
+ <target refid="a">
+ <target refid="b">
+ <paragraph ids="b a" names="b a">
+ <reference name="b" refid="b">
+ b
+ <system_message level="1" line="1" source="test data" type="INFO">
+ <paragraph>
+ Hyperlink target "a" is not referenced.
+"""],
+["""\
+.. _a:
+.. _b:
+
+a_\\ b_
+""",
+"""\
+<document source="test data">
+ <target refid="a">
+ <target refid="b">
+ <paragraph ids="b a" names="b a">
+ <reference name="a" refid="a">
+ a
+ <reference name="b" refid="b">
+ b
+"""],
+["""\
+.. _external hyperlink: http://uri
+
+`External hyperlink`_ reference.
+""",
+"""\
+<document source="test data">
+ <target ids="external-hyperlink" names="external\\ hyperlink" refuri="http://uri">
+ <paragraph>
+ <reference name="External hyperlink" refuri="http://uri">
+ External hyperlink
+ reference.
+"""],
+["""\
+.. _external hyperlink: http://uri
+.. _indirect target: `external hyperlink`_
+""",
+"""\
+<document source="test data">
+ <target ids="external-hyperlink" names="external\\ hyperlink" refuri="http://uri">
+ <target ids="indirect-target" names="indirect\\ target" refuri="http://uri">
+ <system_message level="1" line="2" source="test data" type="INFO">
+ <paragraph>
+ Hyperlink target "indirect target" is not referenced.
+"""],
+["""\
+.. _chained:
+.. _external hyperlink: http://uri
+
+`External hyperlink`_ reference
+and a chained_ reference too.
+""",
+"""\
+<document source="test data">
+ <target refid="chained">
+ <target ids="external-hyperlink chained" names="external\\ hyperlink chained" refuri="http://uri">
+ <paragraph>
+ <reference name="External hyperlink" refuri="http://uri">
+ External hyperlink
+ reference
+ and a \n\
+ <reference name="chained" refuri="http://uri">
+ chained
+ reference too.
+"""],
+["""\
+.. _external hyperlink: http://uri
+.. _indirect hyperlink: `external hyperlink`_
+
+`Indirect hyperlink`_ reference.
+""",
+"""\
+<document source="test data">
+ <target ids="external-hyperlink" names="external\\ hyperlink" refuri="http://uri">
+ <target ids="indirect-hyperlink" names="indirect\\ hyperlink" refuri="http://uri">
+ <paragraph>
+ <reference name="Indirect hyperlink" refuri="http://uri">
+ Indirect hyperlink
+ reference.
+"""],
+["""\
+.. _external hyperlink: http://uri
+.. _chained:
+.. _indirect hyperlink: `external hyperlink`_
+
+Chained_ `indirect hyperlink`_ reference.
+""",
+"""\
+<document source="test data">
+ <target ids="external-hyperlink" names="external\\ hyperlink" refuri="http://uri">
+ <target refuri="http://uri">
+ <target ids="indirect-hyperlink chained" names="indirect\\ hyperlink chained" refuri="http://uri">
+ <paragraph>
+ <reference name="Chained" refuri="http://uri">
+ Chained
+ \n\
+ <reference name="indirect hyperlink" refuri="http://uri">
+ indirect hyperlink
+ reference.
+"""],
+["""\
+.. __: http://full
+__
+__ http://simplified
+.. _external: http://indirect.external
+__ external_
+__
+
+`Full syntax anonymous external hyperlink reference`__,
+`chained anonymous external reference`__,
+`simplified syntax anonymous external hyperlink reference`__,
+`indirect anonymous hyperlink reference`__,
+`internal anonymous hyperlink reference`__.
+""",
+"""\
+<document source="test data">
+ <target anonymous="1" ids="id1" refuri="http://full">
+ <target anonymous="1" refid="id2">
+ <target anonymous="1" ids="id3 id2" refuri="http://simplified">
+ <target ids="external" names="external" refuri="http://indirect.external">
+ <target anonymous="1" ids="id4" refuri="http://indirect.external">
+ <target anonymous="1" refid="id5">
+ <paragraph ids="id5">
+ <reference anonymous="1" name="Full syntax anonymous external hyperlink reference" refuri="http://full">
+ Full syntax anonymous external hyperlink reference
+ ,
+ <reference anonymous="1" name="chained anonymous external reference" refuri="http://simplified">
+ chained anonymous external reference
+ ,
+ <reference anonymous="1" name="simplified syntax anonymous external hyperlink reference" refuri="http://simplified">
+ simplified syntax anonymous external hyperlink reference
+ ,
+ <reference anonymous="1" name="indirect anonymous hyperlink reference" refuri="http://indirect.external">
+ indirect anonymous hyperlink reference
+ ,
+ <reference anonymous="1" name="internal anonymous hyperlink reference" refid="id5">
+ internal anonymous hyperlink reference
+ .
+"""],
+["""\
+Duplicate external target_'s (different URIs):
+
+.. _target: first
+
+.. _target: second
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ Duplicate external \n\
+ <problematic ids="id3" refid="id2">
+ target_
+ 's (different URIs):
+ <target dupnames="target" ids="target" refuri="first">
+ <system_message backrefs="id1" level="2" line="5" source="test data" type="WARNING">
+ <paragraph>
+ Duplicate explicit target name: "target".
+ <target dupnames="target" ids="id1" refuri="second">
+ <system_message backrefs="id3" ids="id2" level="3" line="1" source="test data" type="ERROR">
+ <paragraph>
+ Duplicate target name, cannot be used as a unique reference: "target".
+"""],
+["""\
+Duplicate external targets (different URIs) without reference:
+
+.. _target: first
+
+.. _target: second
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ Duplicate external targets (different URIs) without reference:
+ <target dupnames="target" ids="target" refuri="first">
+ <system_message backrefs="id1" level="2" line="5" source="test data" type="WARNING">
+ <paragraph>
+ Duplicate explicit target name: "target".
+ <target dupnames="target" ids="id1" refuri="second">
+"""],
+["""\
+Several__ anonymous__ hyperlinks__, but not enough targets.
+
+__ http://example.org
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ <problematic ids="id3" refid="id2">
+ Several__
+ \n\
+ <problematic ids="id4" refid="id2">
+ anonymous__
+ \n\
+ <problematic ids="id5" refid="id2">
+ hyperlinks__
+ , but not enough targets.
+ <target anonymous="1" ids="id1" refuri="http://example.org">
+ <system_message backrefs="id3 id4 id5" ids="id2" level="3" source="test data" type="ERROR">
+ <paragraph>
+ Anonymous hyperlink mismatch: 3 references but 1 targets.
+ See "backrefs" attribute for IDs.
+"""],
+["""\
+.. _external: http://uri
+.. _indirect: external_
+.. _internal:
+
+.. image:: picture.png
+ :target: external_
+
+.. image:: picture.png
+ :target: indirect_
+
+.. image:: picture.png
+ :target: internal_
+""",
+"""\
+<document source="test data">
+ <target ids="external" names="external" refuri="http://uri">
+ <target ids="indirect" names="indirect" refuri="http://uri">
+ <target refid="internal">
+ <reference ids="internal" name="external" names="internal" refuri="http://uri">
+ <image uri="picture.png">
+ <reference name="indirect" refuri="http://uri">
+ <image uri="picture.png">
+ <reference name="internal" refid="internal">
+ <image uri="picture.png">
+"""],
+["""\
+.. contents:: Table of Contents
+.. _indirect reference to the table of contents: `table of contents`_
+
+Section
+=======
+
+Testing an `indirect reference to the table of contents`_.
+""",
+"""\
+<document source="test data">
+ <topic classes="contents" ids="table-of-contents" names="table\\ of\\ contents">
+ <title>
+ Table of Contents
+ <bullet_list>
+ <list_item>
+ <paragraph>
+ <reference ids="id1" refid="section">
+ Section
+ <target ids="indirect-reference-to-the-table-of-contents" names="indirect\\ reference\\ to\\ the\\ table\\ of\\ contents" refid="table-of-contents">
+ <section ids="section" names="section">
+ <title refid="id1">
+ Section
+ <paragraph>
+ Testing an
+ <reference name="indirect reference to the table of contents" refid="table-of-contents">
+ indirect reference to the table of contents
+ .
+"""],
+["""\
+.. _explicit target:
+
+Title
+-----
+
+Let's reference it (`explicit target`_) to avoid an irrelevant error.
+""",
+"""\
+<document source="test data">
+ <target refid="explicit-target">
+ <section ids="title explicit-target" names="title explicit\\ target">
+ <title>
+ Title
+ <paragraph>
+ Let's reference it (
+ <reference name="explicit target" refid="explicit-target">
+ explicit target
+ ) to avoid an irrelevant error.
+"""],
+["""\
+target1_ should refer to target2_, not the Title.
+
+.. _target1:
+.. _target2: URI
+
+Title
+=====
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ <reference name="target1" refuri="URI">
+ target1
+ should refer to \n\
+ <reference name="target2" refuri="URI">
+ target2
+ , not the Title.
+ <target refid="target1">
+ <target ids="target2 target1" names="target2 target1" refuri="URI">
+ <section ids="title" names="title">
+ <title>
+ Title
+"""],
+["""\
+Unknown reference_.
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ Unknown \n\
+ <problematic ids="id2" refid="id1">
+ reference_
+ .
+ <system_message backrefs="id2" ids="id1" level="3" line="1" source="test data" type="ERROR">
+ <paragraph>
+ Unknown target name: "reference".
+"""],
+["""\
+Duplicate manual footnote labels, with reference ([1]_):
+
+.. [1] Footnote.
+
+.. [1] Footnote.
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ Duplicate manual footnote labels, with reference (
+ <problematic ids="id1" refid="id4">
+ [1]_
+ ):
+ <footnote dupnames="1" ids="id2">
+ <label>
+ 1
+ <paragraph>
+ Footnote.
+ <footnote dupnames="1" ids="id3">
+ <label>
+ 1
+ <system_message backrefs="id3" level="2" line="5" source="test data" type="WARNING">
+ <paragraph>
+ Duplicate explicit target name: "1".
+ <paragraph>
+ Footnote.
+ <system_message backrefs="id1" ids="id4" level="3" line="1" source="test data" type="ERROR">
+ <paragraph>
+ Duplicate target name, cannot be used as a unique reference: "1".
+"""],
+])
+
+
+if __name__ == '__main__':
+ import unittest
+ unittest.main(defaultTest='suite')
--- /dev/null
+#! /usr/bin/env python
+
+# $Id: test_messages.py 8356 2019-08-26 16:44:19Z milde $
+# Author: David Goodger <goodger@python.org>
+# Copyright: This module has been placed in the public domain.
+
+"""
+Tests for docutils.transforms.universal.Messages.
+"""
+from __future__ import absolute_import
+
+from . import DocutilsTestSupport
+from docutils.transforms.universal import Messages
+from docutils.transforms.references import Substitutions
+from docutils.parsers.rst import Parser
+
+
+def suite():
+ parser = Parser()
+ s = DocutilsTestSupport.TransformTestSuite(parser)
+ s.generateTests(totest)
+ return s
+
+totest = {}
+
+totest['system_message_sections'] = ((Substitutions, Messages), [
+["""\
+This |unknown substitution| will generate a system message, thanks to
+the ``Substitutions`` transform. The ``Messages`` transform will
+generate a "System Messages" section.
+
+(A second copy of the system message is tacked on to the end of the
+document by the test framework.)
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ This \n\
+ <problematic ids="id2" refid="id1">
+ |unknown substitution|
+ will generate a system message, thanks to
+ the \n\
+ <literal>
+ Substitutions
+ transform. The \n\
+ <literal>
+ Messages
+ transform will
+ generate a "System Messages" section.
+ <paragraph>
+ (A second copy of the system message is tacked on to the end of the
+ document by the test framework.)
+ <section classes="system-messages">
+ <title>
+ Docutils System Messages
+ <system_message backrefs="id2" ids="id1" level="3" line="1" source="test data" type="ERROR">
+ <paragraph>
+ Undefined substitution referenced: "unknown substitution".
+"""],
+])
+
+
+if __name__ == '__main__':
+ import unittest
+ unittest.main(defaultTest='suite')
--- /dev/null
+#! /usr/bin/env python
+
+# $Id: test_peps.py 8356 2019-08-26 16:44:19Z milde $
+# Author: David Goodger <goodger@python.org>
+# Copyright: This module has been placed in the public domain.
+
+"""
+Tests for docutils.transforms.peps.
+"""
+from __future__ import absolute_import
+
+from . import DocutilsTestSupport
+from docutils.transforms.peps import TargetNotes
+from docutils.parsers.rst import Parser
+
+
+def suite():
+ parser = Parser()
+ s = DocutilsTestSupport.TransformTestSuite(parser)
+ s.generateTests(totest)
+ return s
+
+totest = {}
+
+totest['target_notes'] = ((TargetNotes,), [
+["""\
+No references or targets exist, therefore
+no "References" section should be generated.
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ No references or targets exist, therefore
+ no "References" section should be generated.
+"""],
+["""\
+A target exists, here's the reference_.
+A "References" section should be generated.
+
+.. _reference: http://www.example.org
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ A target exists, here's the \n\
+ <reference name="reference" refname="reference">
+ reference
+ \n\
+ <footnote_reference auto="1" ids="id3" refname="TARGET_NOTE: id2">
+ .
+ A "References" section should be generated.
+ <target ids="reference" names="reference" refuri="http://www.example.org">
+ <section ids="id1">
+ <title>
+ References
+ <footnote auto="1" ids="id2" names="TARGET_NOTE:\\ id2">
+ <paragraph>
+ <reference refuri="http://www.example.org">
+ http://www.example.org
+"""],
+])
+
+
+
+if __name__ == '__main__':
+ import unittest
+ unittest.main(defaultTest='suite')
--- /dev/null
+#! /usr/bin/env python
+
+# $Id: test_sectnum.py 8356 2019-08-26 16:44:19Z milde $
+# Authors: David Goodger <goodger@python.org>; Dmitry Jemerov
+# Copyright: This module has been placed in the public domain.
+
+"""
+Tests for `docutils.transforms.parts.SectNum` (via
+`docutils.transforms.universal.LastReaderPending`).
+"""
+from __future__ import absolute_import
+
+from . import DocutilsTestSupport
+from docutils.transforms.references import Substitutions
+from docutils.parsers.rst import Parser
+
+
+def suite():
+ parser = Parser()
+ s = DocutilsTestSupport.TransformTestSuite(parser)
+ s.generateTests(totest)
+ return s
+
+totest = {}
+
+totest['section_numbers'] = ((Substitutions,), [
+["""\
+.. sectnum::
+
+Title 1
+=======
+Paragraph 1.
+
+Title 2
+-------
+Paragraph 2.
+
+Title 3
+```````
+Paragraph 3.
+
+Title 4
+-------
+Paragraph 4.
+""",
+u"""\
+<document source="test data">
+ <section ids="title-1" names="title\\ 1">
+ <title auto="1">
+ <generated classes="sectnum">
+ 1\u00a0\u00a0\u00a0
+ Title 1
+ <paragraph>
+ Paragraph 1.
+ <section ids="title-2" names="title\\ 2">
+ <title auto="1">
+ <generated classes="sectnum">
+ 1.1\u00a0\u00a0\u00a0
+ Title 2
+ <paragraph>
+ Paragraph 2.
+ <section ids="title-3" names="title\\ 3">
+ <title auto="1">
+ <generated classes="sectnum">
+ 1.1.1\u00a0\u00a0\u00a0
+ Title 3
+ <paragraph>
+ Paragraph 3.
+ <section ids="title-4" names="title\\ 4">
+ <title auto="1">
+ <generated classes="sectnum">
+ 1.2\u00a0\u00a0\u00a0
+ Title 4
+ <paragraph>
+ Paragraph 4.
+"""],
+["""\
+.. sectnum::
+
+**Bold Title**
+==============
+Paragraph 1.
+""",
+u"""\
+<document source="test data">
+ <section ids="bold-title" names="bold\\ title">
+ <title auto="1">
+ <generated classes="sectnum">
+ 1\u00a0\u00a0\u00a0
+ <strong>
+ Bold Title
+ <paragraph>
+ Paragraph 1.
+"""],
+["""\
+.. sectnum:: :depth: 2
+
+Title 1
+=======
+Paragraph 1.
+
+Title 2
+-------
+Paragraph 2.
+
+Title 3
+```````
+Paragraph 3.
+
+Title 4
+-------
+Paragraph 4.
+""",
+u"""\
+<document source="test data">
+ <section ids="title-1" names="title\\ 1">
+ <title auto="1">
+ <generated classes="sectnum">
+ 1\u00a0\u00a0\u00a0
+ Title 1
+ <paragraph>
+ Paragraph 1.
+ <section ids="title-2" names="title\\ 2">
+ <title auto="1">
+ <generated classes="sectnum">
+ 1.1\u00a0\u00a0\u00a0
+ Title 2
+ <paragraph>
+ Paragraph 2.
+ <section ids="title-3" names="title\\ 3">
+ <title>
+ Title 3
+ <paragraph>
+ Paragraph 3.
+ <section ids="title-4" names="title\\ 4">
+ <title auto="1">
+ <generated classes="sectnum">
+ 1.2\u00a0\u00a0\u00a0
+ Title 4
+ <paragraph>
+ Paragraph 4.
+"""],
+["""\
+.. contents::
+.. sectnum:: :depth: 2
+
+Title 1
+=======
+Paragraph 1.
+
+Title 2
+-------
+Paragraph 2.
+
+Title 3
+```````
+Paragraph 3.
+
+Title 4
+-------
+Paragraph 4.
+""",
+u"""\
+<document source="test data">
+ <topic classes="contents" ids="contents" names="contents">
+ <title>
+ Contents
+ <bullet_list classes="auto-toc">
+ <list_item>
+ <paragraph>
+ <reference ids="id1" refid="title-1">
+ <generated classes="sectnum">
+ 1\u00a0\u00a0\u00a0
+ Title 1
+ <bullet_list classes="auto-toc">
+ <list_item>
+ <paragraph>
+ <reference ids="id2" refid="title-2">
+ <generated classes="sectnum">
+ 1.1\u00a0\u00a0\u00a0
+ Title 2
+ <bullet_list>
+ <list_item>
+ <paragraph>
+ <reference ids="id3" refid="title-3">
+ Title 3
+ <list_item>
+ <paragraph>
+ <reference ids="id4" refid="title-4">
+ <generated classes="sectnum">
+ 1.2\u00a0\u00a0\u00a0
+ Title 4
+ <section ids="title-1" names="title\\ 1">
+ <title auto="1" refid="id1">
+ <generated classes="sectnum">
+ 1\u00a0\u00a0\u00a0
+ Title 1
+ <paragraph>
+ Paragraph 1.
+ <section ids="title-2" names="title\\ 2">
+ <title auto="1" refid="id2">
+ <generated classes="sectnum">
+ 1.1\u00a0\u00a0\u00a0
+ Title 2
+ <paragraph>
+ Paragraph 2.
+ <section ids="title-3" names="title\\ 3">
+ <title refid="id3">
+ Title 3
+ <paragraph>
+ Paragraph 3.
+ <section ids="title-4" names="title\\ 4">
+ <title auto="1" refid="id4">
+ <generated classes="sectnum">
+ 1.2\u00a0\u00a0\u00a0
+ Title 4
+ <paragraph>
+ Paragraph 4.
+"""],
+["""\
+.. sectnum::
+ :prefix: Arbitrary-
+
+Title 1
+=======
+Paragraph 1.
+
+Title 2
+-------
+Paragraph 2.
+
+Title 3
+```````
+Paragraph 3.
+
+Title 4
+-------
+Paragraph 4.
+""",
+u"""\
+<document source="test data">
+ <section ids="title-1" names="title\\ 1">
+ <title auto="1">
+ <generated classes="sectnum">
+ Arbitrary-1\u00a0\u00a0\u00a0
+ Title 1
+ <paragraph>
+ Paragraph 1.
+ <section ids="title-2" names="title\\ 2">
+ <title auto="1">
+ <generated classes="sectnum">
+ Arbitrary-1.1\u00a0\u00a0\u00a0
+ Title 2
+ <paragraph>
+ Paragraph 2.
+ <section ids="title-3" names="title\\ 3">
+ <title auto="1">
+ <generated classes="sectnum">
+ Arbitrary-1.1.1\u00a0\u00a0\u00a0
+ Title 3
+ <paragraph>
+ Paragraph 3.
+ <section ids="title-4" names="title\\ 4">
+ <title auto="1">
+ <generated classes="sectnum">
+ Arbitrary-1.2\u00a0\u00a0\u00a0
+ Title 4
+ <paragraph>
+ Paragraph 4.
+"""],
+["""\
+.. sectnum::
+ :start: 3
+
+Title 1
+=======
+Paragraph 1.
+
+Title 2
+-------
+Paragraph 2.
+
+Title 3
+```````
+Paragraph 3.
+
+Title 4
+-------
+Paragraph 4.
+""",
+u"""\
+<document source="test data">
+ <section ids="title-1" names="title\\ 1">
+ <title auto="1">
+ <generated classes="sectnum">
+ 3\u00a0\u00a0\u00a0
+ Title 1
+ <paragraph>
+ Paragraph 1.
+ <section ids="title-2" names="title\\ 2">
+ <title auto="1">
+ <generated classes="sectnum">
+ 3.1\u00a0\u00a0\u00a0
+ Title 2
+ <paragraph>
+ Paragraph 2.
+ <section ids="title-3" names="title\\ 3">
+ <title auto="1">
+ <generated classes="sectnum">
+ 3.1.1\u00a0\u00a0\u00a0
+ Title 3
+ <paragraph>
+ Paragraph 3.
+ <section ids="title-4" names="title\\ 4">
+ <title auto="1">
+ <generated classes="sectnum">
+ 3.2\u00a0\u00a0\u00a0
+ Title 4
+ <paragraph>
+ Paragraph 4.
+"""],
+["""\
+.. sectnum::
+ :prefix: (5.9.
+ :suffix: )
+ :start: 3
+
+Title 1
+=======
+Paragraph 1.
+
+Title 2
+-------
+Paragraph 2.
+
+Title 3
+```````
+Paragraph 3.
+
+Title 4
+-------
+Paragraph 4.
+""",
+u"""\
+<document source="test data">
+ <section ids="title-1" names="title\\ 1">
+ <title auto="1">
+ <generated classes="sectnum">
+ (5.9.3)\u00a0\u00a0\u00a0
+ Title 1
+ <paragraph>
+ Paragraph 1.
+ <section ids="title-2" names="title\\ 2">
+ <title auto="1">
+ <generated classes="sectnum">
+ (5.9.3.1)\u00a0\u00a0\u00a0
+ Title 2
+ <paragraph>
+ Paragraph 2.
+ <section ids="title-3" names="title\\ 3">
+ <title auto="1">
+ <generated classes="sectnum">
+ (5.9.3.1.1)\u00a0\u00a0\u00a0
+ Title 3
+ <paragraph>
+ Paragraph 3.
+ <section ids="title-4" names="title\\ 4">
+ <title auto="1">
+ <generated classes="sectnum">
+ (5.9.3.2)\u00a0\u00a0\u00a0
+ Title 4
+ <paragraph>
+ Paragraph 4.
+"""],
+])
+
+
+if __name__ == '__main__':
+ import unittest
+ unittest.main(defaultTest='suite')
--- /dev/null
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+# $Id: test_smartquotes.py 8356 2019-08-26 16:44:19Z milde $
+#
+# :Copyright: © 2011 Günter Milde.
+# :Maintainer: docutils-develop@lists.sourceforge.net
+# :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
+
+"""
+Test module for universal.SmartQuotes transform.
+"""
+from __future__ import absolute_import
+
+from . import DocutilsTestSupport # must be imported before docutils
+from docutils.transforms.universal import SmartQuotes
+from docutils.parsers.rst import Parser
+
+
+def suite():
+ parser = Parser()
+ settings = {'smart_quotes': True,
+ 'trim_footnote_ref_space': True}
+ s = DocutilsTestSupport.TransformTestSuite(
+ parser, suite_settings=settings)
+ s.generateTests(totest)
+ settings['language_code'] = 'de'
+ s.generateTests(totest_de)
+ settings['smart_quotes'] = 'alternative'
+ s.generateTests(totest_de_alt)
+ settings['smart_quotes'] = True
+ settings['smartquotes_locales'] = [('de', u'«»()'), ('nl', u'„”’’')]
+ s.generateTests(totest_locales)
+ return s
+
+
+totest = {}
+totest_de = {}
+totest_de_alt = {}
+totest_locales = {}
+
+totest['smartquotes'] = ((SmartQuotes,), [
+["""\
+Test "smart quotes", 'secondary smart quotes',
+"'nested' smart" quotes
+-- and ---also long--- dashes.
+""",
+u"""\
+<document source="test data">
+ <paragraph>
+ Test “smart quotes”, ‘secondary smart quotes’,
+ “‘nested’ smart” quotes
+ – and —also long— dashes.
+"""],
+[r"""Escaped \"ASCII quotes\" and \'secondary ASCII quotes\'.
+""",
+u"""\
+<document source="test data">
+ <paragraph>
+ Escaped "ASCII quotes" and 'secondary ASCII quotes'.
+"""],
+["""\
+Do not "educate" quotes ``inside "literal" text`` and ::
+
+ "literal" blocks.
+
+.. role:: python(code)
+ :class: python
+
+Keep quotes straight in code and math:
+:code:`print "hello"` :python:`print("hello")` :math:`1' 12"`.
+
+.. code::
+
+ print("hello")
+
+.. math::
+
+ f'(x) = df(x)/dx
+
+""",
+u"""\
+<document source="test data">
+ <paragraph>
+ Do not “educate” quotes
+ <literal>
+ inside "literal" text
+ and
+ <literal_block xml:space="preserve">
+ "literal" blocks.
+ <paragraph>
+ Keep quotes straight in code and math:
+ <literal classes="code">
+ print "hello"
+
+ <literal classes="code python">
+ print("hello")
+
+ <math>
+ 1' 12"
+ .
+ <literal_block classes="code" xml:space="preserve">
+ print("hello")
+ <math_block xml:space="preserve">
+ f'(x) = df(x)/dx
+"""],
+[u"""\
+Quotes preceded by
+a word"a" and'a',
+punctuation:"a",'a',
+
+normal space "a" 'a',
+thin space "a" 'a',
+em space "a" 'a',
+NBSP "a" 'a',
+ZWSP\u200B"a" and\u200B'a',
+ZWNJ\u200C"a" and\u200C'a',
+escaped space\\ "a" and\\ 'a',
+
+—"a",—'a'
+en dash–"a"–'a',
+em dash—"a"—'a'.
+""",
+u"""\
+<document source="test data">
+ <paragraph>
+ Quotes preceded by
+ a word”a” and’a’,
+ punctuation:”a”,’a’,
+ <paragraph>
+ normal space “a” ‘a’,
+ thin space “a” ‘a’,
+ em space “a” ‘a’,
+ NBSP “a” ‘a’,
+ ZWSP\u200B“a” and\u200B‘a’,
+ ZWNJ\u200C“a” and\u200C‘a’,
+ escaped space“a” and‘a’,
+ <paragraph>
+ —“a”,—‘a’
+ en dash–“a”–‘a’,
+ em dash—“a”—‘a’.
+"""],
+["""\
+Quotes and inline-elements:
+
+* Around "_`targets`", "*emphasized*" or "``literal``" text
+ and links to "targets_".
+
+* Inside *"emphasized"* or other `inline "roles"`
+
+Do not drop characters from intra-word inline markup like
+*re*\\ ``Structured``\\ *Text*.
+""",
+u"""\
+<document source="test data">
+ <paragraph>
+ Quotes and inline-elements:
+ <bullet_list bullet="*">
+ <list_item>
+ <paragraph>
+ Around “
+ <target ids="targets" names="targets">
+ targets
+ ”, “
+ <emphasis>
+ emphasized
+ ” or “
+ <literal>
+ literal
+ ” text
+ and links to “
+ <reference name="targets" refname="targets">
+ targets
+ ”.
+ <list_item>
+ <paragraph>
+ Inside \n\
+ <emphasis>
+ “emphasized”
+ or other \n\
+ <title_reference>
+ inline “roles”
+ <paragraph>
+ Do not drop characters from intra-word inline markup like
+ <emphasis>
+ re
+ <literal>
+ Structured
+ <emphasis>
+ Text
+ .\
+"""],
+["""\
+Do not convert context-character at inline-tag boundaries
+(in French, smart quotes expand to two characters).
+
+.. class:: language-fr-ch-x-altquot
+
+ Around "_`targets`", "*emphasized*" or "``literal``" text
+ and links to "targets_".
+
+ Inside *"emphasized"* or other `inline "roles"`:
+ (``"string"``), (``'string'``), *\"betont\"*, \"*betont*".
+
+ Do not drop characters from intra-word inline markup like
+ *re*\\ ``Structured``\\ *Text*.
+""",
+u"""\
+<document source="test data">
+ <paragraph>
+ Do not convert context-character at inline-tag boundaries
+ (in French, smart quotes expand to two characters).
+ <paragraph classes="language-fr-ch-x-altquot">
+ Around «\u202f
+ <target ids="targets" names="targets">
+ targets
+ \u202f», «\u202f
+ <emphasis>
+ emphasized
+ \u202f» or «\u202f
+ <literal>
+ literal
+ \u202f» text
+ and links to «\u202f
+ <reference name="targets" refname="targets">
+ targets
+ \u202f».
+ <paragraph classes="language-fr-ch-x-altquot">
+ Inside \n\
+ <emphasis>
+ «\u202femphasized\u202f»
+ or other \n\
+ <title_reference>
+ inline «\u202froles\u202f»
+ :
+ (
+ <literal>
+ "string"
+ ), (
+ <literal>
+ 'string'
+ ),
+ <emphasis>
+ «\u202fbetont\u202f»
+ , «\u202f
+ <emphasis>
+ betont
+ \u202f».
+ <paragraph classes="language-fr-ch-x-altquot">
+ Do not drop characters from intra-word inline markup like
+ <emphasis>
+ re
+ <literal>
+ Structured
+ <emphasis>
+ Text
+ .
+"""],
+[r"""
+Docutils escape mechanism uses the backslash:
+
+\Remove \non-escaped \backslashes\:
+\item \newline \tab \" \' \*.
+
+\ Remove-\ escaped-\ white\ space-\
+including-\ newlines.
+
+\\Keep\\escaped\\backslashes\\
+(but\\only\\one).
+
+\\ Keep \\ space\\ around \\ backslashes.
+
+Keep backslashes ``\in\ literal``, :math:`in \mathrm{math}`,
+and :code:`in\ code`.
+
+Test around inline elements:\ [*]_
+
+*emphasized*, H\ :sub:`2`\ O and :math:`x^2`
+
+*emphasized*, H\ :sub:`2`\ O and :math:`x^2`
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+.. [*] and footnotes
+""",
+u"""\
+<document source="test data">
+ <paragraph>
+ Docutils escape mechanism uses the backslash:
+ <paragraph>
+ Remove non-escaped backslashes:
+ item newline tab " \' *.
+ <paragraph>
+ Remove-escaped-whitespace-including-newlines.
+ <paragraph>
+ \\Keep\\escaped\\backslashes\\
+ (but\\only\\one).
+ <paragraph>
+ \\ Keep \\ space\\ around \\ backslashes.
+ <paragraph>
+ Keep backslashes \n\
+ <literal>
+ \\in\\ literal
+ , \n\
+ <math>
+ in \\mathrm{math}
+ ,
+ and \n\
+ <literal classes="code">
+ in\\ code
+ .
+ <paragraph>
+ Test around inline elements:
+ <footnote_reference auto="*" ids="id1">
+ <paragraph>
+ <emphasis>
+ emphasized
+ , H
+ <subscript>
+ 2
+ O and \n\
+ <math>
+ x^2
+ <section ids="emphasized-h2o-and-x-2" names="emphasized,\\ h2o\\ and\\ x^2">
+ <title>
+ <emphasis>
+ emphasized
+ , H
+ <subscript>
+ 2
+ O and \n\
+ <math>
+ x^2
+ <footnote auto="*" ids="id2">
+ <paragraph>
+ and footnotes
+"""],
+[r"""
+Character-level m\ *a*\ **r**\ ``k``\ `u`:title:\p
+with backslash-escaped whitespace, including new\
+lines.
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ Character-level m
+ <emphasis>
+ a
+ <strong>
+ r
+ <literal>
+ k
+ <title_reference>
+ u
+ p
+ with backslash-escaped whitespace, including newlines.
+"""],
+["""\
+.. class:: language-de
+
+German "smart quotes" and 'secondary smart quotes'.
+
+.. class:: language-en-UK-x-altquot
+
+British "primary quotes" use single and
+'secondary quotes' double quote signs.
+
+.. class:: language-foo
+
+"Quoting style" for unknown languages is 'ASCII'.
+
+.. class:: language-de-x-altquot
+
+Alternative German "smart quotes" and 'secondary smart quotes'.
+""",
+u"""\
+<document source="test data">
+ <paragraph classes="language-de">
+ German „smart quotes“ and ‚secondary smart quotes‘.
+ <paragraph classes="language-en-uk-x-altquot">
+ British ‘primary quotes’ use single and
+ “secondary quotes” double quote signs.
+ <paragraph classes="language-foo">
+ "Quoting style" for unknown languages is 'ASCII'.
+ <paragraph classes="language-de-x-altquot">
+ Alternative German »smart quotes« and ›secondary smart quotes‹.
+ <system_message level="2" line="12" source="test data" type="WARNING">
+ <paragraph>
+ No smart quotes defined for language "foo".
+"""],
+])
+
+totest_de['smartquotes'] = ((SmartQuotes,), [
+["""\
+German "smart quotes" and 'secondary smart quotes'.
+
+.. class:: language-en
+
+English "smart quotes" and 'secondary smart quotes'.
+""",
+u"""\
+<document source="test data">
+ <paragraph>
+ German „smart quotes“ and ‚secondary smart quotes‘.
+ <paragraph classes="language-en">
+ English “smart quotes” and ‘secondary smart quotes’.
+"""],
+])
+
+totest_de_alt['smartquotes'] = ((SmartQuotes,), [
+["""\
+Alternative German "smart quotes" and 'secondary smart quotes'.
+
+In this case, the apostrophe isn't a closing secondary quote!
+
+.. class:: language-en-UK
+
+British "quotes" use single and 'secondary quotes' double quote signs
+(there are no alternative quotes defined).
+
+.. class:: language-ro
+
+Romanian "smart quotes" and 'secondary' smart quotes.
+""",
+u"""\
+<document source="test data">
+ <paragraph>
+ Alternative German »smart quotes« and ›secondary smart quotes‹.
+ <paragraph>
+ In this case, the apostrophe isn’t a closing secondary quote!
+ <paragraph classes="language-en-uk">
+ British ‘quotes’ use single and “secondary quotes” double quote signs
+ (there are no alternative quotes defined).
+ <paragraph classes="language-ro">
+ Romanian „smart quotes” and «secondary» smart quotes.
+"""],
+])
+
+totest_locales['smartquotes'] = ((SmartQuotes,), [
+["""\
+German "smart quotes" and 'secondary smart quotes'.
+
+.. class:: language-nl
+
+Dutch "smart quotes" and 's Gravenhage (leading apostrophe).
+""",
+u"""\
+<document source="test data">
+ <paragraph>
+ German «smart quotes» and (secondary smart quotes).
+ <paragraph classes="language-nl">
+ Dutch „smart quotes” and ’s Gravenhage (leading apostrophe).
+"""],
+])
+
+
+if __name__ == '__main__':
+ import unittest
+ unittest.main(defaultTest='suite')
--- /dev/null
+#! /usr/bin/env python
+
+# $Id: test_strip_comments.py 8387 2019-09-06 13:16:34Z milde $
+# Author: David Goodger <goodger@python.org>
+# Copyright: This module has been placed in the public domain.
+
+"""
+Tests for docutils.transforms.universal.StripComments.
+"""
+from __future__ import absolute_import
+
+from . import DocutilsTestSupport
+from docutils.transforms.universal import StripComments
+from docutils.parsers.rst import Parser
+
+
+def suite():
+ parser = Parser()
+ s = DocutilsTestSupport.TransformTestSuite(
+ parser, suite_settings={'strip_comments': 1})
+ s.generateTests(totest)
+ return s
+
+totest = {}
+
+totest['strip_comments'] = ((StripComments,), [
+["""\
+.. this is a comment
+
+Title
+=====
+
+Paragraph.
+
+.. second comment
+""",
+"""\
+<document source="test data">
+ <section ids="title" names="title">
+ <title>
+ Title
+ <paragraph>
+ Paragraph.
+"""],
+])
+
+
+if __name__ == '__main__':
+ import unittest
+ unittest.main(defaultTest='suite')
--- /dev/null
+#! /usr/bin/env python
+
+# $Id: test_strip_elements_with_class.py 8385 2019-09-06 13:16:07Z milde $
+# Author: Guenter Milde <milde@users.sf.net>
+# Copyright: This module has been placed in the public domain.
+
+"""
+Tests for docutils.transforms.universal.StripClassesAndElements.
+"""
+from __future__ import absolute_import
+
+from . import DocutilsTestSupport
+from docutils.parsers.rst import Parser
+from docutils.transforms.universal import StripClassesAndElements
+
+def suite():
+ parser = Parser()
+ s = DocutilsTestSupport.TransformTestSuite(parser,
+ suite_settings={'strip_elements_with_classes': ['spam', 'no-ham'],
+ 'strip_classes': ['spam', 'noise']})
+ s.generateTests(totest)
+ return s
+
+totest = {}
+
+totest['strip_spam'] = ((StripClassesAndElements,), [
+["""\
+not classy
+
+.. class:: spam
+
+this is spam
+
+.. class:: ham noise
+
+this is ham
+
+.. code::
+ :class: spam
+
+ print("spam")
+
+.. image:: spam.jpg
+ :class: spam
+
+this is not ham
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ not classy
+ <paragraph classes="ham">
+ this is ham
+ <paragraph>
+ this is not ham
+"""],
+])
+
+
+if __name__ == '__main__':
+ import unittest
+ unittest.main(defaultTest='suite')
--- /dev/null
+#! /usr/bin/env python
+
+# $Id: test_substitutions.py 8356 2019-08-26 16:44:19Z milde $
+# Author: David Goodger <goodger@python.org>
+# Copyright: This module has been placed in the public domain.
+
+"""
+Tests for docutils.transforms.references.Substitutions.
+"""
+from __future__ import absolute_import
+
+from . import DocutilsTestSupport
+from docutils.transforms.references import Substitutions
+from docutils.parsers.rst import Parser
+
+
+def suite():
+ parser = Parser()
+ s = DocutilsTestSupport.TransformTestSuite(parser)
+ s.generateTests(totest)
+ return s
+
+totest = {}
+
+totest['substitutions'] = ((Substitutions,), [
+["""\
+The |biohazard| symbol is deservedly scary-looking.
+
+.. |biohazard| image:: biohazard.png
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ The \n\
+ <image alt="biohazard" uri="biohazard.png">
+ symbol is deservedly scary-looking.
+ <substitution_definition names="biohazard">
+ <image alt="biohazard" uri="biohazard.png">
+"""],
+["""\
+Here's an |unknown| substitution.
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ Here's an \n\
+ <problematic ids="id2" refid="id1">
+ |unknown|
+ substitution.
+ <system_message backrefs="id2" ids="id1" level="3" line="1" source="test data" type="ERROR">
+ <paragraph>
+ Undefined substitution referenced: "unknown".
+"""],
+[u"""\
+Substitutions support case differences:
+
+.. |eacute| replace:: \u00E9
+.. |Eacute| replace:: \u00C9
+
+|Eacute|\\t\\ |eacute|, and even |EACUTE|.
+""",
+u"""\
+<document source="test data">
+ <paragraph>
+ Substitutions support case differences:
+ <substitution_definition names="eacute">
+ \u00E9
+ <substitution_definition names="Eacute">
+ \u00C9
+ <paragraph>
+ \u00C9
+ t
+ \u00E9
+ , and even \n\
+ \u00C9
+ .
+"""],
+[u"""\
+Indirect substitution definitions with multiple references:
+
+|substitute| my coke for gin
+|substitute| you for my mum
+at least I'll get my washing done
+
+.. |substitute| replace:: |replace|
+.. |replace| replace:: swap
+""",
+u"""\
+<document source="test data">
+ <paragraph>
+ Indirect substitution definitions with multiple references:
+ <paragraph>
+ swap
+ my coke for gin
+ swap
+ you for my mum
+ at least I'll get my washing done
+ <substitution_definition names="substitute">
+ swap
+ <substitution_definition names="replace">
+ swap
+"""],
+["""\
+.. |l| unicode:: U+00AB .. left chevron
+.. |r| unicode:: U+00BB .. right chevron
+.. |.| replace:: |l|\\ ``.``\\ |r|
+
+.. Delete either of the following lines, and there is no error.
+
+Regular expression |.| will match any character
+
+.. Note:: Note that |.| matches *exactly* one character
+""",
+u"""\
+<document source="test data">
+ <substitution_definition names="l">
+ \xab
+ <substitution_definition names="r">
+ \xbb
+ <substitution_definition names=".">
+ \xab
+ <literal>
+ .
+ \xbb
+ <comment xml:space="preserve">
+ Delete either of the following lines, and there is no error.
+ <paragraph>
+ Regular expression \n\
+ \xab
+ <literal>
+ .
+ \xbb
+ will match any character
+ <note>
+ <paragraph>
+ Note that \n\
+ \xab
+ <literal>
+ .
+ \xbb
+ matches \n\
+ <emphasis>
+ exactly
+ one character
+"""],
+["""\
+.. |sub| replace:: |sub|
+""",
+"""\
+<document source="test data">
+ <system_message level="3" line="1" names="sub" source="test data" type="ERROR">
+ <paragraph>
+ Circular substitution definition detected:
+ <literal_block xml:space="preserve">
+ .. |sub| replace:: |sub|
+"""],
+["""\
+.. |sub| replace:: |indirect1|
+.. |indirect1| replace:: |indirect2|
+.. |indirect2| replace:: |Sub|
+""",
+"""\
+<document source="test data">
+ <system_message level="3" line="1" names="sub" source="test data" type="ERROR">
+ <paragraph>
+ Circular substitution definition detected:
+ <literal_block xml:space="preserve">
+ .. |sub| replace:: |indirect1|
+ <system_message level="3" line="2" names="indirect1" source="test data" type="ERROR">
+ <paragraph>
+ Circular substitution definition detected:
+ <literal_block xml:space="preserve">
+ .. |indirect1| replace:: |indirect2|
+ <system_message level="3" line="3" names="indirect2" source="test data" type="ERROR">
+ <paragraph>
+ Circular substitution definition detected:
+ <literal_block xml:space="preserve">
+ .. |indirect2| replace:: |Sub|
+"""],
+["""\
+.. |indirect1| replace:: |indirect2|
+.. |indirect2| replace:: |Sub|
+.. |sub| replace:: |indirect1|
+
+Use |sub| and |indirect1| and |sub| again (and |sub| one more time).
+""",
+"""\
+<document source="test data">
+ <system_message level="3" line="1" names="indirect1" source="test data" type="ERROR">
+ <paragraph>
+ Circular substitution definition detected:
+ <literal_block xml:space="preserve">
+ .. |indirect1| replace:: |indirect2|
+ <system_message level="3" line="2" names="indirect2" source="test data" type="ERROR">
+ <paragraph>
+ Circular substitution definition detected:
+ <literal_block xml:space="preserve">
+ .. |indirect2| replace:: |Sub|
+ <system_message level="3" line="3" names="sub" source="test data" type="ERROR">
+ <paragraph>
+ Circular substitution definition detected:
+ <literal_block xml:space="preserve">
+ .. |sub| replace:: |indirect1|
+ <paragraph>
+ Use \n\
+ <problematic ids="id8" refid="id7">
+ |Sub|
+ and \n\
+ <problematic ids="id2" refid="id1">
+ |indirect1|
+ and \n\
+ <problematic ids="id4" refid="id3">
+ |sub|
+ again (and \n\
+ <problematic ids="id6" refid="id5">
+ |sub|
+ one more time).
+ <system_message backrefs="id2" ids="id1" level="3" line="5" source="test data" type="ERROR">
+ <paragraph>
+ Circular substitution definition referenced: "indirect1".
+ <system_message backrefs="id4" ids="id3" level="3" line="5" source="test data" type="ERROR">
+ <paragraph>
+ Circular substitution definition referenced: "sub".
+ <system_message backrefs="id6" ids="id5" level="3" line="5" source="test data" type="ERROR">
+ <paragraph>
+ Circular substitution definition referenced: "sub".
+ <system_message backrefs="id8" ids="id7" level="3" line="5" source="test data" type="ERROR">
+ <paragraph>
+ Circular substitution definition referenced: "Sub".
+"""],
+])
+
+totest['unicode'] = ((Substitutions,), [
+["""\
+Insert an em-dash (|mdash|), a copyright symbol (|copy|), a non-breaking
+space (|nbsp|), a backwards-not-equals (|bne|), and a captial omega (|Omega|).
+
+.. |mdash| unicode:: 0x02014
+.. |copy| unicode:: \\u00A9
+.. |nbsp| unicode::  
+.. |bne| unicode:: U0003D U020E5
+.. |Omega| unicode:: U+003A9
+""",
+u"""\
+<document source="test data">
+ <paragraph>
+ Insert an em-dash (
+ \u2014
+ ), a copyright symbol (
+ \u00a9
+ ), a non-breaking
+ space (
+ \u00a0
+ ), a backwards-not-equals (
+ =
+ \u20e5
+ ), and a captial omega (
+ \u03a9
+ ).
+ <substitution_definition names="mdash">
+ \u2014
+ <substitution_definition names="copy">
+ \u00a9
+ <substitution_definition names="nbsp">
+ \u00a0
+ <substitution_definition names="bne">
+ =
+ \u20e5
+ <substitution_definition names="Omega">
+ \u03a9
+"""],
+["""
+Testing comments and extra text.
+
+Copyright |copy| 2003, |BogusMegaCorp (TM)|.
+
+.. |copy| unicode:: 0xA9 .. copyright sign
+.. |BogusMegaCorp (TM)| unicode:: BogusMegaCorp U+2122
+ .. with trademark sign
+""",
+u"""\
+<document source="test data">
+ <paragraph>
+ Testing comments and extra text.
+ <paragraph>
+ Copyright \n\
+ \u00a9
+ 2003, \n\
+ BogusMegaCorp
+ \u2122
+ .
+ <substitution_definition names="copy">
+ \u00a9
+ <substitution_definition names="BogusMegaCorp\\ (TM)">
+ BogusMegaCorp
+ \u2122
+"""],
+["""\
+Insert an em-dash |---| automatically trimming whitespace.
+Some substitutions |TM| only need |rarrow| trimming on one side.
+
+.. |---| unicode:: U+02014
+ :trim:
+.. |TM| unicode:: U+02122
+ :ltrim:
+.. |rarrow| unicode:: U+2192
+ :rtrim:
+""",
+u"""\
+<document source="test data">
+ <paragraph>
+ Insert an em-dash
+ \u2014
+ automatically trimming whitespace.
+ Some substitutions
+ \u2122
+ only need \n\
+ \u2192
+ trimming on one side.
+ <substitution_definition ltrim="1" names="---" rtrim="1">
+ \u2014
+ <substitution_definition ltrim="1" names="TM">
+ \u2122
+ <substitution_definition names="rarrow" rtrim="1">
+ \u2192
+"""],
+["""\
+Substitution definition with an illegal element:
+
+.. |target| replace:: _`target`
+
+Make sure this substitution definition is not registered: |target|
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ Substitution definition with an illegal element:
+ <system_message level="3" line="3" source="test data" type="ERROR">
+ <paragraph>
+ Substitution definition contains illegal element <target>:
+ <literal_block xml:space="preserve">
+ <target ids="target" names="target">
+ target
+ <literal_block xml:space="preserve">
+ .. |target| replace:: _`target`
+ <paragraph>
+ Make sure this substitution definition is not registered: \n\
+ <problematic ids="id2" refid="id1">
+ |target|
+ <system_message backrefs="id2" ids="id1" level="3" line="5" source="test data" type="ERROR">
+ <paragraph>
+ Undefined substitution referenced: "target".
+"""],
+])
+
+
+if __name__ == '__main__':
+ import unittest
+ unittest.main(defaultTest='suite')
--- /dev/null
+#! /usr/bin/env python
+
+# $Id: test_target_notes.py 8356 2019-08-26 16:44:19Z milde $
+# Author: David Goodger <goodger@python.org>
+# Copyright: This module has been placed in the public domain.
+
+"""
+Tests for `docutils.transforms.references.TargetNotes` (via
+`docutils.transforms.universal.LastReaderPending`).
+"""
+from __future__ import absolute_import
+
+from . import DocutilsTestSupport
+from docutils.transforms.references import PropagateTargets, \
+ AnonymousHyperlinks, IndirectHyperlinks, ExternalTargets, \
+ InternalTargets, DanglingReferences, Footnotes
+from docutils.parsers.rst import Parser
+
+
+def suite():
+ parser = Parser()
+ s = DocutilsTestSupport.TransformTestSuite(parser)
+ s.generateTests(totest)
+ return s
+
+totest = {}
+
+totest['tables_of_contents'] = ((PropagateTargets, AnonymousHyperlinks,
+ IndirectHyperlinks,
+ ExternalTargets, InternalTargets,
+ DanglingReferences,
+ ), [
+["""\
+.. _target: http://example.org
+
+A reference to a target_.
+
+.. target-notes::
+""",
+"""\
+<document source="test data">
+ <target ids="target" names="target" refuri="http://example.org">
+ <paragraph>
+ A reference to a \n\
+ <reference name="target" refuri="http://example.org">
+ target
+ \n\
+ <footnote_reference auto="1" ids="id2" refid="id1">
+ .
+ <footnote auto="1" ids="id1" names="TARGET_NOTE:\\ id1">
+ <paragraph>
+ <reference refuri="http://example.org">
+ http://example.org
+"""],
+["""\
+.. _target: http://example.org
+
+A reference to a target_.
+
+.. target-notes:: :class: custom
+""",
+"""\
+<document source="test data">
+ <target ids="target" names="target" refuri="http://example.org">
+ <paragraph>
+ A reference to a \n\
+ <reference name="target" refuri="http://example.org">
+ target
+ <inline classes="custom">
+ \n\
+ <footnote_reference auto="1" classes="custom" ids="id2" refid="id1">
+ .
+ <footnote auto="1" ids="id1" names="TARGET_NOTE:\\ id1">
+ <paragraph>
+ <reference refuri="http://example.org">
+ http://example.org
+"""],
+])
+
+
+if __name__ == '__main__':
+ import unittest
+ unittest.main(defaultTest='suite')
--- /dev/null
+#! /usr/bin/env python
+
+# $Id: test_transitions.py 8356 2019-08-26 16:44:19Z milde $
+# Author: David Goodger <goodger@python.org>
+# Copyright: This module has been placed in the public domain.
+
+"""
+Test module for misc.Transitions transform.
+"""
+from __future__ import absolute_import
+
+from . import DocutilsTestSupport # must be imported before docutils
+from docutils.transforms.misc import Transitions
+from docutils.parsers.rst import Parser
+
+
+def suite():
+ parser = Parser()
+ s = DocutilsTestSupport.TransformTestSuite(parser)
+ s.generateTests(totest)
+ return s
+
+
+totest = {}
+
+totest['transitions'] = ((Transitions,), [
+["""\
+Section 1
+=========
+
+Subsection 1
+------------
+
+Some text.
+
+----------
+
+Section 2
+=========
+
+Some text.
+""",
+"""\
+<document source="test data">
+ <section ids="section-1" names="section\\ 1">
+ <title>
+ Section 1
+ <section ids="subsection-1" names="subsection\\ 1">
+ <title>
+ Subsection 1
+ <paragraph>
+ Some text.
+ <transition>
+ <section ids="section-2" names="section\\ 2">
+ <title>
+ Section 2
+ <paragraph>
+ Some text.
+"""],
+["""\
+A paragraph.
+
+----------
+
+Section 1
+=========
+
+Paragraph.
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ A paragraph.
+ <transition>
+ <section ids="section-1" names="section\\ 1">
+ <title>
+ Section 1
+ <paragraph>
+ Paragraph.
+"""],
+["""\
+--------
+
+A section or document may not begin with a transition.
+
+The DTD specifies that two transitions may not
+be adjacent:
+
+--------
+
+--------
+
+--------
+
+The DTD also specifies that a section or document
+may not end with a transition.
+
+--------
+""",
+"""\
+<document source="test data">
+ <system_message level="3" line="1" source="test data" type="ERROR">
+ <paragraph>
+ Document or section may not begin with a transition.
+ <transition>
+ <paragraph>
+ A section or document may not begin with a transition.
+ <paragraph>
+ The DTD specifies that two transitions may not
+ be adjacent:
+ <transition>
+ <system_message level="3" line="10" source="test data" type="ERROR">
+ <paragraph>
+ At least one body element must separate transitions; adjacent transitions are not allowed.
+ <transition>
+ <system_message level="3" line="12" source="test data" type="ERROR">
+ <paragraph>
+ At least one body element must separate transitions; adjacent transitions are not allowed.
+ <transition>
+ <paragraph>
+ The DTD also specifies that a section or document
+ may not end with a transition.
+ <transition>
+ <system_message level="3" line="17" source="test data" type="ERROR">
+ <paragraph>
+ Document may not end with a transition.
+"""],
+["""\
+Sections with transitions at beginning and end.
+
+Section 1
+=========
+
+----------
+
+The next transition is legal:
+
+----------
+
+Section 2
+=========
+
+----------
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ Sections with transitions at beginning and end.
+ <section ids="section-1" names="section\\ 1">
+ <title>
+ Section 1
+ <system_message level="3" line="6" source="test data" type="ERROR">
+ <paragraph>
+ Document or section may not begin with a transition.
+ <transition>
+ <paragraph>
+ The next transition is legal:
+ <transition>
+ <section ids="section-2" names="section\\ 2">
+ <title>
+ Section 2
+ <system_message level="3" line="15" source="test data" type="ERROR">
+ <paragraph>
+ Document or section may not begin with a transition.
+ <transition>
+ <system_message level="3" line="15" source="test data" type="ERROR">
+ <paragraph>
+ Document may not end with a transition.
+"""],
+["""\
+A paragraph and two transitions.
+
+----------
+
+----------
+""", # the same:
+"""\
+<document source="test data">
+ <paragraph>
+ A paragraph and two transitions.
+ <transition>
+ <system_message level="3" line="5" source="test data" type="ERROR">
+ <paragraph>
+ At least one body element must separate transitions; adjacent transitions are not allowed.
+ <transition>
+ <system_message level="3" line="5" source="test data" type="ERROR">
+ <paragraph>
+ Document may not end with a transition.
+"""],
+["""\
+A paragraph, two transitions, and a blank line.
+
+----------
+
+----------
+
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ A paragraph, two transitions, and a blank line.
+ <transition>
+ <system_message level="3" line="5" source="test data" type="ERROR">
+ <paragraph>
+ At least one body element must separate transitions; adjacent transitions are not allowed.
+ <transition>
+ <system_message level="3" line="5" source="test data" type="ERROR">
+ <paragraph>
+ Document may not end with a transition.
+"""],
+["""\
+----------
+
+Document beginning with a transition.
+""",
+"""\
+<document source="test data">
+ <system_message level="3" line="1" source="test data" type="ERROR">
+ <paragraph>
+ Document or section may not begin with a transition.
+ <transition>
+ <paragraph>
+ Document beginning with a transition.
+"""],
+["""\
+Section 1
+=========
+
+----------
+
+----------
+
+----------
+
+Section 2
+=========
+
+Some text.
+""",
+"""\
+<document source="test data">
+ <section ids="section-1" names="section\\ 1">
+ <title>
+ Section 1
+ <system_message level="3" line="4" source="test data" type="ERROR">
+ <paragraph>
+ Document or section may not begin with a transition.
+ <transition>
+ <system_message level="3" line="6" source="test data" type="ERROR">
+ <paragraph>
+ At least one body element must separate transitions; adjacent transitions are not allowed.
+ <transition>
+ <system_message level="3" line="8" source="test data" type="ERROR">
+ <paragraph>
+ At least one body element must separate transitions; adjacent transitions are not allowed.
+ <transition>
+ <section ids="section-2" names="section\\ 2">
+ <title>
+ Section 2
+ <paragraph>
+ Some text.
+"""],
+["""\
+----------
+
+----------
+
+----------
+""",
+"""\
+<document source="test data">
+ <system_message level="3" line="1" source="test data" type="ERROR">
+ <paragraph>
+ Document or section may not begin with a transition.
+ <transition>
+ <system_message level="3" line="3" source="test data" type="ERROR">
+ <paragraph>
+ At least one body element must separate transitions; adjacent transitions are not allowed.
+ <transition>
+ <system_message level="3" line="5" source="test data" type="ERROR">
+ <paragraph>
+ At least one body element must separate transitions; adjacent transitions are not allowed.
+ <transition>
+ <system_message level="3" line="5" source="test data" type="ERROR">
+ <paragraph>
+ Document may not end with a transition.
+"""],
+["""\
+A paragraph.
+
+----------
+
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ A paragraph.
+ <transition>
+ <system_message level="3" line="3" source="test data" type="ERROR">
+ <paragraph>
+ Document may not end with a transition.
+"""],
+])
+
+
+if __name__ == '__main__':
+ import unittest
+ unittest.main(defaultTest='suite')
--- /dev/null
+#! /usr/bin/env python
+
+# $Id: test_writer_aux.py 8356 2019-08-26 16:44:19Z milde $
+# Author: Lea Wiemann <LeWiemann@gmail.com>
+# Copyright: This module has been placed in the public domain.
+
+"""
+Test module for writer_aux transforms.
+"""
+from __future__ import absolute_import
+
+from . import DocutilsTestSupport # must be imported before docutils
+from docutils.transforms import writer_aux
+from docutils.parsers.rst import Parser
+
+def suite():
+ parser = Parser()
+ s = DocutilsTestSupport.TransformTestSuite(parser)
+ s.generateTests(totest)
+ return s
+
+
+totest = {}
+
+totest['compound'] = ((writer_aux.Compound,), [
+["""\
+.. class:: compound
+
+.. compound::
+
+ .. class:: paragraph1
+
+ Paragraph 1.
+
+ .. class:: paragraph2
+
+ Paragraph 2.
+
+ Block quote.
+""",
+"""\
+<document source="test data">
+ <paragraph classes="paragraph1 compound">
+ Paragraph 1.
+ <paragraph classes="paragraph2 continued">
+ Paragraph 2.
+ <block_quote classes="continued">
+ <paragraph>
+ Block quote.
+"""],
+])
+
+totest['admonitions'] = ((writer_aux.Admonitions,), [
+["""\
+.. note::
+
+ These are the note contents.
+
+ Another paragraph.
+""",
+"""\
+<document source="test data">
+ <admonition classes="note">
+ <title>
+ Note
+ <paragraph>
+ These are the note contents.
+ <paragraph>
+ Another paragraph.
+"""],
+["""\
+.. admonition:: Generic
+
+ Admonitions contents...
+""",
+"""\
+<document source="test data">
+ <admonition classes="admonition-generic admonition">
+ <title>
+ Generic
+ <paragraph>
+ Admonitions contents...
+"""],
+])
+
+
+if __name__ == '__main__':
+ import unittest
+ unittest.main(defaultTest='suite')
--- /dev/null
+#! /usr/bin/env python
+
+# $Id: test_traversals.py 7463 2012-06-22 19:49:51Z milde $
+# Author: Martin Blais <blais@furius.ca>
+# Copyright: This module has been placed in the public domain.
+
+"""
+Test module for traversals.
+"""
+
+import unittest
+import DocutilsTestSupport # must be imported before docutils
+from docutils import nodes, core, io, utils, writers
+from docutils.writers.null import Writer as NullWriter
+import docutils
+
+
+
+stop_traversal_input = '''
+==================
+ Train Travel
+==================
+
+Happily, happily going by train.
+
+.. attention:: Attention, attention. This is a public annoucement.
+ You must get off the train now.
+
+KaZoom! Train crashes.
+
+- Told ya!!! Get off the train next time.
+
+'''
+
+class AttentiveVisitor(nodes.SparseNodeVisitor):
+
+ def visit_attention(self, node):
+ raise nodes.StopTraversal
+
+ def visit_bullet_list(self, node):
+ raise RuntimeError("It's too late for attention, "
+ "more discipline is needed!.")
+
+class AttentiveWriter(writers.Writer):
+
+ def translate(self):
+ self.visitor = visitor = AttentiveVisitor(self.document)
+
+ # Test both kinds of traversals.
+ self.document.walkabout(visitor)
+ self.document.walk(visitor)
+
+class StopTraversalTests(unittest.TestCase, docutils.SettingsSpec):
+
+ """
+ Test interrupting the visitor during traversal. In this test we stop it
+ when we reach an attention node.
+ """
+ def test_stop_traversal(self):
+ # Load some document tree in memory.
+ doctree = docutils.core.publish_doctree(
+ source=stop_traversal_input,
+ reader_name='standalone',
+ parser_name='restructuredtext',
+ settings_spec=self)
+ self.assertTrue(isinstance(doctree, nodes.document))
+
+ parts = docutils.core.publish_parts(
+ reader_name='doctree', source_class=docutils.io.DocTreeInput,
+ source=doctree, source_path='test',
+ writer=AttentiveWriter())
+
+
+if __name__ == '__main__':
+ unittest.main()
+
--- /dev/null
+#! /usr/bin/env python
+# -*- coding: utf-8 -*-
+
+# $Id: test_utils.py 8368 2019-08-27 12:10:14Z milde $
+# Author: David Goodger <goodger@python.org>
+# Copyright: This module has been placed in the public domain.
+
+"""
+Test module for utils/__init__.py.
+"""
+
+import os
+import sys
+import unittest
+
+from DocutilsTestSupport import docutils, utils, nodes
+
+if sys.version_info >= (3, 0):
+ from io import StringIO
+else:
+ from StringIO import StringIO
+
+
+class ReporterTests(unittest.TestCase):
+
+ stream = StringIO()
+ reporter = utils.Reporter('test data', 2, 4, stream, 1)
+
+ def setUp(self):
+ self.stream.seek(0)
+ self.stream.truncate()
+
+ def test_level0(self):
+ sw = self.reporter.system_message(0, 'debug output')
+ self.assertEqual(sw.pformat(), """\
+<system_message level="0" source="test data" type="DEBUG">
+ <paragraph>
+ debug output
+""")
+ self.assertEqual(self.stream.getvalue(),
+ 'test data:: (DEBUG/0) debug output\n')
+
+ def test_level1(self):
+ sw = self.reporter.system_message(1, 'a little reminder')
+ self.assertEqual(sw.pformat(), """\
+<system_message level="1" source="test data" type="INFO">
+ <paragraph>
+ a little reminder
+""")
+ self.assertEqual(self.stream.getvalue(), '')
+
+ def test_level2(self):
+ sw = self.reporter.system_message(2, 'a warning')
+ self.assertEqual(sw.pformat(), """\
+<system_message level="2" source="test data" type="WARNING">
+ <paragraph>
+ a warning
+""")
+ self.assertEqual(self.stream.getvalue(),
+ 'test data:: (WARNING/2) a warning\n')
+
+ def test_level3(self):
+ sw = self.reporter.system_message(3, 'an error')
+ self.assertEqual(sw.pformat(), """\
+<system_message level="3" source="test data" type="ERROR">
+ <paragraph>
+ an error
+""")
+ self.assertEqual(self.stream.getvalue(),
+ 'test data:: (ERROR/3) an error\n')
+
+ def test_level4(self):
+ self.assertRaises(utils.SystemMessage, self.reporter.system_message, 4,
+ 'a severe error, raises an exception')
+ self.assertEqual(self.stream.getvalue(), 'test data:: (SEVERE/4) '
+ 'a severe error, raises an exception\n')
+
+
+ def test_unicode_message(self):
+ sw = self.reporter.system_message(0, u'mesidʒ')
+ self.assertEqual(sw.pformat(), u"""\
+<system_message level="0" source="test data" type="DEBUG">
+ <paragraph>
+ mesidʒ
+""")
+
+ def test_unicode_message_from_exception(self):
+ """Workaround for Python < 2.6 bug:
+ unicode(<exception instance>) uses __str__
+ and hence fails with unicode message"""
+ try:
+ raise Exception(u'mesidʒ')
+ except Exception as err:
+ sw = self.reporter.system_message(0, err)
+ self.assertEqual(sw.pformat(), u"""\
+<system_message level="0" source="test data" type="DEBUG">
+ <paragraph>
+ mesidʒ
+""")
+
+class QuietReporterTests(unittest.TestCase):
+
+ stream = StringIO()
+ reporter = utils.Reporter('test data', 5, 5, stream, 0)
+
+ def setUp(self):
+ self.stream.seek(0)
+ self.stream.truncate()
+
+ def test_debug(self):
+ sw = self.reporter.debug('a debug message')
+ # None because debug is disabled.
+ self.assertEqual(sw, None)
+ self.assertEqual(self.stream.getvalue(), '')
+
+ def test_info(self):
+ sw = self.reporter.info('an informational message')
+ self.assertEqual(sw.pformat(), """\
+<system_message level="1" source="test data" type="INFO">
+ <paragraph>
+ an informational message
+""")
+ self.assertEqual(self.stream.getvalue(), '')
+
+ def test_warning(self):
+ sw = self.reporter.warning('a warning')
+ self.assertEqual(sw.pformat(), """\
+<system_message level="2" source="test data" type="WARNING">
+ <paragraph>
+ a warning
+""")
+ self.assertEqual(self.stream.getvalue(), '')
+
+ def test_error(self):
+ sw = self.reporter.error('an error')
+ self.assertEqual(sw.pformat(), """\
+<system_message level="3" source="test data" type="ERROR">
+ <paragraph>
+ an error
+""")
+ self.assertEqual(self.stream.getvalue(), '')
+
+ def test_severe(self):
+ sw = self.reporter.severe('a severe error')
+ self.assertEqual(sw.pformat(), """\
+<system_message level="4" source="test data" type="SEVERE">
+ <paragraph>
+ a severe error
+""")
+ self.assertEqual(self.stream.getvalue(), '')
+
+
+class NameValueTests(unittest.TestCase):
+
+ def test_extract_name_value(self):
+ self.assertRaises(utils.NameValueError, utils.extract_name_value,
+ 'hello')
+ self.assertRaises(utils.NameValueError, utils.extract_name_value,
+ 'hello')
+ self.assertRaises(utils.NameValueError, utils.extract_name_value,
+ '=hello')
+ self.assertRaises(utils.NameValueError, utils.extract_name_value,
+ 'hello=')
+ self.assertRaises(utils.NameValueError, utils.extract_name_value,
+ 'hello="')
+ self.assertRaises(utils.NameValueError, utils.extract_name_value,
+ 'hello="something')
+ self.assertRaises(utils.NameValueError, utils.extract_name_value,
+ 'hello="something"else')
+ output = utils.extract_name_value(
+ """att1=val1 att2=val2 att3="value number '3'" att4=val4""")
+ self.assertEqual(output, [('att1', 'val1'), ('att2', 'val2'),
+ ('att3', "value number '3'"),
+ ('att4', 'val4')])
+
+
+class ExtensionOptionTests(unittest.TestCase):
+
+ optionspec = {'a': int, 'bbb': float, 'cdef': (lambda x: x),
+ 'empty': (lambda x: x)}
+
+ def test_assemble_option_dict(self):
+ input = utils.extract_name_value('a=1 bbb=2.0 cdef=hol%s' % chr(224))
+ self.assertEqual(
+ utils.assemble_option_dict(input, self.optionspec),
+ {'a': 1, 'bbb': 2.0, 'cdef': ('hol%s' % chr(224))})
+ input = utils.extract_name_value('a=1 b=2.0 c=hol%s' % chr(224))
+ self.assertRaises(KeyError, utils.assemble_option_dict,
+ input, self.optionspec)
+ input = utils.extract_name_value('a=1 bbb=two cdef=hol%s' % chr(224))
+ self.assertRaises(ValueError, utils.assemble_option_dict,
+ input, self.optionspec)
+
+ def test_extract_extension_options(self):
+ field_list = nodes.field_list()
+ field_list += nodes.field(
+ '', nodes.field_name('', 'a'),
+ nodes.field_body('', nodes.paragraph('', '1')))
+ field_list += nodes.field(
+ '', nodes.field_name('', 'bbb'),
+ nodes.field_body('', nodes.paragraph('', '2.0')))
+ field_list += nodes.field(
+ '', nodes.field_name('', 'cdef'),
+ nodes.field_body('', nodes.paragraph('', u'hol\u00e0')))
+ field_list += nodes.field(
+ '', nodes.field_name('', 'empty'), nodes.field_body())
+ self.assertEqual(
+ utils.extract_extension_options(field_list, self.optionspec),
+ {'a': 1, 'bbb': 2.0,
+ 'cdef': u'hol\u00e0',
+ 'empty': None})
+ self.assertRaises(KeyError, utils.extract_extension_options,
+ field_list, {})
+ field_list += nodes.field(
+ '', nodes.field_name('', 'cdef'),
+ nodes.field_body('', nodes.paragraph('', 'one'),
+ nodes.paragraph('', 'two')))
+ self.assertRaises(utils.BadOptionDataError,
+ utils.extract_extension_options,
+ field_list, self.optionspec)
+ field_list[-1] = nodes.field(
+ '', nodes.field_name('', 'cdef bad'),
+ nodes.field_body('', nodes.paragraph('', 'no arguments')))
+ self.assertRaises(utils.BadOptionError,
+ utils.extract_extension_options,
+ field_list, self.optionspec)
+ field_list[-1] = nodes.field(
+ '', nodes.field_name('', 'cdef'),
+ nodes.field_body('', nodes.paragraph('', 'duplicate')))
+ self.assertRaises(utils.DuplicateOptionError,
+ utils.extract_extension_options,
+ field_list, self.optionspec)
+ field_list[-2] = nodes.field(
+ '', nodes.field_name('', 'unkown'),
+ nodes.field_body('', nodes.paragraph('', 'unknown')))
+ self.assertRaises(KeyError, utils.extract_extension_options,
+ field_list, self.optionspec)
+
+
+class HelperFunctionTests(unittest.TestCase):
+
+ # Test conversion from `version information tuple` to a PEP 440 compliant
+ # Docutils version identifier.
+ # See 'Version Numbering' in docs/dev/policies.txt.
+ def test_version_identifier(self):
+ release_0_14_final = docutils.VersionInfo(
+ major=0, minor=14, micro=0,
+ releaselevel='final', serial=0, release=True)
+ self.assertEqual(utils.version_identifier(release_0_14_final), '0.14')
+ dev_0_15_beta = docutils.VersionInfo(
+ major=0, minor=15, micro=0,
+ releaselevel='beta', serial=0, release=False)
+ self.assertEqual(utils.version_identifier(dev_0_15_beta), '0.15b.dev')
+ release_0_14_rc1 = docutils.VersionInfo(
+ major=0, minor=14, micro=0,
+ releaselevel='candidate', serial=1, release=True)
+ self.assertEqual(utils.version_identifier(release_0_14_rc1), '0.14rc1')
+
+ def test_implicit_version_identifier(self):
+ self.assertEqual(
+ utils.version_identifier(docutils.__version_info__),
+ utils.version_identifier())
+
+ def test_normalize_language_tag(self):
+ self.assertEqual(utils.normalize_language_tag('de'), ['de'])
+ self.assertEqual(utils.normalize_language_tag('de-AT'),
+ ['de-at', 'de'])
+ self.assertEqual(utils.normalize_language_tag('de-AT-1901'),
+ ['de-at-1901', 'de-at', 'de-1901', 'de'])
+ self.assertEqual(utils.normalize_language_tag('de-AT-1901-frak'),
+ ['de-at-1901-frak', 'de-at-1901', 'de-at-frak',
+ 'de-1901-frak', 'de-at', 'de-1901', 'de-frak', 'de'])
+ self.assertEqual(utils.normalize_language_tag('grc-ibycus-x-altquot'),
+ ['grc-ibycus-x-altquot', 'grc-ibycus',
+ 'grc-x-altquot', 'grc'])
+
+ def test_column_width(self):
+ self.assertEqual(utils.column_width(u'de'), 2)
+ self.assertEqual(utils.column_width(u'dâ'), 2) # pre-composed
+ self.assertEqual(utils.column_width(u'dâ'), 2) # combining
+
+ def test_relative_path(self):
+ # Build and return a path to `target`, relative to `source`:
+ # Use '/' as path sep in result.
+ self.assertEqual(utils.relative_path('spam', 'spam'), '')
+ source = os.path.join('h\xE4m', 'spam', 'fileA')
+ target = os.path.join('h\xE4m', 'spam', 'fileB')
+ self.assertEqual(utils.relative_path(source, target), 'fileB')
+ source = os.path.join('h\xE4m', 'spam', 'fileA')
+ target = os.path.join('h\xE4m', 'fileB')
+ self.assertEqual(utils.relative_path(source, target), '../fileB')
+ # if source is None, default to the cwd:
+ target = os.path.join('eggs', 'fileB')
+ self.assertEqual(utils.relative_path(None, target), 'eggs/fileB')
+ # If there is no common prefix, return the absolute path to `target`:
+ # source = '/foo/bar/fileA' # POSIX
+ # TODO: how to specify an absolute path independent of the OS?
+ # target = os.path.join('eggs', 'fileB')
+ # self.assertEqual(utils.relative_path(source, target),
+ # os.path.abspath('fileB'))
+ # Correctly process unicode instances:
+ self.assertEqual(utils.relative_path(u'spam', u'spam'), u'')
+ source = os.path.join(u'h\xE4m', u'spam', u'fileA')
+ target = os.path.join(u'h\xE4m', u'spam', u'fileB')
+ self.assertEqual(utils.relative_path(source, target), u'fileB')
+ source = os.path.join(u'h\xE4m', u'spam', u'fileA')
+ target = os.path.join(u'h\xE4m', u'fileB')
+ self.assertEqual(utils.relative_path(source, target), u'../fileB')
+ # if source is None, default to the cwd:
+ target = os.path.join(u'eggs', u'fileB')
+ self.assertEqual(utils.relative_path(None, target), u'eggs/fileB')
+
+ def test_find_file_in_dirs(self):
+ # Search for file `path` in the sequence of directories `dirs`.
+ # Return the first expansion that matches an existing file.
+ dirs = ('nonex', '.', '..')
+ found = utils.find_file_in_dirs('HISTORY.txt', dirs)
+ # returns
+ # '..\\HISTORY.txt' on windows
+ # '../HISTORY.txt' on other platforms
+ # 'HISTORY.txt' if not called from docutils directory.
+ self.assertTrue(found.startswith('..'))
+ # Return `path` if the file exists in the cwd or if there is no match
+ self.assertEqual(utils.find_file_in_dirs('alltests.py', dirs),
+ 'alltests.py')
+ self.assertEqual(utils.find_file_in_dirs('gibts/nicht.txt', dirs),
+ 'gibts/nicht.txt')
+
+ # samples for the (un)escaping tests:
+ escaped = r'escapes: \*one, \\*two, \\\*three in\side no\ space' + '\\'
+ nulled = ('escapes: \x00*one, \x00\\*two, \x00\\\x00*three'
+ + ' in\x00side no\x00 space\x00')
+ unescaped = r'escapes: *one, \*two, \*three inside nospace'
+
+ def test_escape2null(self):
+ nulled = utils.escape2null(self.escaped)
+ self.assertEqual(nulled, self.nulled)
+
+ def test_unescape(self):
+ unescaped = utils.unescape(self.nulled)
+ self.assertEqual(unescaped, self.unescaped)
+ restored = utils.unescape(self.nulled, restore_backslashes=True)
+ self.assertEqual(restored, self.escaped)
+
+if __name__ == '__main__':
+ unittest.main()
--- /dev/null
+#! /usr/bin/env python
+
+# $Id: test_viewlist.py 8346 2019-08-26 12:11:32Z milde $
+# Author: David Goodger <goodger@python.org>
+# Copyright: This module has been placed in the public domain.
+
+"""
+Test module for the ViewList class from statemachine.py.
+"""
+
+import unittest
+from DocutilsTestSupport import statemachine
+
+
+class ViewListTests(unittest.TestCase):
+
+ a_list = list('abcdefg')
+ b_list = list('AEIOU')
+ c_list = list('XYZ')
+
+ def setUp(self):
+ self.a = statemachine.ViewList(self.a_list, 'a')
+ self.b = statemachine.ViewList(self.b_list, 'b')
+ self.c = statemachine.ViewList(self.c_list, 'c')
+
+ def test_xitems(self):
+ self.assertEqual(list(self.b.xitems()),
+ [('b', 0, 'A'), ('b', 1, 'E'),
+ ('b', 2, 'I'), ('b', 3, 'O'), ('b', 4, 'U')])
+ self.assertEqual(list(self.c.xitems()),
+ [('c', 0, 'X'), ('c', 1, 'Y'), ('c', 2, 'Z')])
+
+ def test_lists(self):
+ # be compatible to standard lists whenever sensible:
+ self.assertEqual(self.a, self.a_list)
+ self.assertEqual(str(self.a), str(self.a_list))
+ self.assertEqual(self.b, self.b_list)
+ self.assertEqual(self.c, self.c_list)
+ self.assertEqual(len(self.a), len(self.a_list))
+ self.assertTrue('d' in self.a) # __contains__
+ self.assertEqual([value for value in self.a], self.a_list)
+ # get and set values
+ self.assertEqual(self.a[2], self.a_list[2])
+ a = self.a[:]
+ self.assertEqual(a, self.a)
+ a[1] = 3
+ self.assertEqual(a[1], 3)
+ # the `items` list contains the metadata (source/offset tuples)
+ self.assertEqual(self.a.items,
+ [('a', i) for (i, v) in enumerate(self.a_list)])
+
+ def test_special_class_methods(self):
+ # `repr` returns instantiation expression
+ self.assertEqual(repr(self.a), "ViewList(%s, items=%s)" %
+ (repr(self.a_list), repr(self.a.items)))
+ # `del` also deletes meta-data:
+ del(self.c[1])
+ self.assertEqual(list(self.c.xitems()),
+ [('c', 0, 'X'), ('c', 2, 'Z')])
+ # operators with extended behaviour
+ ab = self.a + self.b
+ self.assertEqual(ab, self.a_list + self.b_list)
+ self.assertEqual(ab.items, self.a.items + self.b.items)
+ aa = self.a * 2
+ self.assertEqual(aa, self.a_list * 2)
+ self.assertEqual(aa.items, self.a.items * 2)
+ self.a += self.b
+ self.assertEqual(self.a, self.a_list + self.b_list)
+ # self.assertEqual(self.a.items, self.a.items + self.b.items)
+
+ def test_get_slice(self):
+ a = self.a[1:-1]
+ a_list = self.a_list[1:-1]
+ self.assertEqual(a, a_list)
+ self.assertEqual(a.items, [('a', i+1) for (i, v) in enumerate(a_list)])
+ self.assertEqual(a.parent, self.a)
+
+ def test_set_slice(self):
+ a = statemachine.ViewList(self.a[:])
+ s = a[2:-2]
+ s[2:2] = self.b
+ s_list = self.a_list[2:-2]
+ s_list[2:2] = self.b_list
+ self.assertEqual(s, s_list)
+ self.assertEqual(s, a[2:-2])
+ self.assertEqual(s.items, a[2:-2].items)
+
+ def test_del_slice(self):
+ a = statemachine.ViewList(self.a[:])
+ s = a[2:]
+ s_list = self.a_list[2:]
+ del s[3:5]
+ del s_list[3:5]
+ self.assertEqual(s, s_list)
+ self.assertEqual(s, a[2:])
+ self.assertEqual(s.items, a[2:].items)
+
+ def test_insert(self):
+ a_list = self.a_list[:]
+ a_list.insert(2, 'Q')
+ a_list[4:4] = self.b_list
+ a = self.a[:]
+ self.assertTrue(isinstance(a, statemachine.ViewList))
+ a.insert(2, 'Q', 'runtime')
+ a.insert(4, self.b)
+ self.assertEqual(a, a_list)
+ self.assertEqual(a.info(2), ('runtime', 0))
+ self.assertEqual(a.info(5), ('b', 1))
+
+ def test_append(self):
+ a_list = self.a_list[:]
+ a_list.append('Q')
+ a_list.extend(self.b_list)
+ a = statemachine.ViewList(self.a)
+ a.append('Q', 'runtime')
+ a.append(self.b)
+ self.assertEqual(a, a_list)
+ self.assertEqual(a.info(len(self.a)), ('runtime', 0))
+ self.assertEqual(a.info(-2), ('b', len(self.b) - 2))
+
+ def test_extend(self):
+ a_list = self.a_list[:]
+ a_list.extend(self.b_list)
+ a = statemachine.ViewList(self.a)
+ a.extend(self.b)
+ self.assertEqual(a, a_list)
+ self.assertEqual(a.info(len(self.a) + 1), ('b', 1))
+
+ def test_view(self):
+ a = statemachine.ViewList(self.a[:])
+ a.insert(4, self.b)
+ s = a[2:-2]
+ s.insert(5, self.c)
+ self.assertEqual(s, a[2:-2])
+ self.assertEqual(s.items, a[2:-2].items)
+ s.pop()
+ self.assertEqual(s, a[2:-2])
+ self.assertEqual(s.items, a[2:-2].items)
+ s.remove('X')
+ self.assertEqual(s, a[2:-2])
+ self.assertEqual(s.items, a[2:-2].items)
+
+ def test_trim(self):
+ a = statemachine.ViewList(self.a[:])
+ s = a[1:-1]
+ s.trim_start(1)
+ self.assertEqual(a, self.a)
+ self.assertEqual(s, a[2:-1])
+ s.trim_end(1)
+ self.assertEqual(a, self.a)
+ self.assertEqual(s, a[2:-2])
+
+ def test_info(self):
+ ab = self.a + self.b
+ self.assertEqual(ab.info(0), ('a', 0))
+ self.assertEqual(ab.info(-1), ('b', len(self.b)-1))
+ # report source if index is off the list by one
+ self.assertEqual(ab.info(len(ab)), ('b', None))
+ # `source` and `offset` methods are based on info
+ self.assertEqual(ab.source(-1), 'b')
+ self.assertEqual(ab.offset(-1), len(self.b)-1)
+
+ def test_reverse(self):
+ c = self.c[:]
+ c.reverse()
+ self.assertEqual(list(c.xitems()),
+ [('c', 2, 'Z'), ('c', 1, 'Y'), ('c', 0, 'X')])
+
+ def test_sort(self):
+ c = self.c[:]
+ c.reverse()
+ c.sort()
+ self.assertEqual(self.c, c)
+
+
+class StringList(unittest.TestCase):
+
+ text = """\
+This is some
+example text.
+
+ Here is some
+ indented text.
+
+Unindented text.
+"""
+
+ indented_string = """\
+ a
+ literal
+ block"""
+
+
+ def setUp(self):
+ self.a_list = self.text.splitlines(1)
+ self.a = statemachine.StringList(self.a_list, 'a')
+
+ def test_trim_left(self):
+ s = self.a[3:5]
+ s.trim_left(4)
+ self.assertEqual(s, [line.lstrip() for line in self.a_list[3:5]])
+
+ def test_get_indented(self):
+ self.assertEqual(self.a.get_indented(),
+ ([], 0, 0))
+ block = statemachine.StringList(
+ statemachine.string2lines(self.indented_string))
+ self.assertEqual(block.get_indented(),
+ ([s[6:] for s in block], 6, 1))
+
+
+if __name__ == '__main__':
+ unittest.main()
--- /dev/null
+import os
+import os.path
+import sys
+
+sys.path.insert(0, os.path.abspath(os.path.dirname(__file__)))
+prev = ''
+while sys.path[0] != prev:
+ try:
+ import DocutilsTestSupport
+ break
+ except ImportError:
+ prev = sys.path[0]
+ sys.path[0] = os.path.dirname(prev)
+sys.path.pop(0)
--- /dev/null
+#!/usr/bin/env python
+
+# $Id: test_docutils_xml.py 8368 2019-08-27 12:10:14Z milde $
+# Author: Lea Wiemann <LeWiemann@gmail.com>
+# Copyright: This module has been placed in the public domain.
+
+"""
+Test for docutils XML writer.
+
+.. Attention::
+ While the tests compare the output on the string-level, no guarantee
+ is given against changes to identical XML representations like
+ ``<empty></empty>`` vs. ``<empty/>``. The sample strings in this test
+ module mirrors the current behaviour of the docutils_xml writer.
+"""
+from __future__ import absolute_import
+
+import sys
+
+from . import DocutilsTestSupport # must be imported before docutils
+import docutils
+import docutils.core
+
+if sys.version_info >= (3, 0):
+ from io import StringIO
+else:
+ from StringIO import StringIO
+
+# sample strings
+# --------------
+
+source = u"""\
+Test
+
+----------
+
+Test. \xe4\xf6\xfc\u20ac"""
+
+xmldecl = u"""<?xml version="1.0" encoding="iso-8859-1"?>
+"""
+
+doctypedecl = u"""\
+<!DOCTYPE document PUBLIC "+//IDN docutils.sourceforge.net\
+//DTD Docutils Generic//EN//XML"\
+ "http://docutils.sourceforge.net/docs/ref/docutils.dtd">
+"""
+
+generatedby = u'<!-- Generated by Docutils %s -->\n' % docutils.__version__
+
+bodynormal = u"""\
+<document source="<string>"><paragraph>Test</paragraph>\
+<transition></transition><paragraph>Test. \xe4\xf6\xfc€</paragraph>\
+</document>"""
+
+bodynewlines = u"""\
+<document source="<string>">
+<paragraph>Test</paragraph>
+<transition></transition>
+<paragraph>Test. \xe4\xf6\xfc€</paragraph>
+</document>
+"""
+
+bodyindents = u"""\
+<document source="<string>">
+ <paragraph>Test</paragraph>
+ <transition></transition>
+ <paragraph>Test. \xe4\xf6\xfc€</paragraph>
+</document>
+"""
+
+# raw XML
+# """""""
+
+raw_xml_source = u"""\
+.. raw:: xml
+
+ <root>
+ <child>Test \xe4\xf6\xfc\u20ac</child>
+ >
+ <
+
+ </root>
+
+.. role:: xml(raw)
+ :format: xml
+
+:xml:`<test>inline raw XML</test>`.
+"""
+
+raw_xml = u"""\
+<document source="<string>">
+<raw format="xml" xml:space="preserve"><root>
+ <child>Test \xe4\xf6\xfc€</child>
+ >
+ <
+
+</root></raw>
+<paragraph><raw classes="xml" format="xml" xml:space="preserve">\
+<test>inline raw XML</test></raw>.</paragraph>
+</document>
+"""
+
+invalid_raw_xml_source = u"""\
+.. raw:: xml
+
+ <root>
+ <child>Test \xe4\xf6\xfc\u20ac</child>
+ </mismatch>
+
+.. role:: xml(raw)
+ :format: xml
+
+:xml:`<test>inline raw XML</test>`.
+"""
+
+invalid_raw_xml = u"""\
+<document source="<string>">
+<raw format="xml" xml:space="preserve"><root>
+ <child>Test \xe4\xf6\xfc\u20ac</child>
+</mismatch></raw>
+<paragraph><raw classes="xml" format="xml" xml:space="preserve">\
+<test>inline raw XML</test></raw>.</paragraph>
+</document>
+"""
+
+
+def publish_xml(settings, source):
+ return docutils.core.publish_string(source=source.encode('utf8'),
+ reader_name='standalone',
+ writer_name='docutils_xml',
+ settings_overrides=settings)
+
+# XML Test Case
+# -------------
+
+class DocutilsXMLTestCase(DocutilsTestSupport.StandardTestCase):
+
+ settings = {'input_encoding': 'utf8',
+ 'output_encoding': 'iso-8859-1',
+ '_disable_config': True,
+ 'indents': False,
+ 'newlines': True,
+ 'xml_declaration': False,
+ 'doctype_declaration': False,
+ }
+
+ def test_publish(self):
+ settings = self.settings.copy()
+ settings['newlines'] = False
+ for settings['xml_declaration'] in True, False:
+ for settings['doctype_declaration'] in True, False:
+ expected = u''
+ if settings['xml_declaration']:
+ expected += xmldecl
+ if settings['doctype_declaration']:
+ expected += doctypedecl
+ expected += generatedby
+ expected += bodynormal
+ result = publish_xml(settings, source)
+ self.assertEqual(result, expected.encode('latin1'))
+
+ def test_publish_indents(self):
+ settings = self.settings.copy()
+ settings['indents'] = True
+ result = publish_xml(settings, source)
+ expected = (generatedby + bodyindents).encode('latin1')
+ self.assertEqual(result, expected)
+
+ def test_publish_newlines(self):
+ settings = self.settings.copy()
+ result = publish_xml(settings, source)
+ expected = (generatedby + bodynewlines).encode('latin1')
+ self.assertEqual(result, expected)
+
+ def test_raw_xml(self):
+ result = publish_xml(self.settings, raw_xml_source)
+ expected = (generatedby
+ + raw_xml).encode('latin1', 'xmlcharrefreplace')
+ self.assertEqual(result, expected)
+
+ def test_invalid_raw_xml(self):
+ warnings = StringIO()
+ settings = self.settings.copy()
+ settings['warning_stream'] = warnings
+ result = publish_xml(settings, invalid_raw_xml_source)
+ expected = (generatedby
+ + invalid_raw_xml).encode('latin1', 'xmlcharrefreplace')
+ self.assertEqual(result, expected)
+ warnings.seek(0)
+ self.assertEqual(warnings.readlines(),
+ [u'<string>:5: '
+ u'(WARNING/2) Invalid raw XML in column 2, line offset 3:\n',
+ u'<root>\n',
+ u' <child>Test \xe4\xf6\xfc\u20ac</child>\n',
+ u'</mismatch>\n',
+ u'<string>:10: '
+ u'(WARNING/2) Invalid raw XML in column 30, line offset 1:\n',
+ u'<test>inline raw XML</test>\n'])
+ # abort with SystemMessage if halt_level is "info":
+ settings['halt_level'] = 2
+ settings['warning_stream'] = ''
+ self.assertRaises(docutils.utils.SystemMessage,
+ publish_xml, settings, invalid_raw_xml_source)
+
+
+if __name__ == '__main__':
+ import unittest
+ unittest.main()
--- /dev/null
+#! /usr/bin/env python
+
+# $Id: test_get_writer_class.py 8356 2019-08-26 16:44:19Z milde $
+# Author: grubert
+# Maintainer: docutils-develop@lists.sourceforge.net
+# Copyright: This module has been placed in the public domain.
+
+"""
+test get_writer_class
+"""
+from __future__ import absolute_import
+
+from . import DocutilsTestSupport
+from docutils.writers import get_writer_class
+
+
+class GetWriterClassTestCase(DocutilsTestSupport.StandardTestCase):
+ #tests = ( ('manpage', 1), ('nope', 0), ('dummy-writer', 1))
+
+ def test_registered_writer(self):
+ wr = get_writer_class('manpage')
+ # raises ImportError on failure
+
+ def test_bogus_writer(self):
+ self.assertRaises(ImportError,
+ get_writer_class, 'nope')
+
+ def test_local_writer(self):
+ # requires local-writer.py in test directory (testroot)
+ wr = get_writer_class('local-writer')
+
+if __name__ == '__main__':
+ import unittest
+ unittest.main()
+
--- /dev/null
+#! /usr/bin/env python
+# coding: utf-8
+
+# $Id: test_html4css1_misc.py 8356 2019-08-26 16:44:19Z milde $
+# Authors: Lea Wiemann, Dmitry Shachnev, Günter Milde
+# Maintainer: docutils-develop@lists.sourceforge.net
+# Copyright: This module has been placed in the public domain.
+
+"""
+Miscellaneous HTML writer tests.
+"""
+from __future__ import absolute_import
+
+import os
+
+from .__init__ import DocutilsTestSupport
+from docutils import core
+
+
+class EncodingTestCase(DocutilsTestSupport.StandardTestCase):
+
+ def test_xmlcharrefreplace(self):
+ # Test that xmlcharrefreplace is the default output encoding
+ # error handler.
+ settings_overrides={
+ 'output_encoding': 'latin1',
+ 'stylesheet': '',
+ '_disable_config': True,}
+ result = core.publish_string(
+ u'EUR = \u20ac', writer_name='html4css1',
+ settings_overrides=settings_overrides)
+ # Encoding a euro sign with latin1 doesn't work, so the
+ # xmlcharrefreplace handler is used.
+ self.assertIn(b'EUR = €', result)
+
+class MovingArgsTestCase(DocutilsTestSupport.StandardTestCase):
+
+ settings_overrides={'stylesheet_path': '',
+ # 'embed_stylesheet': False,
+ '_disable_config': True,
+ }
+
+ def test_definition_list_item_classes(self):
+ # Do not drop class arguments for the definition list item.
+ # Pass them to to the term node instead.
+ data = """\
+first term:
+ fist def
+
+ .. class:: for the second item
+
+second term:
+ second def
+"""
+ result = core.publish_string(data, writer_name='html4css1',
+ settings_overrides=self.settings_overrides)
+ self.assertIn(b'<dt class="for the second item">second term:</dt>',
+ result)
+
+ def test_definition_list_item_name(self):
+ # Do not drop the "name" of the definition list item.
+ # Pass it to to the term node instead.
+ data = """\
+first term:
+ first def
+
+ .. _second item:
+
+second term:
+ second def
+"""
+ result = core.publish_string(data, writer_name='html4css1',
+ settings_overrides=self.settings_overrides)
+ self.assertIn(b'<dt id="second-item">second term:</dt>',
+ result)
+
+
+class SettingsTestCase(DocutilsTestSupport.StandardTestCase):
+ data = 'test'
+
+ def test_default_stylesheet(self):
+ # default style sheet, embedded
+ mysettings = {'_disable_config': True,}
+ styles = core.publish_parts(self.data, writer_name='html4css1',
+ settings_overrides=mysettings)['stylesheet']
+ self.assertIn('Default cascading style sheet '
+ 'for the HTML output of Docutils.', styles)
+
+ def test_default_stylesheet_linked(self):
+ # default style sheet, linked
+ mysettings = {'_disable_config': True,
+ 'embed_stylesheet': False}
+ styles = core.publish_parts(self.data, writer_name='html4css1',
+ settings_overrides=mysettings)['stylesheet']
+ self.assertIn('docutils/writers/html4css1/html4css1.css', styles)
+
+ def test_math_stylesheet_linked(self):
+ # default + math style sheet, linked
+ mysettings = {'_disable_config': True,
+ 'embed_stylesheet': False,
+ 'stylesheet_path': 'html4css1.css, math.css'}
+ styles = core.publish_parts(self.data, writer_name='html4css1',
+ settings_overrides=mysettings)['stylesheet']
+ self.assertIn('docutils/writers/html4css1/html4css1.css', styles)
+ self.assertIn('docutils/writers/html5_polyglot/math.css', styles)
+
+ def test_custom_stylesheet_linked(self):
+ # default + custom style sheet, linked
+ mysettings = {'_disable_config': True,
+ 'embed_stylesheet': False,
+ 'stylesheet_path': 'html4css1.css, '
+ 'data/ham.css'}
+ styles = core.publish_parts(self.data, writer_name='html4css1',
+ settings_overrides=mysettings)['stylesheet']
+ self.assertIn('docutils/writers/html4css1/html4css1.css', styles)
+ self.assertIn('href="data/ham.css"', styles)
+
+ def test_custom_stylesheet_dir(self):
+ mysettings = {'_disable_config': True,
+ 'embed_stylesheet': False,
+ 'stylesheet_dirs': ('../docutils/writers/html4css1/',
+ 'data'),
+ 'stylesheet_path': 'html4css1.css, ham.css'}
+ styles = core.publish_parts(self.data, writer_name='html4css1',
+ settings_overrides=mysettings)['stylesheet']
+ if os.path.isdir('../docutils/writers/html4css1/'):
+ self.assertIn('docutils/writers/html4css1/html4css1.css', styles)
+ self.assertIn('href="data/ham.css"', styles)
+
+ def test_custom_stylesheet_dir_embedded(self):
+ mysettings = {'_disable_config': True,
+ 'embed_stylesheet': True,
+ 'stylesheet_dirs': ('../docutils/writers/html4css1/',
+ 'data'),
+ 'stylesheet_path': 'ham.css'}
+ styles = core.publish_parts(self.data, writer_name='html4css1',
+ settings_overrides=mysettings)['stylesheet']
+ self.assertIn('dl.docutils dd {\n margin-bottom: 0.5em }', styles)
+
+class MathTestCase(DocutilsTestSupport.StandardTestCase):
+
+ """Attention: This class tests the current implementation of maths support
+ which is open to change in future Docutils releases. """
+
+ mathjax_script = '<script type="text/javascript" src="%s">'
+ default_mathjax_url = ('file:/usr/share/javascript/mathjax/MathJax.js'
+ '?config=TeX-AMS_CHTML')
+ custom_mathjax_url = ('/mathjax/MathJax.js?config=TeX-AMS-MML_HTMLorMML')
+ data = ':math:`42`'
+
+ def test_math_output_default(self):
+ # HTML with math.css stylesheet (since 0.11)
+ mysettings = {'_disable_config': True,}
+ styles = core.publish_parts(self.data, writer_name='html4css1',
+ settings_overrides=mysettings)['stylesheet']
+ self.assertIn('convert LaTeX equations to HTML output.', styles)
+
+ def test_math_output_mathjax(self):
+ # Explicitly specifying math_output=MathJax, case insensitively
+ # use default MathJax URL
+ mysettings = {'_disable_config': True,
+ 'report_level': 3,
+ 'math_output': 'MathJax'}
+ head = core.publish_parts(self.data, writer_name='html4css1',
+ settings_overrides=mysettings)['head']
+ self.assertIn(self.mathjax_script % self.default_mathjax_url, head)
+
+ def test_math_output_mathjax_custom(self):
+ # Customizing MathJax URL
+ mysettings = {'_disable_config': True,
+ 'math_output':
+ 'mathjax %s' % self.custom_mathjax_url}
+ head = core.publish_parts(self.data, writer_name='html4css1',
+ settings_overrides=mysettings)['head']
+ self.assertIn(self.mathjax_script % self.custom_mathjax_url, head)
+
+ def test_math_output_html(self):
+ mysettings = {'_disable_config': True,
+ 'math_output': 'HTML'}
+ head = core.publish_parts(self.data, writer_name='html4css1',
+ settings_overrides=mysettings)['head']
+ # There should be no MathJax script when math_output is not MathJax
+ self.assertNotIn('MathJax.js', head)
+
+ def test_math_output_html_stylesheet(self):
+ mysettings = {'_disable_config': True,
+ 'math_output': 'HTML math.css,custom/style.css',
+ 'stylesheet_dirs': ('.', 'functional/input/data'),
+ 'embed_stylesheet': False}
+ styles = core.publish_parts(self.data, writer_name='html4css1',
+ settings_overrides=mysettings)['stylesheet']
+ self.assertEqual(u"""\
+<link rel="stylesheet" href="functional/input/data/html4css1.css" type="text/css" />
+<link rel="stylesheet" href="functional/input/data/math.css" type="text/css" />
+<link rel="stylesheet" href="custom/style.css" type="text/css" />
+""", styles)
+
+ def test_math_output_mathjax_no_math(self):
+ mysettings = {'_disable_config': True,
+ 'math_output': 'MathJax'}
+ # There should be no math script when text does not contain math
+ head = core.publish_parts('No math.', writer_name='html4css1')['head']
+ self.assertNotIn('MathJax', head)
+
+
+if __name__ == '__main__':
+ import unittest
+ unittest.main()
--- /dev/null
+#! /usr/bin/env python
+
+# $Id: test_html4css1_parts.py 8356 2019-08-26 16:44:19Z milde $
+# Author: reggie dugard <reggie@users.sourceforge.net>
+# Copyright: This module has been placed in the public domain.
+
+"""
+Test for fragment code in HTML writer.
+
+Note: the 'body' and 'whole' entries have been removed from the parts
+dictionaries (redundant), along with 'meta' and 'stylesheet' entries with
+standard values, and any entries with empty values.
+"""
+from __future__ import absolute_import
+
+from . import DocutilsTestSupport
+from docutils import core
+
+
+def suite():
+ s = DocutilsTestSupport.HtmlPublishPartsTestSuite()
+ s.generateTests(totest)
+ return s
+
+
+totest = {}
+
+totest['Title promotion'] = ({'stylesheet_path': '',
+ 'embed_stylesheet': 0}, [
+["""\
+Simple String
+""",
+"""\
+{'fragment': '''<p>Simple String</p>\\n''',
+ 'html_body': '''<div class="document">
+<p>Simple String</p>
+</div>\\n''',
+ 'html_head': '''...<title><string></title>\\n'''}
+"""],
+["""\
+Simple String with *markup*
+""",
+"""\
+{'fragment': '''<p>Simple String with <em>markup</em></p>\\n''',
+ 'html_body': '''<div class="document">
+<p>Simple String with <em>markup</em></p>
+</div>\\n''',
+ 'html_head': '''...<title><string></title>\\n'''}
+"""],
+["""\
+Simple String with an even simpler ``inline literal``
+""",
+"""\
+{'fragment': '''<p>Simple String with an even simpler <tt class="docutils literal">inline literal</tt></p>\\n''',
+ 'html_body': '''<div class="document">
+<p>Simple String with an even simpler <tt class="docutils literal">inline literal</tt></p>
+</div>\\n''',
+ 'html_head': '''...<title><string></title>\\n'''}
+"""],
+["""\
+Simple ``inline\xA0literal`` with NBSP
+""",
+"""\
+{'fragment': '''<p>Simple <tt class="docutils literal">inline literal</tt> with NBSP</p>\\n''',
+ 'html_body': '''<div class="document">
+<p>Simple <tt class="docutils literal">inline literal</tt> with NBSP</p>
+</div>\\n''',
+ 'html_head': '''...<title><string></title>\\n'''}
+"""],
+["""\
+A simple `anonymous reference`__
+
+__ http://www.test.com/test_url
+""",
+"""\
+{'fragment': '''<p>A simple <a class="reference external" href="http://www.test.com/test_url">anonymous reference</a></p>\\n''',
+ 'html_body': '''<div class="document">
+<p>A simple <a class="reference external" href="http://www.test.com/test_url">anonymous reference</a></p>
+</div>\\n''',
+ 'html_head': '''...<title><string></title>\\n'''}
+"""],
+["""\
+One paragraph.
+
+Two paragraphs.
+""",
+"""\
+{'fragment': '''<p>One paragraph.</p>
+<p>Two paragraphs.</p>\\n''',
+ 'html_body': '''<div class="document">
+<p>One paragraph.</p>
+<p>Two paragraphs.</p>
+</div>\\n''',
+ 'html_head': '''...<title><string></title>\\n'''}
+"""],
+["""\
+A simple `named reference`_ with stuff in between the
+reference and the target.
+
+.. _`named reference`: http://www.test.com/test_url
+""",
+"""\
+{'fragment': '''<p>A simple <a class="reference external" href="http://www.test.com/test_url">named reference</a> with stuff in between the
+reference and the target.</p>\\n''',
+ 'html_body': '''<div class="document">
+<p>A simple <a class="reference external" href="http://www.test.com/test_url">named reference</a> with stuff in between the
+reference and the target.</p>
+</div>\\n''',
+ 'html_head': '''...<title><string></title>\\n'''}
+"""],
+["""\
++++++
+Title
++++++
+
+Subtitle
+========
+
+Some stuff
+
+Section
+-------
+
+Some more stuff
+
+Another Section
+...............
+
+And even more stuff
+""",
+"""\
+{'fragment': '''<p>Some stuff</p>
+<div class="section" id="section">
+<h1>Section</h1>
+<p>Some more stuff</p>
+<div class="section" id="another-section">
+<h2>Another Section</h2>
+<p>And even more stuff</p>
+</div>
+</div>\\n''',
+ 'html_body': '''<div class="document" id="title">
+<h1 class="title">Title</h1>
+<h2 class="subtitle" id="subtitle">Subtitle</h2>
+<p>Some stuff</p>
+<div class="section" id="section">
+<h1>Section</h1>
+<p>Some more stuff</p>
+<div class="section" id="another-section">
+<h2>Another Section</h2>
+<p>And even more stuff</p>
+</div>
+</div>
+</div>\\n''',
+ 'html_head': '''...<title>Title</title>\\n''',
+ 'html_subtitle': '''<h2 class="subtitle" id="subtitle">Subtitle</h2>\\n''',
+ 'html_title': '''<h1 class="title">Title</h1>\\n''',
+ 'subtitle': '''Subtitle''',
+ 'title': '''Title'''}
+"""],
+["""\
++++++
+Title
++++++
+
+:author: me
+
+Some stuff
+""",
+"""\
+{'docinfo': '''<table class="docinfo" frame="void" rules="none">
+<col class="docinfo-name" />
+<col class="docinfo-content" />
+<tbody valign="top">
+<tr><th class="docinfo-name">Author:</th>
+<td>me</td></tr>
+</tbody>
+</table>\\n''',
+ 'fragment': '''<p>Some stuff</p>\\n''',
+ 'html_body': '''<div class="document" id="title">
+<h1 class="title">Title</h1>
+<table class="docinfo" frame="void" rules="none">
+<col class="docinfo-name" />
+<col class="docinfo-content" />
+<tbody valign="top">
+<tr><th class="docinfo-name">Author:</th>
+<td>me</td></tr>
+</tbody>
+</table>
+<p>Some stuff</p>
+</div>\\n''',
+ 'html_head': '''...<title>Title</title>
+<meta name="author" content="me" />\\n''',
+ 'html_title': '''<h1 class="title">Title</h1>\\n''',
+ 'meta': '''<meta name="author" content="me" />\\n''',
+ 'title': '''Title'''}
+"""]
+])
+
+totest['No title promotion'] = ({'doctitle_xform' : 0,
+ 'stylesheet_path': '',
+ 'embed_stylesheet': 0}, [
+["""\
+Simple String
+""",
+"""\
+{'fragment': '''<p>Simple String</p>\\n''',
+ 'html_body': '''<div class="document">
+<p>Simple String</p>
+</div>\\n''',
+ 'html_head': '''...<title><string></title>\\n'''}
+"""],
+["""\
+Simple String with *markup*
+""",
+"""\
+{'fragment': '''<p>Simple String with <em>markup</em></p>\\n''',
+ 'html_body': '''<div class="document">
+<p>Simple String with <em>markup</em></p>
+</div>\\n''',
+ 'html_head': '''...<title><string></title>\\n'''}
+"""],
+["""\
+Simple String with an even simpler ``inline literal``
+""",
+"""\
+{'fragment': '''<p>Simple String with an even simpler <tt class="docutils literal">inline literal</tt></p>\\n''',
+ 'html_body': '''<div class="document">
+<p>Simple String with an even simpler <tt class="docutils literal">inline literal</tt></p>
+</div>\\n''',
+ 'html_head': '''...<title><string></title>\\n'''}
+"""],
+["""\
+A simple `anonymous reference`__
+
+__ http://www.test.com/test_url
+""",
+"""\
+{'fragment': '''<p>A simple <a class="reference external" href="http://www.test.com/test_url">anonymous reference</a></p>\\n''',
+ 'html_body': '''<div class="document">
+<p>A simple <a class="reference external" href="http://www.test.com/test_url">anonymous reference</a></p>
+</div>\\n''',
+ 'html_head': '''...<title><string></title>\\n'''}
+"""],
+["""\
+A simple `named reference`_ with stuff in between the
+reference and the target.
+
+.. _`named reference`: http://www.test.com/test_url
+""",
+"""\
+{'fragment': '''<p>A simple <a class="reference external" href="http://www.test.com/test_url">named reference</a> with stuff in between the
+reference and the target.</p>\\n''',
+ 'html_body': '''<div class="document">
+<p>A simple <a class="reference external" href="http://www.test.com/test_url">named reference</a> with stuff in between the
+reference and the target.</p>
+</div>\\n''',
+ 'html_head': '''...<title><string></title>\\n'''}
+"""],
+["""\
++++++
+Title
++++++
+
+Not A Subtitle
+==============
+
+Some stuff
+
+Section
+-------
+
+Some more stuff
+
+Another Section
+...............
+
+And even more stuff
+""",
+"""\
+{'fragment': '''<div class="section" id="title">
+<h1>Title</h1>
+<div class="section" id="not-a-subtitle">
+<h2>Not A Subtitle</h2>
+<p>Some stuff</p>
+<div class="section" id="section">
+<h3>Section</h3>
+<p>Some more stuff</p>
+<div class="section" id="another-section">
+<h4>Another Section</h4>
+<p>And even more stuff</p>
+</div>
+</div>
+</div>
+</div>\\n''',
+ 'html_body': '''<div class="document">
+<div class="section" id="title">
+<h1>Title</h1>
+<div class="section" id="not-a-subtitle">
+<h2>Not A Subtitle</h2>
+<p>Some stuff</p>
+<div class="section" id="section">
+<h3>Section</h3>
+<p>Some more stuff</p>
+<div class="section" id="another-section">
+<h4>Another Section</h4>
+<p>And even more stuff</p>
+</div>
+</div>
+</div>
+</div>
+</div>\\n''',
+ 'html_head': '''...<title><string></title>\\n'''}
+"""],
+["""\
+* bullet
+* list
+""",
+"""\
+{'fragment': '''<ul class="simple">
+<li>bullet</li>
+<li>list</li>
+</ul>\\n''',
+ 'html_body': '''<div class="document">
+<ul class="simple">
+<li>bullet</li>
+<li>list</li>
+</ul>
+</div>\\n''',
+ 'html_head': '''...<title><string></title>\\n'''}
+"""],
+["""\
+.. table::
+ :align: right
+
+ +-----+-----+
+ | 1 | 2 |
+ +-----+-----+
+ | 3 | 4 |
+ +-----+-----+
+""",
+"""\
+{'fragment': '''<table border="1" class="docutils align-right">
+<colgroup>
+<col width="50%%" />
+<col width="50%%" />
+</colgroup>
+<tbody valign="top">
+<tr><td>1</td>
+<td>2</td>
+</tr>
+<tr><td>3</td>
+<td>4</td>
+</tr>
+</tbody>
+</table>\\n''',
+ 'html_body': '''<div class="document">
+<table border="1" class="docutils align-right">
+<colgroup>
+<col width="50%%" />
+<col width="50%%" />
+</colgroup>
+<tbody valign="top">
+<tr><td>1</td>
+<td>2</td>
+</tr>
+<tr><td>3</td>
+<td>4</td>
+</tr>
+</tbody>
+</table>
+</div>\\n''',
+ 'html_head': '''...<title><string></title>\\n'''}
+"""],
+["""\
+Not a docinfo.
+
+:This: .. _target:
+
+ is
+:a:
+:simple:
+:field: list
+""",
+"""\
+{'fragment': '''<p>Not a docinfo.</p>
+<table class="docutils field-list" frame="void" rules="none">
+<col class="field-name" />
+<col class="field-body" />
+<tbody valign="top">
+<tr class="field"><th class="field-name">This:</th><td class="field-body"><p class="first last" id="target">is</p>
+</td>
+</tr>
+<tr class="field"><th class="field-name">a:</th><td class="field-body"></td>
+</tr>
+<tr class="field"><th class="field-name">simple:</th><td class="field-body"></td>
+</tr>
+<tr class="field"><th class="field-name">field:</th><td class="field-body">list</td>
+</tr>
+</tbody>
+</table>\\n''',
+ 'html_body': '''<div class="document">
+<p>Not a docinfo.</p>
+<table class="docutils field-list" frame="void" rules="none">
+<col class="field-name" />
+<col class="field-body" />
+<tbody valign="top">
+<tr class="field"><th class="field-name">This:</th><td class="field-body"><p class="first last" id="target">is</p>
+</td>
+</tr>
+<tr class="field"><th class="field-name">a:</th><td class="field-body"></td>
+</tr>
+<tr class="field"><th class="field-name">simple:</th><td class="field-body"></td>
+</tr>
+<tr class="field"><th class="field-name">field:</th><td class="field-body">list</td>
+</tr>
+</tbody>
+</table>
+</div>\\n''',
+ 'html_head': '''...<title><string></title>\\n'''}
+"""],
+["""\
+Not a docinfo.
+
+:This is: a
+:simple field list with loooong field: names
+""",
+"""\
+{'fragment': '''<p>Not a docinfo.</p>
+<table class="docutils field-list" frame="void" rules="none">
+<col class="field-name" />
+<col class="field-body" />
+<tbody valign="top">
+<tr class="field"><th class="field-name">This is:</th><td class="field-body">a</td>
+</tr>
+<tr class="field"><th class="field-name" colspan="2">simple field list with loooong field:</th></tr>
+<tr class="field"><td> </td><td class="field-body">names</td>
+</tr>
+</tbody>
+</table>\\n''',
+ 'html_body': '''<div class="document">
+<p>Not a docinfo.</p>
+<table class="docutils field-list" frame="void" rules="none">
+<col class="field-name" />
+<col class="field-body" />
+<tbody valign="top">
+<tr class="field"><th class="field-name">This is:</th><td class="field-body">a</td>
+</tr>
+<tr class="field"><th class="field-name" colspan="2">simple field list with loooong field:</th></tr>
+<tr class="field"><td> </td><td class="field-body">names</td>
+</tr>
+</tbody>
+</table>
+</div>\\n''',
+ 'html_head': '''...<title><string></title>\\n'''}
+"""],
+])
+
+
+if __name__ == '__main__':
+ import unittest
+ unittest.main(defaultTest='suite')
--- /dev/null
+#!/usr/bin/env python
+
+# $Id: test_html4css1_template.py 8356 2019-08-26 16:44:19Z milde $
+# Author: David Goodger <goodger@python.org>
+# Copyright: This module has been placed in the public domain.
+
+"""
+Tests for the HTML writer.
+"""
+from __future__ import absolute_import
+
+import os
+import platform
+
+from . import DocutilsTestSupport
+
+
+def suite():
+ settings = {'template': os.path.join(DocutilsTestSupport.testroot,
+ 'data', 'full-template.txt'),
+ 'stylesheet_path': '/test.css',
+ 'embed_stylesheet': 0,}
+ s = DocutilsTestSupport.PublishTestSuite('html', suite_settings=settings)
+ s.generateTests(totest)
+ return s
+
+if platform.system() == "Windows":
+ drive_prefix = "C:"
+else:
+ drive_prefix = ""
+
+totest = {}
+
+totest['template'] = [
+["""\
+================
+ Document Title
+================
+----------
+ Subtitle
+----------
+
+:Author: Me
+
+.. footer:: footer text
+
+Section
+=======
+
+Some text.
+""",
+r'''head_prefix = """\
+<?xml version="1.0" encoding="utf-8" ?>
+<!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">
+<head>"""
+
+
+head = """\
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<meta name="generator" content="Docutils %(version)s: http://docutils.sourceforge.net/" />
+<title>Document Title</title>
+<meta name="author" content="Me" />"""
+
+
+stylesheet = """\
+<link rel="stylesheet" href="%(drive)s/test.css" type="text/css" />"""
+
+
+body_prefix = """\
+</head>
+<body>
+<div class="document" id="document-title">"""
+
+
+body_pre_docinfo = """\
+<h1 class="title">Document Title</h1>
+<h2 class="subtitle" id="subtitle">Subtitle</h2>"""
+
+
+docinfo = """\
+<table class="docinfo" frame="void" rules="none">
+<col class="docinfo-name" />
+<col class="docinfo-content" />
+<tbody valign="top">
+<tr><th class="docinfo-name">Author:</th>
+<td>Me</td></tr>
+</tbody>
+</table>"""
+
+
+body = """\
+<div class="section" id="section">
+<h1>Section</h1>
+<p>Some text.</p>
+</div>"""
+
+
+body_suffix = """\
+</div>
+<div class="footer">
+<hr class="footer" />
+footer text
+</div>
+</body>
+</html>"""
+
+
+head_prefix = """\
+<?xml version="1.0" encoding="utf-8" ?>
+<!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">
+<head>"""
+
+
+head = """\
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<meta name="generator" content="Docutils %(version)s: http://docutils.sourceforge.net/" />
+<title>Document Title</title>
+<meta name="author" content="Me" />"""
+
+
+stylesheet = """\
+<link rel="stylesheet" href="%(drive)s/test.css" type="text/css" />"""
+
+
+body_prefix = """\
+</head>
+<body>
+<div class="document" id="document-title">"""
+
+
+body_pre_docinfo = """\
+<h1 class="title">Document Title</h1>
+<h2 class="subtitle" id="subtitle">Subtitle</h2>"""
+
+
+docinfo = """\
+<table class="docinfo" frame="void" rules="none">
+<col class="docinfo-name" />
+<col class="docinfo-content" />
+<tbody valign="top">
+<tr><th class="docinfo-name">Author:</th>
+<td>Me</td></tr>
+</tbody>
+</table>"""
+
+
+body = """\
+<div class="section" id="section">
+<h1>Section</h1>
+<p>Some text.</p>
+</div>"""
+
+
+body_suffix = """\
+</div>
+<div class="footer">
+<hr class="footer" />
+footer text
+</div>
+</body>
+</html>"""
+
+
+title = """\
+Document Title"""
+
+
+subtitle = """\
+Subtitle"""
+
+
+header = """\
+"""
+
+
+footer = """\
+<div class="footer">
+<hr class="footer" />
+footer text
+</div>"""
+
+
+meta = """\
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<meta name="generator" content="Docutils %(version)s: http://docutils.sourceforge.net/" />
+<meta name="author" content="Me" />"""
+
+
+fragment = """\
+<div class="section" id="section">
+<h1>Section</h1>
+<p>Some text.</p>
+</div>"""
+
+
+html_prolog = """\
+<?xml version="1.0" encoding="%%s" ?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">"""
+
+
+html_head = """\
+<meta http-equiv="Content-Type" content="text/html; charset=%%s" />
+<meta name="generator" content="Docutils %(version)s: http://docutils.sourceforge.net/" />
+<title>Document Title</title>
+<meta name="author" content="Me" />"""
+
+
+html_title = """\
+<h1 class="title">Document Title</h1>"""
+
+
+html_subtitle = """\
+<h2 class="subtitle" id="subtitle">Subtitle</h2>"""
+
+
+html_body = """\
+<div class="document" id="document-title">
+<h1 class="title">Document Title</h1>
+<h2 class="subtitle" id="subtitle">Subtitle</h2>
+<table class="docinfo" frame="void" rules="none">
+<col class="docinfo-name" />
+<col class="docinfo-content" />
+<tbody valign="top">
+<tr><th class="docinfo-name">Author:</th>
+<td>Me</td></tr>
+</tbody>
+</table>
+<div class="section" id="section">
+<h1>Section</h1>
+<p>Some text.</p>
+</div>
+</div>
+<div class="footer">
+<hr class="footer" />
+footer text
+</div>"""
+''' % {'version': DocutilsTestSupport.docutils.__version__,
+ 'drive': drive_prefix,
+ }]
+]
+
+if __name__ == '__main__':
+ import unittest
+ unittest.main(defaultTest='suite')
--- /dev/null
+#! /usr/bin/env python
+# coding: utf-8
+
+# $Id: test_html5_polyglot_misc.py 8356 2019-08-26 16:44:19Z milde $
+# Authors: Lea Wiemann, Dmitry Shachnev, Günter Milde
+# Maintainer: docutils-develop@lists.sourceforge.net
+# Copyright: This module has been placed in the public domain.
+
+"""
+Miscellaneous HTML writer tests.
+"""
+from __future__ import absolute_import
+
+import os
+
+from . import DocutilsTestSupport
+from docutils import core
+
+
+class EncodingTestCase(DocutilsTestSupport.StandardTestCase):
+
+ def test_xmlcharrefreplace(self):
+ # Test that xmlcharrefreplace is the default output encoding
+ # error handler.
+ settings_overrides={
+ 'output_encoding': 'latin1',
+ 'stylesheet': '',
+ '_disable_config': True,}
+ result = core.publish_string(
+ u'EUR = \u20ac', writer_name='html5_polyglot',
+ settings_overrides=settings_overrides)
+ # Encoding a euro sign with latin1 doesn't work, so the
+ # xmlcharrefreplace handler is used.
+ self.assertIn(b'EUR = €', result)
+
+class MovingArgsTestCase(DocutilsTestSupport.StandardTestCase):
+
+ settings_overrides={'stylesheet_path': '',
+ # 'embed_stylesheet': False,
+ '_disable_config': True,
+ }
+
+ def test_definition_list_item_classes(self):
+ # Do not drop class arguments for the definition list item.
+ # Pass them to the term node instead.
+ data = """\
+first term:
+ fist def
+
+ .. class:: for the second item
+
+second term:
+ second def
+"""
+ result = core.publish_string(data, writer_name='html5_polyglot',
+ settings_overrides=self.settings_overrides)
+ self.assertIn(b'<dt class="for the second item">second term:</dt>',
+ result)
+
+ def test_definition_list_item_name(self):
+ # Do not drop the "name" of the definition list item.
+ # Pass it to to the term node instead.
+ data = """\
+first term:
+ first def
+
+ .. _second item:
+
+second term:
+ second def
+"""
+ result = core.publish_string(data, writer_name='html5_polyglot',
+ settings_overrides=self.settings_overrides)
+ self.assertIn(b'<dt id="second-item">second term:</dt>',
+ result)
+
+
+class SettingsTestCase(DocutilsTestSupport.StandardTestCase):
+ data = 'test'
+
+ def test_default_stylesheet(self):
+ # default style sheet, embedded
+ mysettings = {'_disable_config': True,}
+ styles = core.publish_parts(self.data, writer_name='html5_polyglot',
+ settings_overrides=mysettings)['stylesheet']
+ self.assertIn('Minimal style sheet '
+ 'for the HTML output of Docutils.', styles)
+
+ def test_default_stylesheet_linked(self):
+ # default style sheet, linked
+ mysettings = {'_disable_config': True,
+ 'embed_stylesheet': False}
+ styles = core.publish_parts(self.data, writer_name='html5_polyglot',
+ settings_overrides=mysettings)['stylesheet']
+ self.assertIn('docutils/writers/html5_polyglot/minimal.css', styles)
+
+ def test_math_stylesheet_linked(self):
+ # default + math style sheet, linked
+ mysettings = {'_disable_config': True,
+ 'embed_stylesheet': False,
+ 'stylesheet_path': 'minimal.css, math.css'}
+ styles = core.publish_parts(self.data, writer_name='html5_polyglot',
+ settings_overrides=mysettings)['stylesheet']
+ self.assertIn('docutils/writers/html5_polyglot/minimal.css', styles)
+ self.assertIn('docutils/writers/html5_polyglot/math.css', styles)
+
+ def test_custom_stylesheet_linked(self):
+ # default + custom style sheet, linked
+ mysettings = {'_disable_config': True,
+ 'embed_stylesheet': False,
+ 'stylesheet_path': 'minimal.css, '
+ 'data/ham.css'}
+ styles = core.publish_parts(self.data, writer_name='html5_polyglot',
+ settings_overrides=mysettings)['stylesheet']
+ self.assertIn('docutils/writers/html5_polyglot/minimal.css', styles)
+ self.assertIn('href="data/ham.css"', styles)
+
+ def test_custom_stylesheet_dir(self):
+ mysettings = {'_disable_config': True,
+ 'embed_stylesheet': False,
+ 'stylesheet_dirs': ('../docutils/writers/html5_polyglot/',
+ 'data'),
+ 'stylesheet_path': 'minimal.css, ham.css'}
+ styles = core.publish_parts(self.data, writer_name='html5_polyglot',
+ settings_overrides=mysettings)['stylesheet']
+ if os.path.isdir('../docutils/writers/html5_polyglot/'):
+ self.assertIn('docutils/writers/html5_polyglot/minimal.css', styles)
+ self.assertIn('href="data/ham.css"', styles)
+
+ def test_custom_stylesheet_dir_embedded(self):
+ mysettings = {'_disable_config': True,
+ 'embed_stylesheet': True,
+ 'stylesheet_dirs': ('../docutils/writers/html5_polyglot/',
+ 'data'),
+ 'stylesheet_path': 'ham.css'}
+ styles = core.publish_parts(self.data, writer_name='html5_polyglot',
+ settings_overrides=mysettings)['stylesheet']
+ self.assertIn('dl.docutils dd {\n margin-bottom: 0.5em }', styles)
+
+class MathTestCase(DocutilsTestSupport.StandardTestCase):
+
+ """Attention: This class tests the current implementation of maths support
+ which is open to change in future Docutils releases. """
+
+ mathjax_script = '<script type="text/javascript" src="%s">'
+ default_mathjax_url = ('file:/usr/share/javascript/mathjax/MathJax.js'
+ '?config=TeX-AMS_CHTML')
+ custom_mathjax_url = ('/mathjax/MathJax.js?config=TeX-AMS-MML_HTMLorMML')
+ data = ':math:`42`'
+
+ def test_math_output_default(self):
+ # HTML with math.css stylesheet (since 0.11)
+ mysettings = {'_disable_config': True,}
+ styles = core.publish_parts(self.data, writer_name='html5_polyglot',
+ settings_overrides=mysettings)['stylesheet']
+ self.assertIn('convert LaTeX equations to HTML output.', styles)
+
+ def test_math_output_mathjax(self):
+ # Explicitly specifying math_output=MathJax, case insensitively
+ # use default MathJax URL
+ mysettings = {'_disable_config': True,
+ 'report_level': 3,
+ 'math_output': 'MathJax'}
+ head = core.publish_parts(self.data, writer_name='html5_polyglot',
+ settings_overrides=mysettings)['head']
+ self.assertIn(self.mathjax_script % self.default_mathjax_url, head)
+
+ def test_math_output_mathjax_custom(self):
+ # Customizing MathJax URL
+ mysettings = {'_disable_config': True,
+ 'math_output':
+ 'mathjax %s' % self.custom_mathjax_url}
+ head = core.publish_parts(self.data, writer_name='html5_polyglot',
+ settings_overrides=mysettings)['head']
+ self.assertIn(self.mathjax_script % self.custom_mathjax_url, head)
+
+ def test_math_output_html(self):
+ mysettings = {'_disable_config': True,
+ 'math_output': 'HTML'}
+ head = core.publish_parts(self.data, writer_name='html5_polyglot',
+ settings_overrides=mysettings)['head']
+ # There should be no MathJax script when math_output is not MathJax
+ self.assertNotIn('MathJax.js', head)
+
+ def test_math_output_html_stylesheet(self):
+ mysettings = {'_disable_config': True,
+ 'math_output': 'HTML math.css,custom/style.css',
+ 'stylesheet_dirs': ('.', 'functional/input/data'),
+ 'embed_stylesheet': False}
+ styles = core.publish_parts(self.data, writer_name='html5_polyglot',
+ settings_overrides=mysettings)['stylesheet']
+ self.assertEqual(u"""\
+<link rel="stylesheet" href="functional/input/data/minimal.css" type="text/css" />
+<link rel="stylesheet" href="functional/input/data/plain.css" type="text/css" />
+<link rel="stylesheet" href="functional/input/data/math.css" type="text/css" />
+<link rel="stylesheet" href="custom/style.css" type="text/css" />
+""", styles)
+
+ def test_math_output_mathjax_no_math(self):
+ mysettings = {'_disable_config': True,
+ 'math_output': 'MathJax'}
+ # There should be no math script when text does not contain math
+ head = core.publish_parts('No math.', writer_name='html5_polyglot')['head']
+ self.assertNotIn('MathJax', head)
+
+
+if __name__ == '__main__':
+ import unittest
+ unittest.main()
--- /dev/null
+#! /usr/bin/env python
+
+# $Id: test_html5_polyglot_parts.py 8356 2019-08-26 16:44:19Z milde $
+# Author: reggie dugard <reggie@users.sourceforge.net>
+# Copyright: This module has been placed in the public domain.
+
+"""
+Test for fragment code in HTML writer.
+
+Note: the 'body' and 'whole' entries have been removed from the parts
+dictionaries (redundant), along with 'meta' and 'stylesheet' entries with
+standard values, and any entries with empty values.
+"""
+from __future__ import absolute_import
+
+from . import DocutilsTestSupport
+from DocutilsTestSupport import (HtmlWriterPublishPartsTestCase,
+ HtmlPublishPartsTestSuite)
+from docutils import core, __version__
+
+
+class Html5WriterPublishPartsTestCase(HtmlWriterPublishPartsTestCase):
+ """Test case for HTML5 writer via the publish_parts interface."""
+
+ writer_name = 'html5'
+ standard_content_type_template = ('<meta charset="%s"/>\n')
+ standard_generator_template = (
+ '<meta name="generator"'
+ ' content="Docutils %s: http://docutils.sourceforge.net/" />\n')
+ standard_html_meta_value = (standard_content_type_template
+ + standard_generator_template % __version__)
+ standard_meta_value = standard_html_meta_value % 'utf-8'
+ standard_html_prolog = '<!DOCTYPE html>\n'
+
+class Html5PublishPartsTestSuite(HtmlPublishPartsTestSuite):
+
+ testcase_class = Html5WriterPublishPartsTestCase
+
+
+def suite():
+ s = Html5PublishPartsTestSuite()
+ s.generateTests(totest)
+ return s
+
+
+totest = {}
+
+totest['Title promotion'] = ({'stylesheet_path': '',
+ 'embed_stylesheet': 0}, [
+["""\
+Simple String
+""",
+"""\
+{'fragment': '''<p>Simple String</p>\\n''',
+ 'html_body': '''<div class="document">
+<p>Simple String</p>
+</div>\\n''',
+ 'html_head': '''...<title><string></title>\\n'''}
+"""],
+["""\
+Simple String with *markup*
+""",
+"""\
+{'fragment': '''<p>Simple String with <em>markup</em></p>\\n''',
+ 'html_body': '''<div class="document">
+<p>Simple String with <em>markup</em></p>
+</div>\\n''',
+ 'html_head': '''...<title><string></title>\\n'''}
+"""],
+["""\
+Simple String with an even simpler ``inline literal``
+""",
+"""\
+{'fragment': '''<p>Simple String with an even simpler <span class="docutils literal">inline literal</span></p>\\n''',
+ 'html_body': '''<div class="document">
+<p>Simple String with an even simpler <span class="docutils literal">inline literal</span></p>
+</div>\\n''',
+ 'html_head': '''...<title><string></title>\\n'''}
+"""],
+["""\
+A simple `anonymous reference`__
+
+__ http://www.test.com/test_url
+""",
+"""\
+{'fragment': '''<p>A simple <a class="reference external" href="http://www.test.com/test_url">anonymous reference</a></p>\\n''',
+ 'html_body': '''<div class="document">
+<p>A simple <a class="reference external" href="http://www.test.com/test_url">anonymous reference</a></p>
+</div>\\n''',
+ 'html_head': '''...<title><string></title>\\n'''}
+"""],
+["""\
+One paragraph.
+
+Two paragraphs.
+""",
+"""\
+{'fragment': '''<p>One paragraph.</p>
+<p>Two paragraphs.</p>\\n''',
+ 'html_body': '''<div class="document">
+<p>One paragraph.</p>
+<p>Two paragraphs.</p>
+</div>\\n''',
+ 'html_head': '''...<title><string></title>\\n'''}
+"""],
+["""\
+A simple `named reference`_ with stuff in between the
+reference and the target.
+
+.. _`named reference`: http://www.test.com/test_url
+""",
+"""\
+{'fragment': '''<p>A simple <a class="reference external" href="http://www.test.com/test_url">named reference</a> with stuff in between the
+reference and the target.</p>\\n''',
+ 'html_body': '''<div class="document">
+<p>A simple <a class="reference external" href="http://www.test.com/test_url">named reference</a> with stuff in between the
+reference and the target.</p>
+</div>\\n''',
+ 'html_head': '''...<title><string></title>\\n'''}
+"""],
+["""\
++++++
+Title
++++++
+
+Subtitle
+========
+
+Some stuff
+
+Section
+-------
+
+Some more stuff
+
+Another Section
+...............
+
+And even more stuff
+""",
+"""\
+{'fragment': '''<p>Some stuff</p>
+<div class="section" id="section">
+<h1>Section</h1>
+<p>Some more stuff</p>
+<div class="section" id="another-section">
+<h2>Another Section</h2>
+<p>And even more stuff</p>
+</div>
+</div>\\n''',
+ 'html_body': '''<div class="document" id="title">
+<h1 class="title">Title</h1>
+<p class="subtitle" id="subtitle">Subtitle</p>
+<p>Some stuff</p>
+<div class="section" id="section">
+<h1>Section</h1>
+<p>Some more stuff</p>
+<div class="section" id="another-section">
+<h2>Another Section</h2>
+<p>And even more stuff</p>
+</div>
+</div>
+</div>\\n''',
+ 'html_head': '''...<title>Title</title>\\n''',
+ 'html_subtitle': '''<p class="subtitle" id="subtitle">Subtitle</p>\\n''',
+ 'html_title': '''<h1 class="title">Title</h1>\\n''',
+ 'subtitle': '''Subtitle''',
+ 'title': '''Title'''}
+"""],
+["""\
++++++
+Title
++++++
+
+:author: me
+
+Some stuff
+""",
+"""\
+{'docinfo': '''<dl class="docinfo simple">
+<dt class="author">Author</dt>
+<dd class="author"><p>me</p></dd>
+</dl>\\n''',
+ 'fragment': '''<p>Some stuff</p>\\n''',
+ 'html_body': '''<div class="document" id="title">
+<h1 class="title">Title</h1>
+<dl class="docinfo simple">
+<dt class="author">Author</dt>
+<dd class="author"><p>me</p></dd>
+</dl>
+<p>Some stuff</p>
+</div>\\n''',
+ 'html_head': '''...<title>Title</title>
+<meta name="author" content="me" />\\n''',
+ 'html_title': '''<h1 class="title">Title</h1>\\n''',
+ 'meta': '''<meta name="author" content="me" />\\n''',
+ 'title': '''Title'''}
+"""]
+])
+
+totest['No title promotion'] = ({'doctitle_xform' : 0,
+ 'stylesheet_path': '',
+ 'embed_stylesheet': 0}, [
+["""\
+Simple String
+""",
+"""\
+{'fragment': '''<p>Simple String</p>\\n''',
+ 'html_body': '''<div class="document">
+<p>Simple String</p>
+</div>\\n''',
+ 'html_head': '''...<title><string></title>\\n'''}
+"""],
+["""\
+Simple String with *markup*
+""",
+"""\
+{'fragment': '''<p>Simple String with <em>markup</em></p>\\n''',
+ 'html_body': '''<div class="document">
+<p>Simple String with <em>markup</em></p>
+</div>\\n''',
+ 'html_head': '''...<title><string></title>\\n'''}
+"""],
+["""\
+Simple String with an even simpler ``inline literal``
+""",
+"""\
+{'fragment': '''<p>Simple String with an even simpler <span class="docutils literal">inline literal</span></p>\\n''',
+ 'html_body': '''<div class="document">
+<p>Simple String with an even simpler <span class="docutils literal">inline literal</span></p>
+</div>\\n''',
+ 'html_head': '''...<title><string></title>\\n'''}
+"""],
+["""\
+A simple `anonymous reference`__
+
+__ http://www.test.com/test_url
+""",
+"""\
+{'fragment': '''<p>A simple <a class="reference external" href="http://www.test.com/test_url">anonymous reference</a></p>\\n''',
+ 'html_body': '''<div class="document">
+<p>A simple <a class="reference external" href="http://www.test.com/test_url">anonymous reference</a></p>
+</div>\\n''',
+ 'html_head': '''...<title><string></title>\\n'''}
+"""],
+["""\
+A simple `named reference`_ with stuff in between the
+reference and the target.
+
+.. _`named reference`: http://www.test.com/test_url
+""",
+"""\
+{'fragment': '''<p>A simple <a class="reference external" href="http://www.test.com/test_url">named reference</a> with stuff in between the
+reference and the target.</p>\\n''',
+ 'html_body': '''<div class="document">
+<p>A simple <a class="reference external" href="http://www.test.com/test_url">named reference</a> with stuff in between the
+reference and the target.</p>
+</div>\\n''',
+ 'html_head': '''...<title><string></title>\\n'''}
+"""],
+["""\
++++++
+Title
++++++
+
+Not A Subtitle
+==============
+
+Some stuff
+
+Section
+-------
+
+Some more stuff
+
+Another Section
+...............
+
+And even more stuff
+""",
+"""\
+{'fragment': '''<div class="section" id="title">
+<h1>Title</h1>
+<div class="section" id="not-a-subtitle">
+<h2>Not A Subtitle</h2>
+<p>Some stuff</p>
+<div class="section" id="section">
+<h3>Section</h3>
+<p>Some more stuff</p>
+<div class="section" id="another-section">
+<h4>Another Section</h4>
+<p>And even more stuff</p>
+</div>
+</div>
+</div>
+</div>\\n''',
+ 'html_body': '''<div class="document">
+<div class="section" id="title">
+<h1>Title</h1>
+<div class="section" id="not-a-subtitle">
+<h2>Not A Subtitle</h2>
+<p>Some stuff</p>
+<div class="section" id="section">
+<h3>Section</h3>
+<p>Some more stuff</p>
+<div class="section" id="another-section">
+<h4>Another Section</h4>
+<p>And even more stuff</p>
+</div>
+</div>
+</div>
+</div>
+</div>\\n''',
+ 'html_head': '''...<title><string></title>\\n'''}
+"""],
+["""\
+* bullet
+* list
+""",
+"""\
+{'fragment': '''<ul class="simple">
+<li><p>bullet</p></li>
+<li><p>list</p></li>
+</ul>\\n''',
+ 'html_body': '''<div class="document">
+<ul class="simple">
+<li><p>bullet</p></li>
+<li><p>list</p></li>
+</ul>
+</div>\\n''',
+ 'html_head': '''...<title><string></title>\\n'''}
+"""],
+["""\
+.. table::
+ :align: right
+
+ +-----+-----+
+ | 1 | 2 |
+ +-----+-----+
+ | 3 | 4 |
+ +-----+-----+
+""",
+"""\
+{'fragment': '''<table class="align-right">
+<colgroup>
+<col style="width: 50%%" />
+<col style="width: 50%%" />
+</colgroup>
+<tbody>
+<tr><td><p>1</p></td>
+<td><p>2</p></td>
+</tr>
+<tr><td><p>3</p></td>
+<td><p>4</p></td>
+</tr>
+</tbody>
+</table>\\n''',
+ 'html_body': '''<div class="document">
+<table class="align-right">
+<colgroup>
+<col style="width: 50%%" />
+<col style="width: 50%%" />
+</colgroup>
+<tbody>
+<tr><td><p>1</p></td>
+<td><p>2</p></td>
+</tr>
+<tr><td><p>3</p></td>
+<td><p>4</p></td>
+</tr>
+</tbody>
+</table>
+</div>\\n''',
+ 'html_head': '''...<title><string></title>\\n'''}
+"""],
+["""\
+Not a docinfo.
+
+:This: .. _target:
+
+ is
+:a:
+:simple:
+:field: list
+""",
+"""\
+{'fragment': '''<p>Not a docinfo.</p>
+<dl class="field-list simple">
+<dt>This</dt>
+<dd><p id="target">is</p>
+</dd>
+<dt>a</dt>
+<dd><p></p></dd>
+<dt>simple</dt>
+<dd><p></p></dd>
+<dt>field</dt>
+<dd><p>list</p>
+</dd>
+</dl>\\n''',
+ 'html_body': '''<div class="document">
+<p>Not a docinfo.</p>
+<dl class="field-list simple">
+<dt>This</dt>
+<dd><p id="target">is</p>
+</dd>
+<dt>a</dt>
+<dd><p></p></dd>
+<dt>simple</dt>
+<dd><p></p></dd>
+<dt>field</dt>
+<dd><p>list</p>
+</dd>
+</dl>
+</div>\\n''',
+ 'html_head': '''...<title><string></title>\\n'''}
+"""],
+["""\
+Not a docinfo.
+
+:This is: a
+:simple field list with loooong field: names
+""",
+"""\
+{'fragment': '''<p>Not a docinfo.</p>
+<dl class="field-list simple">
+<dt>This is</dt>
+<dd><p>a</p>
+</dd>
+<dt>simple field list with loooong field</dt>
+<dd><p>names</p>
+</dd>
+</dl>\\n''',
+ 'html_body': '''<div class="document">
+<p>Not a docinfo.</p>
+<dl class="field-list simple">
+<dt>This is</dt>
+<dd><p>a</p>
+</dd>
+<dt>simple field list with loooong field</dt>
+<dd><p>names</p>
+</dd>
+</dl>
+</div>\\n''',
+ 'html_head': '''...<title><string></title>\\n'''}
+"""],
+])
+
+
+if __name__ == '__main__':
+ import unittest
+ unittest.main(defaultTest='suite')
--- /dev/null
+# -*- coding: utf-8 -*-
+#! /usr/bin/env python
+
+# $Id: test_latex2e.py 8392 2019-09-17 08:41:21Z milde $
+# Author: engelbert gruber <grubert@users.sourceforge.net>
+# Copyright: This module has been placed in the public domain.
+
+"""
+Tests for latex2e writer.
+"""
+from __future__ import absolute_import
+
+import string
+
+from . import DocutilsTestSupport
+
+
+def suite():
+ settings = {'use_latex_toc': False}
+ s = DocutilsTestSupport.PublishTestSuite('latex', suite_settings=settings)
+ s.generateTests(totest)
+ settings['use_latex_toc'] = True
+ s.generateTests(totest_latex_toc)
+ settings['use_latex_toc'] = False
+ settings['sectnum_xform'] = False
+ s.generateTests(totest_latex_sectnum)
+ settings['sectnum_xform'] = True
+ settings['use_latex_citations'] = True
+ s.generateTests(totest_latex_citations)
+ settings['table_style'] = ['colwidths-auto']
+ s.generateTests(totest_table_style_auto)
+ settings['table_style'] = ['booktabs']
+ s.generateTests(totest_table_style_booktabs)
+ settings['stylesheet_path'] = 'data/spam,data/ham.tex'
+ s.generateTests(totest_stylesheet)
+ settings['embed_stylesheet'] = True
+ settings['warning_stream'] = ''
+ s.generateTests(totest_stylesheet_embed)
+ return s
+
+head_template = string.Template(
+r"""$head_prefix% generated by Docutils <http://docutils.sourceforge.net/>
+\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""")
+
+parts = dict(
+head_prefix = r"""\documentclass[a4paper]{article}
+""",
+requirements = r"""\usepackage{ifthen}
+\usepackage[T1]{fontenc}
+\usepackage[utf8]{inputenc}
+""",
+latex_preamble = r"""% PDF Standard Fonts
+\usepackage{mathptmx} % Times
+\usepackage[scaled=.90]{helvet}
+\usepackage{courier}
+""",
+longtable = r"""\usepackage{longtable,ltcaption,array}
+\setlength{\extrarowheight}{2pt}
+\newlength{\DUtablewidth} % internal use in tables
+""",
+stylesheet = '',
+fallbacks = '',
+fallbacks_highlight = r"""% 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}}
+
+% inline markup (custom roles)
+% \DUrole{#1}{#2} tries \DUrole#1{#2}
+\providecommand*{\DUrole}[2]{%
+ \ifcsname DUrole#1\endcsname%
+ \csname DUrole#1\endcsname{#2}%
+ \else
+ % backwards compatibility: try \docutilsrole#1{#2}
+ \ifcsname docutilsrole#1\endcsname%
+ \PackageWarningNoLine{docutils}{Command prefix "docutilsrole" is
+ deprecated, \MessageBreak use `\protect\DUrole #1`}
+ \csname docutilsrole#1\endcsname{#2}%
+ \else%
+ #2%
+ \fi%
+ \fi%
+}
+""",
+pdfsetup = r"""
+% hyperlinks:
+\ifthenelse{\isundefined{\hypersetup}}{
+ \usepackage[colorlinks=true,linkcolor=blue,urlcolor=blue]{hyperref}
+ \usepackage{bookmark}
+ \urlstyle{same} % normal text font (alternatives: tt, rm, sf)
+}{}
+""",
+titledata = '')
+
+head = head_template.substitute(parts)
+
+head_table = head_template.substitute(
+ dict(parts, requirements = parts['requirements'] + parts['longtable']))
+
+head_booktabs = head_template.substitute(
+ dict(parts, requirements=parts['requirements']
+ + '\\usepackage{booktabs}\n' + parts['longtable']))
+
+head_textcomp = head_template.substitute(
+ dict(parts, requirements = parts['requirements'] +
+r"""\usepackage{textcomp} % text symbol macros
+"""))
+
+head_alltt = head_template.substitute(
+ dict(parts, requirements = parts['requirements'] +
+r"""\usepackage{alltt}
+"""))
+
+
+totest = {}
+totest_latex_toc = {}
+totest_latex_sectnum = {}
+totest_latex_citations = {}
+totest_stylesheet = {}
+totest_stylesheet_embed = {}
+totest_table_style_auto = {}
+totest_table_style_booktabs = {}
+
+totest['url_chars'] = [
+["http://nowhere/url_with%28parens%29",
+head + r"""
+\url{http://nowhere/url_with\%28parens\%29}
+
+\end{document}
+"""],
+]
+
+totest['textcomp'] = [
+["2 µm is just 2/1000000 m",
+head_textcomp + r"""
+2 µm is just 2/1000000 m
+
+\end{document}
+"""],
+]
+
+totest['spanish quote'] = [
+[".. role:: language-es\n\nUnd damit :language-es:`basta`!",
+head_template.substitute(dict(parts, requirements =
+r"""\usepackage{ifthen}
+\usepackage[T1]{fontenc}
+\usepackage[utf8]{inputenc}
+\usepackage[spanish,english]{babel}
+\AtBeginDocument{\shorthandoff{.<>}}
+""")) + r"""
+Und damit \foreignlanguage{spanish}{basta}!
+
+\end{document}
+"""],
+]
+
+totest['code role'] = [
+[":code:`x=1`",
+head_template.substitute(dict(parts, requirements = parts['requirements']+
+r"""\usepackage{color}
+""", fallbacks = parts['fallbacks_highlight'])) + r"""
+\texttt{\DUrole{code}{x=1}}
+
+\end{document}
+"""],
+]
+
+totest['table_of_contents'] = [
+# input
+["""\
+.. contents:: Table of Contents
+
+Title 1
+=======
+Paragraph 1.
+
+Title 2
+-------
+Paragraph 2.
+""",
+## # expected output
+head_template.substitute(dict(parts,
+ requirements=parts['requirements'] + '\\setcounter{secnumdepth}{0}\n',
+ fallbacks=r"""
+% title for topics, admonitions, unsupported section levels, and sidebar
+\providecommand*{\DUtitle}[2][class-arg]{%
+ % call \DUtitle#1{#2} if it exists:
+ \ifcsname DUtitle#1\endcsname%
+ \csname DUtitle#1\endcsname{#2}%
+ \else
+ \smallskip\noindent\textbf{#2}\smallskip%
+ \fi
+}
+""")) + r"""
+\phantomsection\label{table-of-contents}
+\pdfbookmark[1]{Table of Contents}{table-of-contents}
+\DUtitle[contents]{Table of Contents}
+
+\begin{list}{}{}
+\item \hyperref[title-1]{Title 1}
+
+\begin{list}{}{}
+\item \hyperref[title-2]{Title 2}
+\end{list}
+\end{list}
+
+
+\section{Title 1%
+ \label{title-1}%
+}
+
+Paragraph 1.
+
+
+\subsection{Title 2%
+ \label{title-2}%
+}
+
+Paragraph 2.
+
+\end{document}
+"""],
+]
+
+totest['footnote text'] = [
+# input
+["""\
+.. [1] paragraph
+
+.. [2]
+
+.. [3] 1. enumeration
+""",
+## # expected output
+head_template.substitute(dict(parts,
+ fallbacks=r"""% numeric or symbol footnotes with hyperlinks
+\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%
+}
+""")) + r"""%
+\DUfootnotetext{id1}{id1}{1}{%
+paragraph
+}
+%
+\DUfootnotetext{id2}{id2}{2}{}
+%
+\DUfootnotetext{id3}{id3}{3}{
+\begin{enumerate}
+\item enumeration
+\end{enumerate}
+}
+
+\end{document}
+"""],
+]
+
+totest_latex_toc['no_sectnum'] = [
+# input
+["""\
+.. contents::
+
+first section
+-------------
+""",
+## # expected output
+head_template.substitute(dict(parts,
+ requirements=parts['requirements'] + '\\setcounter{secnumdepth}{0}\n'
+)) + r"""
+\phantomsection\label{contents}
+\pdfbookmark[1]{Contents}{contents}
+\tableofcontents
+
+
+\section{first section%
+ \label{first-section}%
+}
+
+\end{document}
+"""],
+]
+
+totest_latex_toc['sectnum'] = [
+# input
+["""\
+.. contents::
+.. sectnum::
+
+first section
+-------------
+""",
+## # expected output
+head_template.substitute(dict(parts,
+ requirements=parts['requirements'] + '\\setcounter{secnumdepth}{0}\n'
+)) + r"""
+\phantomsection\label{contents}
+\pdfbookmark[1]{Contents}{contents}
+\tableofcontents
+
+
+\section{1 first section%
+ \label{first-section}%
+}
+
+\end{document}
+"""],
+]
+
+
+totest_latex_sectnum['no_sectnum'] = [
+# input
+["""\
+some text
+
+first section
+-------------
+""",
+## # expected output
+head_template.substitute(dict(parts, requirements = parts['requirements'] +
+r"""\setcounter{secnumdepth}{0}
+""")) + r"""
+some text
+
+
+\section{first section%
+ \label{first-section}%
+}
+
+\end{document}
+"""],
+]
+
+totest_latex_sectnum['sectnum'] = [
+# input
+["""\
+.. sectnum::
+
+some text
+
+first section
+-------------
+""",
+## # expected output
+head_template.substitute(dict(parts,
+ requirements=parts['requirements'] + '\\setcounter{secnumdepth}{0}\n'
+)) + r"""
+some text
+
+
+\section{first section%
+ \label{first-section}%
+}
+
+\end{document}
+"""],
+]
+
+totest_latex_citations['citations_with_underscore'] = [
+# input
+["""\
+Just a test citation [my_cite2006]_.
+
+.. [my_cite2006]
+ The underscore is mishandled.
+""",
+## # expected output
+head + r"""
+Just a test citation \cite{my_cite2006}.
+
+\begin{thebibliography}{my\_cite2006}
+\bibitem[my\_cite2006]{my_cite2006}{
+The underscore is mishandled.
+}
+\end{thebibliography}
+
+\end{document}
+"""],
+]
+
+
+totest_latex_citations['adjacent_citations'] = [
+# input
+["""\
+Two non-citations: [MeYou2007]_[YouMe2007]_.
+
+Need to be separated for grouping: [MeYou2007]_ [YouMe2007]_.
+
+Two spaces (or anything else) for no grouping: [MeYou2007]_ [YouMe2007]_.
+
+But a line break should work: [MeYou2007]_
+[YouMe2007]_.
+
+.. [MeYou2007] not.
+.. [YouMe2007] important.
+""",
+# expected output
+head + r"""
+Two non-citations: {[}MeYou2007{]}\_{[}YouMe2007{]}\_.
+
+Need to be separated for grouping: \cite{MeYou2007,YouMe2007}.
+
+Two spaces (or anything else) for no grouping: \cite{MeYou2007} \cite{YouMe2007}.
+
+But a line break should work: \cite{MeYou2007,YouMe2007}.
+
+\begin{thebibliography}{MeYou2007}
+\bibitem[MeYou2007]{MeYou2007}{
+not.
+}
+\bibitem[YouMe2007]{YouMe2007}{
+important.
+}
+\end{thebibliography}
+
+\end{document}
+"""],
+]
+
+
+totest['enumerated_lists'] = [
+# input
+["""\
+1. Item 1.
+2. Second to the previous item this one will explain
+
+ a) nothing.
+ b) or some other.
+
+3. Third is
+
+ (I) having pre and postfixes
+ (II) in roman numerals.
+""",
+# expected output
+head + r"""
+\begin{enumerate}
+\item Item 1.
+
+\item Second to the previous item this one will explain
+\end{enumerate}
+
+\begin{quote}
+\begin{enumerate}
+\renewcommand{\labelenumi}{\alph{enumi})}
+\item nothing.
+
+\item or some other.
+\end{enumerate}
+\end{quote}
+
+\begin{enumerate}
+\setcounter{enumi}{2}
+\item Third is
+\end{enumerate}
+
+\begin{quote}
+\begin{enumerate}
+\renewcommand{\labelenumi}{(\Roman{enumi})}
+\item having pre and postfixes
+
+\item in roman numerals.
+\end{enumerate}
+\end{quote}
+
+\end{document}
+"""],
+]
+
+# TODO: need to test for quote replacing if the language uses "ASCII-quotes"
+# as active character (e.g. de (ngerman)).
+
+
+totest['table_caption'] = [
+# input
+["""\
+.. table:: Foo
+
+ +-----+-----+
+ | | |
+ +-----+-----+
+ | | |
+ +-----+-----+
+""",
+head_table + r"""
+\setlength{\DUtablewidth}{\linewidth}
+\begin{longtable}[c]{|p{0.075\DUtablewidth}|p{0.075\DUtablewidth}|}
+\caption{Foo}\\
+\hline
+ & \\
+\hline
+ & \\
+\hline
+\end{longtable}
+
+\end{document}
+"""],
+]
+
+totest['table_styles'] = [
+["""\
+.. table::
+ :class: borderless
+
+ +-----+-----+
+ | 1 | 2 |
+ +-----+-----+
+ | 3 | 4 |
+ +-----+-----+
+""",
+head_table + r"""
+\setlength{\DUtablewidth}{\linewidth}
+\begin{longtable*}[c]{p{0.075\DUtablewidth}p{0.075\DUtablewidth}}
+
+1
+ &
+2
+ \\
+
+3
+ &
+4
+ \\
+\end{longtable*}
+
+\end{document}
+"""],
+["""\
+.. table::
+ :class: booktabs
+
+ +-----+-+
+ | 1 |2|
+ +-----+-+
+""",
+head_booktabs + r"""
+\setlength{\DUtablewidth}{\linewidth}
+\begin{longtable*}[c]{p{0.075\DUtablewidth}p{0.028\DUtablewidth}}
+\toprule
+
+1
+ &
+2
+ \\
+\bottomrule
+\end{longtable*}
+
+\end{document}
+"""],
+["""\
+.. table::
+ :class: colwidths-auto
+
+ +-----+-+
+ | 1 |2|
+ +-----+-+
+""",
+head_table + r"""
+\begin{longtable*}[c]{|l|l|}
+\hline
+1 & 2 \\
+\hline
+\end{longtable*}
+
+\end{document}
+"""],
+["""\
+.. table::
+ :widths: auto
+
+ +-----+-+
+ | 1 |2|
+ +-----+-+
+""",
+head_table + r"""
+\begin{longtable*}[c]{|l|l|}
+\hline
+1 & 2 \\
+\hline
+\end{longtable*}
+
+\end{document}
+"""],
+["""\
+.. table::
+ :widths: 15, 30
+
+ +-----+-----+
+ | 1 | 2 |
+ +-----+-----+
+""",
+head_table + r"""
+\setlength{\DUtablewidth}{\linewidth}
+\begin{longtable*}[c]{|p{0.191\DUtablewidth}|p{0.365\DUtablewidth}|}
+\hline
+
+1
+ &
+2
+ \\
+\hline
+\end{longtable*}
+
+\end{document}
+"""],
+]
+
+totest_table_style_booktabs['table_styles'] = [
+# borderless overrides "booktabs" table_style
+["""\
+.. table::
+ :class: borderless
+
+ +-----+-----+
+ | 1 | 2 |
+ +-----+-----+
+ | 3 | 4 |
+ +-----+-----+
+""",
+head_table + r"""
+\setlength{\DUtablewidth}{\linewidth}
+\begin{longtable*}[c]{p{0.075\DUtablewidth}p{0.075\DUtablewidth}}
+
+1
+ &
+2
+ \\
+
+3
+ &
+4
+ \\
+\end{longtable*}
+
+\end{document}
+"""],
+["""\
+.. table::
+ :widths: auto
+
+ +-----+-+
+ | 1 |2|
+ +-----+-+
+""",
+head_booktabs + r"""
+\begin{longtable*}[c]{ll}
+\toprule
+1 & 2 \\
+\bottomrule
+\end{longtable*}
+
+\end{document}
+"""],
+["""\
+.. table::
+ :widths: 15, 30
+
+ +-----+-----+
+ | 1 | 2 |
+ +-----+-----+
+""",
+head_booktabs + r"""
+\setlength{\DUtablewidth}{\linewidth}
+\begin{longtable*}[c]{p{0.191\DUtablewidth}p{0.365\DUtablewidth}}
+\toprule
+
+1
+ &
+2
+ \\
+\bottomrule
+\end{longtable*}
+
+\end{document}
+"""],
+]
+totest_table_style_auto['table_styles'] = [
+["""\
+.. table::
+ :class: borderless
+
+ +-----+-----+
+ | 1 | 2 |
+ +-----+-----+
+ | 3 | 4 |
+ +-----+-----+
+""",
+head_table + r"""
+\begin{longtable*}[c]{ll}
+1 & 2 \\
+3 & 4 \\
+\end{longtable*}
+
+\end{document}
+"""],
+["""\
+.. table::
+ :class: booktabs
+
+ +-----+-+
+ | 1 |2|
+ +-----+-+
+""",
+head_booktabs + r"""
+\begin{longtable*}[c]{ll}
+\toprule
+1 & 2 \\
+\bottomrule
+\end{longtable*}
+
+\end{document}
+"""],
+# given width overrides "colwidth-auto"
+["""\
+.. table::
+ :widths: 15, 30
+
+ +-----+-----+
+ | 1 | 2 |
+ +-----+-----+
+""",
+head_table + r"""
+\setlength{\DUtablewidth}{\linewidth}
+\begin{longtable*}[c]{|p{0.191\DUtablewidth}|p{0.365\DUtablewidth}|}
+\hline
+
+1
+ &
+2
+ \\
+\hline
+\end{longtable*}
+
+\end{document}
+"""],
+]
+
+totest['table_align'] = [
+# input
+["""\
+.. table::
+ :align: right
+
+ +-----+-----+
+ | 1 | 2 |
+ +-----+-----+
+""",
+head_table + r"""
+\setlength{\DUtablewidth}{\linewidth}
+\begin{longtable*}[r]{|p{0.075\DUtablewidth}|p{0.075\DUtablewidth}|}
+\hline
+
+1
+ &
+2
+ \\
+\hline
+\end{longtable*}
+
+\end{document}
+"""],
+]
+
+totest['table_empty_cells'] = [
+["""\
+===== ======
+Title
+===== ======
+entry value1
+===== ======
+""",
+head_table + r"""
+\setlength{\DUtablewidth}{\linewidth}
+\begin{longtable*}[c]{|p{0.075\DUtablewidth}|p{0.086\DUtablewidth}|}
+\hline
+\textbf{%
+Title
+} & \\
+\hline
+\endfirsthead
+\hline
+\textbf{%
+Title
+} & \\
+\hline
+\endhead
+\multicolumn{2}{c}{\hfill ... continued on next page} \\
+\endfoot
+\endlastfoot
+
+entry
+ &
+value1
+ \\
+\hline
+\end{longtable*}
+
+\end{document}
+"""],
+["""\
++----+----+
+| c3 | c4 |
++----+----+
+| |
++---------+
+""",
+head_table + r"""
+\setlength{\DUtablewidth}{\linewidth}
+\begin{longtable*}[c]{|p{0.063\DUtablewidth}|p{0.063\DUtablewidth}|}
+\hline
+
+c3
+ &
+c4
+ \\
+\hline
+\multicolumn{2}{|p{0.13\DUtablewidth}|}{} \\
+\hline
+\end{longtable*}
+
+\end{document}
+"""],
+]
+
+# The "[" needs to be protected (otherwise it will be seen as an
+# option to "\\", "\item", etc. ).
+
+totest['bracket_protection'] = [
+# input
+["""
+* [no option] to this item
+""",
+head + r"""
+\begin{itemize}
+\item {[}no option{]} to this item
+\end{itemize}
+
+\end{document}
+"""],
+]
+
+totest['literal_block'] = [
+# input
+["""\
+Test special characters { [ \\\\ ] } in literal block::
+
+ { [ ( \\macro
+
+ } ] )
+""",
+head_alltt + r"""
+Test special characters \{ {[} \textbackslash{} {]} \} in literal block:
+
+\begin{quote}
+\begin{alltt}
+\{ [ ( \textbackslash{}macro
+
+\} ] )
+\end{alltt}
+\end{quote}
+
+\end{document}
+"""],
+]
+
+totest['raw'] = [
+[r""".. raw:: latex
+
+ $E=mc^2$
+
+A paragraph.
+
+.. |sub| raw:: latex
+
+ (some raw text)
+
+Foo |sub|
+same paragraph.
+""",
+head + r"""
+$E=mc^2$
+
+A paragraph.
+
+Foo (some raw text)
+same paragraph.
+
+\end{document}
+"""],
+]
+
+totest['title_with_inline_markup'] = [
+["""\
+This is the *Title*
+===================
+
+This is the *Subtitle*
+----------------------
+
+This is a *section title*
+~~~~~~~~~~~~~~~~~~~~~~~~~
+
+This is the *document*.
+""",
+head_template.substitute(dict(parts,
+ requirements=parts['requirements'] + '\\setcounter{secnumdepth}{0}\n',
+ fallbacks=r"""
+% subtitle (in document title)
+\providecommand*{\DUdocumentsubtitle}[1]{{\large #1}}
+""",
+ pdfsetup=parts['pdfsetup'] + r"""\hypersetup{
+ pdftitle={This is the Title},
+}
+""", titledata=r"""\title{This is the \emph{Title}%
+ \label{this-is-the-title}%
+ \\%
+ \DUdocumentsubtitle{This is the \emph{Subtitle}}%
+ \label{this-is-the-subtitle}}
+\author{}
+\date{}
+""")) + r"""\maketitle
+
+
+\section{This is a \emph{section title}%
+ \label{this-is-a-section-title}%
+}
+
+This is the \emph{document}.
+
+\end{document}
+"""],
+]
+
+totest_stylesheet['two-styles'] = [
+# input
+["""two stylesheet links in the header""",
+head_template.substitute(dict(parts, stylesheet =
+r"""\usepackage{data/spam}
+\input{data/ham.tex}
+""")) + r"""
+two stylesheet links in the header
+
+\end{document}
+"""],
+]
+
+totest_stylesheet_embed['two-styles'] = [
+# input
+["""two stylesheets embedded in the header""",
+head_template.substitute(dict(parts, stylesheet =
+r"""% Cannot embed stylesheet 'data/spam.sty':
+% No such file or directory.
+% embedded stylesheet: data/ham.tex
+\newcommand{\ham}{wonderful ham}
+
+""")) + r"""
+two stylesheets embedded in the header
+
+\end{document}
+"""],
+]
+
+if __name__ == '__main__':
+ import unittest
+ unittest.main(defaultTest='suite')
--- /dev/null
+#! /usr/bin/env python
+
+# $Id: test_latex2e.py 6003 2009-06-27 20:44:09Z milde $
+# Author: engelbert gruber <grubert@users.sourceforge.net>
+# Copyright: This module has been placed in the public domain.
+
+"""
+Tests for manpage writer.
+"""
+from __future__ import absolute_import
+
+from . import DocutilsTestSupport
+
+
+def suite():
+ settings = {}
+ s = DocutilsTestSupport.PublishTestSuite('manpage', suite_settings=settings)
+ s.generateTests(totest)
+ return s
+
+indend_macros = r""".
+.nr rst2man-indent-level 0
+.
+.de1 rstReportMargin
+\\$1 \\n[an-margin]
+level \\n[rst2man-indent-level]
+level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
+-
+\\n[rst2man-indent0]
+\\n[rst2man-indent1]
+\\n[rst2man-indent2]
+..
+.de1 INDENT
+.\" .rstReportMargin pre:
+. RS \\$1
+. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin]
+. nr rst2man-indent-level +1
+.\" .rstReportMargin post:
+..
+.de UNINDENT
+. RE
+.\" indent \\n[an-margin]
+.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.nr rst2man-indent-level -1
+.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
+..
+"""
+
+totest = {}
+
+totest['blank'] = [
+ ["",
+ r""".\" Man page generated from reStructuredText.
+.
+.TH "" "" ""
+.SH NAME
+ \-
+"""+indend_macros+
+r""".\" Generated by docutils manpage writer.
+.
+"""],
+ [r"""Hello, world.
+=============
+
+.. WARNING::
+ This broke docutils-sphinx.
+
+""",
+ r""".\" Man page generated from reStructuredText.
+.
+.TH HELLO, WORLD. "" "" ""
+.SH NAME
+Hello, world. \-
+"""+indend_macros+
+r""".sp
+\fBWARNING:\fP
+.INDENT 0.0
+.INDENT 3.5
+This broke docutils\-sphinx.
+.UNINDENT
+.UNINDENT
+.\" Generated by docutils manpage writer.
+.
+"""],
+ ]
+
+totest['simple'] = [
+ ["""\
+========
+ simple
+========
+
+---------------
+ The way to go
+---------------
+
+:Author: someone@somewhere.net
+:Date: 2009-08-05
+:Copyright: public domain
+:Version: 0.1
+:Manual section: 1
+:Manual group: text processing
+:Arbitrary field: some text
+
+SYNOPSIS
+========
+
+::
+
+ K.I.S.S keep it simple.
+
+DESCRIPTION
+===========
+
+General rule of life.
+
+OPTIONS
+=======
+
+--config=<file> Read configuration settings from <file>, if it exists.
+--version, -V Show this program's version number and exit.
+--help, -h Show this help message and exit.
+
+OtHeR SECTION
+=============
+
+With mixed case.
+
+.. Attention::
+
+ Admonition with title
+
+ * bullet list
+ * bull and list
+
+.. admonition:: homegrown
+
+ something important
+
+. period at line start.
+
+and . in a line and at line start
+.in a paragraph
+""",
+ r""".\" Man page generated from reStructuredText.
+.
+.TH SIMPLE 1 "2009-08-05" "0.1" "text processing"
+.SH NAME
+simple \- The way to go
+"""+indend_macros+
+r""".SH SYNOPSIS
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+K.I.S.S keep it simple.
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.SH DESCRIPTION
+.sp
+General rule of life.
+.SH OPTIONS
+.INDENT 0.0
+.TP
+.BI \-\-config\fB= <file>
+Read configuration settings from <file>, if it exists.
+.TP
+.B \-\-version\fP,\fB \-V
+Show this program\(aqs version number and exit.
+.TP
+.B \-\-help\fP,\fB \-h
+Show this help message and exit.
+.UNINDENT
+.SH OTHER SECTION
+.sp
+With mixed case.
+.sp
+\fBATTENTION!:\fP
+.INDENT 0.0
+.INDENT 3.5
+Admonition with title
+.INDENT 0.0
+.IP \(bu 2
+bullet list
+.IP \(bu 2
+bull and list
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.INDENT 0.0
+.INDENT 3.5
+.IP "homegrown"
+.sp
+something important
+.UNINDENT
+.UNINDENT
+.sp
+\&. period at line start.
+.sp
+and . in a line and at line start
+\&.in a paragraph
+.SH AUTHOR
+someone@somewhere.net
+
+Arbitrary field: some text
+.SH COPYRIGHT
+public domain
+.\" Generated by docutils manpage writer.
+.
+"""],
+ ]
+
+totest['table'] = [
+ ["""\
+ ====== =====
+ head and
+ ====== =====
+ 1 2
+ abc so
+ ====== =====
+""",
+'''\
+.\\" Man page generated from reStructuredText.
+.
+.TH "" "" ""
+.SH NAME
+ \\- \n\
+'''+indend_macros+
+'''.INDENT 0.0
+.INDENT 3.5
+.TS
+center;
+|l|l|.
+_
+T{
+head
+T}\tT{
+and
+T}
+_
+T{
+1
+T}\tT{
+2
+T}
+_
+T{
+abc
+T}\tT{
+so
+T}
+_
+.TE
+.UNINDENT
+.UNINDENT
+.\\" Generated by docutils manpage writer.
+.
+''']
+]
+
+totest['optiongroup'] = [
+ ["""
+optin group with dot as group item
+
+$
+ bla bla bla
+
+#
+ bla bla bla
+
+.
+ bla bla bla
+
+[
+ bla bla bla
+
+]
+ bla bla bla
+""",
+ """\
+.\\" Man page generated from reStructuredText.
+.
+.TH "" "" ""
+.SH NAME
+ \\- \n\
+"""+indend_macros+
+"""optin group with dot as group item
+.INDENT 0.0
+.TP
+.B $
+bla bla bla
+.UNINDENT
+.INDENT 0.0
+.TP
+.B #
+bla bla bla
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \\&.
+bla bla bla
+.UNINDENT
+.INDENT 0.0
+.TP
+.B [
+bla bla bla
+.UNINDENT
+.INDENT 0.0
+.TP
+.B ]
+bla bla bla
+.UNINDENT
+.\\" Generated by docutils manpage writer.
+."""],
+ ]
+
+totest['definitionlist'] = [
+ ["""
+====================
+Definition List Test
+====================
+
+:Abstract: Docinfo is required.
+
+Section
+=======
+
+:term1:
+
+ Description of Term 1 Description of Term 1 Description of Term 1
+ Description of Term 1 Description of Term 1
+
+ Description of Term 1 Description of Term 1 Description of Term 1
+ Description of Term 1 Description of Term 1
+
+""",
+'''\
+.\\" Man page generated from reStructuredText.
+.
+.TH DEFINITION LIST TEST "" "" ""
+.SH NAME
+Definition List Test \\- \n\
+'''+indend_macros+
+'''.SS Abstract
+.sp
+Docinfo is required.
+.SH SECTION
+.INDENT 0.0
+.TP
+.B term1
+Description of Term 1 Description of Term 1 Description of Term 1
+Description of Term 1 Description of Term 1
+.sp
+Description of Term 1 Description of Term 1 Description of Term 1
+Description of Term 1 Description of Term 1
+.UNINDENT
+.\\" Generated by docutils manpage writer.
+.'''],
+ ]
+
+totest['cmdlineoptions'] = [
+ ["""optional arguments:
+ -h, --help show this help
+ --output FILE, -o FILE output filename
+ -i DEVICE, --input DEVICE input device
+""",
+ r""".\" Man page generated from reStructuredText.
+.
+.TH "" "" ""
+.SH NAME
+ \-
+"""+indend_macros+
+r""".INDENT 0.0
+.TP
+.B optional arguments:
+.INDENT 7.0
+.TP
+.B \-h\fP,\fB \-\-help
+show this help
+.TP
+.BI \-\-output \ FILE\fR,\fB \ \-o \ FILE
+output filename
+.TP
+.BI \-i \ DEVICE\fR,\fB \ \-\-input \ DEVICE
+input device
+.UNINDENT
+.UNINDENT
+.\" Generated by docutils manpage writer.
+.
+"""],
+ ]
+
+
+if __name__ == '__main__':
+ import unittest
+ unittest.main(defaultTest='suite')
--- /dev/null
+#!/usr/bin/env python
+
+# $Id: test_null.py 8356 2019-08-26 16:44:19Z milde $
+# Author: Lea Wiemann <LeWiemann@gmail.com>
+# Copyright: This module has been placed in the public domain.
+
+"""
+Test for Null writer.
+"""
+from __future__ import absolute_import
+
+from . import DocutilsTestSupport
+
+
+def suite():
+ s = DocutilsTestSupport.PublishTestSuite('null')
+ s.generateTests(totest)
+ return s
+
+totest = {}
+
+totest['basic'] = [
+["""\
+This is a paragraph.
+""",
+None]
+]
+
+if __name__ == '__main__':
+ import unittest
+ unittest.main(defaultTest='suite')
--- /dev/null
+#!/usr/bin/env python
+
+# $Id: test_odt.py 8369 2019-08-27 12:10:26Z milde $
+# Author: Dave Kuhlman <dkuhlman@rexx.com>
+# Copyright: This module has been placed in the public domain.
+
+"""
+Tests for docutils odtwriter.
+
+Instructions for adding a new test:
+
+1. Add a new method to class DocutilsOdtTestCase (below) named
+ test_odt_xxxx, where xxxx describes your new feature. See
+ test_odt_basic for an example.
+
+2. Add a new input reST (.txt) file in test/functional/input. This
+ file should contain the smallest amount of reST that tests your
+ new feature. Name this file odt_xxxx.txt.
+
+3. Convert your input reST (.txt) file to an ODF (.odt) file using
+ rst2odt.py. Place this ODF (.odt) file in
+ test/functional/expected. Name this file odt_xxxx.odt.
+ You can also pass parameter save_output_name='filename' to method
+ process_test() in order to produce expected output.
+ See and modify variable TEMP_FILE_PATH for destination.
+
+4. Run your test. Your new test should pass.
+
+5. If any other tests fail, that's a possible regression.
+
+"""
+from __future__ import absolute_import
+
+import os
+import zipfile
+import xml.etree.ElementTree as etree
+from io import BytesIO
+
+from . import DocutilsTestSupport
+import docutils
+import docutils.core
+
+#
+# Globals
+TEMP_FILE_PATH = 'functional/output/'
+INPUT_PATH = 'functional/input/'
+EXPECTED_PATH = 'functional/expected/'
+
+
+class DocutilsOdtTestCase(DocutilsTestSupport.StandardTestCase):
+
+ def process_test(self, input_filename, expected_filename,
+ save_output_name=None, settings_overrides=None):
+ # Test that xmlcharrefreplace is the default output encoding
+ # error handler.
+ input_file = open(INPUT_PATH + input_filename, 'rb')
+ expected_file = open(EXPECTED_PATH + expected_filename, 'rb')
+ input = input_file.read()
+ expected = expected_file.read()
+ input_file.close()
+ expected_file.close()
+ if settings_overrides is None:
+ settings_overrides={}
+ settings_overrides['_disable_config'] = True
+ settings_overrides['language_code'] = 'en-US'
+
+ result = docutils.core.publish_string(
+ source=input,
+ reader_name='standalone',
+ writer_name='odf_odt',
+ settings_overrides=settings_overrides)
+## msg = 'file length not equal: expected length: %d actual length: %d' % (
+## len(expected), len(result), )
+## self.assertEqual(str(len(result)), str(len(expected)))
+ if save_output_name:
+ filename = '%s%s%s' % (TEMP_FILE_PATH, os.sep, save_output_name,)
+ outfile = open(filename, 'wb')
+ outfile.write(result)
+ outfile.close()
+ content1 = self.extract_file(result, 'content.xml')
+ content2 = self.extract_file(expected, 'content.xml')
+ msg = 'content.xml not equal: expected len: %d actual len: %d' % (
+ len(content2), len(content1), )
+ self.assertEqual(content1, content2, msg)
+
+ def reorder_attributes(self, root):
+ """
+ Make attribute order independent of python version.
+ python3.8 is different to previous.
+ """
+ for el in root.iter():
+ attrib = el.attrib
+ if len(attrib) > 1:
+ # adjust attribute order, e.g. by sorting
+ attribs = sorted(attrib.items())
+ attrib.clear()
+ attrib.update(attribs)
+
+ def extract_file(self, payload, filename):
+ payloadfile = BytesIO()
+ payloadfile.write(payload)
+ payloadfile.seek(0)
+ zfile = zipfile.ZipFile(payloadfile, 'r')
+ content1 = zfile.read(filename)
+ doc = etree.fromstring(content1)
+ self.reorder_attributes(doc)
+ #content2 = doc.toprettyxml(indent=' ')
+ content2 = etree.tostring(doc)
+ return content2
+
+ def assertEqual(self, first, second, msg=None):
+ if msg is None:
+ msg2 = msg
+ else:
+ sep = '+' * 60
+ msg1 = '\n%s\nresult:\n%s\n%s\nexpected:\n%s\n%s' % (
+ sep, first, sep, second, sep, )
+ #msg2 = '%s\n%s' % (msg1, msg, )
+ msg2 = '%s' % (msg, )
+ DocutilsTestSupport.StandardTestCase.assertEqual(self,
+ first, second, msg2)
+
+ #
+ # Unit test methods
+ #
+ # All test methods should be named "test_odt_xxxx", where
+ # xxxx is replaced with a name for the new test.
+ # See instructions above in module doc-string.
+ #
+
+ def test_odt_basic(self):
+ self.process_test('odt_basic.txt', 'odt_basic.odt',
+ save_output_name='odt_basic.odt'
+ )
+
+ def test_odt_nested_class(self):
+ self.process_test('odt_nested_class.txt',
+ 'odt_nested_class.odt',
+ save_output_name='odt_nested_class.odt'
+ )
+ self.process_test('odt_unnested_class.txt',
+ 'odt_unnested_class.odt',
+ save_output_name='odt_unnested_class.odt'
+ )
+ self.process_test('odt_no_class.txt',
+ 'odt_no_class.odt',
+ save_output_name='odt_no_class.odt'
+ )
+
+ def test_odt_tables1(self):
+ self.process_test('odt_tables1.txt', 'odt_tables1.odt',
+ save_output_name='odt_tables1.odt'
+ )
+
+ def test_odt_custom_headfoot(self):
+ settings_overrides = {
+ 'custom_header': 'Page %p% of %P%',
+ 'custom_footer': 'Title: %t% Date: %d3% Time: %t4%',
+ 'language_code': 'en-US',
+ }
+ self.process_test('odt_custom_headfoot.txt', 'odt_custom_headfoot.odt',
+ settings_overrides=settings_overrides,
+ save_output_name='odt_custom_headfoot.odt'
+ )
+
+ def test_odt_header_footer(self):
+ self.process_test('odt_header_footer.txt', 'odt_header_footer.odt',
+ save_output_name='odt_header_footer.odt'
+ )
+
+ def test_odt_literal_block(self):
+ self.process_test('odt_literal_block.txt', 'odt_literal_block.odt')
+
+ def test_odt_contents(self):
+ self.process_test('odt_contents.txt', 'odt_contents.odt')
+
+ def test_odt_classifier(self):
+ self.process_test('odt_classifier.txt', 'odt_classifier.odt')
+
+ def test_odt_footnotes(self):
+ self.process_test('odt_footnotes.txt', 'odt_footnotes.odt',
+ save_output_name='odt_footnotes.odt'
+ )
+ def test_odt_raw(self):
+ self.process_test('odt_raw.txt', 'odt_raw.odt',
+ save_output_name='odt_raw.odt'
+ )
+
+ #
+ # Template for new tests.
+ # Also add functional/input/odt_xxxx.txt and
+ # functional/expected/odt_xxxx.odt
+ # Replace all xxxx with name of your test.
+ #
+## def test_odt_xxxx(self):
+## self.process_test('odt_xxxx.txt', 'odt_xxxx.odt')
+
+
+# -----------------------------------------------------------------
+
+
+if __name__ == '__main__':
+ import unittest
+ unittest.main()
--- /dev/null
+#!/usr/bin/env python
+
+# $Id: test_pseudoxml.py 8356 2019-08-26 16:44:19Z milde $
+# Author: Lea Wiemann <LeWiemann@gmail.com>
+# Copyright: This module has been placed in the public domain.
+
+"""
+Test for pseudo-XML writer.
+"""
+from __future__ import absolute_import
+
+from . import DocutilsTestSupport
+
+
+def suite():
+ s = DocutilsTestSupport.PublishTestSuite('pseudoxml')
+ s.generateTests(totest)
+ return s
+
+totest = {}
+
+totest['basic'] = [
+# input
+["""\
+This is a paragraph.
+
+----------
+
+This is another paragraph.
+
+A Section
+---------
+
+Foo.
+""",
+# output
+"""\
+<document source="<string>">
+ <paragraph>
+ This is a paragraph.
+ <transition>
+ <paragraph>
+ This is another paragraph.
+ <section ids="a-section" names="a\\ section">
+ <title>
+ A Section
+ <paragraph>
+ Foo.
+"""]
+]
+
+if __name__ == '__main__':
+ import unittest
+ unittest.main(defaultTest='suite')
--- /dev/null
+#!/usr/bin/env python
+
+# $Id: test_s5.py 8356 2019-08-26 16:44:19Z milde $
+# Author: David Goodger <goodger@python.org>
+# Copyright: This module has been placed in the public domain.
+
+"""
+Tests for the S5/HTML writer.
+"""
+from __future__ import absolute_import
+
+import os
+import platform
+
+from . import DocutilsTestSupport
+
+
+def suite():
+ settings = {'stylesheet_path': '/test.css',
+ 'embed_stylesheet': 0,}
+ s = DocutilsTestSupport.PublishTestSuite('s5', suite_settings=settings)
+ s.generateTests(totest_1)
+ settings['hidden_controls'] = 0
+ settings['view_mode'] = 'outline'
+ s.generateTests(totest_2)
+ return s
+
+interpolations = {
+ 'version': DocutilsTestSupport.docutils.__version__,
+ 'drive': '', }
+
+if platform.system() == "Windows":
+ interpolations['drive'] = "C:"
+
+totest_1 = {}
+totest_2 = {}
+
+totest_1['basics'] = [
+["""\
+============
+ Show Title
+============
+
+Title slide
+
+First Slide
+===========
+
+Slide text.
+""",
+"""\
+<?xml version="1.0" encoding="utf-8" ?>
+<!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">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<meta name="generator" content="Docutils %(version)s: http://docutils.sourceforge.net/" />
+<meta name="version" content="S5 1.1" />
+<title>Show Title</title>
+<link rel="stylesheet" href="%(drive)s/test.css" type="text/css" />
+<!-- configuration parameters -->
+<meta name="defaultView" content="slideshow" />
+<meta name="controlVis" content="hidden" />
+<!-- style sheet links -->
+<script src="ui/default/slides.js" type="text/javascript"></script>
+<link rel="stylesheet" href="ui/default/slides.css"
+ type="text/css" media="projection" id="slideProj" />
+<link rel="stylesheet" href="ui/default/outline.css"
+ type="text/css" media="screen" id="outlineStyle" />
+<link rel="stylesheet" href="ui/default/print.css"
+ type="text/css" media="print" id="slidePrint" />
+<link rel="stylesheet" href="ui/default/opera.css"
+ type="text/css" media="projection" id="operaFix" />
+
+<style type="text/css">
+#currentSlide {display: none;}
+</style>
+</head>
+<body>
+<div class="layout">
+<div id="controls"></div>
+<div id="currentSlide"></div>
+<div id="header">
+
+</div>
+<div id="footer">
+<h1>Show Title</h1>
+
+</div>
+</div>
+<div class="presentation">
+<div class="slide" id="slide0">
+<h1 class="title">Show Title</h1>
+
+<p>Title slide</p>
+
+</div>
+<div class="slide" id="first-slide">
+<h1>First Slide</h1>
+<p>Slide text.</p>
+</div>
+</div>
+</body>
+</html>
+""" % interpolations]
+]
+
+totest_2['settings'] = [
+["""\
+==================
+ Bogus Slide Show
+==================
+
+We're just checking the settings
+""",
+"""\
+<?xml version="1.0" encoding="utf-8" ?>
+<!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">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<meta name="generator" content="Docutils %(version)s: http://docutils.sourceforge.net/" />
+<meta name="version" content="S5 1.1" />
+<title>Bogus Slide Show</title>
+<link rel="stylesheet" href="%(drive)s/test.css" type="text/css" />
+<!-- configuration parameters -->
+<meta name="defaultView" content="outline" />
+<meta name="controlVis" content="visible" />
+<!-- style sheet links -->
+<script src="ui/default/slides.js" type="text/javascript"></script>
+<link rel="stylesheet" href="ui/default/slides.css"
+ type="text/css" media="projection" id="slideProj" />
+<link rel="stylesheet" href="ui/default/outline.css"
+ type="text/css" media="screen" id="outlineStyle" />
+<link rel="stylesheet" href="ui/default/print.css"
+ type="text/css" media="print" id="slidePrint" />
+<link rel="stylesheet" href="ui/default/opera.css"
+ type="text/css" media="projection" id="operaFix" />
+
+<style type="text/css">
+#currentSlide {display: none;}
+</style>
+</head>
+<body>
+<div class="layout">
+<div id="controls"></div>
+<div id="currentSlide"></div>
+<div id="header">
+
+</div>
+<div id="footer">
+<h1>Bogus Slide Show</h1>
+
+</div>
+</div>
+<div class="presentation">
+<div class="slide" id="slide0">
+<h1 class="title">Bogus Slide Show</h1>
+
+<p>We're just checking the settings</p>
+</div>
+</div>
+</body>
+</html>
+""" % interpolations]
+]
+
+if __name__ == '__main__':
+ import unittest
+ unittest.main(defaultTest='suite')
--- /dev/null
+#!/usr/bin/env python
+
+# $Id: buildhtml.py 8410 2019-11-04 21:14:43Z milde $
+# Author: David Goodger <goodger@python.org>
+# Copyright: This module has been placed in the public domain.
+
+"""
+Generates .html from all the .txt files in a directory.
+
+Ordinary .txt files are understood to be standalone reStructuredText.
+Files named ``pep-*.txt`` are interpreted as reStructuredText PEPs.
+"""
+# Once PySource is here, build .html from .py as well.
+
+__docformat__ = 'reStructuredText'
+
+
+try:
+ import locale
+ locale.setlocale(locale.LC_ALL, '')
+except:
+ pass
+
+import sys
+import os
+import os.path
+import copy
+from fnmatch import fnmatch
+import docutils
+from docutils import ApplicationError
+from docutils import core, frontend, utils
+from docutils.utils.error_reporting import ErrorOutput, ErrorString
+from docutils.parsers import rst
+from docutils.readers import standalone, pep
+from docutils.writers import html4css1, html5_polyglot, pep_html
+
+
+usage = '%prog [options] [<directory> ...]'
+description = ('Generates .html from all the reStructuredText .txt files '
+ '(including PEPs) in each <directory> '
+ '(default is the current directory).')
+
+
+class SettingsSpec(docutils.SettingsSpec):
+
+ """
+ Runtime settings & command-line options for the front end.
+ """
+
+ prune_default = ['.hg', '.bzr', '.git', '.svn', 'CVS']
+
+ # Can't be included in OptionParser below because we don't want to
+ # override the base class.
+ settings_spec = (
+ 'Build-HTML Options',
+ None,
+ (('Recursively scan subdirectories for files to process. This is '
+ 'the default.',
+ ['--recurse'],
+ {'action': 'store_true', 'default': 1,
+ 'validator': frontend.validate_boolean}),
+ ('Do not scan subdirectories for files to process.',
+ ['--local'], {'dest': 'recurse', 'action': 'store_false'}),
+ ('Do not process files in <directory> (shell globbing patterns, '
+ 'separated by colons). This option may be used '
+ 'more than once to specify multiple directories. Default: "%s".'
+ % ':'.join(prune_default),
+ ['--prune'],
+ {'metavar': '<directory>', 'action': 'append',
+ 'validator': frontend.validate_colon_separated_string_list,
+ 'default': prune_default,}),
+ ('Recursively ignore files matching any of the given '
+ 'wildcard (shell globbing) patterns (separated by colons).',
+ ['--ignore'],
+ {'metavar': '<patterns>', 'action': 'append',
+ 'default': [],
+ 'validator': frontend.validate_colon_separated_string_list}),
+ ('HTML version, one of "html", "html4", "html5". '
+ 'Default: "html" (use Docutils\' default HTML writer).',
+ ['--html-writer'],
+ {'metavar': '<html_writer>',
+ 'choices': ['html', 'html4', 'html5'],
+ 'default': 'html'}),
+ ('Work silently (no progress messages). Independent of "--quiet".',
+ ['--silent'],
+ {'action': 'store_true', 'validator': frontend.validate_boolean}),
+ ('Do not process files, show files that would be processed.',
+ ['--dry-run'],
+ {'action': 'store_true', 'validator': frontend.validate_boolean}),))
+
+ relative_path_settings = ('prune',)
+ config_section = 'buildhtml application'
+ config_section_dependencies = ('applications',)
+
+
+class OptionParser(frontend.OptionParser):
+
+ """
+ Command-line option processing for the ``buildhtml.py`` front end.
+ """
+
+ def check_values(self, values, args):
+ frontend.OptionParser.check_values(self, values, args)
+ values._source = None
+ return values
+
+ def check_args(self, args):
+ source = destination = None
+ if args:
+ self.values._directories = args
+ else:
+ self.values._directories = [os.getcwd()]
+ return source, destination
+
+
+class Struct(object):
+
+ """Stores data attributes for dotted-attribute access."""
+
+ def __init__(self, **keywordargs):
+ self.__dict__.update(keywordargs)
+
+
+class Builder(object):
+
+ def __init__(self):
+ self.publishers = {
+ '': Struct(components=(pep.Reader, rst.Parser, pep_html.Writer,
+ SettingsSpec)),
+ 'html4': Struct(components=(rst.Parser, standalone.Reader,
+ html4css1.Writer, SettingsSpec),
+ reader_name='standalone',
+ writer_name='html4'),
+ 'html5': Struct(components=(rst.Parser, standalone.Reader,
+ html5_polyglot.Writer, SettingsSpec),
+ reader_name='standalone',
+ writer_name='html5'),
+ 'PEPs': Struct(components=(rst.Parser, pep.Reader,
+ pep_html.Writer, SettingsSpec),
+ reader_name='pep',
+ writer_name='pep_html')}
+ """Publisher-specific settings. Key '' is for the front-end script
+ itself. ``self.publishers[''].components`` must contain a superset of
+ all components used by individual publishers."""
+
+ self.setup_publishers()
+ # default html writer (may change to html5 some time):
+ self.publishers['html'] = self.publishers['html4']
+
+ def setup_publishers(self):
+ """
+ Manage configurations for individual publishers.
+
+ Each publisher (combination of parser, reader, and writer) may have
+ its own configuration defaults, which must be kept separate from those
+ of the other publishers. Setting defaults are combined with the
+ config file settings and command-line options by
+ `self.get_settings()`.
+ """
+ for name, publisher in self.publishers.items():
+ option_parser = OptionParser(
+ components=publisher.components, read_config_files=1,
+ usage=usage, description=description)
+ publisher.option_parser = option_parser
+ publisher.setting_defaults = option_parser.get_default_values()
+ frontend.make_paths_absolute(publisher.setting_defaults.__dict__,
+ option_parser.relative_path_settings)
+ publisher.config_settings = (
+ option_parser.get_standard_config_settings())
+ self.settings_spec = self.publishers[''].option_parser.parse_args(
+ values=frontend.Values()) # no defaults; just the cmdline opts
+ self.initial_settings = self.get_settings('')
+
+ def get_settings(self, publisher_name, directory=None):
+ """
+ Return a settings object, from multiple sources.
+
+ Copy the setting defaults, overlay the startup config file settings,
+ then the local config file settings, then the command-line options.
+ Assumes the current directory has been set.
+ """
+ publisher = self.publishers[publisher_name]
+ settings = frontend.Values(publisher.setting_defaults.__dict__)
+ settings.update(publisher.config_settings, publisher.option_parser)
+ if directory:
+ local_config = publisher.option_parser.get_config_file_settings(
+ os.path.join(directory, 'docutils.conf'))
+ frontend.make_paths_absolute(
+ local_config, publisher.option_parser.relative_path_settings,
+ directory)
+ settings.update(local_config, publisher.option_parser)
+ settings.update(self.settings_spec.__dict__, publisher.option_parser)
+ return settings
+
+ def run(self, directory=None, recurse=1):
+ recurse = recurse and self.initial_settings.recurse
+ if directory:
+ self.directories = [directory]
+ elif self.settings_spec._directories:
+ self.directories = self.settings_spec._directories
+ else:
+ self.directories = [os.getcwd()]
+ for directory in self.directories:
+ for root, dirs, files in os.walk(directory):
+ # os.walk by default this recurses down the tree,
+ # influence by modifying dirs.
+ if not recurse:
+ del dirs[:]
+ self.visit(root, files, dirs)
+
+ def visit(self, directory, names, subdirectories):
+ settings = self.get_settings('', directory)
+ errout = ErrorOutput(encoding=settings.error_encoding)
+ if settings.prune and (os.path.abspath(directory) in settings.prune):
+ errout.write('/// ...Skipping directory (pruned): %s\n' %
+ directory)
+ sys.stderr.flush()
+ del subdirectories[:]
+ return
+ if not self.initial_settings.silent:
+ errout.write('/// Processing directory: %s\n' % directory)
+ sys.stderr.flush()
+ # settings.ignore grows many duplicate entries as we recurse
+ # if we add patterns in config files or on the command line.
+ for pattern in utils.uniq(settings.ignore):
+ for i in range(len(names) - 1, -1, -1):
+ if fnmatch(names[i], pattern):
+ # Modify in place!
+ del names[i]
+ for name in names:
+ if name.endswith('.txt'):
+ self.process_txt(directory, name)
+
+ def process_txt(self, directory, name):
+ if name.startswith('pep-'):
+ publisher = 'PEPs'
+ else:
+ publisher = self.initial_settings.html_writer
+ settings = self.get_settings(publisher, directory)
+ errout = ErrorOutput(encoding=settings.error_encoding)
+ pub_struct = self.publishers[publisher]
+ settings._source = os.path.normpath(os.path.join(directory, name))
+ settings._destination = settings._source[:-4]+'.html'
+ if not self.initial_settings.silent:
+ errout.write(' ::: Processing: %s\n' % name)
+ sys.stderr.flush()
+ try:
+ if not settings.dry_run:
+ core.publish_file(source_path=settings._source,
+ destination_path=settings._destination,
+ reader_name=pub_struct.reader_name,
+ parser_name='restructuredtext',
+ writer_name=pub_struct.writer_name,
+ settings=settings)
+ except ApplicationError:
+ error = sys.exc_info()[1] # get exception in Python 3.x
+ errout.write(' %s\n' % ErrorString(error))
+
+
+if __name__ == "__main__":
+ Builder().run()
--- /dev/null
+Tools for developers.
--- /dev/null
+#!/usr/bin/env python
+
+# $Id: create_unimap.py 8367 2019-08-27 12:09:56Z milde $
+# Author: Lea Wiemann <LeWiemann@gmail.com>
+# Copyright: This file has been placed in the public domain.
+
+# Call: create_unimap.py < unicode.xml > unicode_latex.py
+#
+# Get unicode.xml from
+# <http://www.w3.org/2003/entities/xml/unicode.xml>.
+
+from __future__ import print_function
+from xml.dom import minidom
+import sys
+import pprint
+
+if sys.version_info >= (3, 0):
+ unicode = str #noqa
+else:
+ bytes = str # noqa
+ chr = unichr # noqa
+
+
+def w(s):
+ if sys.version_info >= (3, 0) and isinstance(s, unicode):
+ s = s.encode('utf8')
+ sys.stdout.write(s)
+
+text_map = {}
+math_map = {}
+
+
+class Visitor(object):
+ """Node visitor for contents of unicode.xml."""
+
+ def visit_character(self, node):
+ for n in node.childNodes:
+ if n.nodeName == 'latex':
+ code = node.attributes['dec'].value
+ if '-' in code:
+ # I don't know what this means, but we probably
+ # don't need it....
+ continue
+ if int(code) < 128:
+ # Wrong (maps "-" to "$-$", which is too wide) and
+ # unnecessary (maps "a" to "{a}").
+ continue
+ latex_code = n.childNodes[0].nodeValue.encode('ascii').strip()
+ if node.attributes['mode'].value == 'math':
+ math_map[chr(int(code))] = '$%s$' % latex_code
+ else:
+ text_map[chr(int(code))] = '{%s}' % latex_code
+
+def call_visitor(node, visitor=Visitor()):
+ if isinstance(node, minidom.Text):
+ name = 'Text'
+ else:
+ name = node.nodeName.replace('#', '_')
+ if hasattr(visitor, 'visit_' + name):
+ getattr(visitor, 'visit_' + name)(node)
+ for child in node.childNodes:
+ call_visitor(child)
+ if hasattr(visitor, 'depart_' + name):
+ getattr(visitor, 'depart_' + name)(node)
+
+document = minidom.parse(sys.stdin)
+call_visitor(document)
+
+unicode_map = math_map
+unicode_map.update(text_map)
+# Now unicode_map contains the text entries plus dollar-enclosed math
+# entries for those chars for which no text entry exists.
+
+print('# $%s$' % 'Id')
+print('# Author: Lea Wiemann <LeWiemann@gmail.com>')
+print('# Copyright: This file has been placed in the public domain.')
+print('')
+print('# This is a mapping of Unicode characters to LaTeX equivalents.')
+print('# The information has been extracted from')
+print('# <http://www.w3.org/2003/entities/xml/unicode.xml>, written by')
+print('# David Carlisle and Sebastian Rahtz.')
+print('#')
+print('# The extraction has been done by the "create_unimap.py" script')
+print('# located at <http://docutils.sf.net/tools/dev/create_unimap.py>.')
+print('')
+print('unicode_map = %s' % pprint.pformat(unicode_map, indent=0))
--- /dev/null
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+# :Copyright: © 2011, 2017 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
+
+# :Id: $Id: generate_punctuation_chars.py 8367 2019-08-27 12:09:56Z milde $
+#
+# ::
+
+"""(Re)generate the utils.punctuation_chars module."""
+
+# (re)generate the utils.punctuation_chars module
+# ===============================================
+#
+# The category of some characters can change with the development of the
+# Unicode standard. This tool checks the patterns in `utils.punctuation_chars`
+# against a re-calculation based on the "unicodedata" stdlib module
+# which may give different results for different Python versions.
+#
+# Updating the module with changed `unicode_punctuation_categories` (due to
+# a new Python or Unicode standard version is an API cange (may render valid
+# rST documents invalid). It should only be done for "feature releases" and
+# requires also updating the specification of `inline markup recognition
+# rules`_ in ../../docs/ref/rst/restructuredtext.txt.
+#
+# .. _inline markup recognition rules:
+# ../../docs/ref/rst/restructuredtext.html#inline-markup
+
+from __future__ import print_function
+
+import sys
+import unicodedata
+
+if sys.version_info >= (3, 0):
+ unichr = chr # unichr not available in Py3k
+else:
+ import codecs
+ sys.stdout = codecs.getwriter('UTF-8')(sys.stdout)
+
+
+# Template for utils.punctuation_chars
+# ------------------------------------
+#
+# Problem: ``ur`` prefix fails with Py 3.5 ::
+
+module_template = u'''#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+# :Id: $Id: generate_punctuation_chars.py 8367 2019-08-27 12:09:56Z milde $
+# :Copyright: © 2011, 2017 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 file is generated by
+# ``docutils/tools/dev/generate_punctuation_chars.py``.
+# ::
+
+import sys, re
+import unicodedata
+
+"""Docutils character category patterns.
+
+ Patterns for the implementation of the `inline markup recognition rules`_
+ in the reStructuredText parser `docutils.parsers.rst.states.py` based
+ on Unicode character categories.
+ The patterns are used inside ``[ ]`` in regular expressions.
+
+ Rule (5) requires determination of matching open/close pairs. However, the
+ pairing of open/close quotes is ambiguous due to different typographic
+ conventions in different languages. The ``quote_pairs`` function tests
+ whether two characters form an open/close pair.
+
+ The patterns are generated by
+ ``docutils/tools/dev/generate_punctuation_chars.py`` to prevent dependence
+ on the Python version and avoid the time-consuming generation with every
+ Docutils run. See there for motives and implementation details.
+
+ The category of some characters changed with the development of the
+ Unicode standard. The current lists are generated with the help of the
+ "unicodedata" module of Python %(python_version)s (based on Unicode version %(unidata_version)s).
+
+ .. _inline markup recognition rules:
+ http://docutils.sf.net/docs/ref/rst/restructuredtext.html#inline-markup-recognition-rules
+"""
+
+%(openers)s
+%(closers)s
+%(delimiters)s
+if sys.maxunicode >= 0x10FFFF: # "wide" build
+%(delimiters_wide)s
+closing_delimiters = u'\\\\\\\\.,;!?'
+
+
+# Matching open/close quotes
+# --------------------------
+
+quote_pairs = {# open char: matching closing characters # usage example
+ u'\\xbb': u'\\xbb', # » » Swedish
+ u'\\u2018': u'\\u201a', # ‘ ‚ Albanian/Greek/Turkish
+ u'\\u2019': u'\\u2019', # ’ ’ Swedish
+ u'\\u201a': u'\\u2018\\u2019', # ‚ ‘ German ‚ ’ Polish
+ u'\\u201c': u'\\u201e', # “ „ Albanian/Greek/Turkish
+ u'\\u201e': u'\\u201c\\u201d', # „ “ German „ ” Polish
+ u'\\u201d': u'\\u201d', # ” ” Swedish
+ u'\\u203a': u'\\u203a', # › › Swedish
+ }
+"""Additional open/close quote pairs."""
+
+def match_chars(c1, c2):
+ """Test whether `c1` and `c2` are a matching open/close character pair.
+
+ Matching open/close pairs are at the same position in
+ `punctuation_chars.openers` and `punctuation_chars.closers`.
+ The pairing of open/close quotes is ambiguous due to different
+ typographic conventions in different languages,
+ so we test for additional matches stored in `quote_pairs`.
+ """
+ try:
+ i = openers.index(c1)
+ except ValueError: # c1 not in openers
+ return False
+ return c2 == closers[i] or c2 in quote_pairs.get(c1, u'')\
+'''
+
+
+# Generation of the character category patterns
+# ----------------------------------------------
+#
+# Unicode punctuation character categories
+# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+#
+# For details about Unicode categories, see
+# http://www.unicode.org/Public/5.1.0/ucd/UCD.html#General_Category_Values
+# ::
+
+unicode_punctuation_categories = {
+ # 'Pc': 'Connector', # not used in Docutils inline markup recognition
+ 'Pd': 'Dash',
+ 'Ps': 'Open',
+ 'Pe': 'Close',
+ 'Pi': 'Initial quote', # may behave like Ps or Pe depending on usage
+ 'Pf': 'Final quote', # may behave like Ps or Pe depending on usage
+ 'Po': 'Other'
+ }
+"""Unicode character categories for punctuation"""
+
+
+# generate character pattern strings
+# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+#
+# ::
+
+def unicode_charlists(categories, cp_min=0, cp_max=None):
+ """Return dictionary of Unicode character lists.
+
+ For each of the `catagories`, an item contains a list with all Unicode
+ characters with `cp_min` <= code-point <= `cp_max` that belong to
+ the category.
+
+ The default values check every code-point supported by Python
+ (`sys.maxint` is 0x10FFFF in a "wide" build and 0xFFFF in a "narrow"
+ build, i.e. ucs4 and ucs2 respectively).
+ """
+ # Determine highest code point with one of the given categories
+ # (may shorten the search time considerably if there are many
+ # categories with not too high characters):
+ if cp_max is None:
+ cp_max = max(x for x in range(sys.maxunicode+1)
+ if unicodedata.category(unichr(x)) in categories)
+ # print(cp_max) # => 74867 for unicode_punctuation_categories
+ charlists = {}
+ for cat in categories:
+ charlists[cat] = [unichr(x) for x in range(cp_min, cp_max+1)
+ if unicodedata.category(unichr(x)) == cat]
+ return charlists
+
+
+# Character categories in Docutils
+# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+#
+# ::
+
+def character_category_patterns():
+
+ """Docutils character category patterns.
+
+ Return list of pattern strings for the categories "Open", "Close",
+ "Delimiters" and "Closing-Delimiters" used in the `inline markup
+ recognition rules`_.
+ """
+
+ cp_min = 160 # ASCII chars have special rules for backwards compatibility
+ ucharlists = unicode_charlists(unicode_punctuation_categories, cp_min)
+ """Strings of characters in Unicode punctuation character categories"""
+
+ # match opening/closing characters
+ # --------------------------------
+ # Rearange the lists to ensure matching characters at the same
+ # index position.
+
+ # low quotation marks are also used as closers (e.g. in Greek)
+ # move them to category Pi:
+ ucharlists['Ps'].remove(u'‚') # 201A SINGLE LOW-9 QUOTATION MARK
+ ucharlists['Ps'].remove(u'„') # 201E DOUBLE LOW-9 QUOTATION MARK
+ ucharlists['Pi'] += [u'‚', u'„']
+
+ ucharlists['Pi'].remove(u'‛') # 201B SINGLE HIGH-REVERSED-9 QUOTATION MARK
+ ucharlists['Pi'].remove(u'‟') # 201F DOUBLE HIGH-REVERSED-9 QUOTATION MARK
+ ucharlists['Pf'] += [u'‛', u'‟']
+
+ # 301F LOW DOUBLE PRIME QUOTATION MARK misses the opening pendant:
+ ucharlists['Ps'].insert(ucharlists['Pe'].index(u'\u301f'), u'\u301d')
+
+ # print(u''.join(ucharlists['Ps']).encode('utf8')
+ # print(u''.join(ucharlists['Pe']).encode('utf8')
+ # print(u''.join(ucharlists['Pi']).encode('utf8')
+ # print(u''.join(ucharlists['Pf']).encode('utf8')
+
+ # The Docutils character categories
+ # ---------------------------------
+ #
+ # The categorization of ASCII chars is non-standard to reduce
+ # both false positives and need for escaping. (see `inline markup
+ # recognition rules`_)
+
+ # allowed before markup if there is a matching closer
+ openers = [u'"\'(<\\[{']
+ for category in ('Ps', 'Pi', 'Pf'):
+ openers.extend(ucharlists[category])
+
+ # allowed after markup if there is a matching opener
+ closers = [u'"\')>\\]}']
+ for category in ('Pe', 'Pf', 'Pi'):
+ closers.extend(ucharlists[category])
+
+ # non-matching, allowed on both sides
+ delimiters = [u'\\-/:']
+ for category in ('Pd', 'Po'):
+ delimiters.extend(ucharlists[category])
+
+ # non-matching, after markup
+ closing_delimiters = [r'\\.,;!?']
+
+ return [u''.join(chars) for chars in (openers, closers, delimiters,
+ closing_delimiters)]
+
+def separate_wide_chars(s):
+ """Return (s1,s2) with characters above 0xFFFF in s2"""
+ maxunicode_narrow = 0xFFFF
+ l1 = [ch for ch in s if ord(ch) <= maxunicode_narrow]
+ l2 = [ch for ch in s if ord(ch) > maxunicode_narrow]
+ return ''.join(l1), ''.join(l2)
+
+def mark_intervals(s):
+ """Return s with shortcut notation for runs of consecutive characters
+
+ Sort string and replace 'cdef' by 'c-f' and similar.
+ """
+ l =[]
+ s = sorted([ord(ch) for ch in s])
+ for n in s:
+ try:
+ if l[-1][-1]+1 == n:
+ l[-1].append(n)
+ else:
+ l.append([n])
+ except IndexError:
+ l.append([n])
+
+ l2 = []
+ for i in l:
+ i = [unichr(n) for n in i]
+ if len(i) > 2:
+ i = i[0], u'-', i[-1]
+ l2.extend(i)
+
+ return ''.join(l2)
+
+def wrap_string(s, startstring= "(u'",
+ endstring = "')", wrap=67):
+ """Line-wrap a unicode string literal definition."""
+ c = len(startstring)
+ contstring = "'\n" + ' ' * (len(startstring)-2) + "u'"
+ l = [startstring]
+ for ch in s.replace("'", r"\'"):
+ c += 1
+ if ch == '\\' and c > wrap:
+ c = len(startstring)
+ ch = contstring + ch
+ l.append(ch)
+ l.append(endstring)
+ return ''.join(l)
+
+
+def print_differences(old, new, name):
+ """List characters missing in old/new."""
+ if old != new:
+ print('new %s:' % name)
+ for c in new:
+ if c not in old:
+ print(' %04x'%ord(c), unicodedata.name(c))
+ print('removed %s:' % name)
+ for c in old:
+ if c not in new:
+ print(' %04x'%ord(c), unicodedata.name(c))
+ else:
+ print('%s unchanged' % name)
+
+# Output
+# ------
+#
+# ::
+
+if __name__ == '__main__':
+
+ import argparse
+ parser = argparse.ArgumentParser(description=__doc__)
+ parser.add_argument('-t', '--test', action="store_true",
+ help='test for changed character categories')
+ args = parser.parse_args()
+
+# (Re)create character patterns
+# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+#
+# ::
+
+ (o, c, d, cd) = character_category_patterns()
+
+# Characters in the upper plane require a "wide" build::
+
+ o, o_wide = separate_wide_chars(o)
+ c, c_wide = separate_wide_chars(c)
+ d, d_wide = separate_wide_chars(d)
+
+# delimiters: sort and use shortcut for intervals (saves ~150 characters)
+# (`openers` and `closers` must be verbose and keep order
+# because they are also used in `match_chars()`)::
+
+ d = d[:5] + mark_intervals(d[5:])
+ d_wide = mark_intervals(d_wide)
+
+
+# Test: compare module content with re-generated definitions
+# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ::
+
+ if args.test:
+
+# Import the punctuation_chars module from the source
+# or Py3k build path for local Python modules::
+
+ if sys.version_info < (3, 0):
+ sys.path.insert(0, '../../docutils')
+ else:
+ sys.path.insert(0, '../../build/lib')
+
+ from docutils.utils.punctuation_chars import (openers, closers,
+ delimiters, closing_delimiters)
+
+ print('Check for differences between the current `punctuation_chars`'
+ ' module\n and a regeneration based on Unicode version %s:'
+ % unicodedata.unidata_version)
+
+ print_differences(openers, o, 'openers')
+ if o_wide:
+ if sys.version_info < (3, 0):
+ print('+ openers-wide = ur"""%s"""' % o_wide.encode('utf8'))
+ else:
+ print('+ openers-wide = r"""%s"""' % o_wide.encode('utf8'))
+ print_differences(closers, c, 'closers')
+ if c_wide:
+ if sys.version_info < (3, 0):
+ print('+ closers-wide = ur"""%s"""' % c_wide.encode('utf8'))
+ else:
+ print('+ closers-wide = r"""%s"""' % c_wide.encode('utf8'))
+
+ print_differences(delimiters, d + d_wide, 'delimiters')
+ print_differences(closing_delimiters, cd, 'closing_delimiters')
+
+ sys.exit()
+
+# Print re-generation of the punctuation_chars module
+# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+#
+# The output can be copied to docutils/utils if an update is wanted
+# (API change, see Intro).
+
+# Replacements::
+
+ substitutions = {
+ 'python_version': '.'.join(str(s) for s in sys.version_info[:3]),
+ 'unidata_version': unicodedata.unidata_version,
+ 'openers': wrap_string(o.encode('unicode-escape').decode(),
+ startstring="openers = (u'"),
+ 'closers': wrap_string(c.encode('unicode-escape').decode(),
+ startstring="closers = (u'"),
+ 'delimiters': wrap_string(d.encode('unicode-escape').decode(),
+ startstring="delimiters = (u'"),
+ 'delimiters_wide': wrap_string(
+ d_wide.encode('unicode-escape').decode(),
+ startstring=" delimiters += (u'")
+ }
+
+ print(module_template % substitutions)
--- /dev/null
+#!/usr/bin/python -i
+
+# $Id: profile_docutils.py 8346 2019-08-26 12:11:32Z milde $
+# Author: Lea Wiemann <LeWiemann@gmail.com>
+# Copyright: This script has been placed in the public domain.
+
+from __future__ import print_function
+import os.path
+import docutils.core
+import hotshot.stats
+
+print('Profiler started.')
+
+os.chdir(os.path.join(os.path.dirname(docutils.__file__), '..'))
+
+print('Profiling...')
+
+prof = hotshot.Profile('docutils.prof')
+prof.runcall(docutils.core.publish_file, source_path='HISTORY.txt',
+ destination_path='prof.HISTORY.html', writer_name='html')
+prof.close()
+
+print('Loading statistics...')
+
+print("""
+stats = hotshot.stats.load('docutils.prof')
+stats.strip_dirs()
+stats.sort_stats('time') # 'cumulative'; 'calls'
+stats.print_stats(40)
+""")
+
+stats = hotshot.stats.load('docutils.prof')
+stats.strip_dirs()
+stats.sort_stats('time')
+stats.print_stats(40)
+
+try:
+ exec(open(os.environ['PYTHONSTARTUP']).read())
+except:
+ pass
--- /dev/null
+#! /usr/bin/env python
+
+# $Id: unicode2rstsubs.py 8367 2019-08-27 12:09:56Z milde $
+# Author: David Goodger <goodger@python.org>
+# Copyright: This program has been placed in the public domain.
+
+"""
+unicode2subfiles.py -- produce character entity files (reSructuredText
+substitutions) from the W3C master unicode.xml file.
+
+This program extracts character entity and entity set information from a
+unicode.xml file and produces multiple reStructuredText files (in the current
+directory) containing substitutions. Entity sets are from ISO 8879 & ISO
+9573-13 (combined), MathML, and HTML4. One or two files are produced for each
+entity set; a second file with a "-wide.txt" suffix is produced if there are
+wide-Unicode characters in the set.
+
+The input file, unicode.xml, is maintained as part of the MathML 2
+Recommentation XML source, and is available from
+<http://www.w3.org/2003/entities/xml/>.
+"""
+from __future__ import print_function
+
+import sys
+import os
+import optparse
+import re
+from xml.parsers.expat import ParserCreate
+
+
+usage_msg = """Usage: %s [unicode.xml]\n"""
+
+def usage(prog, status=0, msg=None):
+ sys.stderr.write(usage_msg % prog)
+ if msg:
+ sys.stderr.write(msg + '\n')
+ sys.exit(status)
+
+def main(argv=None):
+ if argv is None:
+ argv = sys.argv
+ if len(argv) == 2:
+ inpath = argv[1]
+ elif len(argv) > 2:
+ usage(argv[0], 2,
+ 'Too many arguments (%s): only 1 expected.' % (len(argv) - 1))
+ else:
+ inpath = 'unicode.xml'
+ if not os.path.isfile(inpath):
+ usage(argv[0], 1, 'No such file: "%s".' % inpath)
+ if sys.version_info >= (3, 0):
+ infile = open(inpath, mode='rb')
+ else:
+ infile = open(inpath)
+ process(infile)
+
+def process(infile):
+ grouper = CharacterEntitySetExtractor(infile)
+ grouper.group()
+ grouper.write_sets()
+
+
+class CharacterEntitySetExtractor(object):
+
+ """
+ Extracts character entity information from unicode.xml file, groups it by
+ entity set, and writes out reStructuredText substitution files.
+ """
+
+ unwanted_entity_sets = ['stix', # unknown, buggy set
+ 'predefined']
+
+ header = """\
+.. This data file has been placed in the public domain.
+.. Derived from the Unicode character mappings available from
+ <http://www.w3.org/2003/entities/xml/>.
+ Processed by unicode2rstsubs.py, part of Docutils:
+ <http://docutils.sourceforge.net>.
+"""
+
+ def __init__(self, infile):
+ self.infile = infile
+ """Input unicode.xml file."""
+
+ self.parser = self.setup_parser()
+ """XML parser."""
+
+ self.elements = []
+ """Stack of element names. Last is current element."""
+
+ self.sets = {}
+ """Mapping of charent set name to set dict."""
+
+ self.charid = None
+ """Current character's "id" attribute value."""
+
+ self.descriptions = {}
+ """Mapping of character ID to description."""
+
+ def setup_parser(self):
+ parser = ParserCreate()
+ parser.StartElementHandler = self.StartElementHandler
+ parser.EndElementHandler = self.EndElementHandler
+ parser.CharacterDataHandler = self.CharacterDataHandler
+ return parser
+
+ def group(self):
+ self.parser.ParseFile(self.infile)
+
+ def StartElementHandler(self, name, attributes):
+ self.elements.append(name)
+ handler = name + '_start'
+ if hasattr(self, handler):
+ getattr(self, handler)(name, attributes)
+
+ def EndElementHandler(self, name):
+ assert self.elements[-1] == name, \
+ 'unknown end-tag %r (%r)' % (name, self.element)
+ self.elements.pop()
+ handler = name + '_end'
+ if hasattr(self, handler):
+ getattr(self, handler)(name)
+
+ def CharacterDataHandler(self, data):
+ handler = self.elements[-1] + '_data'
+ if hasattr(self, handler):
+ getattr(self, handler)(data)
+
+ def character_start(self, name, attributes):
+ self.charid = attributes['id']
+
+ def entity_start(self, name, attributes):
+ set = self.entity_set_name(attributes['set'])
+ if not set:
+ return
+ if set not in self.sets:
+ print('bad set: %r' % set)
+ return
+ entity = attributes['id']
+ assert (entity not in self.sets[set]
+ or self.sets[set][entity] == self.charid), \
+ ('sets[%r][%r] == %r (!= %r)'
+ % (set, entity, self.sets[set][entity], self.charid))
+ self.sets[set][entity] = self.charid
+
+ def description_data(self, data):
+ self.descriptions.setdefault(self.charid, '')
+ self.descriptions[self.charid] += data
+
+ entity_set_name_pat = re.compile(r'[0-9-]*(.+)$')
+ """Pattern to strip ISO numbers off the beginning of set names."""
+
+ def entity_set_name(self, name):
+ """
+ Return lowcased and standard-number-free entity set name.
+ Return ``None`` for unwanted entity sets.
+ """
+ match = self.entity_set_name_pat.match(name)
+ name = match.group(1).lower()
+ if name in self.unwanted_entity_sets:
+ return None
+ self.sets.setdefault(name, {})
+ return name
+
+ def write_sets(self):
+ sets = sorted(self.sets.keys())
+ for set_name in sets:
+ self.write_set(set_name)
+
+ def write_set(self, set_name, wide=None):
+ if wide:
+ outname = set_name + '-wide.txt'
+ else:
+ outname = set_name + '.txt'
+ outfile = open(outname, 'w')
+ print('writing file "%s"' % outname)
+ outfile.write(self.header + '\n')
+ set = self.sets[set_name]
+ entities = sorted([(e.lower(), e) for e in set.keys()])
+ longest = 0
+ for _, entity_name in entities:
+ longest = max(longest, len(entity_name))
+ has_wide = None
+ for _, entity_name in entities:
+ has_wide = self.write_entity(
+ set, set_name, entity_name, outfile, longest, wide) or has_wide
+ if has_wide and not wide:
+ self.write_set(set_name, 1)
+
+ def write_entity(self, set, set_name, entity_name, outfile, longest,
+ wide=None):
+ charid = set[entity_name]
+ if not wide:
+ for code in charid[1:].split('-'):
+ if int(code, 16) > 0xFFFF:
+ return 1 # wide-Unicode character
+ codes = ' '.join(['U+%s' % code for code in charid[1:].split('-')])
+ outfile.write('.. %-*s unicode:: %s .. %s\n'
+ % (longest + 2, '|' + entity_name + '|',
+ codes, self.descriptions[charid]))
+
+
+if __name__ == '__main__':
+ sys.exit(main())
--- /dev/null
+# These entries affect all processing:
+[general]
+source-link: yes
+datestamp: %Y-%m-%d %H:%M UTC
+generator: on
+
+# These entries affect HTML output:
+[html writers]
+embed-stylesheet: no
+
+[html4css1 writer]
+# Required for docutils-update, the website build system:
+stylesheet-path: ../docutils/writers/html4css1/html4css1.css
+field-name-limit: 20
+
+[html5 writer]
+stylesheet-dirs: ../docutils/writers/html5_polyglot/
+stylesheet-path: minimal.css, plain.css
+
--- /dev/null
+======================================
+ Editor Support for reStructuredText_
+======================================
+
+:Date: $Date: 2014-10-21 16:07:59 +0200 (Di, 21. Okt 2014) $
+
+The files in this directory contain support code for reStructuredText
+editing for the following editors:
+
+* `Emacs <emacs>`__: see the `README <emacs/README.html>`__ and `Emacs
+ Support for reStructuredText <../../docs/user/emacs.html>`_.
+
+External links:
+
+* `reStructuredText syntax highlighting mode for vim
+ <http://www.vim.org/scripts/script.php?script_id=973>`__
+
+* `VST (Vim reStructured Text) is a plugin for Vim7 with folding for
+ reST <http://www.vim.org/scripts/script.php?script_id=1334>`__
+
+* `rst mode <http://jedmodes.sf.net/mode/rst/>`__ for the `JED`_
+ programmers editor
+
+Additions are welcome.
+
+.. _reStructuredText: http://docutils.sf.net/rst.html
+.. _JED: http://www.jedsoft.org/jed/
--- /dev/null
+The following is a list of ideas of functionality which would be nice
+to have in `rst.el`. In the examples a ``@`` stands for the cursor.
+
+Convert to id
+=============
+
+* Convert the region to an HTML id
+
+ * For instance "Eine Überschrift" to "eine-berschrift"
+
+ * According the same rules as reST does this
+
+Jump to internal target
+=======================
+
+* A command to jump to the internal target the point is on
+
+* A target may be
+
+ * A section title
+
+ * Footnotes / citations
+
+ * Inline internal targets
+
+ * Hyperlink target definition
+
+ * Substitution definition
+
+* See hunk #26 in `rst_el-emacs_V23_1_patch1_1_2` vs. `emacs_V23_1`
+ for some ideas
+
+Completion for directive options
+================================
+
+* Imagine ::
+
+ .. list-table::
+ :@
+
+ with the cursor at the asterisk
+
+* There should be a command which offers all the possible options for
+ this particular directive as completion
+
+* May be `skeleton.el` can also be useful
+
+Completion for directives
+=========================
+
+* Imagine ::
+
+ .. @
+
+* There should be a command which offers all directives as completion
+
+* May be this should work for other keywords as well
+
+* May be this could work even at the beginning of the line
+
+* Completion must be bound to M-TAB
+
+ * Already existing binding must be chained
+
+ * May be `expand.el` can help (look in package finder)?
+
+ * May be `hippie` is good here
+
+ * Check `(info)autotype`
+
+Completion for user-defined elements
+====================================
+
+* Imagine ::
+
+ |@
+
+ or ::
+
+ [@
+
+ or ::
+
+ _@
+
+* There should be a command which offers all defined substitutions /
+ footnotes / links as completion
+
+Insertion of link alias
+=======================
+
+* Imagine ::
+
+ Aspect of something
+ ===================
+
+ This is about the `aspect of something`_@
+
+* There should be a command which asks you for an alias for the link,
+ add the alias and change the link ::
+
+ .. _aspects of something:
+
+ Aspect of something
+ ===================
+
+ This is about the `aspects of something`_@
+
+Smart use of `iimage-mode`
+==========================
+
+* There is `iimage-mode` which shows ``.. image::``\s in Emacs
+
+* May be we can add a binding to toggle it
+
+TOC in speedbar
+===============
+
+* If the TOC is displayed in the speedbar this could be used for
+ permanent navigation
+
+ * Probably `imenu` functionality can be used for this
+
+ * See `imenu` documentation and `speedbar-use-imenu-flag`
+
+ * See `speedbar`
+
+toc-mode without markup
+=======================
+
+* The markup which may be contained in a section title is not useful
+ in toc-mode and should be suppressed
+
+Sophisticated navigation in sections
+====================================
+
+* Navigation in sections similar to navigation in other structured data
+
+ * Like XML, Lisp
+
+ * C-M-u für Up
+
+ * C-M-d für Down
+
+ * C-M-f / C-M-b für Forward / Backward
+
+Display of current location
+===========================
+
+* Display the "section path" to the current point
+
+* Like in XML: In which element is the point?
+
+toc-mode only to a certain level
+================================
+
+* If a TOC buffer is created a prefix argument should limit the depth
+ of the listing to the given level
+
+Imenu support or similar
+========================
+
+* Imenu could be supported
+
+ * See `(elisp)Imenu`
+
+* `etags` could be supported
+
+ * See `(emacs)Tags` and `etags.el`
+
+ * May be this can be used for generating HTML local tags somehow?
+
+ * As requested by `Convert to id`_
+
+ * Could use `complete-tag`
+
+Outline support
+===============
+
+* Support for `outline-mode` / `allout-mode` would be nice
+
+ * Should consider section titles
+
+ * May be item lists can also be included
+
+ * Using `allout-mode` is difficult
+
+ * It's not customizable enough for the complex syntax of
+ reStructuredText
+
+ * However, some commands make sense
+
+ * Motion commands
+
+ * Exposure commands
+
+ * Some alteration commands
+
+ * Should be reimplemented
+
+ * Key bindings need to be reused
+
+ * However, care must be taken if a file uses `allout-mode` for
+ instance by comment strings
+
+ * In this case key bindings must not be overridden
+
+ * A command adding / updating `allout-mode` tags could be a solution
+
+Sophisticated filling
+=====================
+
+* These things must be filled special:
+
+ * Definitions
+
+ * Filling of ::
+
+ * VeryLongWordSuchAsAnURLVeryLongWordSuchAsAnURLVeryLongWordSuchAsAnURLVeryLongWordSuchAsAnURLVeryLongWordSuchAsAnURL
+
+ should work as expected by *not* breaking the line
+
+ * May be `fill-nobreak-predicate` can help here
+
+* These things may not be filled at all
+
+ * Literal blocks
+
+ * Tables
+
+ * Link definitions
+
+ * May be `fill-nobreak-predicate` can help here, too
+
+* May be defining an own `auto-fill-function` may be useful
+
+ * Might prevent auto-filling of literal text
+
+* Filling of a re-indented item doesn't work as expected::
+
+ * Something just indented once more by the user
+ though continuation line is not indented already
+
+ * Alternatively indentation could indent the whole item
+
+ * See `Sophisticated indentation`_
+
+* See also `Filling of section headers`_
+
+Sophisticated indentation
+=========================
+
+* It should be generally possible to shift one more to the right
+
+ * This makes indentation for quotes possible
+
+ * But not for literal blocks
+
+* For item lists the best tab should be on the same level as the last
+ item::
+
+ * bla
+
+ @
+
+ * The second best tab should be where text starts::
+
+ * bla
+
+ @
+
+* <backtab> should be used to indent in the other direction
+
+ * Or may be C-u <tab> but this has a different meaning
+
+* <tab> could obsolete C-c C-r <tab>
+
+ * For this the indentation needs to be determined at the start
+ instead of per line
+
+ * <tab> over list works::
+
+ Text
+
+ * GGGGGG
+ * SSSSSSSSSSSSSSS
+ * TTTTTTTT
+ * ZZZZZZZZ
+
+ * <tab> over list doesn't work::
+
+ Text
+
+ * GGGGGG
+ * SSSSSSSSSSSSSSS
+ * TTTTTTTT
+ * ZZZZZZZZ
+
+* An indenting tab on the head of a list item should indent the whole
+ list item instead of only the first line
+
+ * Alternatively `fill-paragraph` could do so
+
+ * See `Sophisticated filling`_
+
+* May be `refill-mode` can be useful
+
+List to sections
+================
+
+* A command would be nice which
+
+ * transforms the first level of a nested list in a region into a
+ header
+
+ * removes one level of indentation from the rest of the list
+
+Change section level by more than one step
+==========================================
+
+* It would be nice if <C-h> `rst-adjust` could rotate a section
+ adornment more than one level
+
+* A modification of the semantic of the prefix arguments could do this
+
+ * Non-zero numeric prefix arg n rotates n step in the given direction
+
+ * Prefix arg 0 toggles overline / underline
+
+ * This would be different from current setup
+
+Compiling for syntax check
+==========================
+
+* Compiling with results going to `/dev/null` would be useful
+
+ * This would just do a syntax check with no files lying around
+
+* Toolset choice for <C-c C-c C-c> `rst-compile` must be by
+ customizable if at all necessary
+
+ * Customization group must be used
+
+Renumber an exisiting enumeration
+=================================
+
+* Renumbering an exisiting enumeration is not possible yet
+
+Command to move across blocks
+=============================
+
+* A command moving forward / backward across the content blocks of the
+ current block would be nice
+
+ * For instance: Move across all blocks contained in an item or field
+
+ * This would move to the start of the sibling of the current block
+
+ * Would allow to jump to the next item on the same level in a list
+
+* <C-M-f> `forward-sexp` could be a nice binding
+
+rst-toc-insert features
+=======================
+
+* The `contents::` options could be parsed to figure out how deep to
+ render the inserted TOC
+
+* On load, detect any existing TOCs and set the properties for links
+
+* TOC insertion should have an option to add empty lines
+
+* TOC insertion should deal with multiple lines
+
+* Automatically detect if we have a `section-numbering::` in the
+ corresponding section, to render the toc.
+
+Automatic handling of `.txt` files
+==================================
+
+It would be nice to differentiate between text files using
+reStructuredText and other general text files. If we had a function to
+automatically guess whether a `.txt` file is following the
+reStructuredText conventions, we could trigger `rst-mode` without
+having to hard-code this in every text file, nor forcing the user to
+add a local mode variable at the top of the file. We could perform
+this guessing by searching for a valid adornment at the top of the
+document or searching for reStructuredText directives further on.
+
+Entry level for rst-straighten-adornments
+=========================================
+
+* `rst-straighten-adornments` should have an entry level to start at a
+ lower than the top level
+
+ * I for one prefer a verbose style for top level titles which is not
+ appropriate for documents without titles
+
+ * Should be done by a prefix argument
+
+Support for ispell
+==================
+
+* `ispell` may skip certain things
+
+ * Using `ispell-skip-region-alist`
+
+ * ``Code`` should be skipped
+
+ * Literal text after ``::`` should be skipped
+
+ * A customization should switch this on so users are not surprised
+
+Marriage with `forms-mode`
+==========================
+
+* Like I married `forms-mode` with `sdf-mode`
+
+* Would allow editing a number of records with a fixed layout
+
+* The base reStructuredText file should be either
+
+ * a list consisting of field lists
+
+ * The separator needs to be defined, however
+
+ * A section header or transition may be a useful separator
+
+ * a `list-table`
+
+ * a CSV file
+
+ * That would call for a general support for CSV support for forms
+
+ * May be `orgtbl-to-csv` in `org/org-table.el` could be useful for
+ this
+
+Marriage with `org-mode`
+========================
+
+* May be Org mode can be utilized instead of `forms-mode`
+
+ * See `orgtbl-mode`
+
+ * See `orgstruct-mode`
+
+ * Though this looks more like `allout-mode`
+
+Intelligent quote insertion
+===========================
+
+* Use or develop something like `insert-pair`
+
+ * Main use for forgotten quoting
+
+ * Thus may rather quote preceding word than following one
+
+ * If `forward-sexp` could be overridden `insert-pair` might me
+ usable directly
+
+* Also add something like `delete-pair`
+
+Sophisticated alignment
+=======================
+
+* May be aligning can be used to get results like this
+
+ :Some: Field
+
+ :Longer name: Aligned
+
+ :Even longer name: More aligned
+
+ * See `align.el`
+
+toc-mode per buffer
+===================
+
+* At the moment there can only be globally one TOC
+
+ * A TOC could be separate for each buffer
+
+toc-mode could generate reST
+============================
+
+* The format of the generated TOC could be reStructuredText
+
+ * For instance as a bullet list
+
+ * So it could be copied and basted into a reStructuredText document
+
+ * Conversion could be done in toc-mode buffer
+
+* An alternative could be that `rst-bullet-list-region` handles
+ indented text properly
+
+Improvements for comments
+=========================
+
+* `comment-use-syntax` should be set to nil locally
+
+* `comment-forward` should work so `comment-dwim` recognizes a
+ commented region
+
+ * Then it could uncomment it automatically and use of prefix
+ argument is no longer neccessary
+
+Context sensitive M-q
+=====================
+
+* M-q / `fill-paragraph` should check whether point is in section
+ header and call `rst-adjust` in this case
+
+ * This would unify handling of changes in section headers and normal
+ paragraphs
+
+Switch to using `cl-lib`
+========================
+
+* Options to use `cl-lib`
+
+ There are various options, and you'll have to judge for yourself which
+ is best for your particular case:
+ - live with the warnings.
+ - switch to cl-lib and ask users of older Emacsen to install cl-lib
+ (available in GNU ELPA).
+ - add things like (unless (fboundp 'cl-letf) (defalias 'cl-letf 'letf)).
+ - change the code to use something else (e.g. for flet, you can switch
+ to using either defadvice or (let ((f1 (lambda ..))) ...).
+ - ...
+
+ -- Stefan Monnier
+
+* Remove own implementations then
+
+Filling of section headers
+==========================
+
+* Filling should recognize section headers and adjust the adornment
+
+ * Then a fill operation for a region wouldn't break the section
+ header adornment
+
+ * In addition a fill operation could be used instead of adjusting a
+ section header
+
+Cursor after adjusting adornment
+================================
+
+* Adjusting a section header should move the cursor to the end of the
+ adornment
+
+ * Then a following C-j / Return opens a new line instead of breaking
+ the adornment just created
+
+Copying literal blocks
+======================
+
+* Copying literal blocks should eat up the block indentation
+
+ * This way code fragments can be copied without removing the block
+ indentation by hand
+
+Structural operations for toc-mode
+==================================
+
+* Structrual operations for toc-mode
+
+ * Raise or lower sections
+
+ * Move sections around
+
+Inhibit auto-fill in literal blocks
+===================================
+
+* In a literal block a space should not do auto-fill
+
+ * May be variable `normal-auto-fill-function` can be set mode
+ specific
+
+ * Is normally `do-auto-fill`
+
+toc-mode should leave mark
+==========================
+
+* When you jump to a different point in the document by using toc-mode
+ the mark should be set at the point of departure
+
+ * This aligns with the semantic of other far jumps in the document
+ such as `beginning-of-buffer`
+
+Remembering last location per section
+=====================================
+
+* Remembering the last location per section would make it possible to
+ jump back to this location
+
+ * This is useful if several sections are worked on in parallel
+
+* The jump into the section could happen from toc-mode
+
+ * Instead of to the section header
+
+ * May be by a special key
+
+* Other section based jump commands could do similar
+
+ * For instance navigating by sections
+
+* This calls for a general modifier for jumps
+
+Multiple steps for `rst-adjust`
+===============================
+
+* Sometimes it's useful to adjust more than one step in the given
+ direction
+
+ * For instance to follow a 2= title by 1= normal header skipping the
+ usual 2- level
+
+* Therefore using a counter may be useful
+
+Enhance compilation support
+===========================
+
+* Compilation to ODT should be supported
+
+* Arbitrary compilations should be supported using customization
+
+ * Key must be configurable
+
+ * Command must be configurable
+
+* May be the whole toolset stuff needs to be replaced?
+
+Support for longlines mode
+==========================
+
+* `longlines-mode` should use correct indentation for broken lines
+
+ * This is actually an enhancement of `longlines-mode`
+
+ * `longlines-mode` modifies the buffer
+
+ * This is needed to use all the standard functionality like
+ `move-to-column`
+
+ * Using property `display` for inserting indentation does not work
+ properly because of this
+
+ * Indentation must be inserted in the buffer
+
+ * However, it needs to have the property `intangible` so it can
+ not be modified
+
+ * See `Emacs Lisp => 32.19 Text Properties => Special
+ Properties`
+
+ * It would be nice to also have a visible indication for being
+ automatic insertion
+
+ * Such indentation must be removed by `longlines-encode-*`
+
+ * Probably it should be marked by a special property such as
+ `longlines-indentation`
+
+ * `longlines-wrap-line` needs a hook called after replacing the
+ blank by a soft newline
+
+ * May be `longlines-*search-*` needs to be adapted as well?
+
+Indent correctly
+================
+
+* `rst-shift-region` should have a mode to indent correctly
+
+ * I.e.: Indent the region according to the tab given by the line
+ above
+
+* But see also `Copying literal blocks`_
+
+Jumps leaving mark
+==================
+
+* All jumps across a wider distance should push the mark on the local
+ mark ring
+
+ * See C-u C-SPC documentation
+
+ * Jumps to section titles
+
+ * That would result in jumping back to TOC which is especially
+ useful for an internal TOC
+
+ * But not jumps to paragraphs
+
+ * Jumps with C-M-a / C-M-e?
+
+TOC controlling sliding window
+==============================
+
+* `toc-mode` must have a mode where cursor entering a new line moves
+ to the respective section in another window
+
+ * So one can browse through a buffer by using the TOC
+
+Jump to list entry on same level
+================================
+
+* If on a list entry of some sort there should be a way to navigate to
+ a sibling
+
+ * Forward and backward
+
+* May be also up and down
+
+`rst-shift-region` shifts as needed
+===================================
+
+* `rst-shift-region` should have an option to "do the right thing"
+
+* In particular it should shift as needed by the text above
+
+ * This makes indentation of an inserted block easier because you
+ don't need to know the correct number of tabs
+
+ * There should be an option to "align under", "align same" and
+ "align less"
+
+ * May be this could be commanded by one or more C-u's
--- /dev/null
+.. -*- coding: utf-8 -*-
+
+=====================
+ Emacs Support Files
+=====================
+
+:Date: $Date: 2008-11-26 19:07:47 +0100 (Mi, 26. Nov 2008) $
+
+This directory contains the following Emacs lisp package files:
+
+* `<rst.el>`_: Emacs support for reStructuredText_. This file contains a
+ major mode that provides:
+
+ * Section decoration/adornment creation and updating (M. Blais);
+ * Table-of-contents mode and insertion (M. Blais);
+ * Font-lock syntax highlighting (S. Merten);
+ * Some handy editing functions (D. Goodger).
+ * Some functions for converting rest documents from within emacs (M. Blais).
+
+* `<tests/>`_ subdirectory: automated tests for some of the features in rst.el.
+ Please make sure the tests pass if you change the LISP code. Just type "make"
+ to run the tests.
+
+To install the package, put a copy of the package file in a directory on your
+``load-path`` (use ``C-h v load-path`` to check).
+
+For setup and usage details, see `Emacs Support for reStructuredText
+<../../../docs/user/emacs.html>`_.
+
+.. _reStructuredText: http://docutils.sourceforge.net/rst.html
--- /dev/null
+[general]
+input_encoding: latin-1
--- /dev/null
+;;; rst.el --- Mode for viewing and editing reStructuredText-documents -*- lexical-binding: t -*-
+
+;; Copyright (C) 2003-2017 Free Software Foundation, Inc.
+
+;; Maintainer: Stefan Merten <stefan at merten-home dot de>
+;; Author: Stefan Merten <stefan at merten-home dot de>,
+;; Martin Blais <blais@furius.ca>,
+;; David Goodger <goodger@python.org>,
+;; Wei-Wei Guo <wwguocn@gmail.com>
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; This package provides major mode rst-mode, which supports documents marked
+;; up using the reStructuredText format. Support includes font locking as well
+;; as a lot of convenience functions for editing. It does this by defining a
+;; Emacs major mode: rst-mode (ReST). This mode is derived from text-mode.
+;; This package also contains:
+;;
+;; - Functions to automatically adjust and cycle the section underline
+;; adornments;
+;; - A mode that displays the table of contents and allows you to jump anywhere
+;; from it;
+;; - Functions to insert and automatically update a TOC in your source
+;; document;
+;; - Function to insert list, processing item bullets and enumerations
+;; automatically;
+;; - Font-lock highlighting of most reStructuredText structures;
+;; - Indentation and filling according to reStructuredText syntax;
+;; - Cursor movement according to reStructuredText syntax;
+;; - Some other convenience functions.
+;;
+;; See the accompanying document in the docutils documentation about
+;; the contents of this package and how to use it.
+;;
+;; For more information about reStructuredText, see
+;; http://docutils.sourceforge.net/rst.html
+;;
+;; For full details on how to use the contents of this file, see
+;; http://docutils.sourceforge.net/docs/user/emacs.html
+;;
+;; There are a number of convenient key bindings provided by rst-mode. For the
+;; bindings, try C-c C-h when in rst-mode. There are also many variables that
+;; can be customized, look for defcustom in this file or look for the "rst"
+;; customization group contained in the "wp" group.
+;;
+;; If you use the table-of-contents feature, you may want to add a hook to
+;; update the TOC automatically every time you adjust a section title::
+;;
+;; (add-hook 'rst-adjust-hook 'rst-toc-update)
+;;
+;; Syntax highlighting: font-lock is enabled by default. If you want to turn
+;; off syntax highlighting to rst-mode, you can use the following::
+;;
+;; (setq font-lock-global-modes '(not rst-mode ...))
+;;
+
+;;; DOWNLOAD
+
+;; The latest release of this file lies in the docutils source code repository:
+;; http://docutils.svn.sourceforge.net/svnroot/docutils/trunk/docutils/tools/editors/emacs/rst.el
+
+;;; INSTALLATION
+
+;; Add the following lines to your init file:
+;;
+;; (require 'rst)
+;;
+;; If you are using `.txt' as a standard extension for reST files as
+;; http://docutils.sourceforge.net/FAQ.html#what-s-the-standard-filename-extension-for-a-restructuredtext-file
+;; suggests you may use one of the `Local Variables in Files' mechanism Emacs
+;; provides to set the major mode automatically. For instance you may use::
+;;
+;; .. -*- mode: rst -*-
+;;
+;; in the very first line of your file. The following code is useful if you
+;; want automatically enter rst-mode from any file with compatible extensions:
+;;
+;; (setq auto-mode-alist
+;; (append '(("\\.txt\\'" . rst-mode)
+;; ("\\.rst\\'" . rst-mode)
+;; ("\\.rest\\'" . rst-mode)) auto-mode-alist))
+;;
+
+;;; Code:
+
+;; FIXME: Check through major mode conventions again.
+
+;; FIXME: Embed complicated `defconst's in `eval-when-compile'.
+
+;; Common Lisp stuff
+(require 'cl-lib)
+
+;; Correct wrong declaration.
+(def-edebug-spec push
+ (&or [form symbolp] [form gv-place]))
+
+;; Correct wrong declaration. This still doesn't support dotted desctructuring
+;; though.
+(def-edebug-spec cl-lambda-list
+ (([&rest cl-macro-arg]
+ [&optional ["&optional" cl-&optional-arg &rest cl-&optional-arg]]
+ [&optional ["&rest" arg]]
+ [&optional ["&key" [cl-&key-arg &rest cl-&key-arg]
+ &optional "&allow-other-keys"]]
+ [&optional ["&aux" &rest
+ &or (symbolp &optional def-form) symbolp]]
+ )))
+
+;; Add missing declaration.
+(def-edebug-spec cl-type-spec sexp) ;; This is not exactly correct but good
+ ;; enough.
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Support for `testcover'
+
+(when (and (boundp 'testcover-1value-functions)
+ (boundp 'testcover-compose-functions))
+ ;; Below `lambda' is used in a loop with varying parameters and is thus not
+ ;; 1valued.
+ (setq testcover-1value-functions
+ (delq 'lambda testcover-1value-functions))
+ (add-to-list 'testcover-compose-functions 'lambda))
+
+(defun rst-testcover-defcustom ()
+ "Remove all customized variables from `testcover-module-constants'.
+This seems to be a bug in `testcover': `defcustom' variables are
+considered constants. Revert it with this function after each `defcustom'."
+ (when (boundp 'testcover-module-constants)
+ (setq testcover-module-constants
+ (delq nil
+ (mapcar
+ #'(lambda (sym)
+ (if (not (plist-member (symbol-plist sym) 'standard-value))
+ sym))
+ testcover-module-constants)))))
+
+(defun rst-testcover-add-compose (fun)
+ "Add FUN to `testcover-compose-functions'."
+ (when (boundp 'testcover-compose-functions)
+ (add-to-list 'testcover-compose-functions fun)))
+
+(defun rst-testcover-add-1value (fun)
+ "Add FUN to `testcover-1value-functions'."
+ (when (boundp 'testcover-1value-functions)
+ (add-to-list 'testcover-1value-functions fun)))
+
+\f
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Helpers.
+
+(cl-defmacro rst-destructuring-dolist
+ ((arglist list &optional result) &rest body)
+ "`cl-dolist' with destructuring of the list elements.
+ARGLIST is a Common List argument list which may include
+destructuring. LIST, RESULT and BODY are as for `cl-dolist'.
+Note that definitions in ARGLIST are visible only in the BODY and
+neither in RESULT nor in LIST."
+ ;; FIXME: It would be very useful if the definitions in ARGLIST would be
+ ;; visible in RESULT. But may be this is rather a
+ ;; `rst-destructuring-do' then.
+ (declare (debug
+ (&define ([&or symbolp cl-macro-list] def-form &optional def-form)
+ cl-declarations def-body))
+ (indent 1))
+ (let ((var (make-symbol "--rst-destructuring-dolist-var--")))
+ `(cl-dolist (,var ,list ,result)
+ (cl-destructuring-bind ,arglist ,var
+ ,@body))))
+
+(defun rst-forward-line-strict (n &optional limit)
+ ;; testcover: ok.
+ "Try to move point to beginning of line I + N where I is the current line.
+Return t if movement is successful. Otherwise don't move point
+and return nil. If a position is given by LIMIT, movement
+happened but the following line is missing and thus its beginning
+can not be reached but the movement reached at least LIMIT
+consider this a successful movement. LIMIT is ignored in other
+cases."
+ (let ((start (point)))
+ (if (and (zerop (forward-line n))
+ (or (bolp)
+ (and limit
+ (>= (point) limit))))
+ t
+ (goto-char start)
+ nil)))
+
+(defun rst-forward-line-looking-at (n rst-re-args &optional fun)
+ ;; testcover: ok.
+ "Move forward N lines and if successful check whether RST-RE-ARGS is matched.
+Moving forward is done by `rst-forward-line-strict'. RST-RE-ARGS
+is a single or a list of arguments for `rst-re'. FUN is a
+function defaulting to `identity' which is called after the call
+to `looking-at' receiving its return value as the first argument.
+When FUN is called match data is just set by `looking-at' and
+point is at the beginning of the line. Return nil if moving
+forward failed or otherwise the return value of FUN. Preserve
+global match data, point, mark and current buffer."
+ (unless (listp rst-re-args)
+ (setq rst-re-args (list rst-re-args)))
+ (unless fun
+ (setq fun #'identity))
+ (save-match-data
+ (save-excursion
+ (when (rst-forward-line-strict n)
+ (funcall fun (looking-at (apply #'rst-re rst-re-args)))))))
+
+(rst-testcover-add-1value 'rst-delete-entire-line)
+(defun rst-delete-entire-line (n)
+ "Move N lines and delete the entire line."
+ (delete-region (line-beginning-position (+ n 1))
+ (line-beginning-position (+ n 2))))
+
+\f
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Versions
+
+(defun rst-extract-version (delim-re head-re re tail-re var &optional default)
+ ;; testcover: ok.
+ "Extract the version from a variable according to the given regexes.
+Return the version after regex DELIM-RE and HEAD-RE matching RE
+and before TAIL-RE and DELIM-RE in VAR or DEFAULT for no match."
+ (if (string-match
+ (concat delim-re head-re "\\(" re "\\)" tail-re delim-re)
+ var)
+ (match-string 1 var)
+ default))
+
+;; Use CVSHeader to really get information from CVS and not other version
+;; control systems.
+(defconst rst-cvs-header
+ "$CVSHeader: sm/rst_el/rst.el,v 1.1058.2.8 2017/01/08 09:54:27 stefan Exp $")
+(defconst rst-cvs-rev
+ (rst-extract-version "\\$" "CVSHeader: \\S + " "[0-9]+\\(?:\\.[0-9]+\\)+"
+ " .*" rst-cvs-header "0.0")
+ "The CVS revision of this file. CVS revision is the development revision.")
+(defconst rst-cvs-timestamp
+ (rst-extract-version "\\$" "CVSHeader: \\S + \\S + "
+ "[0-9]+-[0-9]+-[0-9]+ [0-9]+:[0-9]+:[0-9]+" " .*"
+ rst-cvs-header "1970-01-01 00:00:00")
+ "The CVS time stamp of this file.")
+
+;; Use LastChanged... to really get information from SVN.
+(defconst rst-svn-rev
+ (rst-extract-version "\\$" "LastChangedRevision: " "[0-9]+" " "
+ "$LastChangedRevision: 8015 $")
+ "The SVN revision of this file.
+SVN revision is the upstream (docutils) revision.")
+(defconst rst-svn-timestamp
+ (rst-extract-version "\\$" "LastChangedDate: " ".+?+" " "
+ "$LastChangedDate: 2017-01-08 10:54:35 +0100 (So, 08. Jän 2017) $")
+ "The SVN time stamp of this file.")
+
+;; Maintained by the release process.
+(defconst rst-official-version
+ (rst-extract-version "%" "OfficialVersion: " "[0-9]+\\(?:\\.[0-9]+\\)+" " "
+ "%OfficialVersion: 1.5.2 %")
+ "Official version of the package.")
+(defconst rst-official-cvs-rev
+ (rst-extract-version "[%$]" "Revision: " "[0-9]+\\(?:\\.[0-9]+\\)+" " "
+ "$Revision: 8015 $")
+ "CVS revision of this file in the official version.")
+
+(defconst rst-version
+ (if (equal rst-official-cvs-rev rst-cvs-rev)
+ rst-official-version
+ (format "%s (development %s [%s])" rst-official-version
+ rst-cvs-rev rst-cvs-timestamp))
+ "The version string.
+Starts with the current official version. For developer versions
+in parentheses follows the development revision and the time stamp.")
+
+(defconst rst-package-emacs-version-alist
+ '(("1.0.0" . "24.3")
+ ("1.1.0" . "24.3")
+ ("1.2.0" . "24.3")
+ ("1.2.1" . "24.3")
+ ("1.3.0" . "24.3")
+ ("1.3.1" . "24.3")
+ ("1.4.0" . "24.3")
+ ("1.4.1" . "24.5")
+ ("1.4.2" . "24.5")
+ ("1.5.0" . "26.1")
+ ("1.5.1" . "26.2")
+ ("1.5.2" . "26.2")
+ ;; Whatever the Emacs version is this rst.el version ends up in.
+ ))
+
+(unless (assoc rst-official-version rst-package-emacs-version-alist)
+ (error "Version %s not listed in `rst-package-emacs-version-alist'"
+ rst-version))
+
+(add-to-list 'customize-package-emacs-version-alist
+ (cons 'ReST rst-package-emacs-version-alist))
+
+\f
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Initialize customization
+
+(defgroup rst nil "Support for reStructuredText documents."
+ :group 'text
+ :version "23.1"
+ :link '(url-link "http://docutils.sourceforge.net/rst.html"))
+
+\f
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Facilities for regular expressions used everywhere
+
+;; The trailing numbers in the names give the number of referenceable regex
+;; groups contained in the regex.
+
+;; Used to be customizable but really is not customizable but fixed by the reST
+;; syntax.
+(defconst rst-bullets
+ ;; Sorted so they can form a character class when concatenated.
+ '(?- ?* ?+ ?• ?‣ ?⁃)
+ "List of all possible bullet characters for bulleted lists.")
+
+(defconst rst-uri-schemes
+ '("acap" "cid" "data" "dav" "fax" "file" "ftp" "gopher" "http" "https" "imap"
+ "ldap" "mailto" "mid" "modem" "news" "nfs" "nntp" "pop" "prospero" "rtsp"
+ "service" "sip" "tel" "telnet" "tip" "urn" "vemmi" "wais")
+ "Supported URI schemes.")
+
+(defconst rst-adornment-chars
+ ;; Sorted so they can form a character class when concatenated.
+ '(?\]
+ ?! ?\" ?# ?$ ?% ?& ?' ?\( ?\) ?* ?+ ?, ?. ?/ ?: ?\; ?< ?= ?> ?? ?@ ?\[ ?\\
+ ?^ ?_ ?` ?{ ?| ?} ?~
+ ?-)
+ "Characters which may be used in adornments for sections and transitions.")
+
+(defconst rst-max-inline-length
+ 1000
+ "Maximum length of inline markup to recognize.")
+
+(defconst rst-re-alist-def
+ ;; `*-beg' matches * at the beginning of a line.
+ ;; `*-end' matches * at the end of a line.
+ ;; `*-prt' matches a part of *.
+ ;; `*-tag' matches *.
+ ;; `*-sta' matches the start of * which may be followed by respective content.
+ ;; `*-pfx' matches the delimiter left of *.
+ ;; `*-sfx' matches the delimiter right of *.
+ ;; `*-hlp' helper for *.
+ ;;
+ ;; A trailing number says how many referenceable groups are contained.
+ `(
+
+ ;; Horizontal white space (`hws')
+ (hws-prt "[\t ]")
+ (hws-tag hws-prt "*") ; Optional sequence of horizontal white space.
+ (hws-sta hws-prt "+") ; Mandatory sequence of horizontal white space.
+
+ ;; Lines (`lin')
+ (lin-beg "^" hws-tag) ; Beginning of a possibly indented line.
+ (lin-end hws-tag "$") ; End of a line with optional trailing white space.
+ (linemp-tag "^" hws-tag "$") ; Empty line with optional white space.
+
+ ;; Various tags and parts
+ (ell-tag "\\.\\.\\.") ; Ellipsis
+ (bul-tag ,(concat "[" rst-bullets "]")) ; A bullet.
+ (ltr-tag "[a-zA-Z]") ; A letter enumerator tag.
+ (num-prt "[0-9]") ; A number enumerator part.
+ (num-tag num-prt "+") ; A number enumerator tag.
+ (rom-prt "[IVXLCDMivxlcdm]") ; A roman enumerator part.
+ (rom-tag rom-prt "+") ; A roman enumerator tag.
+ (aut-tag "#") ; An automatic enumerator tag.
+ (dcl-tag "::") ; Double colon.
+
+ ;; Block lead in (`bli')
+ (bli-sfx (:alt hws-sta "$")) ; Suffix of a block lead-in with *optional*
+ ; immediate content.
+
+ ;; Various starts
+ (bul-sta bul-tag bli-sfx) ; Start of a bulleted item.
+ (bul-beg lin-beg bul-sta) ; A bullet item at the beginning of a line.
+
+ ;; Explicit markup tag (`exm')
+ (exm-tag "\\.\\.")
+ (exm-sta exm-tag hws-sta)
+ (exm-beg lin-beg exm-sta)
+
+ ;; Counters in enumerations (`cnt')
+ (cntany-tag (:alt ltr-tag num-tag rom-tag aut-tag)) ; An arbitrary counter.
+ (cntexp-tag (:alt ltr-tag num-tag rom-tag)) ; An arbitrary explicit counter.
+
+ ;; Enumerator (`enm')
+ (enmany-tag (:alt
+ (:seq cntany-tag "\\.")
+ (:seq "(?" cntany-tag ")"))) ; An arbitrary enumerator.
+ (enmexp-tag (:alt
+ (:seq cntexp-tag "\\.")
+ (:seq "(?" cntexp-tag ")"))) ; An arbitrary explicit
+ ; enumerator.
+ (enmaut-tag (:alt
+ (:seq aut-tag "\\.")
+ (:seq "(?" aut-tag ")"))) ; An automatic enumerator.
+ (enmany-sta enmany-tag bli-sfx) ; An arbitrary enumerator start.
+ (enmexp-sta enmexp-tag bli-sfx) ; An arbitrary explicit enumerator start.
+ (enmexp-beg lin-beg enmexp-sta) ; An arbitrary explicit enumerator start
+ ; at the beginning of a line.
+
+ ;; Items may be enumerated or bulleted (`itm')
+ (itmany-tag (:alt enmany-tag bul-tag)) ; An arbitrary item tag.
+ (itmany-sta-1 (:grp itmany-tag) bli-sfx) ; An arbitrary item start, group
+ ; is the item tag.
+ (itmany-beg-1 lin-beg itmany-sta-1) ; An arbitrary item start at the
+ ; beginning of a line, group is the
+ ; item tag.
+
+ ;; Inline markup (`ilm')
+ (ilm-pfx (:alt "^" hws-prt "[-'\"([{<‘“«’/:]"))
+ (ilm-sfx (:alt "$" hws-prt "[]-'\")}>’”»/:.,;!?\\]"))
+
+ ;; Inline markup content (`ilc')
+ (ilcsgl-tag "\\S ") ; A single non-white character.
+ (ilcast-prt (:alt "[^*\\]" "\\\\.")) ; Part of non-asterisk content.
+ (ilcbkq-prt (:alt "[^`\\]" "\\\\.")) ; Part of non-backquote content.
+ (ilcbkqdef-prt (:alt "[^`\\\n]" "\\\\.")) ; Part of non-backquote
+ ; definition.
+ (ilcbar-prt (:alt "[^|\\]" "\\\\.")) ; Part of non-vertical-bar content.
+ (ilcbardef-prt (:alt "[^|\\\n]" "\\\\.")) ; Part of non-vertical-bar
+ ; definition.
+ (ilcast-sfx "[^\t *\\]") ; Suffix of non-asterisk content.
+ (ilcbkq-sfx "[^\t `\\]") ; Suffix of non-backquote content.
+ (ilcbar-sfx "[^\t |\\]") ; Suffix of non-vertical-bar content.
+ (ilcrep-hlp ,(format "\\{0,%d\\}" rst-max-inline-length)) ; Repeat count.
+ (ilcast-tag (:alt ilcsgl-tag
+ (:seq ilcsgl-tag
+ ilcast-prt ilcrep-hlp
+ ilcast-sfx))) ; Non-asterisk content.
+ (ilcbkq-tag (:alt ilcsgl-tag
+ (:seq ilcsgl-tag
+ ilcbkq-prt ilcrep-hlp
+ ilcbkq-sfx))) ; Non-backquote content.
+ (ilcbkqdef-tag (:alt ilcsgl-tag
+ (:seq ilcsgl-tag
+ ilcbkqdef-prt ilcrep-hlp
+ ilcbkq-sfx))) ; Non-backquote definition.
+ (ilcbar-tag (:alt ilcsgl-tag
+ (:seq ilcsgl-tag
+ ilcbar-prt ilcrep-hlp
+ ilcbar-sfx))) ; Non-vertical-bar content.
+ (ilcbardef-tag (:alt ilcsgl-tag
+ (:seq ilcsgl-tag
+ ilcbardef-prt ilcrep-hlp
+ ilcbar-sfx))) ; Non-vertical-bar definition.
+
+ ;; Fields (`fld')
+ (fldnam-prt (:alt "[^:\n]" "\\\\:")) ; Part of a field name.
+ (fldnam-tag fldnam-prt "+") ; A field name.
+ (fld-tag ":" fldnam-tag ":") ; A field marker.
+
+ ;; Options (`opt')
+ (optsta-tag (:alt "[-+/]" "--")) ; Start of an option.
+ (optnam-tag "\\sw" (:alt "-" "\\sw") "*") ; Name of an option.
+ (optarg-tag (:shy "[ =]\\S +")) ; Option argument.
+ (optsep-tag (:shy "," hws-prt)) ; Separator between options.
+ (opt-tag (:shy optsta-tag optnam-tag optarg-tag "?")) ; A complete option.
+
+ ;; Footnotes and citations (`fnc')
+ (fncnam-prt "[^]\n]") ; Part of a footnote or citation name.
+ (fncnam-tag fncnam-prt "+") ; A footnote or citation name.
+ (fnc-tag "\\[" fncnam-tag "]") ; A complete footnote or citation tag.
+ (fncdef-tag-2 (:grp exm-sta)
+ (:grp fnc-tag)) ; A complete footnote or citation definition
+ ; tag. First group is the explicit markup
+ ; start, second group is the footnote /
+ ; citation tag.
+ (fnc-sta-2 fncdef-tag-2 bli-sfx) ; Start of a footnote or citation
+ ; definition. First group is the explicit
+ ; markup start, second group is the
+ ; footnote / citation tag.
+
+ ;; Substitutions (`sub')
+ (sub-tag "|" ilcbar-tag "|") ; A complete substitution tag.
+ (subdef-tag "|" ilcbardef-tag "|") ; A complete substitution definition
+ ; tag.
+
+ ;; Symbol (`sym')
+ (sym-prt "[-+.:_]") ; Non-word part of a symbol.
+ (sym-tag (:shy "\\sw+" (:shy sym-prt "\\sw+") "*"))
+
+ ;; URIs (`uri')
+ (uri-tag (:alt ,@rst-uri-schemes))
+
+ ;; Adornment (`ado')
+ (ado-prt "[" ,(concat rst-adornment-chars) "]")
+ (adorep3-hlp "\\{3,\\}") ; There must be at least 3 characters because
+ ; otherwise explicit markup start would be
+ ; recognized.
+ (adorep2-hlp "\\{2,\\}") ; As `adorep3-hlp' but when the first of three
+ ; characters is matched differently.
+ (ado-tag-1-1 (:grp ado-prt)
+ "\\1" adorep2-hlp) ; A complete adornment, group is the first
+ ; adornment character and MUST be the FIRST
+ ; group in the whole expression.
+ (ado-tag-1-2 (:grp ado-prt)
+ "\\2" adorep2-hlp) ; A complete adornment, group is the first
+ ; adornment character and MUST be the
+ ; SECOND group in the whole expression.
+ (ado-beg-2-1 "^" (:grp ado-tag-1-2)
+ lin-end) ; A complete adornment line; first group is the whole
+ ; adornment and MUST be the FIRST group in the whole
+ ; expression; second group is the first adornment
+ ; character.
+
+ ;; Titles (`ttl')
+ (ttl-tag "\\S *\\w.*\\S ") ; A title text.
+ (ttl-beg-1 lin-beg (:grp ttl-tag)) ; A title text at the beginning of a
+ ; line. First group is the complete,
+ ; trimmed title text.
+
+ ;; Directives and substitution definitions (`dir')
+ (dir-tag-3 (:grp exm-sta)
+ (:grp (:shy subdef-tag hws-sta) "?")
+ (:grp sym-tag dcl-tag)) ; A directive or substitution definition
+ ; tag. First group is explicit markup
+ ; start, second group is a possibly
+ ; empty substitution tag, third group is
+ ; the directive tag including the double
+ ; colon.
+ (dir-sta-3 dir-tag-3 bli-sfx) ; Start of a directive or substitution
+ ; definition. Groups are as in dir-tag-3.
+
+ ;; Literal block (`lit')
+ (lit-sta-2 (:grp (:alt "[^.\n]" "\\.[^.\n]") ".*") "?"
+ (:grp dcl-tag) "$") ; Start of a literal block. First group is
+ ; any text before the double colon tag which
+ ; may not exist, second group is the double
+ ; colon tag.
+
+ ;; Comments (`cmt')
+ (cmt-sta-1 (:grp exm-sta) "[^[|_\n]"
+ (:alt "[^:\n]" (:seq ":" (:alt "[^:\n]" "$")))
+ "*$") ; Start of a comment block; first group is explicit markup
+ ; start.
+
+ ;; Paragraphs (`par')
+ (par-tag- (:alt itmany-tag fld-tag opt-tag fncdef-tag-2 dir-tag-3 exm-tag)
+ ) ; Tag at the beginning of a paragraph; there may be groups in
+ ; certain cases.
+ )
+ "Definition alist of relevant regexes.
+Each entry consists of the symbol naming the regex and an
+argument list for `rst-re'.")
+
+(defvar rst-re-alist) ; Forward declare to use it in `rst-re'.
+
+;; FIXME: Use `sregex' or `rx' instead of re-inventing the wheel.
+(rst-testcover-add-compose 'rst-re)
+(defun rst-re (&rest args)
+ ;; testcover: ok.
+ "Interpret ARGS as regular expressions and return a regex string.
+Each element of ARGS may be one of the following:
+
+A string which is inserted unchanged.
+
+A character which is resolved to a quoted regex.
+
+A symbol which is resolved to a string using `rst-re-alist-def'.
+
+A list with a keyword in the car. Each element of the cdr of such
+a list is recursively interpreted as ARGS. The results of this
+interpretation are concatenated according to the keyword.
+
+For the keyword `:seq' the results are simply concatenated.
+
+For the keyword `:shy' the results are concatenated and
+surrounded by a shy-group (\"\\(?:...\\)\").
+
+For the keyword `:alt' the results form an alternative (\"\\|\")
+which is shy-grouped (\"\\(?:...\\)\").
+
+For the keyword `:grp' the results are concatenated and form a
+referenceable group (\"\\(...\\)\").
+
+After interpretation of ARGS the results are concatenated as for
+`:seq'."
+ (apply #'concat
+ (mapcar
+ #'(lambda (re)
+ (cond
+ ((stringp re)
+ re)
+ ((symbolp re)
+ (cadr (assoc re rst-re-alist)))
+ ((characterp re)
+ (regexp-quote (char-to-string re)))
+ ((listp re)
+ (let ((nested
+ (mapcar (lambda (elt)
+ (rst-re elt))
+ (cdr re))))
+ (cond
+ ((eq (car re) :seq)
+ (mapconcat #'identity nested ""))
+ ((eq (car re) :shy)
+ (concat "\\(?:" (mapconcat #'identity nested "") "\\)"))
+ ((eq (car re) :grp)
+ (concat "\\(" (mapconcat #'identity nested "") "\\)"))
+ ((eq (car re) :alt)
+ (concat "\\(?:" (mapconcat #'identity nested "\\|") "\\)"))
+ (t
+ (error "Unknown list car: %s" (car re))))))
+ (t
+ (error "Unknown object type for building regex: %s" re))))
+ args)))
+
+;; FIXME: Remove circular dependency between `rst-re' and `rst-re-alist'.
+(with-no-warnings ; Silence byte-compiler about this construction.
+ (defconst rst-re-alist
+ ;; Shadow global value we are just defining so we can construct it step by
+ ;; step.
+ (let (rst-re-alist)
+ (dolist (re rst-re-alist-def rst-re-alist)
+ (setq rst-re-alist
+ (nconc rst-re-alist
+ (list (list (car re) (apply #'rst-re (cdr re))))))))
+ "Alist mapping symbols from `rst-re-alist-def' to regex strings."))
+
+\f
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Concepts
+
+;; Each of the following classes represents an own concept. The suffix of the
+;; class name is used in the code to represent entities of the respective
+;; class.
+;;
+;; In addition a reStructuredText section header in the buffer is called
+;; "section".
+;;
+;; For lists a "s" is added to the name of the concepts.
+
+\f
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Class rst-Ado
+
+(cl-defstruct
+ (rst-Ado
+ (:constructor nil) ; Prevent creating unchecked values.
+ ;; Construct a transition.
+ (:constructor
+ rst-Ado-new-transition
+ (&aux
+ (char nil)
+ (-style 'transition)))
+ ;; Construct a simple section header.
+ (:constructor
+ rst-Ado-new-simple
+ (char-arg
+ &aux
+ (char (rst-Ado--validate-char char-arg))
+ (-style 'simple)))
+ ;; Construct a over-and-under section header.
+ (:constructor
+ rst-Ado-new-over-and-under
+ (char-arg
+ &aux
+ (char (rst-Ado--validate-char char-arg))
+ (-style 'over-and-under)))
+ ;; Construct from adornment with inverted style.
+ (:constructor
+ rst-Ado-new-invert
+ (ado-arg
+ &aux
+ (char (rst-Ado-char ado-arg))
+ (-style (let ((sty (rst-Ado--style ado-arg)))
+ (cond
+ ((eq sty 'simple)
+ 'over-and-under)
+ ((eq sty 'over-and-under)
+ 'simple)
+ (sty)))))))
+ "Representation of a reStructuredText adornment.
+Adornments are either section markers where they markup the
+section header or transitions.
+
+This type is immutable."
+ ;; The character used for the adornment.
+ (char nil :read-only t)
+ ;; The style of the adornment. This is a private attribute.
+ (-style nil :read-only t))
+
+;; Private class methods
+
+(defun rst-Ado--validate-char (char)
+ ;; testcover: ok.
+ "Validate CHAR to be a valid adornment character.
+Return CHAR if so or signal an error otherwise."
+ (cl-check-type char character)
+ (cl-check-type char (satisfies
+ (lambda (c)
+ (memq c rst-adornment-chars)))
+ "Character must be a valid adornment character")
+ char)
+
+;; Public methods
+
+(defun rst-Ado-is-transition (self)
+ ;; testcover: ok.
+ "Return non-nil if SELF is a transition adornment."
+ (cl-check-type self rst-Ado)
+ (eq (rst-Ado--style self) 'transition))
+
+(defun rst-Ado-is-section (self)
+ ;; testcover: ok.
+ "Return non-nil if SELF is a section adornment."
+ (cl-check-type self rst-Ado)
+ (not (rst-Ado-is-transition self)))
+
+(defun rst-Ado-is-simple (self)
+ ;; testcover: ok.
+ "Return non-nil if SELF is a simple section adornment."
+ (cl-check-type self rst-Ado)
+ (eq (rst-Ado--style self) 'simple))
+
+(defun rst-Ado-is-over-and-under (self)
+ ;; testcover: ok.
+ "Return non-nil if SELF is a over-and-under section adornment."
+ (cl-check-type self rst-Ado)
+ (eq (rst-Ado--style self) 'over-and-under))
+
+(defun rst-Ado-equal (self other)
+ ;; testcover: ok.
+ "Return non-nil when SELF and OTHER are equal."
+ (cl-check-type self rst-Ado)
+ (cl-check-type other rst-Ado)
+ (cond
+ ((not (eq (rst-Ado--style self) (rst-Ado--style other)))
+ nil)
+ ((rst-Ado-is-transition self))
+ ((equal (rst-Ado-char self) (rst-Ado-char other)))))
+
+(defun rst-Ado-position (self ados)
+ ;; testcover: ok.
+ "Return position of SELF in ADOS or nil."
+ (cl-check-type self rst-Ado)
+ (cl-position-if #'(lambda (e)
+ (rst-Ado-equal self e))
+ ados))
+
+\f
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Class rst-Hdr
+
+(cl-defstruct
+ (rst-Hdr
+ (:constructor nil) ; Prevent creating unchecked values.
+ ;; Construct while all parameters must be valid.
+ (:constructor
+ rst-Hdr-new
+ (ado-arg
+ indent-arg
+ &aux
+ (ado (rst-Hdr--validate-ado ado-arg))
+ (indent (rst-Hdr--validate-indent indent-arg ado nil))))
+ ;; Construct while all parameters but `indent' must be valid.
+ (:constructor
+ rst-Hdr-new-lax
+ (ado-arg
+ indent-arg
+ &aux
+ (ado (rst-Hdr--validate-ado ado-arg))
+ (indent (rst-Hdr--validate-indent indent-arg ado t))))
+ ;; Construct a header with same characteristics but opposite style as `ado'.
+ (:constructor
+ rst-Hdr-new-invert
+ (ado-arg
+ indent-arg
+ &aux
+ (ado (rst-Hdr--validate-ado (rst-Ado-new-invert ado-arg)))
+ (indent (rst-Hdr--validate-indent indent-arg ado t))))
+ (:copier nil)) ; Not really needed for an immutable type.
+ "Representation of reStructuredText section header characteristics.
+
+This type is immutable."
+ ;; The adornment of the header.
+ (ado nil :read-only t)
+ ;; The indentation of a title text or nil if not given.
+ (indent nil :read-only t))
+
+;; Private class methods
+
+(defun rst-Hdr--validate-indent (indent ado lax)
+ ;; testcover: ok.
+ "Validate INDENT to be a valid indentation for ADO.
+Return INDENT if so or signal an error otherwise. If LAX don't
+signal an error and return a valid indent."
+ (cl-check-type indent integer)
+ (cond
+ ((zerop indent)
+ indent)
+ ((rst-Ado-is-simple ado)
+ (if lax
+ 0
+ (signal 'args-out-of-range
+ '("Indentation must be 0 for style simple"))))
+ ((< indent 0)
+ (if lax
+ 0
+ (signal 'args-out-of-range
+ '("Indentation must not be negative"))))
+ ;; Implicitly over-and-under.
+ (indent)))
+
+(defun rst-Hdr--validate-ado (ado)
+ ;; testcover: ok.
+ "Validate ADO to be a valid adornment.
+Return ADO if so or signal an error otherwise."
+ (cl-check-type ado rst-Ado)
+ (cond
+ ((rst-Ado-is-transition ado)
+ (signal 'args-out-of-range
+ '("Adornment for header must not be transition.")))
+ (ado)))
+
+;; Public class methods
+
+(defvar rst-preferred-adornments) ; Forward declaration.
+
+(defun rst-Hdr-preferred-adornments ()
+ ;; testcover: ok.
+ "Return preferred adornments as list of `rst-Hdr'."
+ (mapcar (cl-function
+ (lambda ((character style indent))
+ (rst-Hdr-new-lax
+ (if (eq style 'over-and-under)
+ (rst-Ado-new-over-and-under character)
+ (rst-Ado-new-simple character))
+ indent)))
+ rst-preferred-adornments))
+
+;; Public methods
+
+(defun rst-Hdr-member-ado (self hdrs)
+ ;; testcover: ok.
+ "Return sublist of HDRS whose car's adornment equals that of SELF or nil."
+ (cl-check-type self rst-Hdr)
+ (let ((ado (rst-Hdr-ado self)))
+ (cl-member-if #'(lambda (hdr)
+ (rst-Ado-equal ado (rst-Hdr-ado hdr)))
+ hdrs)))
+
+(defun rst-Hdr-ado-map (selves)
+ ;; testcover: ok.
+ "Return `rst-Ado' list extracted from elements of SELVES."
+ (mapcar #'rst-Hdr-ado selves))
+
+(defun rst-Hdr-get-char (self)
+ ;; testcover: ok.
+ "Return character of the adornment of SELF."
+ (cl-check-type self rst-Hdr)
+ (rst-Ado-char (rst-Hdr-ado self)))
+
+(defun rst-Hdr-is-over-and-under (self)
+ ;; testcover: ok.
+ "Return non-nil if SELF is a over-and-under section header."
+ (cl-check-type self rst-Hdr)
+ (rst-Ado-is-over-and-under (rst-Hdr-ado self)))
+
+\f
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Class rst-Ttl
+
+(cl-defstruct
+ (rst-Ttl
+ (:constructor nil) ; Prevent creating unchecked values.
+ ;; Construct with valid parameters for all attributes.
+ (:constructor ; Private constructor
+ rst-Ttl--new
+ (ado-arg
+ match-arg
+ indent-arg
+ text-arg
+ &aux
+ (ado (rst-Ttl--validate-ado ado-arg))
+ (match (rst-Ttl--validate-match match-arg ado))
+ (indent (rst-Ttl--validate-indent indent-arg ado))
+ (text (rst-Ttl--validate-text text-arg ado))
+ (hdr (condition-case nil
+ (rst-Hdr-new ado indent)
+ (error nil)))))
+ (:copier nil)) ; Not really needed for an immutable type.
+ "Representation of a reStructuredText section header as found in a buffer.
+This type gathers information about an adorned part in the buffer.
+
+This type is immutable."
+ ;; The adornment characteristics or nil for a title candidate.
+ (ado nil :read-only t)
+ ;; The match-data for `ado' in a form similarly returned by `match-data' (but
+ ;; not necessarily with markers in buffers). Match group 0 matches the whole
+ ;; construct. Match group 1 matches the overline adornment if present.
+ ;; Match group 2 matches the section title text or the transition. Match
+ ;; group 3 matches the underline adornment.
+ (match nil :read-only t)
+ ;; An indentation found for the title line or nil for a transition.
+ (indent nil :read-only t)
+ ;; The text of the title or nil for a transition.
+ (text nil :read-only t)
+ ;; The header characteristics if it is a valid section header.
+ (hdr nil :read-only t)
+ ;; FIXME refactoring: Should have an attribute `buffer' for the buffer this
+ ;; title is found in. This breaks lots and lots of tests.
+ ;; However, with private constructor they may not be
+ ;; necessary any more. In case it is really a buffer then
+ ;; also `match' could be real data from `match-data' which
+ ;; contains markers instead of integers.
+ )
+
+;; Private class methods
+
+(defun rst-Ttl--validate-ado (ado)
+ ;; testcover: ok.
+ "Return valid ADO or signal error."
+ (cl-check-type ado (or null rst-Ado))
+ ado)
+
+(defun rst-Ttl--validate-match (match ado)
+ ;; testcover: ok.
+ "Return valid MATCH matching ADO or signal error."
+ (cl-check-type ado (or null rst-Ado))
+ (cl-check-type match list)
+ (cl-check-type match (satisfies (lambda (m)
+ (equal (length m) 8)))
+ "Match data must consist of exactly 8 buffer positions.")
+ (dolist (pos match)
+ (cl-check-type pos (or null integer-or-marker)))
+ (cl-destructuring-bind (all-beg all-end
+ ovr-beg ovr-end
+ txt-beg txt-end
+ und-beg und-end) match
+ (unless (and (integer-or-marker-p all-beg) (integer-or-marker-p all-end))
+ (signal 'args-out-of-range
+ '("First two elements of match data must be buffer positions.")))
+ (cond
+ ((null ado)
+ (unless (and (null ovr-beg) (null ovr-end)
+ (integer-or-marker-p txt-beg) (integer-or-marker-p txt-end)
+ (null und-beg) (null und-end))
+ (signal 'args-out-of-range
+ '("For a title candidate exactly the third match pair must be set."))))
+ ((rst-Ado-is-transition ado)
+ (unless (and (null ovr-beg) (null ovr-end)
+ (integer-or-marker-p txt-beg) (integer-or-marker-p txt-end)
+ (null und-beg) (null und-end))
+ (signal 'args-out-of-range
+ '("For a transition exactly the third match pair must be set."))))
+ ((rst-Ado-is-simple ado)
+ (unless (and (null ovr-beg) (null ovr-end)
+ (integer-or-marker-p txt-beg) (integer-or-marker-p txt-end)
+ (integer-or-marker-p und-beg) (integer-or-marker-p und-end))
+ (signal 'args-out-of-range
+ '("For a simple section adornment exactly the third and fourth match pair must be set."))))
+ (t ; over-and-under
+ (unless (and (integer-or-marker-p ovr-beg) (integer-or-marker-p ovr-end)
+ (integer-or-marker-p txt-beg) (integer-or-marker-p txt-end)
+ (or (null und-beg) (integer-or-marker-p und-beg))
+ (or (null und-end) (integer-or-marker-p und-end)))
+ (signal 'args-out-of-range
+ '("For a over-and-under section adornment all match pairs must be set."))))))
+ match)
+
+(defun rst-Ttl--validate-indent (indent ado)
+ ;; testcover: ok.
+ "Return valid INDENT for ADO or signal error."
+ (if (and ado (rst-Ado-is-transition ado))
+ (cl-check-type indent null
+ "Indent for a transition must be nil.")
+ (cl-check-type indent (integer 0 *)
+ "Indent for a section header must be non-negative."))
+ indent)
+
+(defun rst-Ttl--validate-text (text ado)
+ ;; testcover: ok.
+ "Return valid TEXT for ADO or signal error."
+ (if (and ado (rst-Ado-is-transition ado))
+ (cl-check-type text null
+ "Transitions may not have title text.")
+ (cl-check-type text string))
+ text)
+
+;; Public class methods
+
+(defun rst-Ttl-from-buffer (ado beg-ovr beg-txt beg-und txt)
+ ;; testcover: ok.
+ "Return a `rst-Ttl' constructed from information in the current buffer.
+ADO is the adornment or nil for a title candidate. BEG-OVR and
+BEG-UND are the starting points of the overline or underline,
+respectively. They may be nil if the respective thing is missing.
+BEG-TXT is the beginning of the title line or the transition and
+must be given. The end of the line is used as the end point. TXT
+is the title text or nil. If TXT is given the indendation of the
+line containing BEG-TXT is used as indentation. Match group 0 is
+derived from the remaining information."
+ (cl-check-type beg-txt integer-or-marker)
+ (save-excursion
+ (let ((end-ovr (when beg-ovr
+ (goto-char beg-ovr)
+ (line-end-position)))
+ (end-txt (progn
+ (goto-char beg-txt)
+ (line-end-position)))
+ (end-und (when beg-und
+ (goto-char beg-und)
+ (line-end-position)))
+ (ind (when txt
+ (goto-char beg-txt)
+ (current-indentation))))
+ (rst-Ttl--new ado
+ (list
+ (or beg-ovr beg-txt) (or end-und end-txt)
+ beg-ovr end-ovr
+ beg-txt end-txt
+ beg-und end-und)
+ ind txt))))
+
+;; Public methods
+
+(defun rst-Ttl-get-title-beginning (self)
+ ;; testcover: ok.
+ "Return position of beginning of title text of SELF.
+This position should always be at the start of a line."
+ (cl-check-type self rst-Ttl)
+ (nth 4 (rst-Ttl-match self)))
+
+(defun rst-Ttl-get-beginning (self)
+ ;; testcover: ok.
+ "Return position of beginning of whole SELF."
+ (cl-check-type self rst-Ttl)
+ (nth 0 (rst-Ttl-match self)))
+
+(defun rst-Ttl-get-end (self)
+ ;; testcover: ok.
+ "Return position of end of whole SELF."
+ (cl-check-type self rst-Ttl)
+ (nth 1 (rst-Ttl-match self)))
+
+(defun rst-Ttl-is-section (self)
+ ;; testcover: ok.
+ "Return non-nil if SELF is a section header or candidate."
+ (cl-check-type self rst-Ttl)
+ (rst-Ttl-text self))
+
+(defun rst-Ttl-is-candidate (self)
+ ;; testcover: ok.
+ "Return non-nil if SELF is a candidate for a section header."
+ (cl-check-type self rst-Ttl)
+ (not (rst-Ttl-ado self)))
+
+(defun rst-Ttl-contains (self position)
+ "Return whether SELF contain POSITION.
+Return 0 if SELF contains POSITION, < 0 if SELF ends before
+POSITION and > 0 if SELF starts after position."
+ (cl-check-type self rst-Ttl)
+ (cl-check-type position integer-or-marker)
+ (cond
+ ((< (nth 1 (rst-Ttl-match self)) position)
+ -1)
+ ((> (nth 0 (rst-Ttl-match self)) position)
+ +1)
+ (0)))
+
+\f
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Class rst-Stn
+
+(cl-defstruct
+ (rst-Stn
+ (:constructor nil) ; Prevent creating unchecked values.
+ ;; Construct while all parameters must be valid.
+ (:constructor
+ rst-Stn-new
+ (ttl-arg
+ level-arg
+ children-arg
+ &aux
+ (ttl (rst-Stn--validate-ttl ttl-arg))
+ (level (rst-Stn--validate-level level-arg ttl))
+ (children (rst-Stn--validate-children children-arg ttl)))))
+ "Representation of a section tree node.
+
+This type is immutable."
+ ;; The title of the node or nil for a missing node.
+ (ttl nil :read-only t)
+ ;; The level of the node in the tree. Negative for the (virtual) top level
+ ;; node.
+ (level nil :read-only t)
+ ;; The list of children of the node.
+ (children nil :read-only t))
+;; FIXME refactoring: Should have an attribute `buffer' for the buffer this
+;; title is found in. Or use `rst-Ttl-buffer'.
+
+;; Private class methods
+
+(defun rst-Stn--validate-ttl (ttl)
+ ;; testcover: ok.
+ "Return valid TTL or signal error."
+ (cl-check-type ttl (or null rst-Ttl))
+ ttl)
+
+(defun rst-Stn--validate-level (level ttl)
+ ;; testcover: ok.
+ "Return valid LEVEL for TTL or signal error."
+ (cl-check-type level integer)
+ (when (and ttl (< level 0))
+ ;; testcover: Never reached because a title may not have a negative level
+ (signal 'args-out-of-range
+ '("Top level node must not have a title.")))
+ level)
+
+(defun rst-Stn--validate-children (children ttl)
+ ;; testcover: ok.
+ "Return valid CHILDREN for TTL or signal error."
+ (cl-check-type children list)
+ (dolist (child children)
+ (cl-check-type child rst-Stn))
+ (unless (or ttl children)
+ (signal 'args-out-of-range
+ '("A missing node must have children.")))
+ children)
+
+;; Public methods
+
+(defun rst-Stn-get-title-beginning (self)
+ ;; testcover: ok.
+ "Return the beginning of the title of SELF.
+Handles missing node properly."
+ (cl-check-type self rst-Stn)
+ (let ((ttl (rst-Stn-ttl self)))
+ (if ttl
+ (rst-Ttl-get-title-beginning ttl)
+ (rst-Stn-get-title-beginning (car (rst-Stn-children self))))))
+
+(defun rst-Stn-get-text (self &optional default)
+ ;; testcover: ok.
+ "Return title text of SELF or DEFAULT if SELF is a missing node.
+For a missing node and no DEFAULT given return a standard title text."
+ (cl-check-type self rst-Stn)
+ (let ((ttl (rst-Stn-ttl self)))
+ (cond
+ (ttl
+ (rst-Ttl-text ttl))
+ (default)
+ ("[missing node]"))))
+
+(defun rst-Stn-is-top (self)
+ ;; testcover: ok.
+ "Return non-nil if SELF is a top level node."
+ (cl-check-type self rst-Stn)
+ (< (rst-Stn-level self) 0))
+
+\f
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Mode definition
+
+(defun rst-define-key (keymap key def &rest deprecated)
+ ;; testcover: ok.
+ "Bind like `define-key' but add deprecated key definitions.
+KEYMAP, KEY, and DEF are as in `define-key'. DEPRECATED key
+definitions should be in vector notation. These are defined
+as well but give an additional message."
+ (define-key keymap key def)
+ (when deprecated
+ (let* ((command-name (symbol-name def))
+ (forwarder-function-name
+ (if (string-match "^rst-\\(.*\\)$" command-name)
+ (concat "rst-deprecated-"
+ (match-string 1 command-name))
+ (error "Not an RST command: %s" command-name)))
+ (forwarder-function (intern forwarder-function-name)))
+ (unless (fboundp forwarder-function)
+ (defalias forwarder-function
+ (lambda ()
+ (interactive)
+ (call-interactively def)
+ (message "[Deprecated use of key %s; use key %s instead]"
+ (key-description (this-command-keys))
+ (key-description key)))
+ ;; FIXME: In Emacs-25 we could use (:documentation ...) instead.
+ (format "Deprecated binding for %s, use \\[%s] instead."
+ def def)))
+ (dolist (dep-key deprecated)
+ (define-key keymap dep-key forwarder-function)))))
+
+ ;; Key bindings.
+(defvar rst-mode-map
+ (let ((map (make-sparse-keymap)))
+
+ ;; \C-c is the general keymap.
+ (rst-define-key map [?\C-c ?\C-h] #'describe-prefix-bindings)
+
+ ;;
+ ;; Section Adornments
+ ;;
+ ;; The adjustment function that adorns or rotates a section title.
+ (rst-define-key map [?\C-c ?\C-=] #'rst-adjust [?\C-c ?\C-a t])
+ (rst-define-key map [?\C-=] #'rst-adjust) ; Does not work on macOS and
+ ; on consoles.
+
+ ;; \C-c \C-a is the keymap for adornments.
+ (rst-define-key map [?\C-c ?\C-a ?\C-h] #'describe-prefix-bindings)
+ ;; Another binding which works with all types of input.
+ (rst-define-key map [?\C-c ?\C-a ?\C-a] #'rst-adjust)
+ ;; Display the hierarchy of adornments implied by the current document
+ ;; contents.
+ (rst-define-key map [?\C-c ?\C-a ?\C-d] #'rst-display-hdr-hierarchy)
+ ;; Homogenize the adornments in the document.
+ (rst-define-key map [?\C-c ?\C-a ?\C-s] #'rst-straighten-sections
+ [?\C-c ?\C-s])
+
+ ;;
+ ;; Section Movement and Selection
+ ;;
+ ;; Mark the subsection where the cursor is.
+ (rst-define-key map [?\C-\M-h] #'rst-mark-section
+ ;; Same as mark-defun sgml-mark-current-element.
+ [?\C-c ?\C-m])
+ ;; Move backward/forward between section titles.
+ ;; FIXME: Also bind similar to outline mode.
+ (rst-define-key map [?\C-\M-a] #'rst-backward-section
+ ;; Same as beginning-of-defun.
+ [?\C-c ?\C-n])
+ (rst-define-key map [?\C-\M-e] #'rst-forward-section
+ ;; Same as end-of-defun.
+ [?\C-c ?\C-p])
+
+ ;;
+ ;; Operating on regions
+ ;;
+ ;; \C-c \C-r is the keymap for regions.
+ (rst-define-key map [?\C-c ?\C-r ?\C-h] #'describe-prefix-bindings)
+ ;; Makes region a line-block.
+ (rst-define-key map [?\C-c ?\C-r ?\C-l] #'rst-line-block-region
+ [?\C-c ?\C-d])
+ ;; Shift region left or right according to tabs.
+ (rst-define-key map [?\C-c ?\C-r tab] #'rst-shift-region
+ [?\C-c ?\C-r t] [?\C-c ?\C-l t])
+
+ ;;
+ ;; Operating on lists
+ ;;
+ ;; \C-c \C-l is the keymap for lists.
+ (rst-define-key map [?\C-c ?\C-l ?\C-h] #'describe-prefix-bindings)
+ ;; Makes paragraphs in region as a bullet list.
+ (rst-define-key map [?\C-c ?\C-l ?\C-b] #'rst-bullet-list-region
+ [?\C-c ?\C-b])
+ ;; Makes paragraphs in region as a enumeration.
+ (rst-define-key map [?\C-c ?\C-l ?\C-e] #'rst-enumerate-region
+ [?\C-c ?\C-e])
+ ;; Converts bullets to an enumeration.
+ (rst-define-key map [?\C-c ?\C-l ?\C-c] #'rst-convert-bullets-to-enumeration
+ [?\C-c ?\C-v])
+ ;; Make sure that all the bullets in the region are consistent.
+ (rst-define-key map [?\C-c ?\C-l ?\C-s] #'rst-straighten-bullets-region
+ [?\C-c ?\C-w])
+ ;; Insert a list item.
+ (rst-define-key map [?\C-c ?\C-l ?\C-i] #'rst-insert-list)
+
+ ;;
+ ;; Table-of-Contents Features
+ ;;
+ ;; \C-c \C-t is the keymap for table of contents.
+ (rst-define-key map [?\C-c ?\C-t ?\C-h] #'describe-prefix-bindings)
+ ;; Enter a TOC buffer to view and move to a specific section.
+ (rst-define-key map [?\C-c ?\C-t ?\C-t] #'rst-toc)
+ ;; Insert a TOC here.
+ (rst-define-key map [?\C-c ?\C-t ?\C-i] #'rst-toc-insert
+ [?\C-c ?\C-i])
+ ;; Update the document's TOC (without changing the cursor position).
+ (rst-define-key map [?\C-c ?\C-t ?\C-u] #'rst-toc-update
+ [?\C-c ?\C-u])
+ ;; Go to the section under the cursor (cursor must be in internal TOC).
+ (rst-define-key map [?\C-c ?\C-t ?\C-j] #'rst-toc-follow-link
+ [?\C-c ?\C-f])
+
+ ;;
+ ;; Converting Documents from Emacs
+ ;;
+ ;; \C-c \C-c is the keymap for compilation.
+ (rst-define-key map [?\C-c ?\C-c ?\C-h] #'describe-prefix-bindings)
+ ;; Run one of two pre-configured toolset commands on the document.
+ (rst-define-key map [?\C-c ?\C-c ?\C-c] #'rst-compile
+ [?\C-c ?1])
+ (rst-define-key map [?\C-c ?\C-c ?\C-a] #'rst-compile-alt-toolset
+ [?\C-c ?2])
+ ;; Convert the active region to pseudo-xml using the docutils tools.
+ (rst-define-key map [?\C-c ?\C-c ?\C-x] #'rst-compile-pseudo-region
+ [?\C-c ?3])
+ ;; Convert the current document to PDF and launch a viewer on the results.
+ (rst-define-key map [?\C-c ?\C-c ?\C-p] #'rst-compile-pdf-preview
+ [?\C-c ?4])
+ ;; Convert the current document to S5 slides and view in a web browser.
+ (rst-define-key map [?\C-c ?\C-c ?\C-s] #'rst-compile-slides-preview
+ [?\C-c ?5])
+
+ map)
+ "Keymap for reStructuredText mode commands.
+This inherits from Text mode.")
+
+
+;; Abbrevs.
+(define-abbrev-table 'rst-mode-abbrev-table
+ (mapcar #'(lambda (x)
+ (append x '(nil 0 system)))
+ '(("contents" ".. contents::\n..\n ")
+ ("con" ".. contents::\n..\n ")
+ ("cont" "[...]")
+ ("skip" "\n\n[...]\n\n ")
+ ("seq" "\n\n[...]\n\n ")
+ ;; FIXME: Add footnotes, links, and more.
+ ))
+ "Abbrev table used while in `rst-mode'.")
+
+
+;; Syntax table.
+(defvar rst-mode-syntax-table
+ (let ((st (copy-syntax-table text-mode-syntax-table)))
+ (modify-syntax-entry ?$ "." st)
+ (modify-syntax-entry ?% "." st)
+ (modify-syntax-entry ?& "." st)
+ (modify-syntax-entry ?' "." st)
+ (modify-syntax-entry ?* "." st)
+ (modify-syntax-entry ?+ "." st)
+ (modify-syntax-entry ?- "." st)
+ (modify-syntax-entry ?/ "." st)
+ (modify-syntax-entry ?< "." st)
+ (modify-syntax-entry ?= "." st)
+ (modify-syntax-entry ?> "." st)
+ (modify-syntax-entry ?\\ "\\" st)
+ (modify-syntax-entry ?_ "." st)
+ (modify-syntax-entry ?| "." st)
+ (modify-syntax-entry ?« "." st)
+ (modify-syntax-entry ?» "." st)
+ (modify-syntax-entry ?‘ "." st)
+ (modify-syntax-entry ?’ "." st)
+ (modify-syntax-entry ?“ "." st)
+ (modify-syntax-entry ?” "." st)
+ st)
+ "Syntax table used while in `rst-mode'.")
+
+(defcustom rst-mode-hook nil
+ "Hook run when `rst-mode' is turned on.
+The hook for `text-mode' is run before this one."
+ :group 'rst
+ :type '(hook))
+(rst-testcover-defcustom)
+
+;; Pull in variable definitions silencing byte-compiler.
+(require 'newcomment)
+
+(defvar electric-pair-pairs)
+(defvar electric-indent-inhibit)
+
+;; Use rst-mode for *.rst and *.rest files. Many ReStructured-Text files
+;; use *.txt, but this is too generic to be set as a default.
+;;;###autoload (add-to-list 'auto-mode-alist (purecopy '("\\.re?st\\'" . rst-mode)))
+;;;###autoload
+(define-derived-mode rst-mode text-mode "ReST"
+ "Major mode for editing reStructuredText documents.
+\\<rst-mode-map>
+
+Turning on `rst-mode' calls the normal hooks `text-mode-hook'
+and `rst-mode-hook'. This mode also supports font-lock
+highlighting.
+
+\\{rst-mode-map}"
+ :abbrev-table rst-mode-abbrev-table
+ :syntax-table rst-mode-syntax-table
+ :group 'rst
+
+ ;; Paragraph recognition.
+ (setq-local paragraph-separate
+ (rst-re '(:alt
+ "\f"
+ lin-end)))
+ (setq-local paragraph-start
+ (rst-re '(:alt
+ "\f"
+ lin-end
+ (:seq hws-tag par-tag- bli-sfx))))
+
+ ;; Indenting and filling.
+ (setq-local indent-line-function #'rst-indent-line)
+ (setq-local adaptive-fill-mode t)
+ (setq-local adaptive-fill-regexp (rst-re 'hws-tag 'par-tag- "?" 'hws-tag))
+ (setq-local adaptive-fill-function #'rst-adaptive-fill)
+ (setq-local fill-paragraph-handle-comment nil)
+
+ ;; Comments.
+ (setq-local comment-start ".. ")
+ (setq-local comment-start-skip (rst-re 'lin-beg 'exm-tag 'bli-sfx))
+ (setq-local comment-continue " ")
+ (setq-local comment-multi-line t)
+ (setq-local comment-use-syntax nil)
+ ;; reStructuredText has not really a comment ender but nil is not really a
+ ;; permissible value.
+ (setq-local comment-end "")
+ (setq-local comment-end-skip nil)
+
+ ;; Commenting in reStructuredText is very special so use our own set of
+ ;; functions.
+ (setq-local comment-line-break-function #'rst-comment-line-break)
+ (setq-local comment-indent-function #'rst-comment-indent)
+ (setq-local comment-insert-comment-function #'rst-comment-insert-comment)
+ (setq-local comment-region-function #'rst-comment-region)
+ (setq-local uncomment-region-function #'rst-uncomment-region)
+
+ (setq-local electric-pair-pairs '((?\" . ?\") (?\* . ?\*) (?\` . ?\`)))
+
+ ;; Imenu and which function.
+ ;; FIXME: Check documentation of `which-function' for alternative ways to
+ ;; determine the current function name.
+ (setq-local imenu-create-index-function #'rst-imenu-create-index)
+
+ ;; Font lock.
+ (setq-local font-lock-defaults
+ '(rst-font-lock-keywords
+ t nil nil nil
+ (font-lock-multiline . t)
+ (font-lock-mark-block-function . mark-paragraph)))
+ (add-hook 'font-lock-extend-region-functions #'rst-font-lock-extend-region t)
+
+ ;; Text after a changed line may need new fontification.
+ (setq-local jit-lock-contextually t)
+
+ ;; Indentation is not deterministic.
+ (setq-local electric-indent-inhibit t))
+
+;;;###autoload
+(define-minor-mode rst-minor-mode
+ "Toggle ReST minor mode.
+With a prefix argument ARG, enable ReST minor mode if ARG is
+positive, and disable it otherwise. If called from Lisp, enable
+the mode if ARG is omitted or nil.
+
+When ReST minor mode is enabled, the ReST mode keybindings
+are installed on top of the major mode bindings. Use this
+for modes derived from Text mode, like Mail mode."
+ ;; The initial value.
+ nil
+ ;; The indicator for the mode line.
+ " ReST"
+ ;; The minor mode bindings.
+ rst-mode-map
+ :group 'rst)
+
+;; FIXME: can I somehow install these too?
+;; :abbrev-table rst-mode-abbrev-table
+;; :syntax-table rst-mode-syntax-table
+
+\f
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Section adornment adjustment
+
+;; The following functions implement a smart automatic title sectioning feature.
+;; The idea is that with the cursor sitting on a section title, we try to get as
+;; much information from context and try to do the best thing automatically.
+;; This function can be invoked many times and/or with prefix argument to rotate
+;; between the various sectioning adornments.
+;;
+;; Some notes:
+;;
+;; - The underlining character that is used depends on context. The file is
+;; scanned to find other sections and an appropriate character is selected.
+;; If the function is invoked on a section that is complete, the character is
+;; rotated among the existing section adornments.
+;;
+;; Note that when rotating the characters, if we come to the end of the
+;; hierarchy of adornments, the variable `rst-preferred-adornments' is
+;; consulted to propose a new underline adornment, and if continued, we cycle
+;; the adornments all over again. Set this variable to nil if you want to
+;; limit the underlining character propositions to the existing adornments in
+;; the file.
+;;
+;; - An underline/overline that is not extended to the column at which it should
+;; be hanging is dubbed INCOMPLETE. For example::
+;;
+;; |Some Title
+;; |-------
+;;
+;; Examples of default invocation:
+;;
+;; |Some Title ---> |Some Title
+;; | |----------
+;;
+;; |Some Title ---> |Some Title
+;; |----- |----------
+;;
+;; | |------------
+;; | Some Title ---> | Some Title
+;; | |------------
+;;
+;; In over-and-under style, when alternating the style, a variable is
+;; available to select how much default indent to use (it can be zero). Note
+;; that if the current section adornment already has an indent, we don't
+;; adjust it to the default, we rather use the current indent that is already
+;; there for adjustment (unless we cycle, in which case we use the indent
+;; that has been found previously).
+
+(defgroup rst-adjust nil
+ "Settings for adjustment and cycling of section title adornments."
+ :group 'rst
+ :version "21.1")
+
+(define-obsolete-variable-alias
+ 'rst-preferred-decorations 'rst-preferred-adornments "rst 1.0.0")
+;; FIXME: Default must match suggestion in
+;; http://sphinx-doc.org/rest.html#sections for Python documentation.
+(defcustom rst-preferred-adornments '((?= over-and-under 1)
+ (?= simple 0)
+ (?- simple 0)
+ (?~ simple 0)
+ (?+ simple 0)
+ (?` simple 0)
+ (?# simple 0)
+ (?@ simple 0))
+ "Preferred hierarchy of section title adornments.
+A list consisting of lists of the form (CHARACTER STYLE INDENT).
+CHARACTER is the character used. STYLE is one of the symbols
+`over-and-under' or `simple'. INDENT is an integer giving the
+wanted indentation for STYLE `over-and-under'.
+
+This sequence is consulted to offer a new adornment suggestion
+when we rotate the underlines at the end of the existing
+hierarchy of characters, or when there is no existing section
+title in the file.
+
+Set this to an empty list to use only the adornment found in the
+file."
+ :group 'rst-adjust
+ :type `(repeat
+ (group :tag "Adornment specification"
+ (choice :tag "Adornment character"
+ ,@(mapcar #'(lambda (char)
+ (list 'const
+ :tag (char-to-string char) char))
+ rst-adornment-chars))
+ (radio :tag "Adornment type"
+ (const :tag "Overline and underline" over-and-under)
+ (const :tag "Underline only" simple))
+ (integer :tag "Indentation for overline and underline type"
+ :value 0))))
+(rst-testcover-defcustom)
+
+;; FIXME: Rename this to `rst-over-and-under-default-indent' and set default to
+;; 0 because the effect of 1 is probably surprising in the few cases
+;; where this is used.
+;; FIXME: A matching adornment style can be looked for in
+;; `rst-preferred-adornments' and its indentation used before using this
+;; variable.
+(defcustom rst-default-indent 1
+ "Number of characters to indent the section title.
+This is only used while toggling adornment styles when switching
+from a simple adornment style to a over-and-under adornment
+style. In addition this is used in cases where the adornments
+found in the buffer are to be used but the indentation for
+over-and-under adornments is inconsistent across the buffer."
+ :group 'rst-adjust
+ :type '(integer))
+(rst-testcover-defcustom)
+
+(defun rst-new-preferred-hdr (seen prev)
+ ;; testcover: ok.
+ "Return a new, preferred `rst-Hdr' different from all in SEEN.
+PREV is the previous `rst-Hdr' in the buffer. If given the
+search starts after this entry. Return nil if no new preferred
+`rst-Hdr' can be found."
+ ;; All preferred adornments are candidates.
+ (let ((candidates
+ (append
+ (if prev
+ ;; Start searching after the level of the previous adornment.
+ (cdr (rst-Hdr-member-ado prev (rst-Hdr-preferred-adornments))))
+ (rst-Hdr-preferred-adornments))))
+ (cl-find-if #'(lambda (cand)
+ (not (rst-Hdr-member-ado cand seen)))
+ candidates)))
+
+(defun rst-update-section (hdr)
+ ;; testcover: ok.
+ "Unconditionally update the style of the section header at point to HDR.
+If there are existing overline and/or underline from the
+existing adornment, they are removed before adding the
+requested adornment."
+ (end-of-line)
+ (let ((indent (or (rst-Hdr-indent hdr) 0))
+ (marker (point-marker))
+ new)
+
+ ;; Fixup whitespace at the beginning and end of the line.
+ (1value
+ (rst-forward-line-strict 0))
+ (delete-horizontal-space)
+ (insert (make-string indent ? ))
+ (end-of-line)
+ (delete-horizontal-space)
+ (setq new (make-string (+ (current-column) indent) (rst-Hdr-get-char hdr)))
+
+ ;; Remove previous line if it is an adornment.
+ ;; FIXME refactoring: Check whether this deletes `hdr' which *has* all the
+ ;; data necessary.
+ (when (and (rst-forward-line-looking-at -1 'ado-beg-2-1)
+ ;; Avoid removing the underline of a title right above us.
+ (not (rst-forward-line-looking-at -2 'ttl-beg-1)))
+ (rst-delete-entire-line -1))
+
+ ;; Remove following line if it is an adornment.
+ (when (rst-forward-line-looking-at +1 'ado-beg-2-1)
+ (rst-delete-entire-line +1))
+
+ ;; Insert underline.
+ (unless (rst-forward-line-strict +1)
+ ;; Normalize buffer by adding final newline.
+ (newline 1))
+ (open-line 1)
+ (insert new)
+
+ ;; Insert overline.
+ (when (rst-Hdr-is-over-and-under hdr)
+ (1value ; Underline inserted above.
+ (rst-forward-line-strict -1))
+ (open-line 1)
+ (insert new))
+
+ (goto-char marker)))
+
+(defun rst-classify-adornment (adornment end &optional accept-over-only)
+ ;; testcover: ok.
+ "Classify adornment string for section titles and transitions.
+ADORNMENT is the complete adornment string as found in the buffer
+with optional trailing whitespace. END is the point after the
+last character of ADORNMENT. Return a `rst-Ttl' or nil if no
+syntactically valid adornment is found. If ACCEPT-OVER-ONLY an
+overline with a missing underline is accepted as valid and
+returned."
+ (save-excursion
+ (save-match-data
+ (when (string-match (rst-re 'ado-beg-2-1) adornment)
+ (goto-char end)
+ (let* ((ado-ch (string-to-char (match-string 2 adornment)))
+ (ado-re (rst-re ado-ch 'adorep3-hlp)) ; RE matching the
+ ; adornment.
+ (beg-pnt (progn
+ (1value
+ (rst-forward-line-strict 0))
+ (point)))
+ (nxt-emp ; Next line nonexistent or empty
+ (not (rst-forward-line-looking-at +1 'lin-end #'not)))
+ (prv-emp ; Previous line nonexistent or empty
+ (not (rst-forward-line-looking-at -1 'lin-end #'not)))
+ txt-blw
+ (ttl-blw ; Title found below starting here.
+ (rst-forward-line-looking-at
+ +1 'ttl-beg-1
+ #'(lambda (mtcd)
+ (when mtcd
+ (setq txt-blw (match-string-no-properties 1))
+ (point)))))
+ txt-abv
+ (ttl-abv ; Title found above starting here.
+ (rst-forward-line-looking-at
+ -1 'ttl-beg-1
+ #'(lambda (mtcd)
+ (when mtcd
+ (setq txt-abv (match-string-no-properties 1))
+ (point)))))
+ (und-fnd ; Matching underline found starting here.
+ (and ttl-blw
+ (rst-forward-line-looking-at
+ +2 (list ado-re 'lin-end)
+ #'(lambda (mtcd)
+ (when mtcd
+ (point))))))
+ (ovr-fnd ; Matching overline found starting here.
+ (and ttl-abv
+ (rst-forward-line-looking-at
+ -2 (list ado-re 'lin-end)
+ #'(lambda (mtcd)
+ (when mtcd
+ (point))))))
+ (und-wng ; Wrong underline found starting here.
+ (and ttl-blw
+ (not und-fnd)
+ (rst-forward-line-looking-at
+ +2 'ado-beg-2-1
+ #'(lambda (mtcd)
+ (when mtcd
+ (point))))))
+ (ovr-wng ; Wrong overline found starting here.
+ (and ttl-abv (not ovr-fnd)
+ (rst-forward-line-looking-at
+ -2 'ado-beg-2-1
+ #'(lambda (mtcd)
+ (when (and
+ mtcd
+ ;; An adornment above may be a legal
+ ;; adornment for the line above - consider it
+ ;; a wrong overline only when it is equally
+ ;; long.
+ (equal
+ (length (match-string-no-properties 1))
+ (length adornment)))
+ (point)))))))
+ (cond
+ ((and nxt-emp prv-emp)
+ ;; A transition.
+ (rst-Ttl-from-buffer (rst-Ado-new-transition)
+ nil beg-pnt nil nil))
+ (ovr-fnd ; Prefer overline match over underline match.
+ ;; An overline with an underline.
+ (rst-Ttl-from-buffer (rst-Ado-new-over-and-under ado-ch)
+ ovr-fnd ttl-abv beg-pnt txt-abv))
+ (und-fnd
+ ;; An overline with an underline.
+ (rst-Ttl-from-buffer (rst-Ado-new-over-and-under ado-ch)
+ beg-pnt ttl-blw und-fnd txt-blw))
+ ((and ttl-abv (not ovr-wng))
+ ;; An underline.
+ (rst-Ttl-from-buffer (rst-Ado-new-simple ado-ch)
+ nil ttl-abv beg-pnt txt-abv))
+ ((and accept-over-only ttl-blw (not und-wng))
+ ;; An overline with a missing underline.
+ (rst-Ttl-from-buffer (rst-Ado-new-over-and-under ado-ch)
+ beg-pnt ttl-blw nil txt-blw))
+ (t
+ ;; Invalid adornment.
+ nil)))))))
+
+(defun rst-ttl-at-point ()
+ ;; testcover: ok.
+ "Find a section title line around point and return its characteristics.
+If the point is on an adornment line find the respective title
+line. If the point is on an empty line check previous or next
+line whether it is a suitable title line and use it if so. If
+point is on a suitable title line use it. Return a `rst-Ttl' for
+a section header or nil if no title line is found."
+ (save-excursion
+ (save-match-data
+ (1value
+ (rst-forward-line-strict 0))
+ (let* (cnd-beg ; Beginning of a title candidate.
+ cnd-txt ; Text of a title candidate.
+ (cnd-fun #'(lambda (mtcd) ; Function setting title candidate data.
+ (when mtcd
+ (setq cnd-beg (match-beginning 0))
+ (setq cnd-txt (match-string-no-properties 1))
+ t)))
+ ttl)
+ (cond
+ ((looking-at (rst-re 'ado-beg-2-1))
+ ;; Adornment found - consider it.
+ (setq ttl (rst-classify-adornment (match-string-no-properties 0)
+ (match-end 0) t)))
+ ((looking-at (rst-re 'lin-end))
+ ;; Empty line found - check surrounding lines for a title.
+ (or
+ (rst-forward-line-looking-at -1 'ttl-beg-1 cnd-fun)
+ (rst-forward-line-looking-at +1 'ttl-beg-1 cnd-fun)))
+ ((looking-at (rst-re 'ttl-beg-1))
+ ;; Title line found - check for a following underline.
+ (setq ttl (rst-forward-line-looking-at
+ 1 'ado-beg-2-1
+ #'(lambda (mtcd)
+ (when mtcd
+ (rst-classify-adornment
+ (match-string-no-properties 0) (match-end 0))))))
+ ;; Title candidate found if no valid adornment found.
+ (funcall cnd-fun (not ttl))))
+ (cond
+ ((and ttl (rst-Ttl-is-section ttl))
+ ttl)
+ (cnd-beg
+ (rst-Ttl-from-buffer nil nil cnd-beg nil cnd-txt)))))))
+
+;; The following function and variables are used to maintain information about
+;; current section adornment in a buffer local cache. Thus they can be used for
+;; font-locking and manipulation commands.
+
+(defvar-local rst-all-ttls-cache nil
+ "All section adornments in the buffer as found by `rst-all-ttls'.
+Set to t when no section adornments were found.")
+
+;; FIXME: If this variable is set to a different value font-locking of section
+;; headers is wrong.
+(defvar-local rst-hdr-hierarchy-cache nil
+ "Section hierarchy in the buffer as determined by `rst-hdr-hierarchy'.
+Set to t when no section adornments were found.
+Value depends on `rst-all-ttls-cache'.")
+
+(rst-testcover-add-1value 'rst-reset-section-caches)
+(defun rst-reset-section-caches ()
+ "Reset all section cache variables.
+Should be called by interactive functions which deal with sections."
+ (setq rst-all-ttls-cache nil
+ rst-hdr-hierarchy-cache nil))
+
+(defun rst-all-ttls-compute ()
+ ;; testcover: ok.
+ "Return a list of `rst-Ttl' for current buffer with ascending line number."
+ (save-excursion
+ (save-match-data
+ (let (ttls)
+ (goto-char (point-min))
+ ;; Iterate over all the section titles/adornments in the file.
+ (while (re-search-forward (rst-re 'ado-beg-2-1) nil t)
+ (let ((ttl (rst-classify-adornment
+ (match-string-no-properties 0) (point))))
+ (when (and ttl (rst-Ttl-is-section ttl))
+ (when (rst-Ttl-hdr ttl)
+ (push ttl ttls))
+ (goto-char (rst-Ttl-get-end ttl)))))
+ (nreverse ttls)))))
+
+(defun rst-all-ttls ()
+ "Return all the section adornments in the current buffer.
+Return a list of `rst-Ttl' with ascending line number.
+
+Uses and sets `rst-all-ttls-cache'."
+ (unless rst-all-ttls-cache
+ (setq rst-all-ttls-cache (or (rst-all-ttls-compute) t)))
+ (if (eq rst-all-ttls-cache t)
+ nil
+ (copy-sequence rst-all-ttls-cache)))
+
+(defun rst-infer-hdr-hierarchy (hdrs)
+ ;; testcover: ok.
+ "Build a hierarchy from HDRS.
+HDRS reflects the order in which the headers appear in the
+buffer. Return a `rst-Hdr' list representing the hierarchy of
+headers in the buffer. Indentation is unified."
+ (let (ado2indents) ; Asscociates `rst-Ado' with the set of indents seen for
+ ; it.
+ (dolist (hdr hdrs)
+ (let* ((ado (rst-Hdr-ado hdr))
+ (indent (rst-Hdr-indent hdr))
+ (found (assoc ado ado2indents)))
+ (if found
+ (setcdr found (cl-adjoin indent (cdr found)))
+ (push (list ado indent) ado2indents))))
+ (mapcar (cl-function
+ (lambda ((ado consistent &rest inconsistent))
+ (rst-Hdr-new ado (if inconsistent
+ rst-default-indent
+ consistent))))
+ (nreverse ado2indents))))
+
+(defun rst-hdr-hierarchy (&optional ignore-position)
+ ;; testcover: ok.
+ "Return the hierarchy of section titles in the file as a `rst-Hdr' list.
+Each returned element may be used directly to create a section
+adornment on that level. If IGNORE-POSITION a title containing
+this position is not taken into account when building the
+hierarchy unless it appears again elsewhere. This catches cases
+where the current title is edited and may not be final regarding
+its level.
+
+Uses and sets `rst-hdr-hierarchy-cache' unless IGNORE-POSITION is
+given."
+ (let* ((all-ttls (rst-all-ttls))
+ (ignore-ttl
+ (if ignore-position
+ (cl-find-if
+ #'(lambda (ttl)
+ (equal (rst-Ttl-contains ttl ignore-position) 0))
+ all-ttls)))
+ (really-ignore
+ (if ignore-ttl
+ (<= (cl-count-if
+ #'(lambda (ttl)
+ (rst-Ado-equal (rst-Ttl-ado ignore-ttl)
+ (rst-Ttl-ado ttl)))
+ all-ttls)
+ 1)))
+ (real-ttls (delq (if really-ignore ignore-ttl) all-ttls)))
+ (copy-sequence ; Protect cache.
+ (if (and (not ignore-position) rst-hdr-hierarchy-cache)
+ (if (eq rst-hdr-hierarchy-cache t)
+ nil
+ rst-hdr-hierarchy-cache)
+ (let ((r (rst-infer-hdr-hierarchy (mapcar #'rst-Ttl-hdr real-ttls))))
+ (setq rst-hdr-hierarchy-cache
+ (if ignore-position
+ ;; Clear cache reflecting that a possible update is not
+ ;; reflected.
+ nil
+ (or r t)))
+ r)))))
+
+(defun rst-all-ttls-with-level ()
+ ;; testcover: ok.
+ "Return the section adornments with levels set according to hierarchy.
+Return a list of (`rst-Ttl' . LEVEL) with ascending line number."
+ (let ((hier (rst-Hdr-ado-map (rst-hdr-hierarchy))))
+ (mapcar
+ #'(lambda (ttl)
+ (cons ttl (rst-Ado-position (rst-Ttl-ado ttl) hier)))
+ (rst-all-ttls))))
+
+(defun rst-get-previous-hdr ()
+ "Return the `rst-Hdr' before point or nil if none."
+ (let ((prev (cl-find-if #'(lambda (ttl)
+ (< (rst-Ttl-contains ttl (point)) 0))
+ (rst-all-ttls)
+ :from-end t)))
+ (and prev (rst-Ttl-hdr prev))))
+
+(defun rst-adornment-complete-p (ado indent)
+ ;; testcover: ok.
+ "Return t if the adornment ADO around point is complete using INDENT.
+The adornment is complete if it is a completely correct
+reStructuredText adornment for the title line at point. This
+includes indentation and correct length of adornment lines."
+ ;; Note: we assume that the detection of the overline as being the underline
+ ;; of a preceding title has already been detected, and has been eliminated
+ ;; from the adornment that is given to us.
+ (let ((exps (list "^" (rst-Ado-char ado)
+ (format "\\{%d\\}"
+ (+ (save-excursion
+ ;; Determine last column of title.
+ (end-of-line)
+ (current-column))
+ indent)) "$")))
+ (and (rst-forward-line-looking-at +1 exps)
+ (or (rst-Ado-is-simple ado)
+ (rst-forward-line-looking-at -1 exps))
+ t))) ; Normalize return value.
+
+(defun rst-next-hdr (hdr hier prev down)
+ ;; testcover: ok.
+ "Return the next best `rst-Hdr' upward from HDR.
+Consider existing hierarchy HIER and preferred headers. PREV may
+be a previous `rst-Hdr' which may be taken into account. If DOWN
+return the next best `rst-Hdr' downward instead. Return nil in
+HIER is nil."
+ (let* ((normalized-hier (if down
+ hier
+ (reverse hier)))
+ (fnd (rst-Hdr-member-ado hdr normalized-hier))
+ (prev-fnd (and prev (rst-Hdr-member-ado prev normalized-hier))))
+ (or
+ ;; Next entry in existing hierarchy if it exists.
+ (cadr fnd)
+ (if fnd
+ ;; If current header is found try introducing a new one from preferred
+ ;; hierarchy.
+ (rst-new-preferred-hdr hier prev)
+ ;; If not found try using previous header.
+ (if down
+ (cadr prev-fnd)
+ (car prev-fnd)))
+ ;; All failed - rotate by using first from normalized existing hierarchy.
+ (car normalized-hier))))
+
+;; FIXME: A line "``/`` full" is not accepted as a section title.
+(defun rst-adjust (pfxarg)
+ ;; testcover: ok.
+ "Auto-adjust the adornment around point.
+Adjust/rotate the section adornment for the section title around
+point or promote/demote the adornments inside the region,
+depending on whether the region is active. This function is meant
+to be invoked possibly multiple times, and can vary its behavior
+with a positive PFXARG (toggle style), or with a negative
+PFXARG (alternate behavior).
+
+This function is a bit of a swiss knife. It is meant to adjust
+the adornments of a section title in reStructuredText. It tries
+to deal with all the possible cases gracefully and to do \"the
+right thing\" in all cases.
+
+See the documentations of `rst-adjust-section' and
+`rst-adjust-region' for full details.
+
+The method can take either (but not both) of
+
+a. a (non-negative) prefix argument, which means to toggle the
+ adornment style. Invoke with a prefix argument for example;
+
+b. a negative numerical argument, which generally inverts the
+ direction of search in the file or hierarchy. Invoke with C--
+ prefix for example."
+ (interactive "P")
+ (let* ((origpt (point-marker))
+ (reverse-direction (and pfxarg (< (prefix-numeric-value pfxarg) 0)))
+ (toggle-style (and pfxarg (not reverse-direction))))
+ (if (use-region-p)
+ (rst-adjust-region (and pfxarg t))
+ (let ((msg (rst-adjust-section toggle-style reverse-direction)))
+ (when msg
+ (apply #'message msg))))
+ (run-hooks 'rst-adjust-hook)
+ (rst-reset-section-caches)
+ (set-marker
+ (goto-char origpt) nil)))
+
+(defcustom rst-adjust-hook nil
+ "Hooks to be run after running `rst-adjust'."
+ :group 'rst-adjust
+ :type '(hook)
+ :package-version '(rst . "1.1.0"))
+(rst-testcover-defcustom)
+
+(defcustom rst-new-adornment-down nil
+ "Controls level of new adornment for section headers."
+ :group 'rst-adjust
+ :type '(choice
+ (const :tag "Same level as previous one" nil)
+ (const :tag "One level down relative to the previous one" t))
+ :package-version '(rst . "1.1.0"))
+(rst-testcover-defcustom)
+
+(defun rst-adjust-adornment (pfxarg)
+ "Call `rst-adjust-section' interactively.
+Keep this for compatibility for older bindings (are there any?).
+Argument PFXARG has the same meaning as for `rst-adjust'."
+ (interactive "P")
+
+ (let* ((reverse-direction (and pfxarg (< (prefix-numeric-value pfxarg) 0)))
+ (toggle-style (and pfxarg (not reverse-direction))))
+ (rst-adjust-section toggle-style reverse-direction)))
+
+(defun rst-adjust-new-hdr (toggle-style reverse ttl)
+ ;; testcover: ok.
+ "Return a new `rst-Hdr' for `rst-adjust-section' related to TTL.
+TOGGLE-STYLE and REVERSE are from
+`rst-adjust-section'. TOGGLE-STYLE may be consumed and thus is
+returned.
+
+Return a list (HDR TOGGLE-STYLE MSG...). HDR is the result or
+nil. TOGGLE-STYLE is the new TOGGLE-STYLE to use in the
+caller. MSG is a list which is non-empty in case HDR is nil
+giving an argument list for `message'."
+ (save-excursion
+ (goto-char (rst-Ttl-get-title-beginning ttl))
+ (let ((indent (rst-Ttl-indent ttl))
+ (ado (rst-Ttl-ado ttl))
+ (prev (rst-get-previous-hdr))
+ hdr-msg)
+ (setq
+ hdr-msg
+ (cond
+ ((rst-Ttl-is-candidate ttl)
+ ;; Case 1: No adornment at all.
+ (let ((hier (rst-hdr-hierarchy)))
+ (if prev
+ ;; Previous header exists - use it.
+ (cond
+ ;; Customization and parameters require that the previous level
+ ;; is used - use it as is.
+ ((or (and rst-new-adornment-down reverse)
+ (and (not rst-new-adornment-down) (not reverse)))
+ prev)
+ ;; Advance one level down.
+ ((rst-next-hdr prev hier prev t))
+ ("Neither hierarchy nor preferences can suggest a deeper header"))
+ ;; First header in the buffer - use the first adornment from
+ ;; preferences or hierarchy.
+ (let ((p (car (rst-Hdr-preferred-adornments)))
+ (h (car hier)))
+ (cond
+ ((if reverse
+ ;; Prefer hierarchy for downwards
+ (or h p)
+ ;; Prefer preferences for upwards
+ (or p h)))
+ ("No preferences to suggest a top level from"))))))
+ ((not (rst-adornment-complete-p ado indent))
+ ;; Case 2: Incomplete adornment.
+ ;; Use lax since indentation might not match suggestion.
+ (rst-Hdr-new-lax ado indent))
+ ;; Case 3: Complete adornment exists from here on.
+ (toggle-style
+ ;; Simply switch the style of the current adornment.
+ (setq toggle-style nil) ; Remember toggling has been done.
+ (rst-Hdr-new-invert ado rst-default-indent))
+ (t
+ ;; Rotate, ignoring a sole adornment around the current line.
+ (let ((hier (rst-hdr-hierarchy (point))))
+ (cond
+ ;; Next header can be determined from hierarchy or preferences.
+ ((rst-next-hdr
+ ;; Use lax since indentation might not match suggestion.
+ (rst-Hdr-new-lax ado indent) hier prev reverse))
+ ;; No next header found.
+ ("No preferences or hierarchy to suggest another level from"))))))
+ (if (stringp hdr-msg)
+ (list nil toggle-style hdr-msg)
+ (list hdr-msg toggle-style)))))
+
+(defun rst-adjust-section (toggle-style reverse)
+ ;; testcover: ok.
+ "Adjust/rotate the section adornment for the section title around point.
+The action this function takes depends on context around the
+point, and it is meant to be invoked possibly more than once to
+rotate among the various possibilities. Basically, this function
+deals with:
+
+- adding an adornment if the title does not have one;
+
+- adjusting the length of the underline characters to fit a
+ modified title;
+
+- rotating the adornment in the set of already existing
+ sectioning adornments used in the file;
+
+- switching between simple and over-and-under styles by giving
+ TOGGLE-STYLE.
+
+Return nil if the function did something. If the function were
+not able to do something return an argument list for `message' to
+inform the user about what failed.
+
+The following is a detailed description but you should normally
+not have to read it.
+
+Before applying the adornment change, the cursor is placed on the
+closest line that could contain a section title if such is found
+around the cursor. Then the following cases are distinguished.
+
+* Case 1: No Adornment
+
+ If the current line has no adornment around it,
+
+ - search for a previous adornment, and apply this adornment (unless
+ `rst-new-adornment-down') or one level lower (otherwise) to the current
+ line. If there is no defined level below this previous adornment, we
+ suggest the most appropriate of the `rst-preferred-adornments'.
+
+ If REVERSE is true, we simply use the previous adornment found
+ directly.
+
+ - if there is no adornment found in the given direction, we use the first of
+ `rst-preferred-adornments'.
+
+ TOGGLE-STYLE forces a toggle of the prescribed adornment style.
+
+* Case 2: Incomplete Adornment
+
+ If the current line does have an existing adornment, but the adornment is
+ incomplete, that is, the underline/overline does not extend to exactly the
+ end of the title line (it is either too short or too long), we simply extend
+ the length of the underlines/overlines to fit exactly the section title.
+
+ If TOGGLE-STYLE we toggle the style of the adornment as well.
+
+ REVERSE has no effect in this case.
+
+* Case 3: Complete Existing Adornment
+
+ If the adornment is complete (i.e. the underline (overline) length is already
+ adjusted to the end of the title line), we rotate the current title's
+ adornment according to the adornment hierarchy found in the buffer. This is
+ meant to be used potentially multiple times, until the desired adornment is
+ found around the title.
+
+ If we hit the boundary of the hierarchy, exactly one choice from the list of
+ preferred adornments is suggested/chosen, the first of those adornment that
+ has not been seen in the buffer yet, and the next invocation rolls over to
+ the other end of the hierarchy (i.e. it cycles).
+
+ If REVERSE is we go up in the hierarchy. Otherwise we go down.
+
+ However, if TOGGLE-STYLE, we do not rotate the adornment, but instead simply
+ toggle the style of the current adornment."
+ (rst-reset-section-caches)
+ (let ((ttl (rst-ttl-at-point)))
+ (if (not ttl)
+ '("No section header or candidate at point")
+ (cl-destructuring-bind
+ (hdr toggle-style &rest msg
+ &aux
+ (indent (rst-Ttl-indent ttl))
+ (moved (- (line-number-at-pos (rst-Ttl-get-title-beginning ttl))
+ (line-number-at-pos))))
+ (rst-adjust-new-hdr toggle-style reverse ttl)
+ (if msg
+ msg
+ (when toggle-style
+ (setq hdr (rst-Hdr-new-invert (rst-Hdr-ado hdr) indent)))
+ ;; Override indent with present indent if there is some.
+ (when (> indent 0)
+ ;; Use lax since existing indent may not be valid for new style.
+ (setq hdr (rst-Hdr-new-lax (rst-Hdr-ado hdr) indent)))
+ (goto-char (rst-Ttl-get-title-beginning ttl))
+ (rst-update-section hdr)
+ ;; Correct the position of the cursor to more accurately reflect
+ ;; where it was located when the function was invoked.
+ (unless (zerop moved)
+ (1value ; No lines may be left to move.
+ (rst-forward-line-strict (- moved)))
+ (end-of-line))
+ nil)))))
+
+;; Maintain an alias for compatibility.
+(defalias 'rst-adjust-section-title 'rst-adjust)
+
+(defun rst-adjust-region (demote)
+ ;; testcover: ok.
+ "Promote the section titles within the region.
+With argument DEMOTE or a prefix argument, demote the section
+titles instead. The algorithm used at the boundaries of the
+hierarchy is similar to that used by `rst-adjust-section'."
+ (interactive "P")
+ (rst-reset-section-caches)
+ (let* ((beg (region-beginning))
+ (end (region-end))
+ (ttls-reg (cl-remove-if-not
+ #'(lambda (ttl)
+ (and
+ (>= (rst-Ttl-contains ttl beg) 0)
+ (< (rst-Ttl-contains ttl end) 0)))
+ (rst-all-ttls))))
+ (save-excursion
+ ;; Apply modifications.
+ (rst-destructuring-dolist
+ ((marker &rest hdr
+ &aux (hier (rst-hdr-hierarchy)))
+ (mapcar #'(lambda (ttl)
+ (cons (copy-marker (rst-Ttl-get-title-beginning ttl))
+ (rst-Ttl-hdr ttl)))
+ ttls-reg))
+ (set-marker
+ (goto-char marker) nil)
+ ;; `rst-next-hdr' cannot return nil because we apply to a section
+ ;; header so there is some hierarchy.
+ (rst-update-section (rst-next-hdr hdr hier nil demote)))
+ (setq deactivate-mark nil))))
+
+(defun rst-display-hdr-hierarchy ()
+ ;; testcover: ok.
+ "Display the current file's section title adornments hierarchy.
+Hierarchy is displayed in a temporary buffer."
+ (interactive)
+ (rst-reset-section-caches)
+ (let ((hdrs (rst-hdr-hierarchy))
+ (level 1))
+ (with-output-to-temp-buffer "*rest section hierarchy*"
+ (with-current-buffer standard-output
+ (dolist (hdr hdrs)
+ (insert (format "\nSection Level %d" level))
+ (rst-update-section hdr)
+ (goto-char (point-max))
+ (insert "\n")
+ (cl-incf level))))))
+
+;; Maintain an alias for backward compatibility.
+(defalias 'rst-display-adornments-hierarchy 'rst-display-hdr-hierarchy)
+
+;; FIXME: Should accept an argument giving the hierarchy level to start with
+;; instead of the top of the hierarchy.
+(defun rst-straighten-sections ()
+ ;; testcover: ok.
+ "Redo the adornments of all section titles in the current buffer.
+This is done using the preferred set of adornments. This can be
+used, for example, when using somebody else's copy of a document,
+in order to adapt it to our preferred style."
+ (interactive)
+ (rst-reset-section-caches)
+ (save-excursion
+ (rst-destructuring-dolist
+ ((marker &rest level)
+ (mapcar
+ (cl-function
+ (lambda ((ttl &rest level))
+ ;; Use markers so edits don't disturb the position.
+ (cons (copy-marker (rst-Ttl-get-title-beginning ttl)) level)))
+ (rst-all-ttls-with-level)))
+ (set-marker
+ (goto-char marker) nil)
+ (rst-update-section (nth level (rst-Hdr-preferred-adornments))))))
+
+;; Maintain an alias for compatibility.
+(defalias 'rst-straighten-adornments 'rst-straighten-sections)
+
+\f
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Insert list items
+
+;; Borrowed from a2r.el (version 1.3), by Lawrence Mitchell <wence@gmx.li>. I
+;; needed to make some tiny changes to the functions, so I put it here.
+;; -- Wei-Wei Guo
+
+(defconst rst-arabic-to-roman
+ '((1000 . "M") (900 . "CM") (500 . "D") (400 . "CD")
+ (100 . "C") (90 . "XC") (50 . "L") (40 . "XL")
+ (10 . "X") (9 . "IX") (5 . "V") (4 . "IV")
+ (1 . "I"))
+ "List of maps between Arabic numbers and their Roman numeral equivalents.")
+
+(defun rst-arabic-to-roman (num)
+ ;; testcover: ok.
+ "Convert Arabic number NUM to its Roman numeral representation.
+
+Obviously, NUM must be greater than zero. Don't blame me, blame the
+Romans, I mean \"what have the Romans ever _done_ for /us/?\" (with
+apologies to Monty Python)."
+ (cl-check-type num (integer 1 *))
+ (let ((map rst-arabic-to-roman)
+ (r ""))
+ (while (and map (> num 0))
+ (cl-destructuring-bind ((val &rest sym) &rest next) map
+ (if (>= num val)
+ (setq r (concat r sym)
+ num (- num val))
+ (setq map next))))
+ r))
+
+(defun rst-roman-to-arabic (string)
+ ;; testcover: ok.
+ "Convert STRING of Roman numerals to an Arabic number.
+If STRING contains a letter which isn't a valid Roman numeral,
+the rest of the string from that point onwards is ignored.
+Hence:
+MMD == 2500
+and
+MMDFLXXVI == 2500."
+ (cl-check-type string string)
+ (cl-check-type string (satisfies (lambda (s)
+ (not (equal s ""))))
+ "Roman number may not be an empty string.")
+ (let ((res 0)
+ (map rst-arabic-to-roman))
+ (save-match-data
+ (while map
+ (cl-destructuring-bind ((val &rest sym) &rest next) map
+ (if (string-match (concat "^" sym) string)
+ (setq res (+ res val)
+ string (replace-match "" nil t string))
+ (setq map next))))
+ (cl-check-type string (satisfies (lambda (s)
+ (equal s "")))
+ "Invalid characters in roman number")
+ res)))
+
+;; End of borrow.
+
+;; FIXME: All the following code should not consider single lines as items but
+;; paragraphs as reST does.
+
+(defun rst-insert-list-new-tag (tag)
+ ;; testcover: ok.
+ "Insert first item of a new list tagged with TAG.
+
+Adding a new list might consider three situations:
+
+ (a) Current line is a blank line.
+ (b) Previous line is a blank line.
+ (c) Following line is a blank line.
+
+When (a) and (b), just add the new list at current line.
+
+when (a) and not (b), a blank line is added before adding the new list.
+
+When not (a), first forward point to the end of the line, and add two
+blank lines, then add the new list.
+
+Other situations are just ignored and left to users themselves."
+ ;; FIXME: Following line is not considered at all.
+ (let ((pfx-nls
+ ;; FIXME: Doesn't work properly for white-space line. See
+ ;; `rst-insert-list-new-BUGS'.
+ (if (rst-forward-line-looking-at 0 'lin-end)
+ (if (not (rst-forward-line-looking-at -1 'lin-end #'not))
+ 0
+ 1)
+ 2)))
+ (end-of-line)
+ ;; FIXME: The indentation is not fixed to a single space by the syntax. May
+ ;; be this should be configurable or rather taken from the context.
+ (insert (make-string pfx-nls ?\n) tag " ")))
+
+(defconst rst-initial-items
+ (append (mapcar #'char-to-string rst-bullets)
+ (let (vals)
+ (dolist (fmt '("%s." "(%s)" "%s)"))
+ (dolist (c '("#" "1" "a" "A" "I" "i"))
+ (push (format fmt c) vals)))
+ (nreverse vals)))
+ "List of initial items. It's a collection of bullets and enumerations.")
+
+(defun rst-insert-list-new-item ()
+ ;; testcover: ok.
+ "Insert a new list item.
+
+User is asked to select the item style first, for example (a), i), +.
+Use TAB for completion and choices.
+
+If user selects bullets or #, it's just added with position arranged by
+`rst-insert-list-new-tag'.
+
+If user selects enumerations, a further prompt is given. User need to
+input a starting item, for example 'e' for 'A)' style. The position is
+also arranged by `rst-insert-list-new-tag'."
+ (let* ((itemstyle (completing-read
+ "Select preferred item style [#.]: "
+ rst-initial-items nil t nil nil "#."))
+ (cnt (if (string-match (rst-re 'cntexp-tag) itemstyle)
+ (match-string 0 itemstyle)))
+ (no
+ (save-match-data
+ (cond
+ ((equal cnt "a")
+ (let ((itemno (read-string "Give starting value [a]: "
+ nil nil "a")))
+ (downcase (substring itemno 0 1))))
+ ((equal cnt "A")
+ (let ((itemno (read-string "Give starting value [A]: "
+ nil nil "A")))
+ (upcase (substring itemno 0 1))))
+ ((equal cnt "I")
+ (let ((itemno (read-number "Give starting value [1]: " 1)))
+ (rst-arabic-to-roman itemno)))
+ ((equal cnt "i")
+ (let ((itemno (read-number "Give starting value [1]: " 1)))
+ (downcase (rst-arabic-to-roman itemno))))
+ ((equal cnt "1")
+ (let ((itemno (read-number "Give starting value [1]: " 1)))
+ (number-to-string itemno)))))))
+ (if no
+ (setq itemstyle (replace-match no t t itemstyle)))
+ (rst-insert-list-new-tag itemstyle)))
+
+(defcustom rst-preferred-bullets
+ '(?* ?- ?+)
+ "List of favorite bullets."
+ :group 'rst
+ :type `(repeat
+ (choice ,@(mapcar #'(lambda (char)
+ (list 'const
+ :tag (char-to-string char) char))
+ rst-bullets)))
+ :package-version '(rst . "1.1.0"))
+(rst-testcover-defcustom)
+
+(defun rst-insert-list-continue (ind tag tab prefer-roman)
+ ;; testcover: ok.
+ "Insert a new list tag after the current line according to style.
+Style is defined by indentaton IND, TAG and suffix TAB. If
+PREFER-ROMAN roman numbering is preferred over using letters."
+ (end-of-line)
+ (insert
+ ;; FIXME: Separating lines must be possible.
+ "\n"
+ ind
+ (save-match-data
+ (if (not (string-match (rst-re 'cntexp-tag) tag))
+ tag
+ (let ((pfx (substring tag 0 (match-beginning 0)))
+ (cnt (match-string 0 tag))
+ (sfx (substring tag (match-end 0))))
+ (concat
+ pfx
+ (cond
+ ((string-match (rst-re 'num-tag) cnt)
+ (number-to-string (1+ (string-to-number (match-string 0 cnt)))))
+ ((and
+ (string-match (rst-re 'rom-tag) cnt)
+ (save-match-data
+ (if (string-match (rst-re 'ltr-tag) cnt) ; Also a letter tag.
+ (save-excursion
+ ;; FIXME: Assumes one line list items without separating
+ ;; empty lines.
+ ;; Use of `rst-forward-line-looking-at' is very difficult
+ ;; here so don't do it.
+ (if (and (rst-forward-line-strict -1)
+ (looking-at (rst-re 'enmexp-beg)))
+ (string-match
+ (rst-re 'rom-tag)
+ (match-string 0)) ; Previous was a roman tag.
+ prefer-roman)) ; Don't know - use flag.
+ t))) ; Not a letter tag.
+ (let* ((old (match-string 0 cnt))
+ (new (rst-arabic-to-roman
+ (1+ (rst-roman-to-arabic (upcase old))))))
+ (if (equal old (upcase old))
+ (upcase new)
+ (downcase new))))
+ ((string-match (rst-re 'ltr-tag) cnt)
+ (char-to-string (1+ (string-to-char (match-string 0 cnt))))))
+ sfx))))
+ tab))
+
+;; FIXME: At least the continuation may be folded into
+;; `newline-and-indent`. However, this may not be wanted by everyone so
+;; it should be possible to switch this off.
+(defun rst-insert-list (&optional prefer-roman)
+ ;; testcover: ok.
+ "Insert a list item at the current point.
+
+The command can insert a new list or a continuing list. When it is called at a
+non-list line, it will promote to insert new list. When it is called at a list
+line, it will insert a list with the same list style.
+
+1. When inserting a new list:
+
+User is asked to select the item style first, for example (a), i), +. Use TAB
+for completion and choices.
+
+ (a) If user selects bullets or #, it's just added.
+ (b) If user selects enumerations, a further prompt is given. User needs to
+ input a starting item, for example `e' for `A)' style.
+
+The position of the new list is arranged according to whether or not the
+current line and the previous line are blank lines.
+
+2. When continuing a list, one thing needs to be noticed:
+
+List style alphabetical list, such as `a.', and roman numerical list, such as
+`i.', have some overlapping items, for example `v.' The function can deal with
+the problem elegantly in most situations. But when those overlapped list are
+preceded by a blank line, it is hard to determine which type to use
+automatically. The function uses alphabetical list by default. If you want
+roman numerical list, just use a prefix to set PREFER-ROMAN."
+ (interactive "P")
+ (save-match-data
+ (1value
+ (rst-forward-line-strict 0))
+ ;; FIXME: Finds only tags in single line items. Multi-line items should be
+ ;; considered as well.
+ ;; Using `rst-forward-line-looking-at' is more complicated so don't do it.
+ (if (looking-at (rst-re 'itmany-beg-1))
+ (rst-insert-list-continue
+ (buffer-substring-no-properties
+ (match-beginning 0) (match-beginning 1))
+ (match-string 1)
+ (buffer-substring-no-properties (match-end 1) (match-end 0))
+ prefer-roman)
+ (rst-insert-list-new-item))))
+
+;; FIXME: This is wrong because it misses prefixed lines without intervening
+;; new line. See `rst-straighten-bullets-region-BUGS' and
+;; `rst-find-begs-BUGS'.
+(defun rst-find-begs (beg end rst-re-beg)
+ ;; testcover: ok.
+ "Return the positions of begs in region BEG to END.
+RST-RE-BEG is a `rst-re' argument and matched at the beginning of
+a line. Return a list of (POINT . COLUMN) where POINT gives the
+point after indentaton and COLUMN gives its column. The list is
+ordererd by POINT."
+ (let (r)
+ (save-match-data
+ (save-excursion
+ ;; FIXME refactoring: Consider making this construct a macro looping
+ ;; over the lines.
+ (goto-char beg)
+ (1value
+ (rst-forward-line-strict 0))
+ (while (< (point) end)
+ (let ((clm (current-indentation)))
+ ;; FIXME refactoring: Consider using `rst-forward-line-looking-at'.
+ (when (and
+ (looking-at (rst-re rst-re-beg)) ; Start found
+ (not (rst-forward-line-looking-at
+ -1 'lin-end
+ #'(lambda (mtcd) ; Previous line exists and is...
+ (and
+ (not mtcd) ; non-empty,
+ (<= (current-indentation) clm) ; less indented
+ (not (and (= (current-indentation) clm)
+ ; not a beg at same level.
+ (looking-at (rst-re rst-re-beg)))))))))
+ (back-to-indentation)
+ (push (cons (point) clm) r)))
+ (1value ; At least one line is moved in this loop.
+ (rst-forward-line-strict 1 end)))))
+ (nreverse r)))
+
+(defun rst-straighten-bullets-region (beg end)
+ ;; testcover: ok.
+ "Make all the bulleted list items in the region from BEG to END consistent.
+Use this after you have merged multiple bulleted lists to make
+them use the preferred bullet characters given by
+`rst-preferred-bullets' for each level. If bullets are found on
+levels beyond the `rst-preferred-bullets' list, they are not
+modified."
+ (interactive "r")
+ (save-excursion
+ (let (clm2pnts) ; Map a column to a list of points at this column.
+ (rst-destructuring-dolist
+ ((point &rest column
+ &aux (found (assoc column clm2pnts)))
+ (rst-find-begs beg end 'bul-beg))
+ (if found
+ ;;; (push point (cdr found)) ; FIXME: Doesn't work with `testcover'.
+ (setcdr found (cons point (cdr found))) ; Synonym.
+ (push (list column point) clm2pnts)))
+ (rst-destructuring-dolist
+ ((bullet _clm &rest pnts)
+ ;; Zip preferred bullets and sorted columns associating a bullet
+ ;; with a column and all the points this column is found.
+ (cl-mapcar #'(lambda (bullet clm2pnt)
+ (cons bullet clm2pnt))
+ rst-preferred-bullets
+ (sort clm2pnts #'car-less-than-car)))
+ ;; Replace the bullets by the preferred ones.
+ (dolist (pnt pnts)
+ (goto-char pnt)
+ ;; FIXME: Assumes bullet to replace is a single char.
+ (delete-char 1)
+ (insert bullet))))))
+
+\f
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Table of contents
+
+(defun rst-all-stn ()
+ ;; testcover: ok.
+ "Return the hierarchical tree of sections as a top level `rst-Stn'.
+Return value satisfies `rst-Stn-is-top' or is nil for no
+sections."
+ (cdr (rst-remaining-stn (rst-all-ttls-with-level) -1)))
+
+(defun rst-remaining-stn (unprocessed expected)
+ ;; testcover: ok.
+ "Process the first entry of UNPROCESSED expected to be on level EXPECTED.
+UNPROCESSED is the remaining list of (`rst-Ttl' . LEVEL) entries.
+Return (REMAINING . STN) for the first entry of UNPROCESSED.
+REMAINING is the list of still unprocessed entries. STN is a
+`rst-Stn' or nil if UNPROCESSED is empty."
+ (if (not unprocessed)
+ (1value
+ (cons nil nil))
+ (cl-destructuring-bind
+ ((ttl &rest level) &rest next
+ &aux fnd children)
+ unprocessed
+ (when (= level expected)
+ ;; Consume the current entry and create the current node with it.
+ (setq fnd ttl)
+ (setq unprocessed next))
+ ;; Build the child nodes as long as they have deeper level.
+ (while (and unprocessed (> (cdar unprocessed) expected))
+ (cl-destructuring-bind (remaining &rest stn)
+ (rst-remaining-stn unprocessed (1+ expected))
+ (when stn
+ (push stn children))
+ (setq unprocessed remaining)))
+ (cons unprocessed
+ (when (or fnd children)
+ (rst-Stn-new fnd expected (nreverse children)))))))
+
+(defun rst-stn-containing-point (stn &optional point)
+ ;; testcover: ok.
+ "Return `rst-Stn' in STN before POINT or nil if in no section.
+POINT defaults to the current point. STN may be nil for no
+section headers at all."
+ (when stn
+ (setq point (or point (point)))
+ (when (>= point (rst-Stn-get-title-beginning stn))
+ ;; Point may be in this section or a child.
+ (let ((in-child (cl-find-if
+ #'(lambda (child)
+ (>= point (rst-Stn-get-title-beginning child)))
+ (rst-Stn-children stn)
+ :from-end t)))
+ (if in-child
+ (rst-stn-containing-point in-child point)
+ stn)))))
+
+(defgroup rst-toc nil
+ "Settings for reStructuredText table of contents."
+ :group 'rst
+ :version "21.1")
+
+(defcustom rst-toc-indent 2
+ "Indentation for table-of-contents display.
+Also used for formatting insertion, when numbering is disabled."
+ :type 'integer
+ :group 'rst-toc)
+(rst-testcover-defcustom)
+
+(defcustom rst-toc-insert-style 'fixed
+ "Insertion style for table-of-contents.
+Set this to one of the following values to determine numbering and
+indentation style:
+- `plain': no numbering (fixed indentation)
+- `fixed': numbering, but fixed indentation
+- `aligned': numbering, titles aligned under each other
+- `listed': titles as list items"
+ :type '(choice (const plain)
+ (const fixed)
+ (const aligned)
+ (const listed))
+ :group 'rst-toc)
+(rst-testcover-defcustom)
+
+(defcustom rst-toc-insert-number-separator " "
+ "Separator that goes between the TOC number and the title."
+ :type 'string
+ :group 'rst-toc)
+(rst-testcover-defcustom)
+
+(defcustom rst-toc-insert-max-level nil
+ "If non-nil, maximum depth of the inserted TOC."
+ :type '(choice (const nil) integer)
+ :group 'rst-toc)
+(rst-testcover-defcustom)
+
+(defun rst-toc-insert (&optional max-level)
+ ;; testcover: ok.
+ "Insert the table of contents of the current section at the current column.
+By default the top level is ignored if there is only one, because
+we assume that the document will have a single title. A numeric
+prefix argument MAX-LEVEL overrides `rst-toc-insert-max-level'.
+Text in the line beyond column is deleted."
+ (interactive "P")
+ (rst-reset-section-caches)
+ (let ((pt-stn (rst-stn-containing-point (rst-all-stn))))
+ (when pt-stn
+ (let ((max
+ (if (and (integerp max-level)
+ (> (prefix-numeric-value max-level) 0))
+ (prefix-numeric-value max-level)
+ rst-toc-insert-max-level))
+ (ind (current-column))
+ (buf (current-buffer))
+ (tabs indent-tabs-mode) ; Copy buffer local value.
+ txt)
+ (setq txt
+ ;; Render to temporary buffer so markers are created correctly.
+ (with-temp-buffer
+ (rst-toc-insert-tree pt-stn buf rst-toc-insert-style max
+ rst-toc-link-keymap nil)
+ (goto-char (point-min))
+ (when (rst-forward-line-strict 1)
+ ;; There are lines to indent.
+ (let ((indent-tabs-mode tabs))
+ (indent-rigidly (point) (point-max) ind)))
+ (buffer-string)))
+ (unless (zerop (length txt))
+ ;; Delete possible trailing text.
+ (delete-region (point) (line-beginning-position 2))
+ (insert txt)
+ (backward-char 1))))))
+
+(defun rst-toc-insert-link (pfx stn buf keymap)
+ ;; testcover: ok.
+ "Insert text of STN in BUF as a linked section reference at point.
+If KEYMAP use this as keymap property. PFX is inserted before text."
+ (let ((beg (point)))
+ (insert pfx)
+ (insert (rst-Stn-get-text stn))
+ (put-text-property beg (point) 'mouse-face 'highlight)
+ (insert "\n")
+ (put-text-property
+ beg (point) 'rst-toc-target
+ (set-marker (make-marker) (rst-Stn-get-title-beginning stn) buf))
+ (when keymap
+ (put-text-property beg (point) 'keymap keymap))))
+
+(defun rst-toc-get-link (link-buf link-pnt)
+ ;; testcover: ok.
+ "Return the link from text property at LINK-PNT in LINK-BUF."
+ (let ((mrkr (get-text-property link-pnt 'rst-toc-target link-buf)))
+ (unless mrkr
+ (error "No section on this line"))
+ (unless (buffer-live-p (marker-buffer mrkr))
+ (error "Buffer for this section was killed"))
+ mrkr))
+
+(defconst rst-toc-link-keymap
+ (let ((map (make-sparse-keymap)))
+ (define-key map [mouse-1] 'rst-toc-mouse-follow-link)
+ map)
+ "Keymap used for links in TOC.")
+
+(defun rst-toc-insert-tree (stn buf style depth keymap tgt-stn)
+ ;; testcover: ok.
+ "Insert table of contents of tree below top node STN in buffer BUF.
+STYLE is the style to use and must be one of the symbols allowed
+for `rst-toc-insert-style'. DEPTH is the maximum relative depth
+from STN to insert or nil for no maximum depth. See
+`rst-toc-insert-link' for KEYMAP. Return beginning of title line
+if TGT-STN is rendered or nil if not rendered or TGT-STN is nil.
+Just return nil if STN is nil."
+ (when stn
+ (rst-toc-insert-children (rst-Stn-children stn) buf style depth 0 "" keymap
+ tgt-stn)))
+
+(defun rst-toc-insert-children (children buf style depth indent numbering
+ keymap tgt-stn)
+ ;; testcover: ok.
+ "In the current buffer at point insert CHILDREN in BUF to table of contents.
+See `rst-toc-insert-tree' for STYLE, DEPTH and TGT-STN. See
+`rst-toc-insert-stn' for INDENT and NUMBERING. See
+`rst-toc-insert-link' for KEYMAP."
+ (let ((count 1)
+ ;; Child numbering is done from the parent.
+ (num-fmt (format "%%%dd"
+ (1+ (floor (log (1+ (length children)) 10)))))
+ fnd)
+ (when (not (equal numbering ""))
+ ;; Add separating dot to existing numbering.
+ (setq numbering (concat numbering ".")))
+ (dolist (child children fnd)
+ (setq fnd
+ (or (rst-toc-insert-stn child buf style depth indent
+ (concat numbering (format num-fmt count))
+ keymap tgt-stn) fnd))
+ (cl-incf count))))
+
+;; FIXME refactoring: Use `rst-Stn-buffer' instead of `buf'.
+(defun rst-toc-insert-stn (stn buf style depth indent numbering keymap tgt-stn)
+ ;; testcover: ok.
+ "In the current buffer at point insert STN in BUF into table of contents.
+See `rst-toc-insert-tree' for STYLE, DEPTH and TGT-STN. INDENT
+is the indentation depth to use for STN. NUMBERING is the prefix
+numbering for STN. See `rst-toc-insert-link' for KEYMAP."
+ (when (or (not depth) (> depth 0))
+ (cl-destructuring-bind
+ (pfx add
+ &aux (fnd (when (and tgt-stn
+ (equal (rst-Stn-get-title-beginning stn)
+ (rst-Stn-get-title-beginning tgt-stn)))
+ (point))))
+ (cond
+ ((eq style 'plain)
+ (list "" rst-toc-indent))
+ ((eq style 'fixed)
+ (list (concat numbering rst-toc-insert-number-separator)
+ rst-toc-indent))
+ ((eq style 'aligned)
+ (list (concat numbering rst-toc-insert-number-separator)
+ (+ (length numbering)
+ (length rst-toc-insert-number-separator))))
+ ((eq style 'listed)
+ (list (format "%c " (car rst-preferred-bullets)) 2)))
+ ;; Indent using spaces so buffer characteristics like `indent-tabs-mode'
+ ;; do not matter.
+ (rst-toc-insert-link (concat (make-string indent ? ) pfx) stn buf keymap)
+ (or (rst-toc-insert-children (rst-Stn-children stn) buf style
+ (when depth
+ (1- depth))
+ (+ indent add) numbering keymap tgt-stn)
+ fnd))))
+
+(defun rst-toc-update ()
+ ;; testcover: ok.
+ "Automatically find the contents section of a document and update.
+Updates the inserted TOC if present. You can use this in your
+file-write hook to always make it up-to-date automatically."
+ (interactive)
+ (save-match-data
+ (save-excursion
+ ;; Find and delete an existing comment after the first contents
+ ;; directive. Delete that region.
+ (goto-char (point-min))
+ ;; FIXME: Should accept indentation of the whole block.
+ ;; We look for the following and the following only (in other words, if
+ ;; your syntax differs, this won't work.).
+ ;;
+ ;; .. contents:: [...anything here...]
+ ;; [:field: value]...
+ ;; ..
+ ;; XXXXXXXX
+ ;; XXXXXXXX
+ ;; [more lines]
+ ;; FIXME: Works only for the first of these tocs. There should be a
+ ;; fixed text after the comment such as "RST-MODE ELECTRIC TOC".
+ ;; May be parameters such as `max-level' should be appended.
+ (let ((beg (re-search-forward
+ (1value
+ (rst-re "^" 'exm-sta "contents" 'dcl-tag ".*\n"
+ "\\(?:" 'hws-sta 'fld-tag ".*\n\\)*" 'exm-tag))
+ nil t))
+ fnd)
+ (when
+ (and beg
+ (rst-forward-line-looking-at
+ 1 'lin-end
+ #'(lambda (mtcd)
+ (unless mtcd
+ (rst-apply-indented-blocks
+ (point) (point-max) (current-indentation)
+ #'(lambda (count _in-first _in-sub in-super in-empty
+ _relind)
+ (cond
+ ((or (> count 1) in-super))
+ ((not in-empty)
+ (setq fnd (line-end-position))
+ nil)))))
+ t)))
+ (when fnd
+ (delete-region beg fnd))
+ (goto-char beg)
+ (insert "\n ")
+ ;; FIXME: Ignores an `max-level' given to the original
+ ;; `rst-toc-insert'. `max-level' could be rendered to the first
+ ;; line.
+ (rst-toc-insert)))))
+ ;; Note: always return nil, because this may be used as a hook.
+ nil)
+
+;; FIXME: Updating the toc on saving would be nice. However, this doesn't work
+;; correctly:
+;;
+;; (add-hook 'write-contents-hooks 'rst-toc-update-fun)
+;; (defun rst-toc-update-fun ()
+;; ;; Disable undo for the write file hook.
+;; (let ((buffer-undo-list t)) (rst-toc-update) ))
+
+;; Maintain an alias for compatibility.
+(defalias 'rst-toc-insert-update 'rst-toc-update)
+
+(defconst rst-toc-buffer-name "*Table of Contents*"
+ "Name of the Table of Contents buffer.")
+
+(defvar-local rst-toc-mode-return-wincfg nil
+ "Window configuration to which to return when leaving the TOC.")
+
+(defun rst-toc ()
+ ;; testcover: ok.
+ "Display a table of contents for current buffer.
+Displays all section titles found in the current buffer in a
+hierarchical list. The resulting buffer can be navigated, and
+selecting a section title moves the cursor to that section."
+ (interactive)
+ (rst-reset-section-caches)
+ (let* ((wincfg (list (current-window-configuration) (point-marker)))
+ (sectree (rst-all-stn))
+ (target-stn (rst-stn-containing-point sectree))
+ (target-buf (current-buffer))
+ (buf (get-buffer-create rst-toc-buffer-name))
+ target-pos)
+ (with-current-buffer buf
+ (let ((inhibit-read-only t))
+ (rst-toc-mode)
+ (delete-region (point-min) (point-max))
+ ;; FIXME: Could use a customizable style.
+ (setq target-pos (rst-toc-insert-tree
+ sectree target-buf 'plain nil nil target-stn))))
+ (display-buffer buf)
+ (pop-to-buffer buf)
+ (setq rst-toc-mode-return-wincfg wincfg)
+ (goto-char (or target-pos (point-min)))))
+
+;; Maintain an alias for compatibility.
+(defalias 'rst-goto-section 'rst-toc-follow-link)
+
+(defun rst-toc-follow-link (link-buf link-pnt kill)
+ ;; testcover: ok.
+ "Follow the link to the section at LINK-PNT in LINK-BUF.
+LINK-PNT and LINK-BUF default to the point in the current buffer.
+With prefix argument KILL a TOC buffer is destroyed. Throw an
+error if there is no working link at the given position."
+ (interactive "i\nd\nP")
+ (unless link-buf
+ (setq link-buf (current-buffer)))
+ ;; Do not catch errors from `rst-toc-get-link' because otherwise the error is
+ ;; suppressed and invisible in interactve use.
+ (let ((mrkr (rst-toc-get-link link-buf link-pnt)))
+ (condition-case nil
+ (rst-toc-mode-return kill)
+ ;; Catch errors when not in `toc-mode'.
+ (error nil))
+ (pop-to-buffer (marker-buffer mrkr))
+ (goto-char mrkr)
+ ;; FIXME: Should be a customizable number of lines from beginning or end of
+ ;; window just like the argument to `recenter`. It would be ideal if
+ ;; the adornment is always completely visible.
+ (recenter 5)))
+
+;; Maintain an alias for compatibility.
+(defalias 'rst-toc-mode-goto-section 'rst-toc-mode-follow-link-kill)
+
+;; FIXME: Cursor before or behind the list must be handled properly; before the
+;; list should jump to the top and behind the list to the last normal
+;; paragraph.
+(defun rst-toc-mode-follow-link-kill ()
+ ;; testcover: ok.
+ "Follow the link to the section at point and kill the TOC buffer."
+ (interactive)
+ (rst-toc-follow-link (current-buffer) (point) t))
+
+;; Maintain an alias for compatibility.
+(defalias 'rst-toc-mode-mouse-goto 'rst-toc-mouse-follow-link)
+
+(defun rst-toc-mouse-follow-link (event kill)
+ ;; testcover: uncovered.
+ "In `rst-toc' mode, go to the occurrence whose line you click on.
+EVENT is the input event. Kill TOC buffer if KILL."
+ (interactive "e\ni")
+ (rst-toc-follow-link (window-buffer (posn-window (event-end event)))
+ (posn-point (event-end event)) kill))
+
+;; Maintain an alias for compatibility.
+(defalias 'rst-toc-mode-mouse-goto-kill 'rst-toc-mode-mouse-follow-link-kill)
+
+(defun rst-toc-mode-mouse-follow-link-kill (event)
+ ;; testcover: uncovered.
+ "Same as `rst-toc-mouse-follow-link', but kill TOC buffer as well.
+EVENT is the input event."
+ (interactive "e")
+ (rst-toc-mouse-follow-link event t))
+
+;; Maintain an alias for compatibility.
+(defalias 'rst-toc-quit-window 'rst-toc-mode-return)
+
+(defun rst-toc-mode-return (kill)
+ ;; testcover: ok.
+ "Leave the current TOC buffer and return to the previous environment.
+With prefix argument KILL non-nil, kill the buffer instead of
+burying it."
+ (interactive "P")
+ (unless rst-toc-mode-return-wincfg
+ (error "Not in a `toc-mode' buffer"))
+ (cl-destructuring-bind
+ (wincfg pos
+ &aux (toc-buf (current-buffer)))
+ rst-toc-mode-return-wincfg
+ (set-window-configuration wincfg)
+ (goto-char pos)
+ (if kill
+ (kill-buffer toc-buf)
+ (bury-buffer toc-buf))))
+
+(defun rst-toc-mode-return-kill ()
+ ;; testcover: uncovered.
+ "Like `rst-toc-mode-return' but kill TOC buffer."
+ (interactive)
+ (rst-toc-mode-return t))
+
+(defvar rst-toc-mode-map
+ (let ((map (make-sparse-keymap)))
+ (define-key map [mouse-1] #'rst-toc-mode-mouse-follow-link-kill)
+ (define-key map [mouse-2] #'rst-toc-mouse-follow-link)
+ (define-key map "\C-m" #'rst-toc-mode-follow-link-kill)
+ (define-key map "f" #'rst-toc-mode-follow-link-kill)
+ (define-key map "n" #'next-line)
+ (define-key map "p" #'previous-line)
+ (define-key map "q" #'rst-toc-mode-return)
+ (define-key map "z" #'rst-toc-mode-return-kill)
+ map)
+ "Keymap for `rst-toc-mode'.")
+
+(define-derived-mode rst-toc-mode special-mode "ReST-TOC"
+ "Major mode for output from \\[rst-toc], the table-of-contents for the document.
+\\{rst-toc-mode-map}"
+ ;; FIXME: `revert-buffer-function` must be defined so `revert-buffer` works
+ ;; as expected for a special mode. In particular the referred buffer
+ ;; needs to be rescanned and the TOC must be updated accordingly.
+ ;; FIXME: Should contain the name of the buffer this is the toc of.
+ (setq header-line-format "Table of Contents"))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Section movement
+
+;; FIXME testcover: Use `testcover'. Mark up a function with sufficient test
+;; coverage by a comment tagged with `testcover' after the
+;; `defun'. Then move this comment.
+
+(defun rst-forward-section (offset)
+ "Jump forward OFFSET section titles ending up at the start of the title line.
+OFFSET defaults to 1 and may be negative to move backward. An
+OFFSET of 0 does not move unless point is inside a title. Go to
+end or beginning of buffer if no more section titles in the desired
+direction."
+ (interactive "p")
+ (rst-reset-section-caches)
+ (let* ((ttls (rst-all-ttls))
+ (count (length ttls))
+ (pnt (point))
+ (contained nil) ; Title contains point (or is after point otherwise).
+ (found (or (cl-position-if
+ ;; Find a title containing or after point.
+ #'(lambda (ttl)
+ (let ((cmp (rst-Ttl-contains ttl pnt)))
+ (cond
+ ((= cmp 0) ; Title contains point.
+ (setq contained t)
+ t)
+ ((> cmp 0) ; Title after point.
+ t))))
+ ttls)
+ ;; Point after all titles.
+ count))
+ (target (+ found offset
+ ;; If point is in plain text found title is already one
+ ;; step forward.
+ (if (and (not contained) (>= offset 0)) -1 0))))
+ (goto-char (cond
+ ((< target 0)
+ (point-min))
+ ((>= target count)
+ (point-max))
+ ((and (not contained) (= offset 0))
+ ;; Point not in title and should not move - do not move.
+ pnt)
+ ((rst-Ttl-get-title-beginning (nth target ttls)))))))
+
+(defun rst-backward-section (offset)
+ "Like `rst-forward-section', except move backward by OFFSET."
+ (interactive "p")
+ (rst-forward-section (- offset)))
+
+;; FIXME: What is `allow-extend' for? See `mark-paragraph' for an explanation.
+(defun rst-mark-section (&optional count allow-extend)
+ "Select COUNT sections around point.
+Mark following sections for positive COUNT or preceding sections
+for negative COUNT."
+ ;; Cloned from mark-paragraph.
+ (interactive "p\np")
+ (unless count (setq count 1))
+ (when (zerop count)
+ (error "Cannot mark zero sections"))
+ (cond ((and allow-extend
+ (or (and (eq last-command this-command) (mark t))
+ (use-region-p)))
+ (set-mark
+ (save-excursion
+ (goto-char (mark))
+ (rst-forward-section count)
+ (point))))
+ (t
+ (rst-forward-section count)
+ (push-mark nil t t)
+ (rst-forward-section (- count)))))
+
+\f
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Indentation
+
+(defun rst-find-leftmost-column (beg end)
+ "Return the leftmost column spanned by region BEG to END.
+The line containing the start of the region is always considered
+spanned. If the region ends at the beginning of a line this line
+is not considered spanned, otherwise it is spanned."
+ (let (mincol)
+ (save-match-data
+ (save-excursion
+ (goto-char beg)
+ (1value
+ (rst-forward-line-strict 0))
+ (while (< (point) end)
+ (unless (looking-at (rst-re 'lin-end))
+ (setq mincol (if mincol
+ (min mincol (current-indentation))
+ (current-indentation))))
+ (rst-forward-line-strict 1 end)))
+ mincol)))
+
+;; FIXME: At the moment only block comments with leading empty comment line are
+;; supported. Comment lines with leading comment markup should be also
+;; supported. May be a customizable option could control which style to
+;; prefer.
+
+(defgroup rst-indent nil "Settings for indentation in reStructuredText.
+
+In reStructuredText indentation points are usually determined by
+preceding lines. Sometimes the syntax allows arbitrary indentation
+points such as where to start the first line following a directive.
+These indentation widths can be customized here."
+ :group 'rst
+ :package-version '(rst . "1.1.0"))
+
+(define-obsolete-variable-alias
+ 'rst-shift-basic-offset 'rst-indent-width "rst 1.0.0")
+(defcustom rst-indent-width 2
+ "Indentation when there is no more indentation point given."
+ :group 'rst-indent
+ :type '(integer))
+(rst-testcover-defcustom)
+
+(defcustom rst-indent-field 3
+ "Indentation for first line after a field or 0 to always indent for content."
+ :group 'rst-indent
+ :package-version '(rst . "1.1.0")
+ :type '(integer))
+(rst-testcover-defcustom)
+
+(defcustom rst-indent-literal-normal 3
+ "Default indentation for literal block after a markup on an own line."
+ :group 'rst-indent
+ :package-version '(rst . "1.1.0")
+ :type '(integer))
+(rst-testcover-defcustom)
+
+(defcustom rst-indent-literal-minimized 2
+ "Default indentation for literal block after a minimized markup."
+ :group 'rst-indent
+ :package-version '(rst . "1.1.0")
+ :type '(integer))
+(rst-testcover-defcustom)
+
+(defcustom rst-indent-comment 3
+ "Default indentation for first line of a comment."
+ :group 'rst-indent
+ :package-version '(rst . "1.1.0")
+ :type '(integer))
+(rst-testcover-defcustom)
+
+;; FIXME: Must consider other tabs:
+;; * Line blocks
+;; * Definition lists
+;; * Option lists
+(defun rst-line-tabs ()
+ "Return tabs of the current line or nil for no tab.
+The list is sorted so the tab where writing continues most likely
+is the first one. Each tab is of the form (COLUMN . INNER).
+COLUMN is the column of the tab. INNER is non-nil if this is an
+inner tab. I.e. a tab which does come from the basic indentation
+and not from inner alignment points."
+ (save-excursion
+ (rst-forward-line-strict 0)
+ (save-match-data
+ (unless (looking-at (rst-re 'lin-end))
+ (back-to-indentation)
+ ;; Current indentation is always the least likely tab.
+ (let ((tabs (list (list (point) 0 nil)))) ; (POINT OFFSET INNER)
+ ;; Push inner tabs more likely to continue writing.
+ (cond
+ ;; Item.
+ ((looking-at (rst-re '(:grp itmany-tag hws-sta) '(:grp "\\S ") "?"))
+ (when (match-string 2)
+ (push (list (match-beginning 2) 0 t) tabs)))
+ ;; Field.
+ ((looking-at (rst-re '(:grp fld-tag) '(:grp hws-tag)
+ '(:grp "\\S ") "?"))
+ (unless (zerop rst-indent-field)
+ (push (list (match-beginning 1) rst-indent-field t) tabs))
+ (if (match-string 3)
+ (push (list (match-beginning 3) 0 t) tabs)
+ (if (zerop rst-indent-field)
+ (push (list (match-end 2)
+ (if (string= (match-string 2) "") 1 0)
+ t)
+ tabs))))
+ ;; Directive.
+ ((looking-at (rst-re 'dir-sta-3 '(:grp "\\S ") "?"))
+ (push (list (match-end 1) 0 t) tabs)
+ (unless (string= (match-string 2) "")
+ (push (list (match-end 2) 0 t) tabs))
+ (when (match-string 4)
+ (push (list (match-beginning 4) 0 t) tabs)))
+ ;; Footnote or citation definition.
+ ((looking-at (rst-re 'fnc-sta-2 '(:grp "\\S ") "?"))
+ (push (list (match-end 1) 0 t) tabs)
+ (when (match-string 3)
+ (push (list (match-beginning 3) 0 t) tabs)))
+ ;; Comment.
+ ((looking-at (rst-re 'cmt-sta-1))
+ (push (list (point) rst-indent-comment t) tabs)))
+ ;; Start of literal block.
+ (when (looking-at (rst-re 'lit-sta-2))
+ (cl-destructuring-bind (point offset _inner) (car tabs)
+ (push (list point
+ (+ offset
+ (if (match-string 1)
+ rst-indent-literal-minimized
+ rst-indent-literal-normal))
+ t)
+ tabs)))
+ (mapcar (cl-function
+ (lambda ((point offset inner))
+ (goto-char point)
+ (cons (+ (current-column) offset) inner)))
+ tabs))))))
+
+(defun rst-compute-tabs (pt)
+ "Build the list of possible tabs for all lines above.
+Search backwards from point PT to build the list of possible tabs.
+Return a list of tabs sorted by likeliness to continue writing
+like `rst-line-tabs'. Nearer lines have generally a higher
+likeliness than farther lines. Return nil if no tab is found in
+the text above."
+ ;; FIXME: See test `indent-for-tab-command-BUGS`.
+ (save-excursion
+ (goto-char pt)
+ (let (leftmost ; Leftmost column found so far.
+ innermost ; Leftmost column for inner tab.
+ tablist)
+ (while (and (rst-forward-line-strict -1)
+ (or (not leftmost)
+ (> leftmost 0)))
+ (let ((tabs (rst-line-tabs)))
+ (when tabs
+ (let ((leftcol (apply #'min (mapcar #'car tabs))))
+ ;; Consider only lines indented less or same if not INNERMOST.
+ (when (or (not leftmost)
+ (< leftcol leftmost)
+ (and (not innermost) (= leftcol leftmost)))
+ (rst-destructuring-dolist ((column &rest inner) tabs)
+ (when (or
+ (and (not inner)
+ (or (not leftmost)
+ (< column leftmost)))
+ (and inner
+ (or (not innermost)
+ (< column innermost))))
+ (setq tablist (cl-adjoin column tablist))))
+ (setq innermost (if (cl-some #'cdr tabs) ; Has inner.
+ leftcol
+ innermost))
+ (setq leftmost leftcol))))))
+ (nreverse tablist))))
+
+(defun rst-indent-line (&optional dflt)
+ "Indent current line to next best reStructuredText tab.
+The next best tab is taken from the tab list returned by
+`rst-compute-tabs' which is used in a cyclic manner. If the
+current indentation does not end on a tab use the first one. If
+the current indentation is on a tab use the next tab. This allows
+a repeated use of \\[indent-for-tab-command] to cycle through all
+possible tabs. If no indentation is possible return `noindent' or
+use DFLT. Return the indentation indented to. When point is in
+indentation it ends up at its end. Otherwise the point is kept
+relative to the content."
+ (let* ((pt (point-marker))
+ (cur (current-indentation))
+ (clm (current-column))
+ (tabs (rst-compute-tabs (point)))
+ (fnd (cl-position cur tabs :test #'equal))
+ ind)
+ (if (and (not tabs) (not dflt))
+ 'noindent
+ (if (not tabs)
+ (setq ind dflt)
+ (if (not fnd)
+ (setq fnd 0)
+ (setq fnd (1+ fnd))
+ (if (>= fnd (length tabs))
+ (setq fnd 0)))
+ (setq ind (nth fnd tabs)))
+ (indent-line-to ind)
+ (if (> clm cur)
+ (goto-char pt))
+ (set-marker pt nil)
+ ind)))
+
+(defun rst-shift-region (beg end cnt)
+ "Shift region BEG to END by CNT tabs.
+Shift by one tab to the right (CNT > 0) or left (CNT < 0) or
+remove all indentation (CNT = 0). A tab is taken from the text
+above. If no suitable tab is found `rst-indent-width' is used."
+ (interactive "r\np")
+ (let ((tabs (sort (rst-compute-tabs beg)
+ #'(lambda (x y)
+ (<= x y))))
+ (leftmostcol (rst-find-leftmost-column beg end)))
+ (when (or (> leftmostcol 0) (> cnt 0))
+ ;; Apply the indent.
+ (indent-rigidly
+ beg end
+ (if (zerop cnt)
+ (- leftmostcol)
+ ;; Find the next tab after the leftmost column.
+ (let* ((cmp (if (> cnt 0) #'> #'<))
+ (tabs (if (> cnt 0) tabs (reverse tabs)))
+ (len (length tabs))
+ (dir (cl-signum cnt)) ; Direction to take.
+ (abs (abs cnt)) ; Absolute number of steps to take.
+ ;; Get the position of the first tab beyond leftmostcol.
+ (fnd (cl-position-if #'(lambda (elt)
+ (funcall cmp elt leftmostcol))
+ tabs))
+ ;; Virtual position of tab.
+ (pos (+ (or fnd len) (1- abs)))
+ (tab (if (< pos len)
+ ;; Tab exists - use it.
+ (nth pos tabs)
+ ;; Column needs to be computed.
+ (let ((col (+ (or (car (last tabs)) leftmostcol)
+ ;; Base on last known column.
+ (* (- pos (1- len)) ; Distance left.
+ dir ; Direction to take.
+ rst-indent-width))))
+ (if (< col 0) 0 col)))))
+ (- tab leftmostcol)))))))
+
+;; FIXME: A paragraph with an (incorrectly) indented second line is not filled
+;; correctly::
+;;
+;; Some start
+;; continued wrong
+(defun rst-adaptive-fill ()
+ "Return fill prefix found at point.
+Value for `adaptive-fill-function'."
+ (save-match-data
+ (let ((fnd (if (looking-at adaptive-fill-regexp)
+ (match-string-no-properties 0))))
+ (if (save-match-data
+ (not (string-match comment-start-skip fnd)))
+ ;; An non-comment prefix is fine.
+ fnd
+ ;; Matches a comment - return whitespace instead.
+ (make-string (-
+ (save-excursion
+ (goto-char (match-end 0))
+ (current-column))
+ (save-excursion
+ (goto-char (match-beginning 0))
+ (current-column))) ? )))))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Comments
+
+(defun rst-comment-line-break (&optional soft)
+ "Break line and indent, continuing reStructuredText comment if within one.
+Value for `comment-line-break-function'. If SOFT use soft
+newlines as mandated by `comment-line-break-function'."
+ (if soft
+ (insert-and-inherit ?\n)
+ (newline 1))
+ (save-excursion
+ (forward-char -1)
+ (delete-horizontal-space))
+ (delete-horizontal-space)
+ (let ((tabs (rst-compute-tabs (point))))
+ (when tabs
+ (indent-line-to (car tabs)))))
+
+(defun rst-comment-indent ()
+ "Return indentation for current comment line."
+ (car (rst-compute-tabs (point))))
+
+(defun rst-comment-insert-comment ()
+ "Insert a comment in the current line."
+ (rst-indent-line 0)
+ (insert comment-start))
+
+(defun rst-comment-region (beg end &optional arg)
+ "Comment or uncomment the current region.
+Region is from BEG to END. Uncomment if ARG."
+ (save-excursion
+ (if (consp arg)
+ (rst-uncomment-region beg end arg)
+ (goto-char beg)
+ (rst-forward-line-strict 0)
+ (let ((ind (current-indentation))
+ (bol (point)))
+ (indent-rigidly bol end rst-indent-comment)
+ (goto-char bol)
+ (open-line 1)
+ (indent-line-to ind)
+ (insert (comment-string-strip comment-start t t))))))
+
+(defun rst-uncomment-region (beg end &optional _arg)
+ "Uncomment the current region.
+Region is from BEG to END. _ARG is ignored"
+ (save-excursion
+ (goto-char beg)
+ (rst-forward-line-strict 0)
+ (let ((bol (point)))
+ (rst-forward-line-strict 1 end)
+ (indent-rigidly (point) end (- rst-indent-comment))
+ (goto-char bol)
+ (rst-delete-entire-line 0))))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Apply to indented block
+
+;; FIXME: These next functions should become part of a larger effort to redo
+;; the bullets in bulleted lists. The enumerate would just be one of
+;; the possible outputs.
+;;
+;; FIXME: We need to do the enumeration removal as well.
+
+(defun rst-apply-indented-blocks (beg end ind fun)
+ "Apply FUN to all lines from BEG to END in blocks indented to IND.
+The first indented block starts with the first non-empty line
+containing or after BEG and indented to IND. After the first
+line the indented block may contain more lines with same
+indentation (the paragraph) followed by empty lines and lines
+more indented (the sub-blocks). A following line indented to IND
+starts the next paragraph. A non-empty line with less
+indentation than IND terminates the current paragraph. FUN is
+applied to each line like this
+
+ (FUN COUNT IN-FIRST IN-SUB IN-SUPER IN-EMPTY RELIND)
+
+COUNT is 0 before the first paragraph and increments for every
+paragraph found on level IND. IN-FIRST is non-nil if this is the
+first line of such a paragraph. IN-SUB is non-nil if this line
+is part of a sub-block while IN-SUPER is non-nil of this line is
+part of a less indented block (super-block). IN-EMPTY is non-nil
+if this line is empty where an empty line is considered being
+part of the previous block. RELIND is nil for an empty line, 0
+for a line indented to IND, and the positive or negative number
+of columns more or less indented otherwise. When FUN is called
+point is immediately behind indentation of that line. FUN may
+change everything as long as a marker at END and at the beginning
+of the following line is handled correctly by the change. A
+non-nil return value from FUN breaks the loop and is returned.
+Otherwise return nil."
+ (let ((endm (copy-marker end t))
+ (count 0) ; Before first indented block.
+ (nxt (when (< beg end)
+ (copy-marker beg t)))
+ (broken t)
+ in-sub in-super stop)
+ (save-match-data
+ (save-excursion
+ (while (and (not stop) nxt)
+ (set-marker
+ (goto-char nxt) nil)
+ (setq nxt (save-excursion
+ ;; FIXME refactoring: Replace `(forward-line)
+ ;; (back-to-indentation)` by
+ ;; `(forward-to-indentation)`
+ (when (and (rst-forward-line-strict 1 endm)
+ (< (point) endm))
+ (copy-marker (point) t))))
+ (back-to-indentation)
+ (let ((relind (- (current-indentation) ind))
+ (in-empty (looking-at (rst-re 'lin-end)))
+ in-first)
+ (cond
+ (in-empty
+ (setq relind nil))
+ ((< relind 0)
+ (setq in-sub nil)
+ (setq in-super t))
+ ((> relind 0)
+ (setq in-sub t)
+ (setq in-super nil))
+ (t ; Non-empty line in indented block.
+ (when (or broken in-sub in-super)
+ (setq in-first t)
+ (cl-incf count))
+ (setq in-sub nil)
+ (setq in-super nil)))
+ (save-excursion
+ (setq
+ stop
+ (funcall fun count in-first in-sub in-super in-empty relind)))
+ (setq broken in-empty)))
+ (set-marker endm nil)
+ stop))))
+
+(defun rst-enumerate-region (beg end all)
+ "Add enumeration to all the leftmost paragraphs in the given region.
+The region is specified between BEG and END. With ALL,
+do all lines instead of just paragraphs."
+ (interactive "r\nP")
+ (let ((enum 0)
+ (indent ""))
+ (rst-apply-indented-blocks
+ beg end (rst-find-leftmost-column beg end)
+ #'(lambda (count in-first in-sub in-super in-empty _relind)
+ (cond
+ (in-empty)
+ (in-super)
+ ((zerop count))
+ (in-sub
+ (insert indent))
+ ((or in-first all)
+ (let ((tag (format "%d. " (cl-incf enum))))
+ (setq indent (make-string (length tag) ? ))
+ (insert tag)))
+ (t
+ (insert indent)))
+ nil))))
+
+;; FIXME: Does not deal with deeper indentation - although
+;; `rst-apply-indented-blocks' could.
+(defun rst-bullet-list-region (beg end all)
+ "Add bullets to all the leftmost paragraphs in the given region.
+The region is specified between BEG and END. With ALL,
+do all lines instead of just paragraphs."
+ (interactive "r\nP")
+ (unless rst-preferred-bullets
+ (error "No preferred bullets defined"))
+ (let* ((bul (format "%c " (car rst-preferred-bullets)))
+ (indent (make-string (length bul) ? )))
+ (rst-apply-indented-blocks
+ beg end (rst-find-leftmost-column beg end)
+ #'(lambda (count in-first in-sub in-super in-empty _relind)
+ (cond
+ (in-empty)
+ (in-super)
+ ((zerop count))
+ (in-sub
+ (insert indent))
+ ((or in-first all)
+ (insert bul))
+ (t
+ (insert indent)))
+ nil))))
+
+;; FIXME: Does not deal with a varying number of digits appropriately.
+;; FIXME: Does not deal with multiple levels independently.
+;; FIXME: Does not indent a multiline item correctly.
+(defun rst-convert-bullets-to-enumeration (beg end)
+ "Convert the bulleted and enumerated items in the region to enumerated lists.
+Renumber as necessary. Region is from BEG to END."
+ (interactive "r")
+ (let ((count 1))
+ (save-match-data
+ (save-excursion
+ (dolist (marker (mapcar
+ (cl-function
+ (lambda ((pnt &rest clm))
+ (copy-marker pnt)))
+ (rst-find-begs beg end 'itmany-beg-1)))
+ (set-marker
+ (goto-char marker) nil)
+ (looking-at (rst-re 'itmany-beg-1))
+ (replace-match (format "%d." count) nil nil nil 1)
+ (cl-incf count))))))
+
+(defun rst-line-block-region (beg end &optional with-empty)
+ "Add line block prefixes for a region.
+Region is from BEG to END. With WITH-EMPTY prefix empty lines too."
+ (interactive "r\nP")
+ (let ((ind (rst-find-leftmost-column beg end)))
+ (rst-apply-indented-blocks
+ beg end ind
+ #'(lambda (_count _in-first _in-sub in-super in-empty _relind)
+ (when (and (not in-super) (or with-empty (not in-empty)))
+ (move-to-column ind t)
+ (insert "| "))
+ nil))))
+
+\f
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Font lock
+
+(require 'font-lock)
+
+;; FIXME: The obsolete variables need to disappear.
+
+;; The following versions have been done inside Emacs and should not be
+;; replaced by `:package-version' attributes until a change.
+
+(defgroup rst-faces nil "Faces used in Rst Mode."
+ :group 'rst
+ :group 'faces
+ :version "21.1")
+
+(defface rst-block '((t :inherit font-lock-keyword-face))
+ "Face used for all syntax marking up a special block."
+ :version "24.1"
+ :group 'rst-faces)
+
+(defcustom rst-block-face 'rst-block
+ "All syntax marking up a special block."
+ :version "24.1"
+ :group 'rst-faces
+ :type '(face))
+(rst-testcover-defcustom)
+(make-obsolete-variable 'rst-block-face
+ "customize the face `rst-block' instead."
+ "24.1")
+
+(defface rst-external '((t :inherit font-lock-type-face))
+ "Face used for field names and interpreted text."
+ :version "24.1"
+ :group 'rst-faces)
+
+(defcustom rst-external-face 'rst-external
+ "Field names and interpreted text."
+ :version "24.1"
+ :group 'rst-faces
+ :type '(face))
+(rst-testcover-defcustom)
+(make-obsolete-variable 'rst-external-face
+ "customize the face `rst-external' instead."
+ "24.1")
+
+(defface rst-definition '((t :inherit font-lock-function-name-face))
+ "Face used for all other defining constructs."
+ :version "24.1"
+ :group 'rst-faces)
+
+(defcustom rst-definition-face 'rst-definition
+ "All other defining constructs."
+ :version "24.1"
+ :group 'rst-faces
+ :type '(face))
+(rst-testcover-defcustom)
+(make-obsolete-variable 'rst-definition-face
+ "customize the face `rst-definition' instead."
+ "24.1")
+
+;; XEmacs compatibility (?).
+(defface rst-directive (if (boundp 'font-lock-builtin-face)
+ '((t :inherit font-lock-builtin-face))
+ '((t :inherit font-lock-preprocessor-face)))
+ "Face used for directives and roles."
+ :version "24.1"
+ :group 'rst-faces)
+
+(defcustom rst-directive-face 'rst-directive
+ "Directives and roles."
+ :group 'rst-faces
+ :type '(face))
+(rst-testcover-defcustom)
+(make-obsolete-variable 'rst-directive-face
+ "customize the face `rst-directive' instead."
+ "24.1")
+
+(defface rst-comment '((t :inherit font-lock-comment-face))
+ "Face used for comments."
+ :version "24.1"
+ :group 'rst-faces)
+
+(defcustom rst-comment-face 'rst-comment
+ "Comments."
+ :version "24.1"
+ :group 'rst-faces
+ :type '(face))
+(rst-testcover-defcustom)
+(make-obsolete-variable 'rst-comment-face
+ "customize the face `rst-comment' instead."
+ "24.1")
+
+(defface rst-emphasis1 '((t :inherit italic))
+ "Face used for simple emphasis."
+ :version "24.1"
+ :group 'rst-faces)
+
+(defcustom rst-emphasis1-face 'rst-emphasis1
+ "Simple emphasis."
+ :version "24.1"
+ :group 'rst-faces
+ :type '(face))
+(rst-testcover-defcustom)
+(make-obsolete-variable 'rst-emphasis1-face
+ "customize the face `rst-emphasis1' instead."
+ "24.1")
+
+(defface rst-emphasis2 '((t :inherit bold))
+ "Face used for double emphasis."
+ :version "24.1"
+ :group 'rst-faces)
+
+(defcustom rst-emphasis2-face 'rst-emphasis2
+ "Double emphasis."
+ :group 'rst-faces
+ :type '(face))
+(rst-testcover-defcustom)
+(make-obsolete-variable 'rst-emphasis2-face
+ "customize the face `rst-emphasis2' instead."
+ "24.1")
+
+(defface rst-literal '((t :inherit font-lock-string-face))
+ "Face used for literal text."
+ :version "24.1"
+ :group 'rst-faces)
+
+(defcustom rst-literal-face 'rst-literal
+ "Literal text."
+ :version "24.1"
+ :group 'rst-faces
+ :type '(face))
+(rst-testcover-defcustom)
+(make-obsolete-variable 'rst-literal-face
+ "customize the face `rst-literal' instead."
+ "24.1")
+
+(defface rst-reference '((t :inherit font-lock-variable-name-face))
+ "Face used for references to a definition."
+ :version "24.1"
+ :group 'rst-faces)
+
+(defcustom rst-reference-face 'rst-reference
+ "References to a definition."
+ :version "24.1"
+ :group 'rst-faces
+ :type '(face))
+(rst-testcover-defcustom)
+(make-obsolete-variable 'rst-reference-face
+ "customize the face `rst-reference' instead."
+ "24.1")
+
+(defface rst-transition '((t :inherit font-lock-keyword-face))
+ "Face used for a transition."
+ :package-version '(rst . "1.3.0")
+ :group 'rst-faces)
+
+(defface rst-adornment '((t :inherit font-lock-keyword-face))
+ "Face used for the adornment of a section header."
+ :package-version '(rst . "1.3.0")
+ :group 'rst-faces)
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(dolist (var '(rst-level-face-max rst-level-face-base-color
+ rst-level-face-base-light
+ rst-level-face-format-light
+ rst-level-face-step-light
+ rst-level-1-face
+ rst-level-2-face
+ rst-level-3-face
+ rst-level-4-face
+ rst-level-5-face
+ rst-level-6-face))
+ (make-obsolete-variable var "customize the faces `rst-level-*' instead."
+ "24.3"))
+
+;; Define faces for the first 6 levels. More levels are possible, however.
+(defface rst-level-1 '((((background light)) (:background "grey85"))
+ (((background dark)) (:background "grey15")))
+ "Default face for section title text at level 1."
+ :package-version '(rst . "1.4.0"))
+
+(defface rst-level-2 '((((background light)) (:background "grey78"))
+ (((background dark)) (:background "grey22")))
+ "Default face for section title text at level 2."
+ :package-version '(rst . "1.4.0"))
+
+(defface rst-level-3 '((((background light)) (:background "grey71"))
+ (((background dark)) (:background "grey29")))
+ "Default face for section title text at level 3."
+ :package-version '(rst . "1.4.0"))
+
+(defface rst-level-4 '((((background light)) (:background "grey64"))
+ (((background dark)) (:background "grey36")))
+ "Default face for section title text at level 4."
+ :package-version '(rst . "1.4.0"))
+
+(defface rst-level-5 '((((background light)) (:background "grey57"))
+ (((background dark)) (:background "grey43")))
+ "Default face for section title text at level 5."
+ :package-version '(rst . "1.4.0"))
+
+(defface rst-level-6 '((((background light)) (:background "grey50"))
+ (((background dark)) (:background "grey50")))
+ "Default face for section title text at level 6."
+ :package-version '(rst . "1.4.0"))
+
+(defcustom rst-adornment-faces-alist
+ '((t . rst-transition)
+ (nil . rst-adornment)
+ (1 . rst-level-1)
+ (2 . rst-level-2)
+ (3 . rst-level-3)
+ (4 . rst-level-4)
+ (5 . rst-level-5)
+ (6 . rst-level-6))
+ "Faces for the various adornment types.
+Key is a number (for the section title text of that level
+starting with 1), t (for transitions) or nil (for section title
+adornment). If you need levels beyond 6 you have to define faces
+of your own."
+ :group 'rst-faces
+ :type '(alist
+ :key-type
+ (choice
+ (integer :tag "Section level")
+ (const :tag "transitions" t)
+ (const :tag "section title adornment" nil))
+ :value-type (face)))
+(rst-testcover-defcustom)
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(defvar rst-font-lock-keywords
+ ;; The reST-links in the comments below all relate to sections in
+ ;; http://docutils.sourceforge.net/docs/ref/rst/restructuredtext.html.
+ `(;; FIXME: Block markup is not recognized in blocks after explicit markup
+ ;; start.
+
+ ;; Simple `Body Elements`_
+ ;; `Bullet Lists`_
+ ;; FIXME: A bullet directly after a field name is not recognized.
+ (,(rst-re 'lin-beg '(:grp bul-sta))
+ 1 rst-block-face)
+ ;; `Enumerated Lists`_
+ (,(rst-re 'lin-beg '(:grp enmany-sta))
+ 1 rst-block-face)
+ ;; `Definition Lists`_
+ ;; FIXME: missing.
+ ;; `Field Lists`_
+ (,(rst-re 'lin-beg '(:grp fld-tag) 'bli-sfx)
+ 1 rst-external-face)
+ ;; `Option Lists`_
+ (,(rst-re 'lin-beg '(:grp opt-tag (:shy optsep-tag opt-tag) "*")
+ '(:alt "$" (:seq hws-prt "\\{2\\}")))
+ 1 rst-block-face)
+ ;; `Line Blocks`_
+ ;; Only for lines containing no more bar - to distinguish from tables.
+ (,(rst-re 'lin-beg '(:grp "|" bli-sfx) "[^|\n]*$")
+ 1 rst-block-face)
+
+ ;; `Tables`_
+ ;; FIXME: missing
+
+ ;; All the `Explicit Markup Blocks`_
+ ;; `Footnotes`_ / `Citations`_
+ (,(rst-re 'lin-beg 'fnc-sta-2)
+ (1 rst-definition-face)
+ (2 rst-definition-face))
+ ;; `Directives`_ / `Substitution Definitions`_
+ (,(rst-re 'lin-beg 'dir-sta-3)
+ (1 rst-directive-face)
+ (2 rst-definition-face)
+ (3 rst-directive-face))
+ ;; `Hyperlink Targets`_
+ (,(rst-re 'lin-beg
+ '(:grp exm-sta "_" (:alt
+ (:seq "`" ilcbkqdef-tag "`")
+ (:seq (:alt "[^:\\\n]" "\\\\.") "+")) ":")
+ 'bli-sfx)
+ 1 rst-definition-face)
+ (,(rst-re 'lin-beg '(:grp "__") 'bli-sfx)
+ 1 rst-definition-face)
+
+ ;; All `Inline Markup`_
+ ;; Most of them may be multiline though this is uninteresting.
+
+ ;; FIXME: Condition 5 preventing fontification of e.g. "*" not implemented
+ ;; `Strong Emphasis`_.
+ (,(rst-re 'ilm-pfx '(:grp "\\*\\*" ilcast-tag "\\*\\*") 'ilm-sfx)
+ 1 rst-emphasis2-face)
+ ;; `Emphasis`_
+ (,(rst-re 'ilm-pfx '(:grp "\\*" ilcast-tag "\\*") 'ilm-sfx)
+ 1 rst-emphasis1-face)
+ ;; `Inline Literals`_
+ (,(rst-re 'ilm-pfx '(:grp "``" ilcbkq-tag "``") 'ilm-sfx)
+ 1 rst-literal-face)
+ ;; `Inline Internal Targets`_
+ (,(rst-re 'ilm-pfx '(:grp "_`" ilcbkq-tag "`") 'ilm-sfx)
+ 1 rst-definition-face)
+ ;; `Hyperlink References`_
+ ;; FIXME: `Embedded URIs and Aliases`_ not considered.
+ ;; FIXME: Directly adjacent marked up words are not fontified correctly
+ ;; unless they are not separated by two spaces: foo_ bar_.
+ (,(rst-re 'ilm-pfx '(:grp (:alt (:seq "`" ilcbkq-tag "`")
+ (:seq "\\sw" (:alt "\\sw" "-") "+\\sw"))
+ "__?") 'ilm-sfx)
+ 1 rst-reference-face)
+ ;; `Interpreted Text`_
+ (,(rst-re 'ilm-pfx '(:grp (:shy ":" sym-tag ":") "?")
+ '(:grp "`" ilcbkq-tag "`")
+ '(:grp (:shy ":" sym-tag ":") "?") 'ilm-sfx)
+ (1 rst-directive-face)
+ (2 rst-external-face)
+ (3 rst-directive-face))
+ ;; `Footnote References`_ / `Citation References`_
+ (,(rst-re 'ilm-pfx '(:grp fnc-tag "_") 'ilm-sfx)
+ 1 rst-reference-face)
+ ;; `Substitution References`_
+ ;; FIXME: References substitutions like |this|_ or |this|__ are not
+ ;; fontified correctly.
+ (,(rst-re 'ilm-pfx '(:grp sub-tag) 'ilm-sfx)
+ 1 rst-reference-face)
+ ;; `Standalone Hyperlinks`_
+ ;; FIXME: This takes it easy by using a whitespace as delimiter.
+ (,(rst-re 'ilm-pfx '(:grp uri-tag ":\\S +") 'ilm-sfx)
+ 1 rst-definition-face)
+ (,(rst-re 'ilm-pfx '(:grp sym-tag "@" sym-tag ) 'ilm-sfx)
+ 1 rst-definition-face)
+
+ ;; Do all block fontification as late as possible so 'append works.
+
+ ;; Sections_ / Transitions_
+ ;; For sections this is multiline.
+ (,(rst-re 'ado-beg-2-1)
+ (rst-font-lock-handle-adornment-matcher
+ (rst-font-lock-handle-adornment-pre-match-form
+ (match-string-no-properties 1) (match-end 1))
+ nil
+ (1 (cdr (assoc nil rst-adornment-faces-alist)) append t)
+ (2 (cdr (assoc rst-font-lock-adornment-level
+ rst-adornment-faces-alist)) append t)
+ (3 (cdr (assoc nil rst-adornment-faces-alist)) append t)))
+
+ ;; FIXME: FACESPEC could be used instead of ordinary faces to set
+ ;; properties on comments and literal blocks so they are *not*
+ ;; inline fontified. See (elisp)Search-based Fontification.
+
+ ;; FIXME: And / or use `syntax-propertize' functions as in `octave-mod.el'
+ ;; and other V24 modes. May make `font-lock-extend-region'
+ ;; superfluous.
+
+ ;; `Comments`_
+ ;; This is multiline.
+ (,(rst-re 'lin-beg 'cmt-sta-1)
+ (1 rst-comment-face)
+ (rst-font-lock-find-unindented-line-match
+ (rst-font-lock-find-unindented-line-limit (match-end 1))
+ nil
+ (0 rst-comment-face append)))
+ (,(rst-re 'lin-beg '(:grp exm-tag) '(:grp hws-tag) "$")
+ (1 rst-comment-face)
+ (2 rst-comment-face)
+ (rst-font-lock-find-unindented-line-match
+ (rst-font-lock-find-unindented-line-limit 'next)
+ nil
+ (0 rst-comment-face append)))
+
+ ;; FIXME: This is not rendered as comment::
+ ;; .. .. list-table::
+ ;; :stub-columns: 1
+ ;; :header-rows: 1
+
+ ;; FIXME: This is rendered wrong::
+ ;;
+ ;; xxx yyy::
+ ;;
+ ;; ----|> KKKKK <|----
+ ;; / \
+ ;; -|> AAAAAAAAAAPPPPPP <|- -|> AAAAAAAAAABBBBBBB <|-
+ ;; | | | |
+ ;; | | | |
+ ;; PPPPPP PPPPPPDDDDDDD BBBBBBB PPPPPPBBBBBBB
+ ;;
+ ;; Indentation needs to be taken from the line with the ``::`` and not from
+ ;; the first content line.
+
+ ;; `Indented Literal Blocks`_
+ ;; This is multiline.
+ (,(rst-re 'lin-beg 'lit-sta-2)
+ (2 rst-block-face)
+ (rst-font-lock-find-unindented-line-match
+ (rst-font-lock-find-unindented-line-limit t)
+ nil
+ (0 rst-literal-face append)))
+
+ ;; FIXME: `Quoted Literal Blocks`_ missing.
+ ;; This is multiline.
+
+ ;; `Doctest Blocks`_
+ ;; FIXME: This is wrong according to the specification:
+ ;;
+ ;; Doctest blocks are text blocks which begin with ">>> ", the Python
+ ;; interactive interpreter main prompt, and end with a blank line.
+ ;; Doctest blocks are treated as a special case of literal blocks,
+ ;; without requiring the literal block syntax. If both are present, the
+ ;; literal block syntax takes priority over Doctest block syntax:
+ ;;
+ ;; This is an ordinary paragraph.
+ ;;
+ ;; >>> print 'this is a Doctest block'
+ ;; this is a Doctest block
+ ;;
+ ;; The following is a literal block::
+ ;;
+ ;; >>> This is not recognized as a doctest block by
+ ;; reStructuredText. It *will* be recognized by the doctest
+ ;; module, though!
+ ;;
+ ;; Indentation is not required for doctest blocks.
+ (,(rst-re 'lin-beg '(:grp (:alt ">>>" ell-tag)) '(:grp ".+"))
+ (1 rst-block-face)
+ (2 rst-literal-face)))
+ "Keywords to highlight in rst mode.")
+
+(defvar font-lock-beg)
+(defvar font-lock-end)
+
+(defun rst-font-lock-extend-region ()
+ "Extend the font-lock region if it might be in a multi-line construct.
+Return non-nil if so. Font-lock region is from `font-lock-beg'
+to `font-lock-end'."
+ (let ((r (rst-font-lock-extend-region-internal font-lock-beg font-lock-end)))
+ (when r
+ (setq font-lock-beg (car r))
+ (setq font-lock-end (cdr r))
+ t)))
+
+(defun rst-font-lock-extend-region-internal (beg end)
+ "Check the region BEG / END for being in the middle of a multi-line construct.
+Return nil if not or a cons with new values for BEG / END"
+ (let ((nbeg (rst-font-lock-extend-region-extend beg -1))
+ (nend (rst-font-lock-extend-region-extend end 1)))
+ (if (or nbeg nend)
+ (cons (or nbeg beg) (or nend end)))))
+
+;; FIXME refactoring: Use `rst-forward-line-strict' instead.
+(defun rst-forward-line (&optional n)
+ "Like `forward-line' but always end up in column 0 and return accordingly.
+Move N lines forward just as `forward-line'."
+ (let ((left (forward-line n)))
+ (if (bolp)
+ left
+ ;; FIXME: This may move back for positive n - is this desired?
+ (forward-line 0)
+ (- left (cl-signum n)))))
+
+;; FIXME: If a single line is made a section header by `rst-adjust' the header
+;; is not always fontified immediately.
+(defun rst-font-lock-extend-region-extend (pt dir)
+ "Extend the region starting at point PT and extending in direction DIR.
+Return extended point or nil if not moved."
+ ;; There are many potential multiline constructs but there are two groups
+ ;; which are really relevant. The first group consists of
+ ;;
+ ;; * comment lines without leading explicit markup tag and
+ ;;
+ ;; * literal blocks following "::"
+ ;;
+ ;; which are both indented. Thus indentation is the first thing recognized
+ ;; here. The second criteria is an explicit markup tag which may be a comment
+ ;; or a double colon at the end of a line.
+ ;;
+ ;; The second group consists of the adornment cases.
+ (if (not (get-text-property pt 'font-lock-multiline))
+ ;; Move only if we don't start inside a multiline construct already.
+ (save-match-data
+ (save-excursion
+ (let ( ; Non-empty non-indented line, explicit markup tag or literal
+ ; block tag.
+ (stop-re (rst-re '(:alt "[^ \t\n]"
+ (:seq hws-tag exm-tag)
+ (:seq ".*" dcl-tag lin-end)))))
+ ;; The comments below are for dir == -1 / dir == 1.
+ (goto-char pt)
+ (rst-forward-line-strict 0)
+ (setq pt (point))
+ (while (and (not (looking-at stop-re))
+ (zerop (rst-forward-line dir)))) ; try previous / next
+ ; line if it exists.
+ (if (looking-at (rst-re 'ado-beg-2-1)) ; may be an underline /
+ ; overline.
+ (if (zerop (rst-forward-line dir))
+ (if (looking-at (rst-re 'ttl-beg-1)) ; title found, i.e.
+ ; underline / overline
+ ; found.
+ (if (zerop (rst-forward-line dir))
+ (if (not
+ (looking-at (rst-re 'ado-beg-2-1))) ; no
+ ; overline
+ ; /
+ ; underline.
+ (rst-forward-line (- dir)))) ; step back to
+ ; title /
+ ; adornment.
+ (if (< dir 0) ; keep downward adornment.
+ (rst-forward-line (- dir))))) ; step back to adornment.
+ (if (looking-at (rst-re 'ttl-beg-1)) ; may be a title.
+ (if (zerop (rst-forward-line dir))
+ (if (not
+ (looking-at (rst-re 'ado-beg-2-1))) ; no overline /
+ ; underline.
+ (rst-forward-line (- dir)))))) ; step back to line.
+ (if (not (= (point) pt))
+ (point)))))))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Indented blocks
+
+(defun rst-forward-indented-block (&optional column limit)
+ ;; testcover: ok.
+ "Move forward across one indented block.
+Find the next (i.e. excluding the current line) non-empty line
+which is not indented at least to COLUMN (defaults to the column
+of the point). Move point to first character of this line or the
+first of the empty lines immediately before it and return that
+position. If there is no such line before LIMIT (defaults to the
+end of the buffer) return nil and do not move point."
+ (let (fnd candidate)
+ (setq fnd (rst-apply-indented-blocks
+ (line-beginning-position 2) ; Skip the current line
+ (or limit (point-max)) (or column (current-column))
+ #'(lambda (_count _in-first _in-sub in-super in-empty _relind)
+ (cond
+ (in-empty
+ (setq candidate (or candidate (line-beginning-position)))
+ nil)
+ (in-super
+ (or candidate (line-beginning-position)))
+ (t ; Non-empty, same or more indented line.
+ (setq candidate nil)
+ nil)))))
+ (when fnd
+ (goto-char fnd))))
+
+(defvar rst-font-lock-find-unindented-line-begin nil
+ "Beginning of the match if `rst-font-lock-find-unindented-line-end'.")
+
+(defvar rst-font-lock-find-unindented-line-end nil
+ "End of the match as determined by `rst-font-lock-find-unindented-line-limit'.
+Also used as a trigger for `rst-font-lock-find-unindented-line-match'.")
+
+(defun rst-font-lock-find-unindented-line-limit (ind-pnt)
+ "Find the next unindented line relative to indentation at IND-PNT.
+Return this point, the end of the buffer or nil if nothing found.
+If IND-PNT is `next' take the indentation from the next line if
+this is not empty and indented more than the current one. If
+IND-PNT is non-nil but not a number take the indentation from the
+next non-empty line if this is indented more than the current one."
+ (setq rst-font-lock-find-unindented-line-begin ind-pnt)
+ (setq rst-font-lock-find-unindented-line-end
+ (save-match-data
+ (save-excursion
+ (when (not (numberp ind-pnt))
+ ;; Find indentation point in next line if any.
+ (setq ind-pnt
+ ;; FIXME: Should be refactored to two different functions
+ ;; giving their result to this function, may be
+ ;; integrated in caller.
+ (save-match-data
+ (let ((cur-ind (current-indentation)))
+ (if (eq ind-pnt 'next)
+ (when (and (rst-forward-line-strict 1 (point-max))
+ (< (point) (point-max)))
+ ;; Not at EOF.
+ (setq rst-font-lock-find-unindented-line-begin
+ (point))
+ (when (and (not (looking-at (rst-re 'lin-end)))
+ (> (current-indentation) cur-ind))
+ ;; Use end of indentation if non-empty line.
+ (looking-at (rst-re 'hws-tag))
+ (match-end 0)))
+ ;; Skip until non-empty line or EOF.
+ (while (and (rst-forward-line-strict 1 (point-max))
+ (< (point) (point-max))
+ (looking-at (rst-re 'lin-end))))
+ (when (< (point) (point-max))
+ ;; Not at EOF.
+ (setq rst-font-lock-find-unindented-line-begin
+ (point))
+ (when (> (current-indentation) cur-ind)
+ ;; Indentation bigger than line of departure.
+ (looking-at (rst-re 'hws-tag))
+ (match-end 0))))))))
+ (when ind-pnt
+ (goto-char ind-pnt)
+ (or (rst-forward-indented-block nil (point-max))
+ (point-max)))))))
+
+(defun rst-font-lock-find-unindented-line-match (_limit)
+ "Set the match found earlier if match were found.
+Match has been found by `rst-font-lock-find-unindented-line-limit'
+the first time called or no match is found. Return non-nil if
+match was found. _LIMIT is not used but mandated by the caller."
+ (when rst-font-lock-find-unindented-line-end
+ (set-match-data
+ (list rst-font-lock-find-unindented-line-begin
+ rst-font-lock-find-unindented-line-end))
+ (put-text-property rst-font-lock-find-unindented-line-begin
+ rst-font-lock-find-unindented-line-end
+ 'font-lock-multiline t)
+ ;; Make sure this is called only once.
+ (setq rst-font-lock-find-unindented-line-end nil)
+ t))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Adornments
+
+(defvar rst-font-lock-adornment-level nil
+ "Storage for `rst-font-lock-handle-adornment-matcher'.
+Either section level of the current adornment or t for a transition.")
+
+(defun rst-adornment-level (ado)
+ "Return section level for ADO or t for a transition.
+If ADO is found in the hierarchy return its level. Otherwise
+return a level one beyond the existing hierarchy."
+ (if (rst-Ado-is-transition ado)
+ t
+ (let ((hier (rst-Hdr-ado-map (rst-hdr-hierarchy))))
+ (1+ (or (rst-Ado-position ado hier)
+ (length hier))))))
+
+(defvar rst-font-lock-adornment-match nil
+ "Storage for match for current adornment.
+Set by `rst-font-lock-handle-adornment-pre-match-form'. Also used
+as a trigger for `rst-font-lock-handle-adornment-matcher'.")
+
+(defun rst-font-lock-handle-adornment-pre-match-form (ado ado-end)
+ "Determine limit for adornments.
+Determine all things necessary for font-locking section titles
+and transitions and put the result to `rst-font-lock-adornment-match'
+and `rst-font-lock-adornment-level'. ADO is the complete adornment
+matched. ADO-END is the point where ADO ends. Return the point
+where the whole adorned construct ends.
+
+Called as a PRE-MATCH-FORM in the sense of `font-lock-keywords'."
+ (let ((ttl (rst-classify-adornment ado ado-end)))
+ (if (not ttl)
+ (setq rst-font-lock-adornment-level nil
+ rst-font-lock-adornment-match nil)
+ (setq rst-font-lock-adornment-level
+ (rst-adornment-level (rst-Ttl-ado ttl)))
+ (setq rst-font-lock-adornment-match (rst-Ttl-match ttl))
+ (goto-char (rst-Ttl-get-beginning ttl))
+ (rst-Ttl-get-end ttl))))
+
+(defun rst-font-lock-handle-adornment-matcher (_limit)
+ "Set the match found earlier if match were found.
+Match has been found by
+`rst-font-lock-handle-adornment-pre-match-form' the first time
+called or no match is found. Return non-nil if match was found.
+
+Called as a MATCHER in the sense of `font-lock-keywords'.
+_LIMIT is not used but mandated by the caller."
+ (let ((match rst-font-lock-adornment-match))
+ ;; May run only once - enforce this.
+ (setq rst-font-lock-adornment-match nil)
+ (when match
+ (set-match-data match)
+ (goto-char (match-end 0))
+ (put-text-property (match-beginning 0) (match-end 0)
+ 'font-lock-multiline t)
+ t)))
+
+\f
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Compilation
+
+(defgroup rst-compile nil
+ "Settings for support of conversion of reStructuredText
+document with \\[rst-compile]."
+ :group 'rst
+ :version "21.1")
+
+(defcustom rst-compile-toolsets
+ `((html ,(if (executable-find "rst2html.py") "rst2html.py" "rst2html")
+ ".html" nil)
+ (latex ,(if (executable-find "rst2latex.py") "rst2latex.py" "rst2latex")
+ ".tex" nil)
+ (newlatex ,(if (executable-find "rst2newlatex.py") "rst2newlatex.py"
+ "rst2newlatex")
+ ".tex" nil)
+ (pseudoxml ,(if (executable-find "rst2pseudoxml.py") "rst2pseudoxml.py"
+ "rst2pseudoxml")
+ ".xml" nil)
+ (xml ,(if (executable-find "rst2xml.py") "rst2xml.py" "rst2xml")
+ ".xml" nil)
+ (pdf ,(if (executable-find "rst2pdf.py") "rst2pdf.py" "rst2pdf")
+ ".pdf" nil)
+ (s5 ,(if (executable-find "rst2s5.py") "rst2s5.py" "rst2s5")
+ ".html" nil))
+ ;; FIXME: Add at least those converters officially supported like `rst2odt'
+ ;; and `rst2man'.
+ ;; FIXME: To make this really useful there should be a generic command the
+ ;; user gives one of the symbols and this way select the conversion to
+ ;; run. This should replace the toolset stuff somehow.
+ ;; FIXME: Allow a template for the conversion command so `rst2pdf ... -o ...'
+ ;; can be supported.
+ "Table describing the command to use for each tool-set.
+An association list of the tool-set to a list of the (command to use,
+extension of produced filename, options to the tool (nil or a
+string)) to be used for converting the document."
+ ;; FIXME: These are not options but symbols which may be referenced by
+ ;; `rst-compile-*-toolset` below. The `:validate' keyword of
+ ;; `defcustom' may help to define this properly in newer Emacs
+ ;; versions (> 23.1).
+ :type '(alist :options (html latex newlatex pseudoxml xml pdf s5)
+ :key-type symbol
+ :value-type (list :tag "Specification"
+ (file :tag "Command")
+ (string :tag "File extension")
+ (choice :tag "Command options"
+ (const :tag "No options" nil)
+ (string :tag "Options"))))
+ :group 'rst-compile
+ :package-version "1.2.0")
+(rst-testcover-defcustom)
+
+;; FIXME: Must be defcustom.
+(defvar rst-compile-primary-toolset 'html
+ "The default tool-set for `rst-compile'.")
+
+;; FIXME: Must be defcustom.
+(defvar rst-compile-secondary-toolset 'latex
+ "The default tool-set for `rst-compile' with a prefix argument.")
+
+(defun rst-compile-find-conf ()
+ "Look for the configuration file in the parents of the current path."
+ (interactive)
+ (let ((file-name "docutils.conf")
+ (buffer-file (buffer-file-name)))
+ ;; Move up in the dir hierarchy till we find a change log file.
+ (let* ((dir (file-name-directory buffer-file))
+ (prevdir nil))
+ (while (and (or (not (string= dir prevdir))
+ (setq dir nil)
+ nil)
+ (not (file-exists-p (concat dir file-name))))
+ ;; Move up to the parent dir and try again.
+ (setq prevdir dir)
+ (setq dir (expand-file-name (file-name-directory
+ (directory-file-name
+ (file-name-directory dir))))))
+ (or (and dir (concat dir file-name)) nil))))
+
+(require 'compile)
+
+(defun rst-compile (&optional use-alt)
+ "Compile command to convert reST document into some output file.
+Attempts to find configuration file, if it can, overrides the
+options. There are two commands to choose from; with USE-ALT,
+select the alternative tool-set."
+ (interactive "P")
+ ;; Note: maybe we want to check if there is a Makefile too and not do anything
+ ;; if that is the case. I dunno.
+ (cl-destructuring-bind
+ (command extension options
+ &aux (conffile (rst-compile-find-conf))
+ (bufname (file-name-nondirectory buffer-file-name)))
+ (cdr (assq (if use-alt
+ rst-compile-secondary-toolset
+ rst-compile-primary-toolset)
+ rst-compile-toolsets))
+ ;; Set compile-command before invocation of compile.
+ (setq-local
+ compile-command
+ (mapconcat
+ #'identity
+ (list command
+ (or options "")
+ (if conffile
+ (concat "--config=" (shell-quote-argument conffile))
+ "")
+ (shell-quote-argument bufname)
+ (shell-quote-argument (concat (file-name-sans-extension bufname)
+ extension)))
+ " "))
+ ;; Invoke the compile command.
+ (if (or compilation-read-command use-alt)
+ (call-interactively #'compile)
+ (compile compile-command))))
+
+(defun rst-compile-alt-toolset ()
+ "Compile command with the alternative tool-set."
+ (interactive)
+ (rst-compile t))
+
+(defun rst-compile-pseudo-region ()
+ "Show pseudo-XML rendering.
+Rendering is done of the current active region, or of the entire
+buffer, if the region is not selected."
+ ;; FIXME: The region should be given interactively.
+ (interactive)
+ (with-output-to-temp-buffer "*pseudoxml*"
+ (shell-command-on-region
+ (if mark-active (region-beginning) (point-min))
+ (if mark-active (region-end) (point-max))
+ (cadr (assq 'pseudoxml rst-compile-toolsets))
+ standard-output)))
+
+;; FIXME: Should be integrated in `rst-compile-toolsets'.
+(defvar rst-pdf-program "xpdf"
+ "Program used to preview PDF files.")
+
+(defun rst-compile-pdf-preview ()
+ "Convert the document to a PDF file and launch a preview program."
+ (interactive)
+ (let* ((tmp-filename (make-temp-file "rst_el" nil ".pdf"))
+ (command (format "%s %s %s && %s %s ; rm %s"
+ (cadr (assq 'pdf rst-compile-toolsets))
+ buffer-file-name tmp-filename
+ rst-pdf-program tmp-filename tmp-filename)))
+ (start-process-shell-command "rst-pdf-preview" nil command)
+ ;; Note: you could also use (compile command) to view the compilation
+ ;; output.
+ ))
+
+;; FIXME: Should be integrated in `rst-compile-toolsets' defaulting to
+;; something like `browse-url'.
+(defvar rst-slides-program "firefox"
+ "Program used to preview S5 slides.")
+
+(defun rst-compile-slides-preview ()
+ "Convert the document to an S5 slide presentation and launch a preview program."
+ (interactive)
+ (let* ((tmp-filename (make-temp-file "rst_el" nil ".html"))
+ (command (format "%s %s %s && %s %s ; rm %s"
+ (cadr (assq 's5 rst-compile-toolsets))
+ buffer-file-name tmp-filename
+ rst-slides-program tmp-filename tmp-filename)))
+ (start-process-shell-command "rst-slides-preview" nil command)
+ ;; Note: you could also use (compile command) to view the compilation
+ ;; output.
+ ))
+
+;; FIXME: Add `rst-compile-html-preview'.
+
+;; FIXME: Add support for `restview` (http://mg.pov.lt/restview/). May be a
+;; more general facility for calling commands on a reST file would make
+;; sense.
+
+\f
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Imenu support
+
+;; FIXME: Consider a key binding. A key binding needs to definitely switch on
+;; `which-func-mode' - i.e. `which-func-modes' must be set properly.
+
+;; Based on ideas from Masatake YAMATO <yamato@redhat.com>.
+
+(defun rst-imenu-convert-cell (stn)
+ "Convert a STN to an Imenu index node and return it."
+ (let ((ttl (rst-Stn-ttl stn))
+ (children (rst-Stn-children stn))
+ (pos (rst-Stn-get-title-beginning stn))
+ (txt (rst-Stn-get-text stn ""))
+ (pfx " ")
+ (sfx "")
+ name)
+ (when ttl
+ (let ((hdr (rst-Ttl-hdr ttl)))
+ (setq pfx (char-to-string (rst-Hdr-get-char hdr)))
+ (when (rst-Hdr-is-over-and-under hdr)
+ (setq sfx pfx))))
+ ;; FIXME: Overline adornment characters need to be in front so they
+ ;; become visible even for long title lines. May be an additional
+ ;; level number is also useful.
+ (setq name (format "%s%s%s" pfx txt sfx))
+ (cons name ; The name of the entry.
+ (if children
+ (cons ; The entry has a submenu.
+ (cons name pos) ; The entry itself.
+ (mapcar #'rst-imenu-convert-cell children)) ; The children.
+ pos)))) ; The position of a plain entry.
+
+;; FIXME: Document title and subtitle need to be handled properly. They should
+;; get an own "Document" top level entry.
+(defun rst-imenu-create-index ()
+ "Create index for Imenu.
+Return as described for `imenu--index-alist'."
+ (rst-reset-section-caches)
+ (let ((root (rst-all-stn)))
+ (when root
+ (mapcar #'rst-imenu-convert-cell (rst-Stn-children root)))))
+
+\f
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Convenience functions
+
+;; FIXME: Unbound command - should be bound or removed.
+(defun rst-replace-lines (fromchar tochar)
+ "Replace flush-left lines of FROMCHAR with equal-length lines of TOCHAR."
+ (interactive "\
+cSearch for flush-left lines of char:
+cand replace with char: ")
+ (save-excursion
+ (let ((searchre (rst-re "^" fromchar "+\\( *\\)$"))
+ (found 0))
+ (while (search-forward-regexp searchre nil t)
+ (setq found (1+ found))
+ (goto-char (match-beginning 1))
+ (let ((width (current-column)))
+ (rst-delete-entire-line 0)
+ (insert-char tochar width)))
+ (message "%d lines replaced." found))))
+
+;; FIXME: Unbound command - should be bound or removed.
+(defun rst-join-paragraph ()
+ "Join lines in current paragraph into one line, removing end-of-lines."
+ (interactive)
+ (let ((fill-column 65000)) ; Some big number.
+ (call-interactively #'fill-paragraph)))
+
+;; FIXME: Unbound command - should be bound or removed.
+(defun rst-force-fill-paragraph ()
+ "Fill paragraph at point, first joining the paragraph's lines into one.
+This is useful for filling list item paragraphs."
+ (interactive)
+ (rst-join-paragraph)
+ (fill-paragraph nil))
+
+
+;; FIXME: Unbound command - should be bound or removed.
+;; Generic character repeater function.
+;; For sections, better to use the specialized function above, but this can
+;; be useful for creating separators.
+(defun rst-repeat-last-character (use-next)
+ "Fill the current line using the last character on the current line.
+Fill up to the length of the preceding line or up to `fill-column' if preceding
+line is empty.
+
+If USE-NEXT, use the next line rather than the preceding line.
+
+If the current line is longer than the desired length, shave the characters off
+the current line to fit the desired length.
+
+As an added convenience, if the command is repeated immediately, the alternative
+column is used (fill-column vs. end of previous/next line)."
+ (interactive "P")
+ (let* ((curcol (current-column))
+ (curline (+ (count-lines (point-min) (point))
+ (if (zerop curcol) 1 0)))
+ (lbp (line-beginning-position 0))
+ (prevcol (if (and (= curline 1) (not use-next))
+ fill-column
+ (save-excursion
+ (forward-line (if use-next 1 -1))
+ (end-of-line)
+ (skip-chars-backward " \t" lbp)
+ (let ((cc (current-column)))
+ (if (zerop cc) fill-column cc)))))
+ (rightmost-column
+ (cond ((equal last-command 'rst-repeat-last-character)
+ (if (= curcol fill-column) prevcol fill-column))
+ (t (save-excursion
+ (if (zerop prevcol) fill-column prevcol))))))
+ (end-of-line)
+ (if (> (current-column) rightmost-column)
+ ;; Shave characters off the end.
+ (delete-region (- (point)
+ (- (current-column) rightmost-column))
+ (point))
+ ;; Fill with last characters.
+ (insert-char (preceding-char)
+ (- rightmost-column (current-column))))))
+
+\f
+
+;; LocalWords: docutils http sourceforge rst html wp svn svnroot txt reST regex
+;; LocalWords: regexes alist seq alt grp keymap abbrev overline overlines toc
+;; LocalWords: XML PNT propertized init referenceable
+
+(provide 'rst)
+
+;; Local Variables:
+;; sentence-end-double-space: t
+;; End:
+
+;;; rst.el ends here
--- /dev/null
+;; Tests for class `rst-Ado' -*- lexical-binding: t -*-
+
+(add-to-list 'load-path ".")
+(load "init" nil t)
+(init-rst-ert nil)
+
+(ert-deftest rst-Ado-new-transition ()
+ "Test `rst-Ado-new-transition'."
+ (should (rst-Ado-p (rst-Ado-new-transition)))
+ )
+
+(ert-deftest rst-Ado-new-simple ()
+ "Test `rst-Ado-new-simple'."
+ (should-error (rst-Ado-new-simple nil)
+ :type 'wrong-type-argument)
+ (should-error (rst-Ado-new-simple "=")
+ :type 'wrong-type-argument)
+
+ (should-error (rst-Ado-new-simple ?a)
+ :type 'wrong-type-argument)
+
+ (should (rst-Ado-p (rst-Ado-new-simple ?=)))
+ )
+
+(ert-deftest rst-Ado-new-over-and-under ()
+ "Test `rst-Ado-new-over-and-under'."
+ (should-error (rst-Ado-new-over-and-under nil)
+ :type 'wrong-type-argument)
+ (should-error (rst-Ado-new-over-and-under "=")
+ :type 'wrong-type-argument)
+
+ (should-error (rst-Ado-new-over-and-under ?a)
+ :type 'wrong-type-argument)
+
+ (should (rst-Ado-p (rst-Ado-new-over-and-under ?=)))
+ )
+
+(ert-deftest rst-Ado-new-invert ()
+ "Test `rst-Ado-new-invert'."
+ (let ((dbl-eq (rst-Ado-new-over-and-under ?=))
+ (spl-eq (rst-Ado-new-simple ?=))
+ (tsn (rst-Ado-new-transition)))
+ (should (rst-Ado-equal (rst-Ado-new-invert dbl-eq) spl-eq))
+ (should (rst-Ado-equal (rst-Ado-new-invert spl-eq) dbl-eq))
+ (should (rst-Ado-equal (rst-Ado-new-invert tsn) tsn))
+ ))
+
+(ert-deftest rst-Ado-is-transition ()
+ "Test `rst-Ado-is-transition'."
+ (should-error (rst-Ado-is-transition nil)
+ :type 'wrong-type-argument)
+ (should-error (rst-Ado-is-transition 3)
+ :type 'wrong-type-argument)
+
+ (should (rst-Ado-is-transition (rst-Ado-new-transition)))
+
+ (should-not (rst-Ado-is-transition (rst-Ado-new-simple ?=)))
+ )
+
+(ert-deftest rst-Ado-is-section ()
+ "Test `rst-Ado-is-section'."
+ (should-error (rst-Ado-is-section nil)
+ :type 'wrong-type-argument)
+ (should-error (rst-Ado-is-section 3)
+ :type 'wrong-type-argument)
+
+ (should (rst-Ado-is-section (rst-Ado-new-simple ?=)))
+
+ (should-not (rst-Ado-is-section (rst-Ado-new-transition)))
+ )
+
+(ert-deftest rst-Ado-is-simple ()
+ "Test `rst-Ado-is-simple'."
+ (should-error (rst-Ado-is-simple nil)
+ :type 'wrong-type-argument)
+ (should-error (rst-Ado-is-simple 3)
+ :type 'wrong-type-argument)
+
+ (should (rst-Ado-is-simple (rst-Ado-new-simple ?=)))
+
+ (should-not (rst-Ado-is-simple (rst-Ado-new-transition)))
+ (should-not (rst-Ado-is-simple (rst-Ado-new-over-and-under ?=)))
+ )
+
+(ert-deftest rst-Ado-is-over-and-under ()
+ "Test `rst-Ado-is-over-and-under'."
+ (should-error (rst-Ado-is-over-and-under nil)
+ :type 'wrong-type-argument)
+ (should-error (rst-Ado-is-over-and-under 3)
+ :type 'wrong-type-argument)
+
+ (should (rst-Ado-is-over-and-under (rst-Ado-new-over-and-under ?=)))
+
+ (should-not (rst-Ado-is-over-and-under (rst-Ado-new-transition)))
+ (should-not (rst-Ado-is-over-and-under (rst-Ado-new-simple ?=)))
+ )
+
+(ert-deftest rst-Ado-equal ()
+ "Test `rst-Ado-equal'."
+ (let ((dbl-eq (rst-Ado-new-over-and-under ?=))
+ (dbl-pl (rst-Ado-new-over-and-under ?+))
+ (spl-eq (rst-Ado-new-simple ?=))
+ (spl-pl (rst-Ado-new-simple ?+))
+ (tsn (rst-Ado-new-transition)))
+ (should-error (rst-Ado-equal nil dbl-eq)
+ :type 'wrong-type-argument)
+ (should-error (rst-Ado-equal dbl-eq nil)
+ :type 'wrong-type-argument)
+ (should-error (rst-Ado-equal dbl-eq 3)
+ :type 'wrong-type-argument)
+ (should-error (rst-Ado-equal 'some-sym dbl-eq)
+ :type 'wrong-type-argument)
+
+ (should (rst-Ado-equal dbl-eq dbl-eq))
+ (should (rst-Ado-equal spl-eq spl-eq))
+ (should (rst-Ado-equal spl-pl spl-pl))
+
+ (should-not (rst-Ado-equal dbl-eq dbl-pl))
+ (should-not (rst-Ado-equal dbl-eq spl-eq))
+ (should-not (rst-Ado-equal dbl-eq spl-pl))
+ (should-not (rst-Ado-equal dbl-eq tsn))
+ (should-not (rst-Ado-equal spl-eq spl-pl))
+ (should-not (rst-Ado-equal spl-eq tsn))
+ ))
+
+(ert-deftest rst-Ado-position ()
+ "Test `rst-Ado-position'."
+ (let ((dbl-eq (rst-Ado-new-over-and-under ?=))
+ (dbl-pl (rst-Ado-new-over-and-under ?+))
+ (spl-eq (rst-Ado-new-simple ?=))
+ (spl-pl (rst-Ado-new-simple ?+))
+ (tsn- (rst-Ado-new-transition)))
+ (let* ((tsn (list tsn-))
+ (spl_tsn (cons spl-eq tsn))
+ (dbl_spl_tsn (cons dbl-eq spl_tsn)))
+ (should-error (rst-Ado-position nil nil)
+ :type 'wrong-type-argument)
+ (should-error (rst-Ado-position 3 nil)
+ :type 'wrong-type-argument)
+ (should-error (rst-Ado-position dbl-eq '(3))
+ :type 'wrong-type-argument)
+
+ (should (equal (rst-Ado-position tsn- dbl_spl_tsn) 2))
+ (should (equal (rst-Ado-position tsn- tsn) 0))
+ (should (equal (rst-Ado-position spl-eq dbl_spl_tsn) 1))
+ (should (equal (rst-Ado-position dbl-eq dbl_spl_tsn) 0))
+
+ (should-not (rst-Ado-position dbl-pl dbl_spl_tsn))
+ (should-not (rst-Ado-position spl-pl dbl_spl_tsn))
+ )))
--- /dev/null
+;; Tests for class `rst-Hdr' -*- lexical-binding: t -*-
+
+(add-to-list 'load-path ".")
+(load "init" nil t)
+(init-rst-ert nil)
+
+(ert-deftest rst-Hdr-new-ok ()
+ "Test `rst-Hdr-new' with valid values."
+ (should (rst-Hdr-p (rst-Hdr-new (rst-Ado-new-simple ?~) 0)))
+ (should (rst-Hdr-p (rst-Hdr-new (rst-Ado-new-over-and-under ?~) 0)))
+ (should (rst-Hdr-p (rst-Hdr-new (rst-Ado-new-over-and-under ?+) 10)))
+ )
+
+(ert-deftest rst-Hdr-new-wrong-type ()
+ "Test `rst-Hdr-new' with wrong types."
+ (should-error (rst-Hdr-new (rst-Ado-new-simple ?~) nil)
+ :type 'wrong-type-argument)
+ (should-error (rst-Hdr-new (rst-Ado-new-simple ?~) "10")
+ :type 'wrong-type-argument)
+ )
+
+(ert-deftest rst-Hdr-new-invalid ()
+ "Test `rst-Hdr-new' with invalid values."
+ (should-error (rst-Hdr-new (rst-Ado-new-simple ?=) 10)
+ :type 'args-out-of-range)
+ (should-error (rst-Hdr-new (rst-Ado-new-over-and-under ?=) -10)
+ :type 'args-out-of-range)
+ (should-error (rst-Hdr-new (rst-Ado-new-transition) 0)
+ :type 'args-out-of-range)
+ )
+
+(ert-deftest rst-Hdr-new-lax-ok ()
+ "Test `rst-Hdr-new-lax' with valid values."
+ (should (rst-Hdr-p (rst-Hdr-new-lax (rst-Ado-new-simple ?~) 0)))
+ (should (rst-Hdr-p (rst-Hdr-new-lax (rst-Ado-new-over-and-under ?~) 0)))
+ (should (rst-Hdr-p (rst-Hdr-new-lax (rst-Ado-new-over-and-under ?+) 10)))
+ (should (rst-Hdr-p (rst-Hdr-new-lax (rst-Ado-new-simple ?=) 10)))
+ (should (rst-Hdr-p (rst-Hdr-new-lax (rst-Ado-new-over-and-under ?=) -10)))
+ )
+
+(ert-deftest rst-Hdr-new-lax-wrong-type ()
+ "Test `rst-Hdr-new-lax' with wrong types."
+ (should-error (rst-Hdr-new-lax nil 0)
+ :type 'wrong-type-argument)
+ (should-error (rst-Hdr-new-lax "=" 0)
+ :type 'wrong-type-argument)
+ )
+
+(ert-deftest rst-Hdr-new-invert ()
+ "Test `rst-Hdr-new-invert'."
+ (let* ((dbl-eq (rst-Ado-new-over-and-under ?=))
+ (spl-eq (rst-Ado-new-simple ?=))
+ (dbl-eq-1 (rst-Hdr-new dbl-eq 1))
+ (dbl-eq-0 (rst-Hdr-new dbl-eq 0))
+ (spl-eq-0 (rst-Hdr-new spl-eq 0)))
+ (should (equal (rst-Hdr-new-invert dbl-eq 0) spl-eq-0))
+ (should (equal (rst-Hdr-new-invert dbl-eq 1) spl-eq-0))
+ (should (equal (rst-Hdr-new-invert spl-eq 0) dbl-eq-0))
+ (should (equal (rst-Hdr-new-invert spl-eq 1) dbl-eq-1))
+ ))
+
+(ert-deftest rst-Hdr-preferred-adornments ()
+ "Test `rst-Hdr-preferred-adornments'."
+ (let* ((dbl-eq (rst-Ado-new-over-and-under ?=))
+ (spl-dt (rst-Ado-new-simple ?.))
+ (dbl-eq-1 (rst-Hdr-new dbl-eq 1))
+ (dbl-eq-0 (rst-Hdr-new dbl-eq 0))
+ (spl-dt-0 (rst-Hdr-new spl-dt 0))
+ (rst-preferred-adornments '((?= over-and-under 1)
+ (?= over-and-under 0)
+ (?. simple 0))))
+ (should (equal (rst-Hdr-preferred-adornments)
+ (list dbl-eq-1 dbl-eq-0 spl-dt-0)))))
+
+(ert-deftest rst-Hdr-member-ado ()
+ "Test `rst-Hdr-member-ado'."
+ (let ((dbl-eq-1 (rst-Hdr-new (rst-Ado-new-over-and-under ?=) 1))
+ (dbl-eq-3 (rst-Hdr-new (rst-Ado-new-over-and-under ?=) 3))
+ (dbl-eq-0 (rst-Hdr-new (rst-Ado-new-over-and-under ?=) 0))
+ (dbl-pl-0 (rst-Hdr-new (rst-Ado-new-over-and-under ?+) 0))
+ (spl-pl-0 (rst-Hdr-new (rst-Ado-new-simple ?+) 0))
+ (spl-td-0 (rst-Hdr-new (rst-Ado-new-simple ?~) 0))
+ (spl-eq-0 (rst-Hdr-new (rst-Ado-new-simple ?=) 0)))
+ (let* ((spk (list spl-pl-0))
+ (spl_spk (cons spl-eq-0 spk))
+ (dbl_spl_spk (cons dbl-eq-0 spl_spk)))
+ (should-error (rst-Hdr-member-ado nil nil)
+ :type 'wrong-type-argument)
+ (should-error (rst-Hdr-member-ado 3 nil)
+ :type 'wrong-type-argument)
+
+ (should (eq (rst-Hdr-member-ado spl-pl-0 dbl_spl_spk) spk))
+ (should (eq (rst-Hdr-member-ado spl-pl-0 spk) spk))
+ (should (eq (rst-Hdr-member-ado spl-eq-0 dbl_spl_spk) spl_spk))
+ (should (eq (rst-Hdr-member-ado dbl-eq-3 dbl_spl_spk) dbl_spl_spk))
+
+ (should-not (rst-Hdr-member-ado dbl-pl-0 dbl_spl_spk))
+ (should-not (rst-Hdr-member-ado spl-td-0 dbl_spl_spk))
+ )))
+
+(ert-deftest rst-Hdr-get-char ()
+ "Test `rst-Hdr-get-char'."
+ (should-error (rst-Hdr-get-char nil)
+ :type 'wrong-type-argument)
+ (should-error (rst-Hdr-get-char "=")
+ :type 'wrong-type-argument)
+
+ (should (equal (rst-Hdr-get-char (rst-Hdr-new (rst-Ado-new-simple ?=) 0))
+ ?=))
+ )
+
+(ert-deftest rst-Hdr-is-over-and-under ()
+ "Test `rst-Hdr-is-over-and-under'."
+ (should-error (rst-Hdr-is-over-and-under nil)
+ :type 'wrong-type-argument)
+ (should-error (rst-Hdr-is-over-and-under "=")
+ :type 'wrong-type-argument)
+
+ (should (rst-Hdr-is-over-and-under
+ (rst-Hdr-new (rst-Ado-new-over-and-under ?=) 0)))
+ (should-not (rst-Hdr-is-over-and-under
+ (rst-Hdr-new (rst-Ado-new-simple ?=) 0)))
+ )
--- /dev/null
+#!/usr/bin/env make
+
+EMACS = /usr/bin/emacs
+ERT = ~/lib/emacs/ert
+RST_EL = ../rst.el
+
+EMACS_ERT_PFX = $(EMACS) --batch --quick --directory=$(ERT) --load=ert.el
+EMACS_ERT_SFX = --funcall=ert-run-tests-batch-and-exit
+
+ERT_TESTS := $(filter-out ert-%,$(wildcard *.el))
+
+EMACS_COMPILE_PFX = $(EMACS) --batch --quick --eval '(progn \
+ (setq byte-compile-error-on-warn t) \
+ (kill-emacs (if (byte-compile-file
+EMACS_COMPILE_SFX = ) 0 1)))'
+
+all: compile tests
+
+tests:
+ $(EMACS_ERT_PFX) $(addprefix -l ,$(ERT_TESTS)) $(EMACS_ERT_SFX)
+
+compile:
+ $(EMACS_COMPILE_PFX) "$(RST_EL)" $(EMACS_COMPILE_SFX)
+
+clean:
--- /dev/null
+====================
+ Tests for rst.el
+====================
+
+:Author: Martin Blais <blais@furius.ca>, Stefan Merten <smerten@oekonux.de>
+
+The tests are using ERT_. You need to install ERT_ for to run them. If
+you did you should change the path to the library contained in the
+variable `ERT` in `Makefile`.
+
+To run the tests in Emacs use the facilities provided by ERT_. Namely
+evaluate the buffer containing the tests and do::
+
+ M-x ert [RETURN] [RETURN]
+
+To run the tests by `make` use ::
+
+ make ert-tests
+
+.. _ERT: http://www.emacswiki.org/emacs/ErtTestLibrary
--- /dev/null
+;; Tests for class `rst-Stn' -*- lexical-binding: t -*-
+
+(add-to-list 'load-path ".")
+(load "init" nil t)
+(init-rst-ert nil)
+
+(ert-deftest rst-Stn-new ()
+ "Test `rst-Stn-new'."
+ (let* (;; "
+ ;; =====
+ ;; Title
+ ;; =====
+ ;;
+ ;; Header A
+ ;; ========
+ ;;
+ ;; Header B
+ ;; ========
+ ;;
+ ;; Subheader B.a
+ ;; -------------
+ ;;
+ ;; SubSubheader B.a.1
+ ;; ~~~~~~~~~~~~~~~~~~
+ ;;
+ ;; Header C
+ ;; ========
+ ;;
+ ;; Missing node C.a.1
+ ;; ~~~~~~~~~~~~~~~~~~
+ ;; "
+ (ado-T (rst-Ado-new-over-and-under ?=))
+ (ttl-T (rst-Ttl--new ado-T '(1 18 1 6 7 12 13 18) 0
+ "Title"))
+ (ado-A (rst-Ado-new-simple ?=))
+ (ttl-A (rst-Ttl--new ado-A '(20 37 nil nil 20 28 29 37) 0
+ "Header A"))
+ (ttl-B (rst-Ttl--new ado-A '(39 56 nil nil 39 47 48 56) 0
+ "Header B"))
+ (ado-Ba (rst-Ado-new-simple ?-))
+ (ttl-Ba (rst-Ttl--new ado-Ba '(58 85 nil nil 58 71 72 85) 0
+ "Subheader B.a"))
+ (ado-Ba1 (rst-Ado-new-simple ?~))
+ (ttl-Ba1 (rst-Ttl--new ado-Ba1 '(87 124 nil nil 87 105 106 124) 0
+ "SubSubheader B.a.1"))
+ (ttl-C (rst-Ttl--new ado-A '(126 143 nil nil 126 134 135 143) 0
+ "Header C"))
+ (ttl-Ca nil)
+ (ttl-Ca1 (rst-Ttl--new ado-Ba1 '(145 182 nil nil 145 163 164 182) 0
+ "Missing node C.a.1")))
+
+ (should-error (rst-Stn-new "" 0 nil)
+ :type 'wrong-type-argument)
+ (should-error (rst-Stn-new nil "0" nil)
+ :type 'wrong-type-argument)
+ (should-error (rst-Stn-new nil 0 "")
+ :type 'wrong-type-argument)
+ (should-error (rst-Stn-new nil 0 '(1))
+ :type 'wrong-type-argument)
+
+ (should-error (rst-Stn-new nil 0 nil)
+ :type 'args-out-of-range)
+
+ (should-error (rst-Stn-new ttl-T -1 nil)
+ :type 'args-out-of-range)
+
+ (should (rst-Stn-p
+ (rst-Stn-new ttl-T 0 nil)))
+ (should (rst-Stn-p
+ (rst-Stn-new
+ ttl-T 0
+ (list (rst-Stn-new ttl-A 1 nil)))))
+ (should (rst-Stn-p
+ (rst-Stn-new
+ ttl-T 0
+ (list (rst-Stn-new ttl-A 1 nil)
+ (rst-Stn-new ttl-B 1 nil)
+ (rst-Stn-new ttl-C 1 nil)))))
+ (should (rst-Stn-p
+ (rst-Stn-new
+ ttl-T 0
+ (list (rst-Stn-new ttl-A 1 nil)
+ (rst-Stn-new
+ ttl-B 1
+ (list (rst-Stn-new
+ ttl-Ba 2
+ (list (rst-Stn-new ttl-Ba1 3 nil)))))
+ (rst-Stn-new
+ ttl-C 1
+ (list (rst-Stn-new
+ ttl-Ca 2
+ (list (rst-Stn-new ttl-Ca1 3 nil)))))))))
+ ))
+
+(ert-deftest rst-Stn-get-title-beginning ()
+ "Test `rst-Stn-get-title-beginning'."
+ (let* (;; "
+ ;; =====
+ ;; Title
+ ;; =====
+ ;;
+ ;; Header A
+ ;; ========
+ ;;
+ ;; Header B
+ ;; ========
+ ;;
+ ;; Subheader B.a
+ ;; -------------
+ ;;
+ ;; SubSubheader B.a.1
+ ;; ~~~~~~~~~~~~~~~~~~
+ ;;
+ ;; Header C
+ ;; ========
+ ;;
+ ;; Missing node C.a.1
+ ;; ~~~~~~~~~~~~~~~~~~
+ ;; "
+ (ado-T (rst-Ado-new-over-and-under ?=))
+ (ttl-T (rst-Ttl--new ado-T '(1 18 1 6 7 12 13 18) 0
+ "Title"))
+ (ado-A (rst-Ado-new-simple ?=))
+ (ttl-A (rst-Ttl--new ado-A '(20 37 nil nil 20 28 29 37) 0
+ "Header A"))
+ (ttl-B (rst-Ttl--new ado-A '(39 56 nil nil 39 47 48 56) 0
+ "Header B"))
+ (ado-Ba (rst-Ado-new-simple ?-))
+ (ttl-Ba (rst-Ttl--new ado-Ba '(58 85 nil nil 58 71 72 85) 0
+ "Subheader B.a"))
+ (ado-Ba1 (rst-Ado-new-simple ?~))
+ (ttl-Ba1 (rst-Ttl--new ado-Ba1 '(87 124 nil nil 87 105 106 124) 0
+ "SubSubheader B.a.1"))
+ (ttl-C (rst-Ttl--new ado-A '(126 143 nil nil 126 134 135 143) 0
+ "Header C"))
+ (ttl-Ca nil)
+ (ttl-Ca1 (rst-Ttl--new ado-Ba1 '(145 182 nil nil 145 163 164 182) 0
+ "Missing node C.a.1")))
+ (let* ((stn-Ca (rst-Stn-new
+ ttl-Ca 2
+ (list (rst-Stn-new ttl-Ca1 3 nil))))
+ (stn-C (rst-Stn-new
+ ttl-C 1
+ (list stn-Ca)))
+ (stn-A (rst-Stn-new ttl-A 1 nil))
+ (stn-B (rst-Stn-new
+ ttl-B 1
+ (list (rst-Stn-new
+ ttl-Ba 2
+ (list (rst-Stn-new ttl-Ba1 3 nil))))))
+ (stn-T (rst-Stn-new
+ ttl-T 0
+ (list stn-A
+ stn-B
+ stn-C))))
+ (should-error (rst-Stn-get-title-beginning "")
+ :type 'wrong-type-argument)
+
+ (should (equal (rst-Stn-get-title-beginning stn-T) 7))
+ (should (equal (rst-Stn-get-title-beginning stn-B) 39))
+ (should (equal (rst-Stn-get-title-beginning stn-A) 20))
+ (should (equal (rst-Stn-get-title-beginning stn-C) 126))
+ (should (equal (rst-Stn-get-title-beginning stn-Ca) 145))
+ )))
+
+(ert-deftest rst-Stn-get-text ()
+ "Test `rst-Stn-get-text'."
+ (let* (;; "
+ ;; =====
+ ;; Title
+ ;; =====
+ ;;
+ ;; Header A
+ ;; ========
+ ;;
+ ;; Header B
+ ;; ========
+ ;;
+ ;; Subheader B.a
+ ;; -------------
+ ;;
+ ;; SubSubheader B.a.1
+ ;; ~~~~~~~~~~~~~~~~~~
+ ;;
+ ;; Header C
+ ;; ========
+ ;;
+ ;; Missing node C.a.1
+ ;; ~~~~~~~~~~~~~~~~~~
+ ;; "
+ (ado-T (rst-Ado-new-over-and-under ?=))
+ (ttl-T (rst-Ttl--new ado-T '(1 18 1 6 7 12 13 18) 0
+ "Title"))
+ (ado-A (rst-Ado-new-simple ?=))
+ (ttl-A (rst-Ttl--new ado-A '(20 37 nil nil 20 28 29 37) 0
+ "Header A"))
+ (ttl-B (rst-Ttl--new ado-A '(39 56 nil nil 39 47 48 56) 0
+ "Header B"))
+ (ado-Ba (rst-Ado-new-simple ?-))
+ (ttl-Ba (rst-Ttl--new ado-Ba '(58 85 nil nil 58 71 72 85) 0
+ "Subheader B.a"))
+ (ado-Ba1 (rst-Ado-new-simple ?~))
+ (ttl-Ba1 (rst-Ttl--new ado-Ba1 '(87 124 nil nil 87 105 106 124) 0
+ "SubSubheader B.a.1"))
+ (ttl-C (rst-Ttl--new ado-A '(126 143 nil nil 126 134 135 143) 0
+ "Header C"))
+ (ttl-Ca nil)
+ (ttl-Ca1 (rst-Ttl--new ado-Ba1 '(145 182 nil nil 145 163 164 182) 0
+ "Missing node C.a.1")))
+ (let* ((stn-Ca (rst-Stn-new
+ ttl-Ca 2
+ (list (rst-Stn-new ttl-Ca1 3 nil))))
+ (stn-C (rst-Stn-new
+ ttl-C 1
+ (list stn-Ca)))
+ (stn-A (rst-Stn-new ttl-A 1 nil))
+ (stn-B (rst-Stn-new
+ ttl-B 1
+ (list (rst-Stn-new
+ ttl-Ba 2
+ (list (rst-Stn-new ttl-Ba1 3 nil))))))
+ (stn-T (rst-Stn-new
+ ttl-T 0
+ (list stn-A
+ stn-B
+ stn-C))))
+ (should-error (rst-Stn-get-text "")
+ :type 'wrong-type-argument)
+
+ (should (equal (rst-Stn-get-text stn-T) "Title"))
+ (should (equal (rst-Stn-get-text stn-B "Default") "Header B"))
+ (should (equal (rst-Stn-get-text stn-Ca "Default") "Default"))
+ (should (rst-Stn-get-text stn-Ca))
+ )))
+
+(ert-deftest rst-Stn-is-top ()
+ "Test `rst-Stn-is-top'."
+ (let* (;; "
+ ;; =====
+ ;; Title
+ ;; =====
+ ;; "
+ (ado-T (rst-Ado-new-over-and-under ?=))
+ (ttl-T (rst-Ttl--new ado-T '(1 18 1 6 7 12 13 18) 0
+ "Title")))
+ (let ((stn-T (rst-Stn-new ttl-T 0 nil)))
+ (should-error (rst-Stn-is-top nil)
+ :type 'wrong-type-argument)
+ (should (rst-Stn-is-top (rst-Stn-new
+ nil -1
+ (list stn-T))))
+ (should-not (rst-Stn-is-top stn-T))
+ )))
--- /dev/null
+;; Tests for class `rst-Ttl' -*- lexical-binding: t -*-
+
+(add-to-list 'load-path ".")
+(load "init" nil t)
+(init-rst-ert t)
+
+(setq buf-lines
+"Simple
+======
+
+----------
+ Double
+----------
+
+ Candidate
+\^@
+~~~~~~~~~~
+ Half
+
+**********
+"
+ ado-spl (rst-Ado-new-simple ?=)
+ txt-spl-beg 1
+ txt-spl-end 7
+ und-spl-beg 8
+ und-spl-end 14
+ mtc-spl (list txt-spl-beg und-spl-end
+ nil nil
+ txt-spl-beg txt-spl-end
+ und-spl-beg und-spl-end)
+ ind-spl 0
+ hdr-spl (rst-Hdr-new ado-spl 0)
+ txt-spl "Simple"
+ ado-dbl (rst-Ado-new-over-and-under ?-)
+ ovr-dbl-beg 16
+ ovr-dbl-end 26
+ txt-dbl-beg 27
+ txt-dbl-end 35
+ und-dbl-beg 36
+ und-dbl-end 46
+ mtc-dbl (list ovr-dbl-beg und-dbl-end
+ ovr-dbl-beg ovr-dbl-end
+ txt-dbl-beg txt-dbl-end
+ und-dbl-beg und-dbl-end)
+ ind-dbl 2
+ hdr-dbl (rst-Hdr-new ado-dbl 2)
+ txt-dbl "Double"
+ ado-cnd nil
+ txt-cnd-beg 48
+ txt-cnd-end 58
+ mtc-cnd (list txt-cnd-beg txt-cnd-end
+ nil nil
+ txt-cnd-beg txt-cnd-end
+ nil nil)
+ ind-cnd 1
+ txt-cnd "Candidate"
+ ado-hlf (rst-Ado-new-over-and-under ?~)
+ ovr-hlf-beg 60
+ ovr-hlf-end 70
+ txt-hlf-beg 71
+ txt-hlf-end 78
+ mtc-hlf (list ovr-hlf-beg txt-hlf-end
+ ovr-hlf-beg ovr-hlf-end
+ txt-hlf-beg txt-hlf-end
+ nil nil)
+ mtc-hlf (list ovr-hlf-beg txt-hlf-end
+ ovr-hlf-beg ovr-hlf-end
+ txt-hlf-beg txt-hlf-end
+ nil nil)
+ ind-hlf 3
+ txt-hlf "Half"
+ ado-trn (rst-Ado-new-transition)
+ txt-trn-beg 80
+ txt-trn-end 90
+ mtc-trn (list txt-trn-beg txt-trn-end
+ nil nil
+ txt-trn-beg txt-trn-end
+ nil nil)
+ ind-trn nil
+ txt-trn nil
+ )
+
+(ert-deftest rst-Ttl-asserts ()
+ "Check some assertions."
+ (should (equal ert-Buf-point-char "\^@"))
+ (should (equal ert-Buf-mark-char "\^?"))
+ )
+
+(ert-deftest rst-Ttl--new ()
+ "Test `rst-Ttl--new'."
+ ;; Check type checking of ado argument.
+ (should-error (rst-Ttl--new hdr-spl mtc-spl ind-spl txt-spl)
+ :type 'wrong-type-argument)
+
+ ;; Check type and value checking of match argument.
+ (should-error (rst-Ttl--new ado-spl 1 ind-spl txt-spl)
+ :type 'wrong-type-argument)
+ (should-error (rst-Ttl--new ado-spl nil ind-spl txt-spl)
+ :type 'wrong-type-argument)
+ (should-error (rst-Ttl--new ado-spl '(1 2 3) ind-spl txt-spl)
+ :type 'wrong-type-argument)
+ (should-error (rst-Ttl--new ado-spl '(1 2 "3" 4 5 6 7 8) ind-spl txt-spl)
+ :type 'wrong-type-argument)
+ (should-error (rst-Ttl--new nil '(1 2 3 4 5 6 7 8) ind-spl txt-spl)
+ :type 'args-out-of-range)
+
+ ;; Check value checking of match argument for tranisitions.
+ (should-error (rst-Ttl--new ado-trn (list nil nil
+ nil nil
+ txt-spl-beg txt-spl-end
+ und-spl-beg und-spl-end)
+ ind-spl txt-trn)
+ :type 'args-out-of-range)
+ (should-error (rst-Ttl--new ado-trn (list txt-spl-beg und-spl-end
+ txt-spl-beg txt-spl-end
+ und-spl-beg und-spl-end
+ nil nil)
+ ind-spl txt-trn)
+ :type 'args-out-of-range)
+ (should-error (rst-Ttl--new ado-trn (list txt-spl-beg und-spl-end
+ nil nil
+ txt-spl-beg txt-spl-end
+ und-spl-beg und-spl-end)
+ ind-spl txt-trn)
+ :type 'args-out-of-range)
+ (should-error (rst-Ttl--new ado-trn (list txt-spl-beg und-spl-end
+ nil nil
+ nil nil
+ und-spl-beg und-spl-end)
+ ind-spl txt-trn)
+ :type 'args-out-of-range)
+
+ ;; Check value checking of match argument for simple section header.
+ (should-error (rst-Ttl--new ado-spl (list nil nil
+ nil nil
+ txt-spl-beg txt-spl-end
+ und-spl-beg und-spl-end)
+ ind-spl txt-spl)
+ :type 'args-out-of-range)
+ (should-error (rst-Ttl--new ado-spl (list txt-spl-beg und-spl-end
+ txt-spl-beg txt-spl-end
+ und-spl-beg und-spl-end
+ und-spl-beg und-spl-end)
+ ind-spl txt-spl)
+ :type 'args-out-of-range)
+ (should-error (rst-Ttl--new ado-spl (list txt-spl-beg und-spl-end
+ nil nil
+ txt-spl-beg txt-spl-end
+ nil nil)
+ ind-spl txt-spl)
+ :type 'args-out-of-range)
+
+ ;; Check value checking of match argument for double section header.
+ (should-error (rst-Ttl--new ado-dbl (list nil nil
+ ovr-dbl-beg ovr-dbl-end
+ txt-dbl-beg txt-dbl-end
+ und-dbl-beg und-dbl-end)
+ ind-dbl txt-dbl)
+ :type 'args-out-of-range)
+ (should-error (rst-Ttl--new ado-dbl (list ovr-dbl-beg und-dbl-end
+ nil nil
+ txt-dbl-beg txt-dbl-end
+ und-dbl-beg und-dbl-end)
+ ind-dbl txt-dbl)
+ :type 'args-out-of-range)
+ (should-error (rst-Ttl--new ado-dbl (list ovr-dbl-beg und-dbl-end
+ ovr-dbl-beg ovr-dbl-end
+ nil nil
+ und-dbl-beg und-dbl-end)
+ ind-dbl txt-dbl)
+ :type 'args-out-of-range)
+
+ ;; Check type and value checking of indent argument.
+ (should-error (rst-Ttl--new ado-trn mtc-trn 1 txt-trn)
+ :type 'wrong-type-argument)
+ (should-error (rst-Ttl--new ado-spl mtc-spl nil txt-spl)
+ :type 'wrong-type-argument)
+ (should-error (rst-Ttl--new ado-spl mtc-spl -1 txt-spl)
+ :type 'wrong-type-argument)
+
+ ;; Check type and value checking of text argument.
+ (should-error (rst-Ttl--new ado-trn mtc-trn ind-trn "Text")
+ :type 'wrong-type-argument)
+ (should-error (rst-Ttl--new ado-spl mtc-spl ind-spl nil)
+ :type 'wrong-type-argument)
+ (should-error (rst-Ttl--new ado-spl mtc-spl ind-spl 3)
+ :type 'wrong-type-argument)
+ (should-error (rst-Ttl--new ado-trn mtc-spl ind-spl txt-spl)
+ :type 'args-out-of-range)
+
+ (should (rst-Ttl-p (rst-Ttl--new ado-spl mtc-spl ind-spl txt-spl)))
+ (should (rst-Ttl-p (rst-Ttl--new ado-dbl mtc-dbl ind-dbl txt-dbl)))
+ (should (rst-Ttl-p (rst-Ttl--new ado-cnd mtc-cnd ind-cnd txt-cnd)))
+ (should (rst-Ttl-p (rst-Ttl--new ado-hlf mtc-hlf ind-hlf txt-hlf)))
+ (should (rst-Ttl-p (rst-Ttl--new ado-trn mtc-trn ind-trn txt-trn)))
+
+ ;; Check setting of header.
+ (should (equal (rst-Ttl-hdr (rst-Ttl--new ado-spl mtc-spl ind-spl txt-spl))
+ (rst-Hdr-new ado-spl ind-spl)))
+ (should (equal (rst-Ttl-hdr (rst-Ttl--new ado-dbl mtc-dbl ind-dbl txt-dbl))
+ (rst-Hdr-new ado-dbl ind-dbl)))
+ (should (equal (rst-Ttl-hdr (rst-Ttl--new ado-hlf mtc-hlf ind-hlf txt-hlf))
+ (rst-Hdr-new ado-hlf ind-hlf)))
+ (should-not (rst-Ttl-hdr (rst-Ttl--new ado-cnd mtc-cnd ind-cnd txt-cnd)))
+ (should-not (rst-Ttl-hdr (rst-Ttl--new ado-trn mtc-cnd nil txt-trn)))
+
+ )
+
+(ert-deftest rst-Ttl-get-title-beginning ()
+ "Test `rst-Ttl-get-title-beginning'."
+ (should (equal (rst-Ttl-get-title-beginning
+ (rst-Ttl--new ado-spl mtc-spl ind-spl txt-spl)) txt-spl-beg))
+ (should (equal (rst-Ttl-get-title-beginning
+ (rst-Ttl--new ado-dbl mtc-dbl ind-dbl txt-dbl)) txt-dbl-beg))
+ (should (equal (rst-Ttl-get-title-beginning
+ (rst-Ttl--new ado-hlf mtc-hlf ind-hlf txt-hlf)) txt-hlf-beg))
+ (should (equal (rst-Ttl-get-title-beginning
+ (rst-Ttl--new ado-cnd mtc-cnd ind-cnd txt-cnd)) txt-cnd-beg))
+ )
+
+(ert-deftest rst-Ttl-get-beginning_end ()
+ "Test `rst-Ttl-get-beginning' and `rst-Ttl-get-end'."
+ (should (equal (rst-Ttl-get-beginning
+ (rst-Ttl--new ado-spl mtc-spl ind-spl txt-spl)) txt-spl-beg))
+ (should (equal (rst-Ttl-get-end
+ (rst-Ttl--new ado-spl mtc-spl ind-spl txt-spl)) und-spl-end))
+ (should (equal (rst-Ttl-get-beginning
+ (rst-Ttl--new ado-dbl mtc-dbl ind-dbl txt-dbl)) ovr-dbl-beg))
+ (should (equal (rst-Ttl-get-end
+ (rst-Ttl--new ado-dbl mtc-dbl ind-dbl txt-dbl)) und-dbl-end))
+ (should (equal (rst-Ttl-get-beginning
+ (rst-Ttl--new ado-hlf mtc-hlf ind-hlf txt-hlf)) ovr-hlf-beg))
+ (should (equal (rst-Ttl-get-end
+ (rst-Ttl--new ado-hlf mtc-hlf ind-hlf txt-hlf)) txt-hlf-end))
+ (should (equal (rst-Ttl-get-beginning
+ (rst-Ttl--new ado-cnd mtc-cnd ind-cnd txt-cnd)) txt-cnd-beg))
+ (should (equal (rst-Ttl-get-end
+ (rst-Ttl--new ado-cnd mtc-cnd ind-cnd txt-cnd)) txt-cnd-end))
+ )
+
+(ert-deftest rst-Ttl-from-buffer ()
+ "Test `rst-Ttl-from-buffer'."
+ (let ((ttl-spl (rst-Ttl--new ado-spl mtc-spl ind-spl txt-spl))
+ (ttl-dbl (rst-Ttl--new ado-dbl mtc-dbl ind-dbl txt-dbl))
+ (ttl-cnd (rst-Ttl--new nil mtc-cnd ind-cnd txt-cnd))
+ (ttl-hlf (rst-Ttl--new ado-hlf mtc-hlf ind-hlf txt-hlf))
+ (ttl-trn (rst-Ttl--new ado-trn mtc-trn ind-trn txt-trn)))
+
+ ;; Check type checking of beg-txt argument.
+ (should-error (rst-Ttl-from-buffer nil nil nil nil nil)
+ :type 'wrong-type-argument)
+
+ (should (ert-equal-buffer-return
+ '(rst-Ttl-from-buffer
+ ado-spl nil txt-spl-beg und-spl-beg txt-spl)
+ buf-lines
+ t
+ ttl-spl))
+ (should (ert-equal-buffer-return
+ '(rst-Ttl-from-buffer
+ ado-dbl ovr-dbl-beg txt-dbl-beg und-dbl-beg txt-dbl)
+ buf-lines
+ t
+ ttl-dbl))
+ (should (ert-equal-buffer-return
+ '(rst-Ttl-from-buffer
+ nil nil txt-cnd-beg nil txt-cnd)
+ buf-lines
+ t
+ ttl-cnd))
+ (should (ert-equal-buffer-return
+ '(rst-Ttl-from-buffer
+ ado-hlf ovr-hlf-beg txt-hlf-beg nil txt-hlf)
+ buf-lines
+ t
+ ttl-hlf))
+ (should (ert-equal-buffer-return
+ '(rst-Ttl-from-buffer
+ ado-trn nil txt-trn-beg nil txt-trn)
+ buf-lines
+ t
+ ttl-trn))
+ ))
+
+(defun ttl-contains (pnt)
+ "Run `rst-Ttl-contains' on current buffer comparing first title with point."
+ (interactive "d")
+ (rst-Ttl-contains (car (rst-all-ttls-compute)) pnt))
+
+(ert-deftest rst-Ttl-contains ()
+ "Test `rst-Ttl-contains'."
+ (should-error (rst-Ttl-contains nil nil)
+ :type 'wrong-type-argument)
+
+ (should (ert-equal-buffer-return
+ '(ttl-contains nil)
+ "
+===
+\^@One
+===
+"
+ nil
+ 0
+ t))
+ (should (ert-equal-buffer-return
+ '(ttl-contains nil)
+ "
+\^@===
+One
+===
+"
+ nil
+ 0
+ t))
+ (should (ert-equal-buffer-return
+ '(ttl-contains nil)
+ "
+===
+One
+===\^@
+"
+ nil
+ 0
+ t))
+ (should (ert-equal-buffer-return
+ '(ttl-contains nil)
+ "
+\^@One
+===
+"
+ nil
+ 0
+ t))
+ (should (ert-equal-buffer-return
+ '(ttl-contains nil)
+ "
+One
+===\^@
+"
+ nil
+ 0
+ t))
+ (should (ert-equal-buffer-return
+ '(ttl-contains nil)
+ "\^@
+One
+===
+"
+ nil
+ 1
+ t))
+ (should (ert-equal-buffer-return
+ '(ttl-contains nil)
+ "
+One
+===
+\^@"
+ nil
+ -1
+ t))
+ )
--- /dev/null
+;; Tests for rst-adjust -*- lexical-binding: t -*-
+
+(add-to-list 'load-path ".")
+(load "init" nil t)
+(init-rst-ert t)
+
+(ert-deftest adjust-section-asserts ()
+ "Check some assertions."
+ (should (equal ert-Buf-point-char "\^@"))
+ (should (equal ert-Buf-mark-char "\^?"))
+ )
+
+(ert-deftest rst-adjust-no-adornment ()
+ "Tests for `rst-adjust' with no adornment around point."
+ (let ( ;; Set customizable variables to defined values
+ (rst-new-adornment-down t)
+ (rst-default-indent 3)
+ (rst-preferred-adornments '((?= over-and-under 1)
+ (?= simple 0)
+ (?- simple 0)
+ (?~ simple 0)
+ (?+ simple 0)
+ (?` simple 0)
+ (?# simple 0)
+ (?@ simple 0))))
+ (should (ert-equal-buffer
+ '(rst-adjust)
+ "
+Some Title\^@
+
+"
+ "
+============
+ Some Title
+============
+
+"
+ t))
+ (should (ert-equal-buffer
+ '(rst-adjust)
+ "
+Some Title
+\^@
+"
+ "
+============
+ Some Title
+============
+
+"
+ t))
+ (should (ert-equal-buffer
+ '(rst-adjust)
+ "
+Some Tit\^@le
+
+"
+ "
+============
+ Some Title
+============
+
+"
+ t))
+ (should (ert-equal-buffer
+ '(rst-adjust)
+ "
+\^@Some Title
+
+"
+ "
+============
+ Some Title
+============
+
+"
+ t))
+ (should (ert-equal-buffer
+ '(rst-adjust)
+ "
+Some Title\^@
+
+Other Title
+-----------
+
+Other Title2
+~~~~~~~~~~~~
+
+"
+ "
+============
+ Some Title
+============
+
+Other Title
+-----------
+
+Other Title2
+~~~~~~~~~~~~
+
+"
+ t))
+ (should (ert-equal-buffer
+ '(rst-adjust 1)
+ "
+Some Title\^@
+
+"
+ "
+Some Title
+==========
+
+"
+ t))
+ (should (ert-equal-buffer
+ '(rst-adjust)
+ "
+ Some Title\^@
+
+"
+ "
+================
+ Some Title
+================
+
+"
+ t))
+ (should (ert-equal-buffer
+ '(rst-adjust 1)
+ "
+ Some Title\^@
+
+"
+ "
+Some Title
+==========
+
+"
+ t))
+ (should (ert-equal-buffer
+ '(rst-adjust)
+ "
+Previous Title
+--------------
+
+Some Title\^@
+
+"
+ "
+Previous Title
+--------------
+
+Some Title
+~~~~~~~~~~
+
+"
+ t))
+ (should (ert-equal-buffer
+ '(rst-adjust)
+ "
+Previous Title
+--------------
+
+Some Title\^@
+
+Next Title
+~~~~~~~~~~
+
+"
+ "
+Previous Title
+--------------
+
+Some Title
+~~~~~~~~~~
+
+Next Title
+~~~~~~~~~~
+
+"
+ t))
+ (should (ert-equal-buffer
+ '(rst-adjust 1)
+ "
+Previous Title
+--------------
+
+Some Title\^@
+
+"
+ "
+Previous Title
+--------------
+
+~~~~~~~~~~
+Some Title
+~~~~~~~~~~
+
+"
+ t))
+ (should (ert-equal-buffer
+ '(rst-adjust 1)
+ "
+Previous Title
+--------------
+
+ Some Title\^@
+
+"
+ "
+Previous Title
+--------------
+
+~~~~~~~~~~~~~~
+ Some Title
+~~~~~~~~~~~~~~
+
+"
+ t))
+ (should (ert-equal-buffer
+ '(rst-adjust)
+ "
+Previous Title
+--------------
+
+ Some Title\^@
+
+"
+ "
+Previous Title
+--------------
+
+Some Title
+~~~~~~~~~~
+
+"
+ t))
+ (should (ert-equal-buffer
+ '(rst-adjust -)
+ "
+Previous Title
+--------------
+
+Some Title\^@
+
+Next Title
+~~~~~~~~~~
+"
+ "
+Previous Title
+--------------
+
+Some Title
+----------
+
+Next Title
+~~~~~~~~~~
+"
+ t))
+ (should (ert-equal-buffer
+ '(rst-adjust)
+ "
+Document Title\^@
+
+"
+ "
+================
+ Document Title\^@
+================
+
+"
+ t))
+ (should (ert-equal-buffer
+ '(rst-adjust)
+ "
+
+Document Title\^@
+"
+ "
+
+================
+ Document Title\^@
+================
+"
+ t))
+ (should (ert-equal-buffer
+ '(rst-adjust)
+ "
+
+Document Title\^@"
+ "
+
+================
+ Document Title\^@
+================
+"
+ t))
+ (should (ert-equal-buffer
+ '(rst-adjust)
+ "
+Document Title
+==============
+Subtitle\^@
+
+"
+ "
+Document Title
+==============
+Subtitle\^@
+--------
+
+"
+ t))
+ ))
+
+(ert-deftest rst-adjust-incomplete ()
+ "Tests for `rst-adjust' with incomplete adornment."
+ (let ( ;; Set customizable variables to defined values
+ (rst-default-indent 3)
+ (rst-preferred-adornments '((?= over-and-under 1)
+ (?= simple 0)
+ (?- simple 0)
+ (?~ simple 0)
+ (?+ simple 0)
+ (?` simple 0)
+ (?# simple 0)
+ (?@ simple 0))))
+ (should (ert-equal-buffer
+ '(rst-adjust)
+ "
+Previous Title\^@
+----------
+"
+ "
+Previous Title
+--------------
+"
+ t))
+ (should (ert-equal-buffer
+ '(rst-adjust)
+ "
+Previous Title
+----------\^@
+"
+ "
+Previous Title
+--------------
+"
+ t))
+ (should (ert-equal-buffer
+ '(rst-adjust)
+ "
+Previous Title
+-\^@
+"
+ "
+Previous Title
+-
+"
+ t))
+ (should (ert-equal-buffer
+ '(rst-adjust)
+ "
+Previous Title
+--\^@
+"
+ "
+Previous Title
+--
+"
+ t))
+ (should (ert-equal-buffer
+ '(rst-adjust)
+ "
+Previous Title
+---\^@
+"
+ "
+Previous Title
+--------------
+"
+ t))
+ (should (ert-equal-buffer
+ '(rst-adjust)
+ "
+Previous Title
+------------------\^@
+"
+ "
+Previous Title
+--------------
+"
+ t))
+ (should (ert-equal-buffer
+ '(rst-adjust)
+ "
+----------------
+ Previous Title
+----------\^@
+"
+ "
+----------------
+ Previous Title
+----------------
+"
+ t))
+ (should (ert-equal-buffer
+ '(rst-adjust)
+ "
+----------\^@
+ Previous Title
+----------------
+"
+ "
+----------------
+ Previous Title
+----------------
+"
+ t))
+ (should (ert-equal-buffer
+ '(rst-adjust)
+ "
+----------
+ Previous Title\^@
+-----
+"
+ "
+----------------
+ Previous Title
+----------------
+"
+ t))
+ (should (ert-equal-buffer
+ '(rst-adjust 1)
+ "
+Previous Title
+----------\^@
+"
+ "
+--------------
+Previous Title
+--------------
+"
+ t))
+ (should (ert-equal-buffer
+ '(rst-adjust 1)
+ "
+----------------
+ Previous Title\^@
+--------
+"
+ "
+Previous Title
+--------------
+"
+ t))
+ (should (ert-equal-buffer
+ '(rst-adjust 1)
+ "
+--------\^@
+ Previous Title
+----------------
+"
+ "
+Previous Title
+--------------
+"
+ t))
+ (should (ert-equal-buffer
+ '(rst-adjust)
+ "--------\^@
+ Previous Title
+----------------
+"
+ "----------------
+ Previous Title
+----------------
+"
+ t))
+ (should (ert-equal-buffer
+ '(rst-adjust)
+ "=======
+Document Title\^@
+==============
+"
+ "==============
+Document Title
+==============
+"
+ t))
+ ))
+
+(ert-deftest rst-adjust-toggle ()
+ "Tests for `rst-adjust' toggling complete adornment."
+ (let ( ;; Set customizable variables to defined values
+ (rst-default-indent 3)
+ (rst-preferred-adornments '((?= over-and-under 1)
+ (?= simple 0)
+ (?- simple 0)
+ (?~ simple 0)
+ (?+ simple 0)
+ (?` simple 0)
+ (?# simple 0)
+ (?@ simple 0))))
+ (should (ert-equal-buffer
+ '(rst-adjust 1)
+ "
+SubTitle\^@
+~~~~~~~~
+
+"
+ "
+~~~~~~~~~~~~~~
+ SubTitle
+~~~~~~~~~~~~~~
+
+"
+ t))
+ (should (ert-equal-buffer
+ '(rst-adjust 1)
+ "
+~~~~~~~~~~
+ SubTitle\^@
+~~~~~~~~~~
+
+"
+ "
+SubTitle
+~~~~~~~~
+
+"
+ t))
+ ))
+
+(ert-deftest rst-adjust-rotate-up ()
+ "Tests for `rst-adjust' rotating complete adornment upwards."
+ (let ( ;; Set customizable variables to defined values
+ (rst-default-indent 3)
+ (rst-preferred-adornments '((?= over-and-under 1)
+ (?= simple 0)
+ (?- simple 0)
+ (?~ simple 0)
+ (?+ simple 0)
+ (?` simple 0)
+ (?# simple 0)
+ (?@ simple 0))))
+ (should (ert-equal-buffer
+ '(rst-adjust)
+ "
+================
+ Document Title
+================
+
+SubTitle
+--------
+
+My Title\^@
+--------
+
+After Title
+~~~~~~~~~~~
+
+"
+ "
+================
+ Document Title
+================
+
+SubTitle
+--------
+
+==========
+ My Title
+==========
+
+After Title
+~~~~~~~~~~~
+
+"
+ t))
+ (should (ert-equal-buffer
+ '(rst-adjust)
+ "
+================
+ Document Title
+================
+
+SubTitle
+========
+
+==========
+ My Title\^@
+==========
+
+"
+ "
+================
+ Document Title
+================
+
+SubTitle
+========
+
+My Title
+--------
+
+"
+ t))
+ (should (ert-equal-buffer
+ '(rst-adjust)
+ "
+================
+ Document Title
+================
+
+SubTitle
+========
+
+My Title\^@
+--------
+
+After Title
+-----------
+"
+ "
+================
+ Document Title
+================
+
+SubTitle
+========
+
+My Title
+========
+
+After Title
+-----------
+"
+ t))
+ (should (ert-equal-buffer
+ '(rst-adjust)
+ "
+================
+ Document Title
+================
+
+SubTitle
+========
+
+My Title\^@
+--------
+"
+ "
+================
+ Document Title
+================
+
+SubTitle
+========
+
+My Title
+========
+"
+ t))
+ ;; docutils-Bugs #2972588
+ (should (ert-equal-buffer
+ '(rst-adjust)
+ "
+==============
+Document Title
+==============
+
+Subtitle
+========
+
+.. contents::
+ :depth: 2
+..
+ 1 Section 1
+ 2 Section 2
+
+Section 1\^@
+---------
+
+Section 2
+---------
+"
+ "
+==============
+Document Title
+==============
+
+Subtitle
+========
+
+.. contents::
+ :depth: 2
+..
+ 1 Section 1
+ 2 Section 2
+
+Section 1\^@
+=========
+
+Section 2
+---------
+"
+ t))
+ ))
+
+(ert-deftest rst-adjust-rotate-down ()
+ "Tests for `rst-adjust' rotating complete adornment downwards."
+ (let ( ;; Set customizable variables to defined values
+ (rst-default-indent 3)
+ (rst-preferred-adornments '((?= over-and-under 1)
+ (?= simple 0)
+ (?- simple 0)
+ (?~ simple 0)
+ (?+ simple 0)
+ (?` simple 0)
+ (?# simple 0)
+ (?@ simple 0))))
+ (should (ert-equal-buffer
+ '(rst-adjust -)
+ "
+================
+ Document Title
+================
+
+SubTitle
+--------
+
+My Title\^@
+--------
+
+After Title
+~~~~~~~~~~~
+
+"
+ "
+================
+ Document Title
+================
+
+SubTitle
+--------
+
+My Title
+~~~~~~~~
+
+After Title
+~~~~~~~~~~~
+
+"
+ t))
+ (should (ert-equal-buffer
+ '(rst-adjust -)
+ "
+================
+ Document Title
+================
+
+SubTitle
+========
+
+My Title\^@
+========
+
+"
+ "
+================
+ Document Title
+================
+
+SubTitle
+========
+
+My Title
+--------
+
+"
+ t))
+ (should (ert-equal-buffer
+ '(rst-adjust -)
+ "
+================
+ Document Title
+================
+
+SubTitle
+========
+
+My Title\^@
+--------
+
+"
+ "
+================
+ Document Title
+================
+
+SubTitle
+========
+
+==========
+ My Title
+==========
+
+"
+ t))
+ ))
+
+(ert-deftest rst-adjust-adjoined ()
+ "Tests for `rst-adjust' rotating complete adornment adjoined to each other."
+ (let ( ;; Set customizable variables to defined values
+ (rst-default-indent 3)
+ (rst-preferred-adornments '((?= over-and-under 1)
+ (?= simple 0)
+ (?- simple 0)
+ (?~ simple 0)
+ (?+ simple 0)
+ (?` simple 0)
+ (?# simple 0)
+ (?@ simple 0))))
+ (should (ert-equal-buffer
+ '(rst-adjust)
+ "==============
+Document Title\^@
+==============
+Subtitle
+========
+
+"
+ "Document Title\^@
+==============
+Subtitle
+========
+
+"
+ t))
+ (should (ert-equal-buffer
+ '(rst-adjust)
+ "
+==============
+Document Title\^@
+==============
+Subtitle
+========
+
+"
+ "
+Document Title\^@
+==============
+Subtitle
+========
+
+"
+ t))
+ (should (ert-equal-buffer
+ '(rst-adjust)
+ "
+==============
+Document Title
+==============
+===============
+Document Title2\^@
+===============
+
+"
+ "
+==============
+Document Title
+==============
+Document Title2
+===============
+
+"
+ t))
+ ))
+
+(ert-deftest rst-adjust-special ()
+ "Tests for `rst-adjust' for special situations."
+ (let ( ;; Set customizable variables to defined values
+ (rst-new-adornment-down t)
+ (rst-default-indent 3)
+ (rst-preferred-adornments '((?= over-and-under 1)
+ (?= simple 0)
+ (?- simple 0)
+ (?~ simple 0)
+ (?+ simple 0)
+ (?` simple 0)
+ (?# simple 0)
+ (?@ simple 0)))
+ ;; Make sure the region is active.
+ (transient-mark-mode t))
+ ;; Switch to `rst-ajust-region'.
+ (should (ert-equal-buffer
+ '(rst-adjust)
+ "
+\^?
+Some Title
+==========
+\^@
+"
+ "
+
+============
+ Some Title
+============
+
+"
+ t))
+ (should (ert-equal-buffer
+ '(rst-adjust -)
+ "
+\^?
+Some Title
+==========
+\^@
+"
+ "
+
+============
+ Some Title
+============
+
+"
+ t))
+ ))
--- /dev/null
+;; Tests for rst-adjust -*- lexical-binding: t -*-
+;;
+;; These tests are for all use cases not only "filling" an existing adornment
+
+(add-to-list 'load-path ".")
+(load "init" nil t)
+(init-rst-ert t)
+
+(ert-deftest adjust-uc-asserts ()
+ "Check some assertions."
+ (should (equal ert-Buf-point-char "\^@"))
+ (should (equal ert-Buf-mark-char "\^?"))
+ )
+
+;; Each test tests a line in the use case chart. The conditions fixed by the
+;; chart entry are noted before the test. The varying conditions are noted for
+;; the individual test. A condition marked with "<" follows from another
+;; condition setting.
+
+(defun rst-ert-adjust-section (toggle-style reverse)
+ "Call `rst-adjust-section' turning error messages into t."
+ (and (rst-adjust-section toggle-style reverse) t))
+
+;; :Prf: No preferences
+;; :Sel: No adornment around point
+;; :Prv: < No previous header
+;; :Hie: < No hierarchy beyond current header
+;; :Cur: < Does not apply
+(ert-deftest rst-adjust-section-prf-N-sel-N-prv-N-hie-N-cur-!-dir-? ()
+ (let ((rst-new-adornment-down nil)
+ (rst-default-indent 3)
+ (rst-preferred-adornments nil))
+ ;; :Dir: Up
+ (should (ert-equal-buffer-return
+ '(rst-ert-adjust-section nil nil)
+ "
+Document Title\^@
+"
+ t
+ t))
+ ;; :Dir: Down
+ (should (ert-equal-buffer-return
+ '(rst-ert-adjust-section nil t)
+ "
+Document Title\^@
+"
+ t
+ t))
+ ))
+
+;; :Prf: No preferences
+;; :Sel: No adornment around point
+;; :Prv: < No previous header
+;; :Hie: < Existing
+;; :Cur: < Does not apply
+(ert-deftest rst-adjust-section-prf-N-sel-N-prv-N-hie-!-cur-!-dir-? ()
+ (let ((rst-new-adornment-down nil)
+ (rst-default-indent 3)
+ (rst-preferred-adornments nil))
+ ;; :Dir: Up
+ (should (ert-equal-buffer-return
+ '(rst-ert-adjust-section nil nil)
+ "
+Document Title\^@
+
+Hie 1
+=====
+
+Hie 1.1
+-------
+"
+ "
+Document Title
+==============
+
+Hie 1
+=====
+
+Hie 1.1
+-------
+"
+ nil))
+ ;; :Dir: Down
+ (should (ert-equal-buffer-return
+ '(rst-ert-adjust-section nil t)
+ "
+Document Title\^@
+
+Hie 1
+=====
+
+Hie 1.1
+-------
+"
+ "
+Document Title
+==============
+
+Hie 1
+=====
+
+Hie 1.1
+-------
+"
+ nil))
+ ))
+
+;; :Prf: No preferences
+;; :Sel: No adornment around point
+;; :Prv: < Disadvised
+;; :Hie: < Existing
+;; :Cur: < Does not apply
+(ert-deftest rst-adjust-section-prf-N-sel-N-prv-D-hie-!-cur-!-dir-? ()
+ (let ((rst-new-adornment-down nil)
+ (rst-default-indent 3)
+ (rst-preferred-adornments nil))
+ ;; :Dir: Up
+ (should (ert-equal-buffer-return
+ '(rst-ert-adjust-section nil nil)
+ "
+Document Title
+==============
+
+Hie 1\^@
+
+Hie 1.1
+-------
+"
+ "
+Document Title
+==============
+
+Hie 1
+=====
+
+Hie 1.1
+-------
+"
+ nil))
+ ;; :Dir: Down
+ (should (ert-equal-buffer-return
+ '(rst-ert-adjust-section nil t)
+ "
+Document Title
+==============
+
+Hie 1\^@
+
+Hie 1.1
+-------
+"
+ "
+Document Title
+==============
+
+Hie 1
+-----
+
+Hie 1.1
+-------
+"
+ nil))
+ ))
+
+;; :Prf: No preferences
+;; :Sel: Existing header around point
+;; :Prv: < No previous header
+;; :Hie: < No hierarchy beyond current header
+;; :Cur: < Disadvised
+(ert-deftest rst-adjust-section-prf-N-sel-E-prv-N-hie-N-cur-D-dir-? ()
+ (let ((rst-new-adornment-down nil)
+ (rst-default-indent 3)
+ (rst-preferred-adornments nil))
+ ;; :Dir: Up
+ (should (ert-equal-buffer-return
+ '(rst-ert-adjust-section nil nil)
+ "
+Document Title\^@
+==============
+"
+ t
+ t))
+ ;; :Dir: Down
+ (should (ert-equal-buffer-return
+ '(rst-ert-adjust-section nil t)
+ "
+Document Title\^@
+==============
+"
+ t
+ t))
+ ))
+
+;; :Prf: No preferences
+;; :Sel: Existing header around point
+;; :Prv: < No previous header
+;; :Hie: < Multiple occurrence in the middle of existing hierarchy
+;; :Cur: < Disadvised
+(ert-deftest rst-adjust-section-prf-N-sel-E-prv-N-hie-M-cur-D-dir-? ()
+ (let ((rst-new-adornment-down nil)
+ (rst-default-indent 3)
+ (rst-preferred-adornments nil))
+ ;; :Dir: Up
+ (should (ert-equal-buffer-return
+ '(rst-ert-adjust-section nil nil)
+ "
+Hie 1\^@
+-----
+
+Hie 2
+=====
+
+Hie 2.1
+-------
+
+Hie 2.1.1
+~~~~~~~~~
+"
+ "
+Hie 1
+~~~~~
+
+Hie 2
+=====
+
+Hie 2.1
+-------
+
+Hie 2.1.1
+~~~~~~~~~
+"
+ nil))
+ ;; :Dir: Down
+ (should (ert-equal-buffer-return
+ '(rst-ert-adjust-section nil t)
+ "
+Hie 1\^@
+-----
+
+Hie 2
+=====
+
+Hie 2.1
+-------
+
+Hie 2.1.1
+~~~~~~~~~
+"
+ "
+Hie 1
+=====
+
+Hie 2
+=====
+
+Hie 2.1
+-------
+
+Hie 2.1.1
+~~~~~~~~~
+"
+ nil))
+ ))
+
+;; :Prf: No preferences
+;; :Sel: Existing header around point
+;; :Prv: < No previous header
+;; :Hie: < Last in existing hierarchy
+;; :Cur: < Disadvised
+(ert-deftest rst-adjust-section-prf-N-sel-E-prv-N-hie-L-cur-D-dir-? ()
+ (let ((rst-new-adornment-down nil)
+ (rst-default-indent 3)
+ (rst-preferred-adornments nil))
+ ;; :Dir: Up
+ (should (ert-equal-buffer-return
+ '(rst-ert-adjust-section nil nil)
+ "
+Hie 1\^@
+=====
+
+Hie 2
+=====
+
+Hie 2.1
+-------
+
+Hie 2.1.1
+~~~~~~~~~
+"
+ "
+Hie 1
+~~~~~
+
+Hie 2
+=====
+
+Hie 2.1
+-------
+
+Hie 2.1.1
+~~~~~~~~~
+"
+ nil))
+ ;; :Dir: Down
+ (should (ert-equal-buffer-return
+ '(rst-ert-adjust-section nil t)
+ "
+Hie 1\^@
+~~~~~
+
+Hie 2
+=====
+
+Hie 2.1
+-------
+
+Hie 2.1.1
+~~~~~~~~~
+"
+ "
+Hie 1
+=====
+
+Hie 2
+=====
+
+Hie 2.1
+-------
+
+Hie 2.1.1
+~~~~~~~~~
+"
+ nil))
+ ))
+
+;; :Prf: No preferences
+;; :Sel: Existing header around point
+;; :Prv: < No previous header
+;; :Hie: < Once in existing hierarchy
+;; :Cur: < Disadvised
+;; :Dir: Down
+(ert-deftest rst-adjust-section-prf-N-sel-E-prv-N-hie-O-cur-D-dir-D ()
+ (let ((rst-new-adornment-down nil)
+ (rst-default-indent 3)
+ (rst-preferred-adornments nil))
+ (should (ert-equal-buffer-return
+ '(rst-ert-adjust-section nil t)
+ "
+Hie 1\^@
+$$$$$
+
+Hie 2
+=====
+
+Hie 2.1
+-------
+
+Hie 2.1.1
+~~~~~~~~~
+"
+ "
+Hie 1
+=====
+
+Hie 2
+=====
+
+Hie 2.1
+-------
+
+Hie 2.1.1
+~~~~~~~~~
+"
+ nil))
+ ))
+
+;; :Prf: No preferences
+;; :Sel: Existing header around point
+;; :Prv: < No previous header
+;; :Hie: < Once in existing hierarchy
+;; :Cur: < Disadvised
+;; :Dir: Up
+(ert-deftest rst-adjust-section-prf-N-sel-E-prv-N-hie-O-cur-D-dir-U ()
+ (let ((rst-new-adornment-down nil)
+ (rst-default-indent 3)
+ (rst-preferred-adornments nil))
+ (should (ert-equal-buffer-return
+ '(rst-ert-adjust-section nil nil)
+ "
+Hie 1\^@
+$$$$$
+
+Hie 2
+=====
+
+Hie 2.1
+-------
+
+Hie 2.1.1
+~~~~~~~~~
+"
+ "
+Hie 1
+~~~~~
+
+Hie 2
+=====
+
+Hie 2.1
+-------
+
+Hie 2.1.1
+~~~~~~~~~
+"
+ nil))
+ ))
+
+;; :Prf: No preferences
+;; :Sel: Existing header around point
+;; :Prv: < Disadvised previous header
+;; :Hie: < Multiple occurrence in the middle of existing hierarchy
+;; :Cur: < Disadvised
+(ert-deftest rst-adjust-section-prf-N-sel-E-prv-D-hie-M-cur-D-dir-? ()
+ (let ((rst-new-adornment-down nil)
+ (rst-default-indent 3)
+ (rst-preferred-adornments nil))
+ ;; :Dir: Up
+ (should (ert-equal-buffer-return
+ '(rst-ert-adjust-section nil nil)
+ "
+Hie 1
+=====
+
+Hie 2
+=====
+
+Hie 2.1
+-------
+
+Hie 3\^@
+-----
+
+Hie 3.1.1
+~~~~~~~~~
+"
+ "
+Hie 1
+=====
+
+Hie 2
+=====
+
+Hie 2.1
+-------
+
+Hie 3
+=====
+
+Hie 3.1.1
+~~~~~~~~~
+"
+ nil))
+ ;; :Dir: Down
+ (should (ert-equal-buffer-return
+ '(rst-ert-adjust-section nil t)
+ "
+Hie 1
+=====
+
+Hie 2
+=====
+
+Hie 2.1
+-------
+
+Hie 2.1.1\^@
+---------
+
+Hie 2.1.2
+~~~~~~~~~
+"
+ "
+Hie 1
+=====
+
+Hie 2
+=====
+
+Hie 2.1
+-------
+
+Hie 2.1.1
+~~~~~~~~~
+
+Hie 2.1.2
+~~~~~~~~~
+"
+ nil))
+ ))
+
+;; :Prf: No preferences
+;; :Sel: Existing header around point
+;; :Prv: < Disadvised previous header
+;; :Hie: < Breaking single entry in the middle of existing hierarchy
+;; :Cur: < Disadvised
+(ert-deftest rst-adjust-section-prf-N-sel-E-prv-D-hie-B-cur-D-dir-? ()
+ (let ((rst-new-adornment-down nil)
+ (rst-default-indent 3)
+ (rst-preferred-adornments nil))
+ ;; :Dir: Up
+ (should (ert-equal-buffer-return
+ '(rst-ert-adjust-section nil nil)
+ "
+Hie 1
+=====
+
+Hie 2
+=====
+
+Hie 3\^@
+$$$$$
+
+Hie 3.1
+~~~~~~~
+"
+ "
+Hie 1
+=====
+
+Hie 2
+=====
+
+Hie 3
+=====
+
+Hie 3.1
+~~~~~~~
+"
+ nil))
+ ;; :Dir: Down
+ (should (ert-equal-buffer-return
+ '(rst-ert-adjust-section nil t)
+ "
+Hie 1
+=====
+
+Hie 2
+=====
+
+Hie 2.1\^@
+$$$$$$$
+
+Hie 2.2
+~~~~~~~
+"
+ "
+Hie 1
+=====
+
+Hie 2
+=====
+
+Hie 2.1
+~~~~~~~
+
+Hie 2.2
+~~~~~~~
+"
+ nil))
+ ))
+
+;; :Prf: No preferences
+;; :Sel: Existing header around point
+;; :Prv: < Disadvised previous header
+;; :Hie: < Last in existing hierarchy
+;; :Cur: < Disadvised
+(ert-deftest rst-adjust-section-prf-N-sel-E-prv-D-hie-L-cur-D-dir-? ()
+ (let ((rst-new-adornment-down nil)
+ (rst-default-indent 3)
+ (rst-preferred-adornments nil))
+ ;; :Dir: Up
+ (should (ert-equal-buffer-return
+ '(rst-ert-adjust-section nil nil)
+ "
+Hie 1
+=====
+
+Hie 2
+=====
+
+Hie 2.1
+-------
+
+Hie 2.2\^@
+~~~~~~~
+
+Hie 2.2.1
+~~~~~~~~~
+"
+ "
+Hie 1
+=====
+
+Hie 2
+=====
+
+Hie 2.1
+-------
+
+Hie 2.2
+-------
+
+Hie 2.2.1
+~~~~~~~~~
+"
+ nil))
+ ;; :Dir: Down
+ (should (ert-equal-buffer-return
+ '(rst-ert-adjust-section nil t)
+ "
+Hie 1
+=====
+
+Hie 2
+=====
+
+Hie 2.1
+-------
+
+Hie 3\^@
+~~~~~
+
+Hie 3.1.1
+~~~~~~~~~
+"
+ "
+Hie 1
+=====
+
+Hie 2
+=====
+
+Hie 2.1
+-------
+
+Hie 3
+=====
+
+Hie 3.1.1
+~~~~~~~~~
+"
+ nil))
+ ))
+
+;; :Prf: No preferences
+;; :Sel: Existing header around point
+;; :Prv: < Disadvised previous header
+;; :Hie: < Once in existing hierarchy
+;; :Cur: < Disadvised
+(ert-deftest rst-adjust-section-prf-N-sel-E-prv-D-hie-O-cur-D-dir-? ()
+ (let ((rst-new-adornment-down nil)
+ (rst-default-indent 3)
+ (rst-preferred-adornments nil))
+ ;; :Dir: Up
+ (should (ert-equal-buffer-return
+ '(rst-ert-adjust-section nil nil)
+ "
+Hie 1
+=====
+
+Hie 2
+=====
+
+Hie 2.1
+-------
+
+Hie 2.2\^@
+~~~~~~~
+
+Hie 3
+=====
+"
+ "
+Hie 1
+=====
+
+Hie 2
+=====
+
+Hie 2.1
+-------
+
+Hie 2.2
+-------
+
+Hie 3
+=====
+"
+ nil))
+ ;; :Dir: Down
+ (should (ert-equal-buffer-return
+ '(rst-ert-adjust-section nil t)
+ "
+Hie 1
+=====
+
+Hie 2
+=====
+
+Hie 2.1
+-------
+
+Hie 3\^@
+~~~~~
+
+Hie 4
+=====
+"
+ "
+Hie 1
+=====
+
+Hie 2
+=====
+
+Hie 2.1
+-------
+
+Hie 3
+=====
+
+Hie 4
+=====
+"
+ nil))
+ ))
+
+;; :Prf: Preferences exist
+;; :Sel: No adornment around point
+;; :Prv: < No previous header
+;; :Hie: < No hierarchy beyond current header
+;; :Cur: < Does not apply
+;; :Dir: Irrelevant
+(ert-deftest rst-adjust-section-prf-P-sel-N-prv-N-hie-N-cur-!-dir-? ()
+ (let ((rst-new-adornment-down nil)
+ (rst-default-indent 3)
+ (rst-preferred-adornments '((?: over-and-under 1)
+ (?. over-and-under 1)
+ (?: simple 0)
+ (?. simple 0))))
+ ;; :Dir: Up
+ (should (ert-equal-buffer-return
+ '(rst-ert-adjust-section nil nil)
+ "
+Document Title\^@
+"
+ "
+::::::::::::::::
+ Document Title
+::::::::::::::::
+"
+ nil))
+ ;; :Dir: Down
+ (should (ert-equal-buffer-return
+ '(rst-ert-adjust-section nil t)
+ "
+Document Title\^@
+"
+ "
+::::::::::::::::
+ Document Title
+::::::::::::::::
+"
+ nil))
+ ))
+
+;; :Prf: Preferences exist
+;; :Sel: No adornment around point
+;; :Prv: < No previous header
+;; :Hie: < Existing
+;; :Cur: < Does not apply
+;; :Dir: Down
+(ert-deftest rst-adjust-section-prf-P-sel-N-prv-N-hie-!-cur-!-dir-D ()
+ (let ((rst-new-adornment-down nil)
+ (rst-default-indent 3)
+ (rst-preferred-adornments '((?: over-and-under 1)
+ (?. over-and-under 1)
+ (?: simple 0)
+ (?. simple 0))))
+ (should (ert-equal-buffer-return
+ '(rst-ert-adjust-section nil t)
+ "
+Document Title\^@
+
+Hie 1
+=====
+
+Hie 1.1
+-------
+"
+ "
+Document Title
+==============
+
+Hie 1
+=====
+
+Hie 1.1
+-------
+"
+ nil))
+ ))
+
+;; :Prf: Preferences exist
+;; :Sel: No adornment around point
+;; :Prv: < No previous header
+;; :Hie: < Existing
+;; :Cur: < Does not apply
+;; :Dir: Up
+(ert-deftest rst-adjust-section-prf-P-sel-N-prv-N-hie-!-cur-!-dir-U ()
+ (let ((rst-new-adornment-down nil)
+ (rst-default-indent 3)
+ (rst-preferred-adornments '((?: over-and-under 1)
+ (?. over-and-under 1)
+ (?: simple 0)
+ (?. simple 0))))
+ (should (ert-equal-buffer-return
+ '(rst-ert-adjust-section nil nil)
+ "
+Document Title\^@
+
+Hie 1
+=====
+
+Hie 1.1
+-------
+"
+ "
+::::::::::::::::
+ Document Title
+::::::::::::::::
+
+Hie 1
+=====
+
+Hie 1.1
+-------
+"
+ nil))
+ ))
+
+;; :Prf: Preferences exist
+;; :Sel: < Existing adornment around point
+;; :Prv: Disadvised previous header
+;; :Hie: < Multiple occurrence in the middle of existing hierarchy
+;; :Cur: Disadvised
+;; :Dir: Any
+(ert-deftest rst-adjust-section-prf-P-sel-E-prv-D-hie-M-cur-D-dir-? ()
+ (let ((rst-new-adornment-down nil)
+ (rst-default-indent 3)
+ (rst-preferred-adornments '((?: over-and-under 1)
+ (?. over-and-under 1)
+ (?: simple 0)
+ (?. simple 0))))
+ ;; :Dir: Up
+ (should (ert-equal-buffer-return
+ '(rst-ert-adjust-section nil nil)
+ "
+==============
+Document Title
+==============
+
+Additional title\^@
+================
+
+Hie 1.1
+-------
+
+Hie 2
+=====
+"
+ "
+==============
+Document Title
+==============
+
+================
+Additional title
+================
+
+Hie 1.1
+-------
+
+Hie 2
+=====
+"
+ nil))
+ ;; :Dir: Down
+ (should (ert-equal-buffer-return
+ '(rst-ert-adjust-section nil t)
+ "
+==============
+Document Title
+==============
+
+Hie 1.0\^@
+=======
+
+Hie 1.1
+-------
+
+Hie 2
+=====
+"
+ "
+==============
+Document Title
+==============
+
+Hie 1.0
+-------
+
+Hie 1.1
+-------
+
+Hie 2
+=====
+"
+ nil))
+ ))
+
+;; :Prf: Preferences exist
+;; :Sel: < Existing adornment around point
+;; :Prv: Disadvised previous header
+;; :Hie: < Multiple occurrence in the middle of existing hierarchy
+;; :Cur: Successor exists in preferences
+;; :Dir: Any
+(ert-deftest rst-adjust-section-prf-P-sel-E-prv-D-hie-M-cur-S-dir-? ()
+ (let ((rst-new-adornment-down nil)
+ (rst-default-indent 3)
+ (rst-preferred-adornments '((?: over-and-under 1)
+ (?. over-and-under 1)
+ (?: simple 0)
+ (?. simple 0))))
+ ;; :Dir: Up
+ (should (ert-equal-buffer-return
+ '(rst-ert-adjust-section nil nil)
+ "
+==============
+Document Title
+==============
+
+Additional title\^@
+::::::::::::::::
+
+Hie 1.1
+-------
+
+Hie 2
+:::::
+"
+ "
+==============
+Document Title
+==============
+
+================
+Additional title
+================
+
+Hie 1.1
+-------
+
+Hie 2
+:::::
+"
+ nil))
+ ;; :Dir: Down
+ (should (ert-equal-buffer-return
+ '(rst-ert-adjust-section nil t)
+ "
+==============
+Document Title
+==============
+
+Hie 1.0\^@
+:::::::
+
+Hie 1.1
+-------
+
+Hie 2
+:::::
+"
+ "
+==============
+Document Title
+==============
+
+Hie 1.0
+-------
+
+Hie 1.1
+-------
+
+Hie 2
+:::::
+"
+ nil))
+ ))
+
+;; :Prf: Preferences exist
+;; :Sel: < Existing adornment around point
+;; :Prv: Disadvised previous header
+;; :Hie: < Multiple occurrence in the middle of existing hierarchy
+;; :Cur: Last in preferences
+;; :Dir: Any
+(ert-deftest rst-adjust-section-prf-P-sel-E-prv-D-hie-M-cur-L-dir-? ()
+ (let ((rst-new-adornment-down nil)
+ (rst-default-indent 3)
+ (rst-preferred-adornments '((?: over-and-under 1)
+ (?. over-and-under 1)
+ (?: simple 0)
+ (?. simple 0))))
+ ;; :Dir: Up
+ (should (ert-equal-buffer-return
+ '(rst-ert-adjust-section nil nil)
+ "
+==============
+Document Title
+==============
+
+Additional title\^@
+................
+
+Hie 1.1
+-------
+
+Hie 2
+.....
+"
+ "
+==============
+Document Title
+==============
+
+================
+Additional title
+================
+
+Hie 1.1
+-------
+
+Hie 2
+.....
+"
+ nil))
+ ;; :Dir: Down
+ (should (ert-equal-buffer-return
+ '(rst-ert-adjust-section nil t)
+ "
+==============
+Document Title
+==============
+
+Hie 1.0\^@
+.......
+
+Hie 1.1
+-------
+
+Hie 2
+.....
+"
+ "
+==============
+Document Title
+==============
+
+Hie 1.0
+-------
+
+Hie 1.1
+-------
+
+Hie 2
+.....
+"
+ nil))
+ ))
+
+;; :Prf: Preferences exist
+;; :Sel: < Existing adornment around point
+;; :Prv: Disadvised previous header
+;; :Hie: < Breaking single entry in the middle of existing hierarchy
+;; :Cur: Disadvised
+;; :Dir: Any
+(ert-deftest rst-adjust-section-prf-P-sel-E-prv-D-hie-B-cur-D-dir-? ()
+ (let ((rst-new-adornment-down nil)
+ (rst-default-indent 3)
+ (rst-preferred-adornments '((?: over-and-under 1)
+ (?. over-and-under 1)
+ (?: simple 0)
+ (?. simple 0))))
+ ;; :Dir: Up
+ (should (ert-equal-buffer-return
+ '(rst-ert-adjust-section nil nil)
+ "
+==============
+Document Title
+==============
+
+Additional title\^@
+$$$$$$$$$$$$$$$$
+
+Hie 1.1
+-------
+
+Hie 2
+.....
+"
+ "
+==============
+Document Title
+==============
+
+================
+Additional title
+================
+
+Hie 1.1
+-------
+
+Hie 2
+.....
+"
+ nil))
+ ;; :Dir: Down
+ (should (ert-equal-buffer-return
+ '(rst-ert-adjust-section nil t)
+ "
+==============
+Document Title
+==============
+
+Hie 1.0\^@
+$$$$$$$
+
+Hie 1.1
+-------
+
+Hie 2
+.....
+"
+ "
+==============
+Document Title
+==============
+
+Hie 1.0
+-------
+
+Hie 1.1
+-------
+
+Hie 2
+.....
+"
+ nil))
+ ))
+
+;; :Prf: Preferences exist
+;; :Sel: < Existing adornment around point
+;; :Prv: Disadvised previous header
+;; :Hie: < Breaking single entry in the middle of existing hierarchy
+;; :Cur: Successor exists in preferences
+;; :Dir: Any
+(ert-deftest rst-adjust-section-prf-P-sel-E-prv-D-hie-B-cur-S-dir-? ()
+ (let ((rst-new-adornment-down nil)
+ (rst-default-indent 3)
+ (rst-preferred-adornments '((?: over-and-under 1)
+ (?. over-and-under 1)
+ (?: simple 0)
+ (?. simple 0))))
+ ;; :Dir: Up
+ (should (ert-equal-buffer-return
+ '(rst-ert-adjust-section nil nil)
+ "
+==============
+Document Title
+==============
+
+Additional title\^@
+::::::::::::::::
+
+Hie 1.1
+-------
+
+Hie 2
+=====
+"
+ "
+==============
+Document Title
+==============
+
+================
+Additional title
+================
+
+Hie 1.1
+-------
+
+Hie 2
+=====
+"
+ nil))
+ ;; :Dir: Down
+ (should (ert-equal-buffer-return
+ '(rst-ert-adjust-section nil t)
+ "
+==============
+Document Title
+==============
+
+Hie 1.0\^@
+:::::::
+
+Hie 1.1
+-------
+
+Hie 2
+=====
+"
+ "
+==============
+Document Title
+==============
+
+Hie 1.0
+-------
+
+Hie 1.1
+-------
+
+Hie 2
+=====
+"
+ nil))
+ ))
+
+;; :Prf: Preferences exist
+;; :Sel: < Existing adornment around point
+;; :Prv: Disadvised previous header
+;; :Hie: < Breaking single entry in the middle of existing hierarchy
+;; :Cur: Last in preferences
+;; :Dir: Any
+(ert-deftest rst-adjust-section-prf-P-sel-E-prv-D-hie-B-cur-L-dir-? ()
+ (let ((rst-new-adornment-down nil)
+ (rst-default-indent 3)
+ (rst-preferred-adornments '((?: over-and-under 1)
+ (?. over-and-under 1)
+ (?: simple 0)
+ (?. simple 0))))
+ ;; :Dir: Up
+ (should (ert-equal-buffer-return
+ '(rst-ert-adjust-section nil nil)
+ "
+==============
+Document Title
+==============
+
+Additional title\^@
+................
+
+Hie 1.1
+-------
+
+Hie 2
+=====
+"
+ "
+==============
+Document Title
+==============
+
+================
+Additional title
+================
+
+Hie 1.1
+-------
+
+Hie 2
+=====
+"
+ nil))
+ ;; :Dir: Down
+ (should (ert-equal-buffer-return
+ '(rst-ert-adjust-section nil t)
+ "
+==============
+Document Title
+==============
+
+Hie 1.0\^@
+.......
+
+Hie 1.1
+-------
+
+Hie 2
+=====
+"
+ "
+==============
+Document Title
+==============
+
+Hie 1.0
+-------
+
+Hie 1.1
+-------
+
+Hie 2
+=====
+"
+ nil))
+ ))
+
+;; :Prf: Preferences exist
+;; :Sel: < Existing adornment around point
+;; :Prv: Disadvised previous header
+;; :Hie: < Last in existing hierarchy for given direction
+;; :Cur: Disadvised (i.e. not in preferences)
+;; :Dir: Any
+(ert-deftest rst-adjust-section-prf-P-sel-E-prv-D-hie-L-cur-D-dir-? ()
+ (let ((rst-new-adornment-down nil)
+ (rst-default-indent 3)
+ (rst-preferred-adornments '((?: over-and-under 1)
+ (?. over-and-under 1)
+ (?: simple 0)
+ (?. simple 0))))
+ ;; :Dir: Up
+ (should (ert-equal-buffer-return
+ '(rst-ert-adjust-section nil nil)
+ "
+==============
+Document Title
+==============
+
+Hie 1
+=====
+
+Hie 1.1
+-------
+
+=========
+Hie 1.1.1\^@
+=========
+"
+ "
+==============
+Document Title
+==============
+
+Hie 1
+=====
+
+Hie 1.1
+-------
+
+:::::::::::
+ Hie 1.1.1
+:::::::::::
+"
+ nil))
+ ;; :Dir: Down
+ (should (ert-equal-buffer-return
+ '(rst-ert-adjust-section nil t)
+ "
+==============
+Document Title
+==============
+
+Hie 1
+=====
+
+Hie 1.1
+-------
+
+Additional title\^@
+~~~~~~~~~~~~~~~~
+"
+ "
+==============
+Document Title
+==============
+
+Hie 1
+=====
+
+Hie 1.1
+-------
+
+================
+Additional title
+================
+"
+ nil))
+ ))
+
+;; :Prf: Preferences exist
+;; :Sel: < Existing adornment around point
+;; :Prv: Disadvised previous header
+;; :Hie: < Last in existing hierarchy for given direction
+;; :Cur: Successor exists in preferences
+;; :Dir: Any
+(ert-deftest rst-adjust-section-prf-P-sel-E-prv-D-hie-L-cur-S-dir-? ()
+ (let ((rst-new-adornment-down nil)
+ (rst-default-indent 3)
+ (rst-preferred-adornments '((?: over-and-under 1)
+ (?. over-and-under 1)
+ (?: simple 0)
+ (?. simple 0))))
+ ;; :Dir: Up
+ (should (ert-equal-buffer-return
+ '(rst-ert-adjust-section nil nil)
+ "
+::::::::::::::
+Document Title
+::::::::::::::
+
+.....
+Hie 1
+.....
+
+Hie 1.1
+-------
+
+:::::::::
+Hie 1.1.1\^@
+:::::::::
+"
+ "
+::::::::::::::
+Document Title
+::::::::::::::
+
+.....
+Hie 1
+.....
+
+Hie 1.1
+-------
+
+Hie 1.1.1
+:::::::::
+"
+ nil))
+ ;; :Dir: Down
+ (should (ert-equal-buffer-return
+ '(rst-ert-adjust-section nil t)
+ "
+::::::::::::::
+Document Title
+::::::::::::::
+
+.....
+Hie 1
+.....
+
+Hie 1.1
+-------
+
+:::::
+Hie 2\^@
+:::::
+"
+ "
+::::::::::::::
+Document Title
+::::::::::::::
+
+.....
+Hie 1
+.....
+
+Hie 1.1
+-------
+
+.....
+Hie 2
+.....
+"
+ nil))
+ ))
+
+;; :Prf: Preferences exist
+;; :Sel: < Existing adornment around point
+;; :Prv: Disadvised previous header
+;; :Hie: < Last in existing hierarchy for given direction
+;; :Cur: Successor exists in preferences
+;; :Dir: Any
+(ert-deftest rst-adjust-section-prf-P-sel-E-prv-D-hie-L-cur-S-dir-? ()
+ (let ((rst-new-adornment-down nil)
+ (rst-default-indent 3)
+ (rst-preferred-adornments '((?: over-and-under 1)
+ (?. over-and-under 1)
+ (?: simple 0)
+ (?. simple 0))))
+ ;; :Dir: Up
+ (should (ert-equal-buffer-return
+ '(rst-ert-adjust-section nil nil)
+ "
+::::::::::::::
+Document Title
+::::::::::::::
+
+.....
+Hie 1
+.....
+
+Hie 1.1
+-------
+
+:::::::::
+Hie 1.1.1\^@
+:::::::::
+"
+ "
+::::::::::::::
+Document Title
+::::::::::::::
+
+.....
+Hie 1
+.....
+
+Hie 1.1
+-------
+
+Hie 1.1.1
+:::::::::
+"
+ nil))
+ ;; :Dir: Down
+ (should (ert-equal-buffer-return
+ '(rst-ert-adjust-section nil t)
+ "
+::::::::::::::
+Document Title
+::::::::::::::
+
+.....
+Hie 1
+.....
+
+Hie 1.1
+-------
+
+:::::
+Hie 2\^@
+:::::
+"
+ "
+::::::::::::::
+Document Title
+::::::::::::::
+
+.....
+Hie 1
+.....
+
+Hie 1.1
+-------
+
+.....
+Hie 2
+.....
+"
+ nil))
+ ))
+
+;; :Prf: Preferences exist
+;; :Sel: < Existing adornment around point
+;; :Prv: Disadvised previous header
+;; :Hie: < Last in existing hierarchy for given direction
+;; :Cur: Last in preferences
+;; :Dir: Any
+(ert-deftest rst-adjust-section-prf-P-sel-E-prv-D-hie-L-cur-L-dir-? ()
+ (let ((rst-new-adornment-down nil)
+ (rst-default-indent 3)
+ (rst-preferred-adornments '((?: over-and-under 1)
+ (?. over-and-under 1)
+ (?: simple 0)
+ (?. simple 0))))
+ ;; :Dir: Up
+ (should (ert-equal-buffer-return
+ '(rst-ert-adjust-section nil nil)
+ "
+::::::::::::::
+Document Title
+::::::::::::::
+
+.....
+Hie 1
+.....
+
+Hie 1.1
+-------
+
+Hie 1.2\^@
+.......
+"
+ "
+::::::::::::::
+Document Title
+::::::::::::::
+
+.....
+Hie 1
+.....
+
+Hie 1.1
+-------
+
+Hie 1.2
+-------
+"
+ nil))
+ ;; :Dir: Down
+ (should (ert-equal-buffer-return
+ '(rst-ert-adjust-section nil t)
+ "
+::::::::::::::
+Document Title
+::::::::::::::
+
+.....
+Hie 1
+.....
+
+Hie 1.1
+-------
+
+Another title\^@
+.............
+"
+ "
+::::::::::::::
+Document Title
+::::::::::::::
+
+.....
+Hie 1
+.....
+
+Hie 1.1
+-------
+
+:::::::::::::
+Another title
+:::::::::::::
+"
+ nil))
+ ))
+
+;; :Prf: Preferences exist
+;; :Sel: < Existing adornment around point
+;; :Prv: Disadvised previous header
+;; :Hie: Once in existing hierarchy at beginning or end of hierarchy
+;; :Cur: Disadvised (i.e. not in preferences)
+;; :Dir: Any
+(ert-deftest rst-adjust-section-prf-P-sel-E-prv-D-hie-O-cur-D-dir-? ()
+ (let ((rst-new-adornment-down nil)
+ (rst-default-indent 3)
+ (rst-preferred-adornments '((?: over-and-under 1)
+ (?. over-and-under 1)
+ (?: simple 0)
+ (?. simple 0))))
+ ;; :Dir: Up
+ (should (ert-equal-buffer-return
+ '(rst-ert-adjust-section nil nil)
+ "
+::::::::::::::
+Document Title
+::::::::::::::
+
+.....
+Hie 1
+.....
+
+Hie 1.1
+=======
+
+Hie 1.2\^@
+-------
+"
+ "
+::::::::::::::
+Document Title
+::::::::::::::
+
+.....
+Hie 1
+.....
+
+Hie 1.1
+=======
+
+Hie 1.2
+=======
+"
+ nil))
+ ;; :Dir: Down
+ (should (ert-equal-buffer-return
+ '(rst-ert-adjust-section nil t)
+ "
+::::::::::::::
+Document Title
+::::::::::::::
+
+.....
+Hie 1
+.....
+
+Hie 1.1
+=======
+
+Other title\^@
+-----------
+"
+ "
+::::::::::::::
+Document Title
+::::::::::::::
+
+.....
+Hie 1
+.....
+
+Hie 1.1
+=======
+
+:::::::::::
+Other title
+:::::::::::
+"
+ nil))
+ ))
+
+;; :Prf: Preferences exist
+;; :Sel: < Existing adornment around point
+;; :Prv: Disadvised previous header
+;; :Hie: Once in existing hierarchy at beginning or end of hierarchy
+;; :Cur: Successor exists in preferences
+;; :Dir: Any
+(ert-deftest rst-adjust-section-prf-P-sel-E-prv-D-hie-O-cur-S-dir-? ()
+ (let ((rst-new-adornment-down nil)
+ (rst-default-indent 3)
+ (rst-preferred-adornments '((?: over-and-under 1)
+ (?. over-and-under 1)
+ (?: simple 0)
+ (?. simple 0))))
+ ;; :Dir: Up
+ (should (ert-equal-buffer-return
+ '(rst-ert-adjust-section nil nil)
+ "
+::::::::::::::
+Document Title
+::::::::::::::
+
+.....
+Hie 1
+.....
+
+Hie 1.1
+=======
+
+Hie 1.2\^@
+:::::::
+"
+ "
+::::::::::::::
+Document Title
+::::::::::::::
+
+.....
+Hie 1
+.....
+
+Hie 1.1
+=======
+
+Hie 1.2
+=======
+"
+ nil))
+ ;; :Dir: Down
+ (should (ert-equal-buffer-return
+ '(rst-ert-adjust-section nil t)
+ "
+::::::::::::::
+Document Title
+::::::::::::::
+
+.....
+Hie 1
+.....
+
+Hie 1.1
+=======
+
+Other title\^@
+:::::::::::
+"
+ "
+::::::::::::::
+Document Title
+::::::::::::::
+
+.....
+Hie 1
+.....
+
+Hie 1.1
+=======
+
+:::::::::::
+Other title
+:::::::::::
+"
+ nil))
+ ))
+
+;; :Prf: Preferences exist
+;; :Sel: < Existing adornment around point
+;; :Prv: Disadvised previous header
+;; :Hie: Once in existing hierarchy at beginning or end of hierarchy
+;; :Cur: Last in preferences
+;; :Dir: Any
+(ert-deftest rst-adjust-section-prf-P-sel-E-prv-D-hie-O-cur-L-dir-? ()
+ (let ((rst-new-adornment-down nil)
+ (rst-default-indent 3)
+ (rst-preferred-adornments '((?: over-and-under 1)
+ (?. over-and-under 1)
+ (?: simple 0)
+ (?. simple 0))))
+ ;; :Dir: Up
+ (should (ert-equal-buffer-return
+ '(rst-ert-adjust-section nil nil)
+ "
+::::::::::::::
+Document Title
+::::::::::::::
+
+.....
+Hie 1
+.....
+
+Hie 1.1
+=======
+
+Hie 1.2\^@
+.......
+"
+ "
+::::::::::::::
+Document Title
+::::::::::::::
+
+.....
+Hie 1
+.....
+
+Hie 1.1
+=======
+
+Hie 1.2
+=======
+"
+ nil))
+ ;; :Dir: Down
+ (should (ert-equal-buffer-return
+ '(rst-ert-adjust-section nil t)
+ "
+::::::::::::::
+Document Title
+::::::::::::::
+
+.....
+Hie 1
+.....
+
+Hie 1.1
+=======
+
+Other title\^@
+...........
+"
+ "
+::::::::::::::
+Document Title
+::::::::::::::
+
+.....
+Hie 1
+.....
+
+Hie 1.1
+=======
+
+:::::::::::
+Other title
+:::::::::::
+"
+ nil))
+ ))
+
+;; :Prf: Preferences exist
+;; :Sel: < Existing adornment around point
+;; :Prv: Preferences contain previous header
+;; :Hie: < Multiple occurrence in the middle of existing hierarchy
+;; :Cur: Disadvised (i.e. not in preferences)
+;; :Dir: Any
+(ert-deftest rst-adjust-section-prf-P-sel-E-prv-P-hie-M-cur-D-dir-? ()
+ (let ((rst-new-adornment-down nil)
+ (rst-default-indent 3)
+ (rst-preferred-adornments '((?: over-and-under 1)
+ (?. over-and-under 1)
+ (?: simple 0)
+ (?. simple 0))))
+ ;; :Dir: Up
+ (should (ert-equal-buffer-return
+ '(rst-ert-adjust-section nil nil)
+ "
+::::::::::::::
+Document Title
+::::::::::::::
+
+.....
+Hie 1
+.....
+
+Hie 2\^@
+=====
+
+Hie 1.2
+=======
+
+Hie 1.2.1
+---------
+"
+ "
+::::::::::::::
+Document Title
+::::::::::::::
+
+.....
+Hie 1
+.....
+
+.....
+Hie 2
+.....
+
+Hie 1.2
+=======
+
+Hie 1.2.1
+---------
+"
+ nil))
+ ;; :Dir: Down
+ (should (ert-equal-buffer-return
+ '(rst-ert-adjust-section nil t)
+ "
+::::::::::::::
+Document Title
+::::::::::::::
+
+.....
+Hie 1
+.....
+
+Hie 1.x.1\^@
+=========
+
+Hie 1.2
+=======
+
+Hie 1.2.1
+---------
+"
+ "
+::::::::::::::
+Document Title
+::::::::::::::
+
+.....
+Hie 1
+.....
+
+Hie 1.x.1
+---------
+
+Hie 1.2
+=======
+
+Hie 1.2.1
+---------
+"
+ nil))
+ ))
+
+;; :Prf: Preferences exist
+;; :Sel: < Existing adornment around point
+;; :Prv: Preferences contain previous header
+;; :Hie: < Multiple occurrence in the middle of existing hierarchy
+;; :Cur: Successor exists in preferences
+;; :Dir: Any
+(ert-deftest rst-adjust-section-prf-P-sel-E-prv-P-hie-M-cur-S-dir-? ()
+ (let ((rst-new-adornment-down nil)
+ (rst-default-indent 3)
+ (rst-preferred-adornments '((?: over-and-under 1)
+ (?. over-and-under 1)
+ (?: simple 0)
+ (?. simple 0))))
+ ;; :Dir: Up
+ (should (ert-equal-buffer-return
+ '(rst-ert-adjust-section nil nil)
+ "
+::::::::::::::
+Document Title
+::::::::::::::
+
+.....
+Hie 1
+.....
+
+Hie 2\^@
+:::::
+
+Hie 1.2
+:::::::
+
+Hie 1.2.1
+---------
+"
+ "
+::::::::::::::
+Document Title
+::::::::::::::
+
+.....
+Hie 1
+.....
+
+.....
+Hie 2
+.....
+
+Hie 1.2
+:::::::
+
+Hie 1.2.1
+---------
+"
+ nil))
+ ;; :Dir: Down
+ (should (ert-equal-buffer-return
+ '(rst-ert-adjust-section nil t)
+ "
+::::::::::::::
+Document Title
+::::::::::::::
+
+.....
+Hie 1
+.....
+
+Hie 1.x.1\^@
+:::::::::
+
+Hie 1.2
+:::::::
+
+Hie 1.2.1
+---------
+"
+ "
+::::::::::::::
+Document Title
+::::::::::::::
+
+.....
+Hie 1
+.....
+
+Hie 1.x.1
+---------
+
+Hie 1.2
+:::::::
+
+Hie 1.2.1
+---------
+"
+ nil))
+ ))
+
+;; :Prf: Preferences exist
+;; :Sel: < Existing adornment around point
+;; :Prv: Preferences contain previous header
+;; :Hie: < Multiple occurrence in the middle of existing hierarchy
+;; :Cur: Last in preferences
+;; :Dir: Any
+(ert-deftest rst-adjust-section-prf-P-sel-E-prv-P-hie-M-cur-L-dir-? ()
+ (let ((rst-new-adornment-down nil)
+ (rst-default-indent 3)
+ (rst-preferred-adornments '((?: over-and-under 1)
+ (?. over-and-under 1)
+ (?: simple 0)
+ (?. simple 0))))
+ ;; :Dir: Up
+ (should (ert-equal-buffer-return
+ '(rst-ert-adjust-section nil nil)
+ "
+::::::::::::::
+Document Title
+::::::::::::::
+
+.....
+Hie 1
+.....
+
+Hie 2\^@
+.....
+
+Hie 1.2
+.......
+
+Hie 1.2.1
+---------
+"
+ "
+::::::::::::::
+Document Title
+::::::::::::::
+
+.....
+Hie 1
+.....
+
+.....
+Hie 2
+.....
+
+Hie 1.2
+.......
+
+Hie 1.2.1
+---------
+"
+ nil))
+ ;; :Dir: Down
+ (should (ert-equal-buffer-return
+ '(rst-ert-adjust-section nil t)
+ "
+::::::::::::::
+Document Title
+::::::::::::::
+
+.....
+Hie 1
+.....
+
+Hie 1.x.1\^@
+.........
+
+Hie 1.2
+.......
+
+Hie 1.2.1
+---------
+"
+ "
+::::::::::::::
+Document Title
+::::::::::::::
+
+.....
+Hie 1
+.....
+
+Hie 1.x.1
+---------
+
+Hie 1.2
+.......
+
+Hie 1.2.1
+---------
+"
+ nil))
+ ))
+
+;; :Prf: Preferences exist
+;; :Sel: < Existing adornment around point
+;; :Prv: Preferences contain previous header
+;; :Hie: < Breaking single entry in the middle of existing hierarchy
+;; :Cur: Disadvised (i.e. not in preferences)
+;; :Dir: Any
+(ert-deftest rst-adjust-section-prf-P-sel-E-prv-P-hie-B-cur-D-dir-? ()
+ (let ((rst-new-adornment-down nil)
+ (rst-default-indent 3)
+ (rst-preferred-adornments '((?: over-and-under 1)
+ (?. over-and-under 1)
+ (?: simple 0)
+ (?. simple 0))))
+ ;; :Dir: Up
+ (should (ert-equal-buffer-return
+ '(rst-ert-adjust-section nil nil)
+ "
+::::::::::::::
+Document Title
+::::::::::::::
+
+.....
+Hie 1
+.....
+
+Hie 2\^@
+=====
+
+Hie 1.1.1
+---------
+"
+ "
+::::::::::::::
+Document Title
+::::::::::::::
+
+.....
+Hie 1
+.....
+
+.....
+Hie 2
+.....
+
+Hie 1.1.1
+---------
+"
+ nil))
+ ;; :Dir: Down
+ (should (ert-equal-buffer-return
+ '(rst-ert-adjust-section nil t)
+ "
+::::::::::::::
+Document Title
+::::::::::::::
+
+.....
+Hie 1
+.....
+
+Hie 1.x.1\^@
+=========
+
+Hie 1.1.1
+---------
+"
+ "
+::::::::::::::
+Document Title
+::::::::::::::
+
+.....
+Hie 1
+.....
+
+Hie 1.x.1
+---------
+
+Hie 1.1.1
+---------
+"
+ nil))
+ ))
+
+;; :Prf: Preferences exist
+;; :Sel: < Existing adornment around point
+;; :Prv: Preferences contain previous header
+;; :Hie: < Breaking single entry in the middle of existing hierarchy
+;; :Cur: Successor exists in preferences
+;; :Dir: Any
+(ert-deftest rst-adjust-section-prf-P-sel-E-prv-P-hie-B-cur-S-dir-? ()
+ (let ((rst-new-adornment-down nil)
+ (rst-default-indent 3)
+ (rst-preferred-adornments '((?: over-and-under 1)
+ (?. over-and-under 1)
+ (?: simple 0)
+ (?. simple 0))))
+ ;; :Dir: Up
+ (should (ert-equal-buffer-return
+ '(rst-ert-adjust-section nil nil)
+ "
+::::::::::::::
+Document Title
+::::::::::::::
+
+.....
+Hie 1
+.....
+
+Hie 2\^@
+=====
+
+Hie 1.1.1
+.........
+"
+ "
+::::::::::::::
+Document Title
+::::::::::::::
+
+.....
+Hie 1
+.....
+
+.....
+Hie 2
+.....
+
+Hie 1.1.1
+.........
+"
+ nil))
+ ;; :Dir: Down
+ (should (ert-equal-buffer-return
+ '(rst-ert-adjust-section nil t)
+ "
+::::::::::::::
+Document Title
+::::::::::::::
+
+.....
+Hie 1
+.....
+
+Hie 1.x.1\^@
+=========
+
+Hie 1.1.1
+.........
+"
+ "
+::::::::::::::
+Document Title
+::::::::::::::
+
+.....
+Hie 1
+.....
+
+Hie 1.x.1
+.........
+
+Hie 1.1.1
+.........
+"
+ nil))
+ ))
+
+;; :Prf: Preferences exist
+;; :Sel: < Existing adornment around point
+;; :Prv: Preferences contain previous header
+;; :Hie: < Breaking single entry in the middle of existing hierarchy
+;; :Cur: Last in preferences
+;; :Dir: Any
+(ert-deftest rst-adjust-section-prf-P-sel-E-prv-P-hie-B-cur-L-dir-? ()
+ (let ((rst-new-adornment-down nil)
+ (rst-default-indent 3)
+ (rst-preferred-adornments '((?: over-and-under 1)
+ (?. over-and-under 1)
+ (?: simple 0)
+ (?. simple 0))))
+ ;; :Dir: Up
+ (should (ert-equal-buffer-return
+ '(rst-ert-adjust-section nil nil)
+ "
+::::::::::::::
+Document Title
+::::::::::::::
+
+.....
+Hie 1
+.....
+
+Hie 2\^@
+.....
+
+Hie 1.1.1
+---------
+"
+ "
+::::::::::::::
+Document Title
+::::::::::::::
+
+.....
+Hie 1
+.....
+
+.....
+Hie 2
+.....
+
+Hie 1.1.1
+---------
+"
+ nil))
+ ;; :Dir: Down
+ (should (ert-equal-buffer-return
+ '(rst-ert-adjust-section nil t)
+ "
+::::::::::::::
+Document Title
+::::::::::::::
+
+.....
+Hie 1
+.....
+
+Hie 1.x.1\^@
+.........
+
+Hie 1.1.1
+---------
+"
+ "
+::::::::::::::
+Document Title
+::::::::::::::
+
+.....
+Hie 1
+.....
+
+Hie 1.x.1
+---------
+
+Hie 1.1.1
+---------
+"
+ nil))
+ ))
+
+;; :Prf: Preferences exist
+;; :Sel: < Existing adornment around point
+;; :Prv: Preferences contain previous header
+;; :Hie: < Last in existing hierarchy for given direction
+;; :Cur: Disadvised (i.e. not in preferences)
+;; :Dir: Any
+(ert-deftest rst-adjust-section-prf-P-sel-E-prv-P-hie-L-cur-D-dir-? ()
+ (let ((rst-new-adornment-down nil)
+ (rst-default-indent 3)
+ (rst-preferred-adornments '((?: over-and-under 1)
+ (?. over-and-under 1)
+ (?: simple 0)
+ (?. simple 0))))
+ ;; :Dir: Up
+ (should (ert-equal-buffer-return
+ '(rst-ert-adjust-section nil nil)
+ "
+==============
+Document Title
+==============
+
+.....
+Hie 1
+.....
+
+=======
+Hie 1.1\^@
+=======
+
+Hie 1.2
+-------
+"
+ "
+==============
+Document Title
+==============
+
+.....
+Hie 1
+.....
+
+Hie 1.1
+:::::::
+
+Hie 1.2
+-------
+"
+ nil))
+ ;; :Dir: Down
+ (should (ert-equal-buffer-return
+ '(rst-ert-adjust-section nil t)
+ "
+==============
+Document Title
+==============
+
+.....
+Hie 1
+.....
+
+Hie 1.1\^@
+-------
+
+Hie 1.2
+-------
+"
+ "
+==============
+Document Title
+==============
+
+.....
+Hie 1
+.....
+
+Hie 1.1
+:::::::
+
+Hie 1.2
+-------
+"
+ nil))
+ ))
+
+;; :Prf: Preferences exist
+;; :Sel: < Existing adornment around point
+;; :Prv: Preferences contain previous header
+;; :Hie: < Last in existing hierarchy for given direction
+;; :Cur: Successor exists in preferences
+;; :Dir: Any
+(ert-deftest rst-adjust-section-prf-P-sel-E-prv-P-hie-L-cur-S-dir-? ()
+ (let ((rst-new-adornment-down nil)
+ (rst-default-indent 3)
+ (rst-preferred-adornments '((?: over-and-under 1)
+ (?. over-and-under 1)
+ (?: simple 0)
+ (?. simple 0))))
+ ;; :Dir: Up
+ (should (ert-equal-buffer-return
+ '(rst-ert-adjust-section nil nil)
+ "
+::::::::::::::
+Document Title
+::::::::::::::
+
+.....
+Hie 1
+.....
+
+:::::::
+Hie 1.1\^@
+:::::::
+
+Hie 1.2
+-------
+"
+ "
+::::::::::::::
+Document Title
+::::::::::::::
+
+.....
+Hie 1
+.....
+
+Hie 1.1
+:::::::
+
+Hie 1.2
+-------
+"
+ nil))
+ ;; :Dir: Down
+ (should (ert-equal-buffer-return
+ '(rst-ert-adjust-section nil t)
+ "
+==============
+Document Title
+==============
+
+.....
+Hie 1
+.....
+
+Hie 1.1\^@
+:::::::
+
+Hie 1.2
+:::::::
+"
+ "
+==============
+Document Title
+==============
+
+.....
+Hie 1
+.....
+
+Hie 1.1
+.......
+
+Hie 1.2
+:::::::
+"
+ nil))
+ ))
+
+;; :Prf: Preferences exist
+;; :Sel: < Existing adornment around point
+;; :Prv: Preferences contain previous header
+;; :Hie: < Last in existing hierarchy for given direction
+;; :Cur: Last in preferences
+;; :Dir: Any
+(ert-deftest rst-adjust-section-prf-P-sel-E-prv-P-hie-L-cur-L-dir-? ()
+ (let ((rst-new-adornment-down nil)
+ (rst-default-indent 3)
+ (rst-preferred-adornments '((?: over-and-under 1)
+ (?. over-and-under 1)
+ (?: simple 0)
+ (?. simple 0))))
+ ;; :Dir: Up
+ (should (ert-equal-buffer-return
+ '(rst-ert-adjust-section nil nil)
+ "
+Document Title
+..............
+
+.....
+Hie 1
+.....
+
+Hie 1.1\^@
+.......
+
+Hie 1.2
+-------
+"
+ "
+Document Title
+..............
+
+.....
+Hie 1
+.....
+
+Hie 1.1
+:::::::
+
+Hie 1.2
+-------
+"
+ nil))
+ ;; :Dir: Down
+ (should (ert-equal-buffer-return
+ '(rst-ert-adjust-section nil t)
+ "
+==============
+Document Title
+==============
+
+.....
+Hie 1
+.....
+
+Hie 1.1\^@
+.......
+
+Hie 1.2
+.......
+"
+ "
+==============
+Document Title
+==============
+
+.....
+Hie 1
+.....
+
+Hie 1.1
+:::::::
+
+Hie 1.2
+.......
+"
+ nil))
+ ))
+
+;; :Prf: Preferences exist
+;; :Sel: < Existing adornment around point
+;; :Prv: Preferences contain previous header
+;; :Hie: < Once in existing hierarchy at beginning or end of hierarchy
+;; :Cur: Disadvised (i.e. not in preferences)
+;; :Dir: Any
+(ert-deftest rst-adjust-section-prf-P-sel-E-prv-P-hie-O-cur-D-dir-? ()
+ (let ((rst-new-adornment-down nil)
+ (rst-default-indent 3)
+ (rst-preferred-adornments '((?: over-and-under 1)
+ (?. over-and-under 1)
+ (?: simple 0)
+ (?. simple 0))))
+ ;; :Dir: Up
+ (should (ert-equal-buffer-return
+ '(rst-ert-adjust-section nil nil)
+ "
+==============
+Document Title
+==============
+
+.....
+Hie 1
+.....
+
+Hie 2\^@
+=====
+"
+ "
+==============
+Document Title
+==============
+
+.....
+Hie 1
+.....
+
+.....
+Hie 2
+.....
+"
+ nil))
+ ;; :Dir: Down
+ (should (ert-equal-buffer-return
+ '(rst-ert-adjust-section nil t)
+ "
+==============
+Document Title
+==============
+
+.....
+Hie 1
+.....
+
+Title\^@
+=====
+"
+ "
+==============
+Document Title
+==============
+
+.....
+Hie 1
+.....
+
+=====
+Title
+=====
+"
+ nil))
+ ))
+
+;; :Prf: Preferences exist
+;; :Sel: < Existing adornment around point
+;; :Prv: Preferences contain previous header
+;; :Hie: < Once in existing hierarchy at beginning or end of hierarchy
+;; :Cur: Successor exists in preferences
+;; :Dir: Any
+(ert-deftest rst-adjust-section-prf-P-sel-E-prv-P-hie-O-cur-S-dir-? ()
+ (let ((rst-new-adornment-down nil)
+ (rst-default-indent 3)
+ (rst-preferred-adornments '((?: over-and-under 1)
+ (?. over-and-under 1)
+ (?: simple 0)
+ (?. simple 0))))
+ ;; :Dir: Up
+ (should (ert-equal-buffer-return
+ '(rst-ert-adjust-section nil nil)
+ "
+==============
+Document Title
+==============
+
+.....
+Hie 1
+.....
+
+Hie 2\^@
+:::::
+"
+ "
+==============
+Document Title
+==============
+
+.....
+Hie 1
+.....
+
+.....
+Hie 2
+.....
+"
+ nil))
+ ;; :Dir: Down
+ (should (ert-equal-buffer-return
+ '(rst-ert-adjust-section nil t)
+ "
+==============
+Document Title
+==============
+
+.....
+Hie 1
+.....
+
+Title\^@
+:::::
+"
+ "
+==============
+Document Title
+==============
+
+.....
+Hie 1
+.....
+
+=====
+Title
+=====
+"
+ nil))
+ ))
+
+;; :Prf: Preferences exist
+;; :Sel: < Existing adornment around point
+;; :Prv: Preferences contain previous header
+;; :Hie: < Once in existing hierarchy at beginning or end of hierarchy
+;; :Cur: Last in preferences
+;; :Dir: Any
+(ert-deftest rst-adjust-section-prf-P-sel-E-prv-P-hie-O-cur-L-dir-? ()
+ (let ((rst-new-adornment-down nil)
+ (rst-default-indent 3)
+ (rst-preferred-adornments '((?: over-and-under 1)
+ (?. over-and-under 1)
+ (?: simple 0)
+ (?. simple 0))))
+ ;; :Dir: Up
+ (should (ert-equal-buffer-return
+ '(rst-ert-adjust-section nil nil)
+ "
+==============
+Document Title
+==============
+
+.....
+Hie 1
+.....
+
+Hie 2\^@
+.....
+"
+ "
+==============
+Document Title
+==============
+
+.....
+Hie 1
+.....
+
+.....
+Hie 2
+.....
+"
+ nil))
+ ;; :Dir: Down
+ (should (ert-equal-buffer-return
+ '(rst-ert-adjust-section nil t)
+ "
+==============
+Document Title
+==============
+
+.....
+Hie 1
+.....
+
+Title\^@
+.....
+"
+ "
+==============
+Document Title
+==============
+
+.....
+Hie 1
+.....
+
+=====
+Title
+=====
+"
+ nil))
+ ))
--- /dev/null
+Use cases section header adjustment
+===================================
+
+Conditions
+----------
+
+* **Pr**\e\ **f**\erences
+ * **N**\o preferences
+ * **P**\references exist
+
+* **Sel**\ection
+ * **N**\o adornment around point
+ * **E**\xisting adornment around point
+ * **R**\egion
+
+* **Pr**\e\ **v**\ious header
+ * **N**\o previous header
+ * **D**\isadvised previous header (i.e. not in preferences)
+ * **P**\references contain previous header
+
+* Current header in existing **hie**\rarchy
+ * **N**\o hierarchy beyond current header
+ * **M**\ultiple occurrence in the middle of existing hierarchy
+ * **B**\reaking single entry in the middle of existing hierarchy
+ * **L**\ast in existing hierarchy for given direction
+ * **O**\nce in existing hierarchy at beginning or end of hierarchy
+
+* **Cur**\rent header in preferences
+ * **D**\isadvised (i.e. not in preferences)
+ * **S**\uccessor exists in preferences
+ * **L**\ast in preferences
+
+* **Dir**\ection
+ * **D**\ownward
+ * **U**\pward
+
+* **Res**\ult
+ * **N**\o next
+ * **E**\rror
+ * **P**\references give next including rotation
+ * **H**\ierarchy gives next including rotation
+ * **T**\op of hierarchy
+ * **L**\ast of hierarchy
+
+* **Rem**\mark
+
+Use cases
+---------
+
++---+---+---+-----+---+---+-+------+-------------------------------------------+
+|Prf|Sel|Prv|Hie |Cur|Dir|#|Res |Rem |
++---+---+---+-----+---+---+-+------+-------------------------------------------+
+|NP |NER|NDP|NMBLO|DSL|DU |#|NEPHTL| |
++===+===+===+=====+===+===+-+======+===========================================+
+|N> |? |<ND|? |<D |? | |<NEHTL|[No preferences] |
++---+---+---+-----+---+---+-+------+-------------------------------------------+
+|N> |N> |<N>|<N |<! |? | |E |Nothing there at all |
++---+---+---+-----+---+---+-+------+-------------------------------------------+
+|N> |N> |<N>|<! |<! |? | |T |At top use top |
++---+---+---+-----+---+---+-+------+-------------------------------------------+
+|N> |N> |<D>|<! |<! |? | |H |New section header in existing hierarchy |
++---+---+---+-----+---+---+-+------+-------------------------------------------+
+|N> |E |<N>|<N |<D |? | |E |One and only header |
++---+---+---+-----+---+---+-+------+-------------------------------------------+
+|N> |<E |<N>|<M |<D |? | |H |Top header matching medium level - continue|
+| | | | | | | | |reorganisation by a step |
++---+---+---+-----+---+---+-+------+-------------------------------------------+
+|N> |<E |<N>|<L |<D |? | |H |Top header matching extreme level - |
+| | | | | | | | |continue reorganisation by a rotation |
++---+---+---+-----+---+---+-+------+-------------------------------------------+
+|N> |<E |<N>|<O |<D |D | |T |Top header with exclusive level downwards -|
+| | | | | | | | |align to top of remaining hierarchy |
++---+---+---+-----+---+---+-+------+-------------------------------------------+
+|N> |<E |<N>|<O |<D |U | |L |Top header with exclusive level upwards - |
+| | | | | | | | |align to last of remaining hierarchy |
++---+---+---+-----+---+---+-+------+-------------------------------------------+
+|N> |<E |<D |<M |<D |? | |H |Standard step |
++---+---+---+-----+---+---+-+------+-------------------------------------------+
+|N> |<E |<D |<B |<D |? | |H |Align breaking header |
++---+---+---+-----+---+---+-+------+-------------------------------------------+
+|N> |<E |<D |<L |<D |? | |H |Step or rotate |
++---+---+---+-----+---+---+-+------+-------------------------------------------+
+|N> |<E |<D |<O |<D |? | |H |Step or rotate |
++---+---+---+-----+---+---+-+------+-------------------------------------------+
+|###|###|###|#####|###|###|#|######|###########################################|
++---+---+---+-----+---+---+-+------+-------------------------------------------+
+|P |N> |<N>|N> |<! |? | |P |Only preferences exist |
++---+---+---+-----+---+---+-+------+-------------------------------------------+
+|P |N> |N> |<! |<! |D | |T |At top downwards use top of hierarchy |
++---+---+---+-----+---+---+-+------+-------------------------------------------+
+|P |N> |N> |<! |<! |U | |P |At top upwards use top of preferences |
+| | | | | | | | |adding a title |
++---+---+---+-----+---+---+-+------+-------------------------------------------+
+|P |<E |D> |<M |D |? | |H |Prefer hierarchy over preferences |
++---+---+---+-----+---+---+-+------+-------------------------------------------+
+|P |<E |D> |<M |S |? | |H |Prefer hierarchy over preferences |
++---+---+---+-----+---+---+-+------+-------------------------------------------+
+|P |<E |D> |<M |L |? | |H |Prefer hierarchy over preferences |
++---+---+---+-----+---+---+-+------+-------------------------------------------+
+|P |<E |D> |<B |D |? | |H |Prefer hierarchy over preferences |
++---+---+---+-----+---+---+-+------+-------------------------------------------+
+|P |<E |D> |<B |S |? | |H |Prefer hierarchy over preferences |
++---+---+---+-----+---+---+-+------+-------------------------------------------+
+|P |<E |D> |<B |L |? | |H |Prefer hierarchy over preferences |
++---+---+---+-----+---+---+-+------+-------------------------------------------+
+|P |<E |D> |<L |D |D | |H |Wrap to top level |
++---+---+---+-----+---+---+-+------+-------------------------------------------+
+|P |<E |D> |<L |D |U | |P |Use first from preferences |
++---+---+---+-----+---+---+-+------+-------------------------------------------+
+|P |<E |D> |<L |S |D | |P |Prefer hierarchy |
++---+---+---+-----+---+---+-+------+-------------------------------------------+
+|P |<E |D> |<L |S |U | |P |Prefer preferences |
++---+---+---+-----+---+---+-+------+-------------------------------------------+
+|P |<E |D> |<L |L |? | |H |Prefer hierarchy |
++---+---+---+-----+---+---+-+------+-------------------------------------------+
+|P |<E |D> |<O |D |? | |H |Prefer hierarchy |
++---+---+---+-----+---+---+-+------+-------------------------------------------+
+|P |<E |D> |<O |S |? | |H |Prefer hierarchy |
++---+---+---+-----+---+---+-+------+-------------------------------------------+
+|P |<E |D> |<O |L |? | |H |Prefer hierarchy |
++---+---+---+-----+---+---+-+------+-------------------------------------------+
+|P |<E |P> |<M |D |? | |H |Prefer hierarchy |
++---+---+---+-----+---+---+-+------+-------------------------------------------+
+|P |<E |P> |<M |S |? | |H |Prefer hierarchy |
++---+---+---+-----+---+---+-+------+-------------------------------------------+
+|P |<E |P> |<M |L |? | |H |Prefer hierarchy |
++---+---+---+-----+---+---+-+------+-------------------------------------------+
+|P |<E |P> |<B |D |? | |H |Prefer hierarchy |
++---+---+---+-----+---+---+-+------+-------------------------------------------+
+|P |<E |P> |<B |S |? | |H |Prefer hierarchy |
++---+---+---+-----+---+---+-+------+-------------------------------------------+
+|P |<E |P> |<B |L |? | |H |Prefer hierarchy |
++---+---+---+-----+---+---+-+------+-------------------------------------------+
+|P |<E |P> |<L |D |? | |P |Prefer preferences |
++---+---+---+-----+---+---+-+------+-------------------------------------------+
+|P |<E |P> |<L |S |? | |P |Prefer preferences |
++---+---+---+-----+---+---+-+------+-------------------------------------------+
+|P |<E |P> |<L |L |? | |P |Prefer preferences |
++---+---+---+-----+---+---+-+------+-------------------------------------------+
+|P |<E |P> |<O |D |? | |H |Prefer hierarchy |
++---+---+---+-----+---+---+-+------+-------------------------------------------+
+|P |<E |P> |<O |S |? | |H |Prefer hierarchy |
++---+---+---+-----+---+---+-+------+-------------------------------------------+
+|P |<E |P> |<O |L |? | |H |Prefer hierarchy |
++---+---+---+-----+---+---+-+------+-------------------------------------------+
+| | | | | | | | | |
++---+---+---+-----+---+---+-+------+-------------------------------------------+
+| | | | | | | | | |
++---+---+---+-----+---+---+-+------+-------------------------------------------+
+| | | | | | | | | |
++---+---+---+-----+---+---+-+------+-------------------------------------------+
+| | | | | | | | |[CONSTRAINTS] |
++---+---+---+-----+---+---+-+------+-------------------------------------------+
+|N> |? |<ND|? |<D |? | |<NEHTL|Without preferences no header may relate to|
+| | | | | | | | |them |
++---+---+---+-----+---+---+-+------+-------------------------------------------+
+|? |N> |? |<N! |<! |? | | |Without a selection the current header may |
+| | | | | | | | |not relate to anything |
++---+---+---+-----+---+---+-+------+-------------------------------------------+
+|? |? |N> |<NMLO|? |? | | |Without a previous header only certain |
+| | | | | | | | |relations to hierarchy are possible |
++---+---+---+-----+---+---+-+------+-------------------------------------------+
+|? |? |D> |<MBLO|? |? | | |With a disadvised previous header only |
+| | | | | | | | |certain relations to hierarchy are possible|
+| | | | | | | | |for current header |
++---+---+---+-----+---+---+-+------+-------------------------------------------+
+|? |? |<N |N> |? |? | |<NPE |Without hierarchy there can be no previous |
+| | | | | | | | |header and result may not come from |
+| | | | | | | | |hierarchy |
++---+---+---+-----+---+---+-+------+-------------------------------------------+
+|? |<E | |MBLO>| | | | |If the header has a relation than it must |
+| | | | | | | | |exist |
++---+---+---+-----+---+---+-+------+-------------------------------------------+
+| | | | | | | | |REGION |
++---+---+---+-----+---+---+-+------+-------------------------------------------+
+|N> |R |<ND| |<D | | | | |
++---+---+---+-----+---+---+-+------+-------------------------------------------+
+| | | | | | | | | |
++---+---+---+-----+---+---+-+------+-------------------------------------------+
+
+* For each line in the table there should be an ert test named
+ `rst-adjust-section-prf-_-sel-_-prv-_-hie-_-cur-_-dir-_` where the
+ ``_`` stand for the respective cell entries
+
+* In addition each operation should be reversible by using the
+ opposite direction
+
+ * Unless the information before reversion is lost by the first
+ operation
+
+Legend
+------
+
+* "X>" means "if X"
+
+* "<XY" means "X or Y follow from an if"
+
+* "-" means "irrelevant"
+
+* "!" means "does not apply"
+
+* "?" means "any"
+
+* "[X]" means "header for situation group X"
--- /dev/null
+;; Tests for various functions handling adornments -*- lexical-binding: t -*-
+
+(add-to-list 'load-path ".")
+(load "init" nil t)
+(init-rst-ert t)
+
+(ert-deftest adornment-asserts ()
+ "Check some assertions."
+ (should (equal ert-Buf-point-char "\^@"))
+ (should (equal ert-Buf-mark-char "\^?"))
+ )
+
+(defun ttl-at-point ()
+ "Wrapper for calling `rst-ttl-at-point'."
+ (apply-ttl-match (rst-ttl-at-point)))
+
+(ert-deftest rst-ttl-at-point ()
+ "Tests for `rst-ttl-at-point'."
+ (should (ert-equal-buffer-return
+ '(ttl-at-point)
+ "
+
+Du bon vin tous les jours.
+\^@
+"
+ "
+
+\^@Du bon vin tous les jours.
+
+"
+ '(nil 0 nil "Du bon vin tous les jours." nil)
+ ))
+ (should (ert-equal-buffer-return
+ '(ttl-at-point)
+ "
+\^@
+Du bon vin tous les jours.
+
+"
+ "
+
+\^@Du bon vin tous les jours.
+
+"
+ '(nil 0 nil "Du bon vin tous les jours." nil)
+ ))
+ (should (ert-equal-buffer-return
+ '(ttl-at-point)
+ "
+
+Du bon vin tous les jours.
+------\^@-----
+"
+ "
+
+\^@Du bon vin tous les jours.
+-----------
+"
+ (list
+ (rst-Ado-new-simple ?-) 0
+ nil "Du bon vin tous les jours." "-----------")
+ ))
+ (should (ert-equal-buffer-return
+ '(ttl-at-point)
+ "
+------\^@-----
+Du bon vin tous les jours.
+
+"
+ "
+-----------
+\^@Du bon vin tous les jours.
+
+"
+ (list
+ (rst-Ado-new-over-and-under ?-) 0
+ "-----------" "Du bon vin tous les jours." nil)
+ ))
+ (should (ert-equal-buffer-return
+ '(ttl-at-point)
+ "
+\^@-----------
+Du bon vin tous les jours.
+-----------
+
+"
+ "
+-----------
+\^@Du bon vin tous les jours.
+-----------
+
+"
+ (list
+ (rst-Ado-new-over-and-under ?-) 0
+ "-----------" "Du bon vin tous les jours." "-----------")
+ ))
+ (should (ert-equal-buffer-return
+ '(ttl-at-point)
+ "
+\^@===========
+Du bon vin tous les jours.
+-----------
+"
+ "
+\^@===========
+Du bon vin tous les jours.
+-----------
+"
+ nil
+ ))
+ (should (ert-equal-buffer-return
+ '(ttl-at-point)
+ "
+Du bon vin tous les jours.
+\^@-----------
+Du bon vin tous les jours.
+-----------
+
+"
+ "
+Du bon vin tous les jours.
+-----------
+\^@Du bon vin tous les jours.
+-----------
+
+" ; This is not how the parser works but looks more logical
+ (list
+ (rst-Ado-new-over-and-under ?-) 0
+ "-----------" "Du bon vin tous les jours." "-----------")
+ ))
+ (should (ert-equal-buffer-return
+ '(ttl-at-point)
+ "
+
+\^@===========
+
+"
+ "
+
+\^@===========
+
+"
+ nil
+ ))
+ (should (ert-equal-buffer-return
+ '(ttl-at-point)
+ "\^@"
+ "\^@"
+ nil
+ ))
+ (should (ert-equal-buffer-return
+ '(ttl-at-point)
+ "\^@
+"
+ "\^@
+"
+ nil
+ ))
+ (should (ert-equal-buffer-return
+ '(ttl-at-point)
+ "
+Line 1
+\^@
+Line 2
+
+"
+ "
+\^@Line 1
+
+Line 2
+
+"
+ '(nil 0 nil "Line 1" nil)
+ ))
+ (should (ert-equal-buffer-return
+ '(ttl-at-point)
+ "
+=====================================
+ Project Idea: Panorama Stitcher
+====================================
+
+:Author: Martin Blais <blais@furius.ca>
+\^@
+Another Title
+=============
+"
+ "
+=====================================
+ Project Idea: Panorama Stitcher
+====================================
+
+\^@:Author: Martin Blais <blais@furius.ca>
+
+Another Title
+=============
+"
+ '(nil 0 nil ":Author: Martin Blais <blais@furius.ca>" nil)
+ ))
+ )
+
+(setq text-1
+"===============================
+ Project Idea: My Document
+===============================
+
+:Author: Martin Blais
+
+Introduction
+============
+
+This is the introduction.
+
+Notes
+-----
+
+Some notes.
+
+Main Points
+===========
+
+Yep.
+
+Super Point
+-----------
+
+~~~~~~~~~~~
+\^@ Sub Point
+~~~~~~~~~~~
+
+Isn't this fabulous?
+
+Conclusion
+==========
+
+That's it, really.
+
+")
+
+(setq text-2
+"
+
+Previous
+--------
+
+Current\^@
+~~~~~~~
+
+Next
+++++
+
+")
+
+(setq text-3
+"
+
+Previous
+--------
+
+Current\^@
+~~~~~~~
+
+ Next
+ ++++
+
+")
+
+(setq text-4
+"
+
+Previous
+--------
+
+Current\^@
+~~~~~~~
+
+Next
+++++
+
+Same
+~~~~
+
+")
+
+(defun find-all-adornments ()
+ "Call `rst-all-ttls' and return conses of line and `rst-Ado'."
+ (mapcar (lambda (ttl)
+ (cons (line-number-at-pos (rst-Ttl-get-title-beginning ttl))
+ (rst-Ttl-ado ttl)))
+ (rst-all-ttls-compute)))
+
+(ert-deftest rst-all-ttls ()
+ "Tests for `rst-all-ttls'."
+ (should (ert-equal-buffer-return
+ (find-all-adornments)
+ ""
+ t
+ nil
+ ))
+ (should (ert-equal-buffer-return
+ '(find-all-adornments)
+ "
+ Not a valid section header because of indentation
+===================================================
+"
+ t
+ nil
+ ))
+ (should (ert-equal-buffer-return
+ '(find-all-adornments)
+ "
+Only a...
+
+===================================================
+
+...transition
+"
+ t
+ nil
+ ))
+ (should (ert-equal-buffer-return
+ '(find-all-adornments)
+ "
+=======================================================
+Not a valid section header because of missing underline
+
+"
+ t
+ nil
+ ))
+ (should (ert-equal-buffer-return
+ '(find-all-adornments)
+ "
+=====================================================
+Not a valid section header because of wrong underline
+-----------------------------------------------------
+"
+ t
+ nil
+ ))
+ (should (ert-equal-buffer-return
+ '(find-all-adornments)
+ "
+Valid simple section header
+===========================
+"
+ t
+ (list
+ (cons 2 (rst-Ado-new-simple ?=)))
+ ))
+ (should (ert-equal-buffer-return
+ '(find-all-adornments)
+ "
+=======================================
+ Valid over and under section header
+=======================================
+"
+ t
+ (list
+ (cons 3 (rst-Ado-new-over-and-under ?=)))
+ ))
+ (should (ert-equal-buffer-return
+ '(find-all-adornments)
+ text-1
+ t
+ (list
+ (cons 2 (rst-Ado-new-over-and-under ?=))
+ (cons 7 (rst-Ado-new-simple ?=))
+ (cons 12 (rst-Ado-new-simple ?-))
+ (cons 17 (rst-Ado-new-simple ?=))
+ (cons 22 (rst-Ado-new-simple ?-))
+ (cons 26 (rst-Ado-new-over-and-under ?~))
+ (cons 31 (rst-Ado-new-simple ?=)))
+ ))
+ (should (ert-equal-buffer-return
+ '(find-all-adornments)
+ text-2
+ t
+ (list
+ (cons 3 (rst-Ado-new-simple ?-))
+ (cons 6 (rst-Ado-new-simple ?~))
+ (cons 9 (rst-Ado-new-simple ?+)))
+ ))
+ (should (ert-equal-buffer-return
+ '(find-all-adornments)
+ text-3
+ t
+ (list
+ (cons 3 (rst-Ado-new-simple ?-))
+ (cons 6 (rst-Ado-new-simple ?~)))
+ ))
+ (should (ert-equal-buffer-return
+ '(find-all-adornments)
+ "=====
+Title
+=====
+
+Header A
+========
+
+Header B
+========
+
+Subheader B.a
+-------------
+
+SubSubheader B.a.1
+~~~~~~~~~~~~~~~~~~
+
+Header C
+========
+
+Missing node C.a.1
+~~~~~~~~~~~~~~~~~~
+"
+ t
+ (list
+ (cons 2 (rst-Ado-new-over-and-under ?=))
+ (cons 5 (rst-Ado-new-simple ?=))
+ (cons 8 (rst-Ado-new-simple ?=))
+ (cons 11 (rst-Ado-new-simple ?-))
+ (cons 14 (rst-Ado-new-simple ?~))
+ (cons 17 (rst-Ado-new-simple ?=))
+ (cons 20 (rst-Ado-new-simple ?~)))
+ ))
+ )
+
+(ert-deftest rst-hdr-hierarchy ()
+ "Tests for `rst-hdr-hierarchy'."
+ (let ( ;; Set customizable variables to defined values
+ (rst-default-indent 5))
+ (should (ert-equal-buffer-return
+ '(rst-hdr-hierarchy)
+ text-1
+ t
+ (list
+ (rst-Hdr-new (rst-Ado-new-over-and-under ?=) 3)
+ (rst-Hdr-new (rst-Ado-new-simple ?=) 0)
+ (rst-Hdr-new (rst-Ado-new-simple ?-) 0)
+ (rst-Hdr-new (rst-Ado-new-over-and-under ?~) 1))
+ ))
+ (should (ert-equal-buffer-return
+ '(rst-hdr-hierarchy)
+ (concat text-1
+ "
+=========
+No indent
+=========
+")
+ t
+ (list
+ (rst-Hdr-new (rst-Ado-new-over-and-under ?=) 5)
+ (rst-Hdr-new (rst-Ado-new-simple ?=) 0)
+ (rst-Hdr-new (rst-Ado-new-simple ?-) 0)
+ (rst-Hdr-new (rst-Ado-new-over-and-under ?~) 1))
+ ))
+ ))
+
+(ert-deftest rst-get-hierarchy-ignore ()
+ "Tests for `rst-hdr-hierarchy' with ignoring a line."
+ (should (ert-equal-buffer-return
+ '(rst-hdr-hierarchy (point))
+ text-1
+ t
+ (list
+ (rst-Hdr-new (rst-Ado-new-over-and-under ?=) 3)
+ (rst-Hdr-new (rst-Ado-new-simple ?=) 0)
+ (rst-Hdr-new (rst-Ado-new-simple ?-) 0))
+ ))
+ (should (ert-equal-buffer-return
+ '(rst-hdr-hierarchy (point))
+ text-4
+ t
+ (list
+ (rst-Hdr-new (rst-Ado-new-simple ?-) 0)
+ (rst-Hdr-new (rst-Ado-new-simple ?~) 0)
+ (rst-Hdr-new (rst-Ado-new-simple ?+) 0))
+ ))
+ )
+
+(ert-deftest rst-adornment-level ()
+ "Tests for `rst-adornment-level'."
+ (should (ert-equal-buffer-return
+ '(rst-adornment-level (rst-Ado-new-transition))
+ text-1
+ t
+ t
+ ))
+ (should (ert-equal-buffer-return
+ '(rst-adornment-level (rst-Ado-new-over-and-under ?=))
+ text-1
+ t
+ 1
+ ))
+ (should (ert-equal-buffer-return
+ '(rst-adornment-level (rst-Ado-new-simple ?=))
+ text-1
+ t
+ 2
+ ))
+ (should (ert-equal-buffer-return
+ '(rst-adornment-level (rst-Ado-new-simple ?-))
+ text-1
+ t
+ 3
+ ))
+ (should (ert-equal-buffer-return
+ '(rst-adornment-level (rst-Ado-new-over-and-under ?~))
+ text-1
+ t
+ 4
+ ))
+ (should (ert-equal-buffer-return
+ '(rst-adornment-level (rst-Ado-new-simple ?#))
+ text-1
+ t
+ 5
+ ))
+ )
+
+(ert-deftest rst-adornment-complete-p ()
+ "Tests for `rst-adornment-complete-p'."
+ (should (ert-equal-buffer-return
+ '(rst-adornment-complete-p (rst-Ado-new-simple ?=) 0)
+ "Vaudou\^@"
+ t
+ nil))
+ (should (ert-equal-buffer-return
+ '(rst-adornment-complete-p (rst-Ado-new-over-and-under ?=) 0)
+ "Vaudou\^@
+======"
+ t
+ nil))
+ (should (ert-equal-buffer-return
+ '(rst-adornment-complete-p (rst-Ado-new-simple ?=) 0)
+ "
+
+\^@Vaudou
+
+"
+ t
+ nil))
+ (should (ert-equal-buffer-return
+ '(rst-adornment-complete-p (rst-Ado-new-simple ?=) 0)
+ "
+\^@Vaudou
+======
+"
+ t
+ t))
+ (should (ert-equal-buffer-return
+ '(rst-adornment-complete-p (rst-Ado-new-over-and-under ?=) 0)
+ "
+======
+\^@Vaudou
+======
+"
+ t
+ t))
+ (should (ert-equal-buffer-return
+ '(rst-adornment-complete-p (rst-Ado-new-over-and-under ?=) 2)
+ "
+==========
+\^@ Vaudou
+==========
+"
+ t
+ t))
+ (should (ert-equal-buffer-return
+ '(rst-adornment-complete-p (rst-Ado-new-simple ?=) 0)
+ "
+\^@Vaudou
+=====
+"
+ t
+ nil))
+ (should (ert-equal-buffer-return
+ '(rst-adornment-complete-p (rst-Ado-new-simple ?=) 0)
+ "
+\^@Vaudou
+=======
+"
+ t
+ nil))
+ (should (ert-equal-buffer-return
+ '(rst-adornment-complete-p (rst-Ado-new-simple ?=) 0)
+ "
+\^@Vaudou
+===-==
+"
+ t
+ nil))
+ (should (ert-equal-buffer-return
+ '(rst-adornment-complete-p (rst-Ado-new-over-and-under ?=) 0)
+ "
+======
+\^@Vaudou
+=====
+"
+ t
+ nil))
+ (should (ert-equal-buffer-return
+ '(rst-adornment-complete-p (rst-Ado-new-over-and-under ?=) 0)
+ "
+=====
+\^@Vaudou
+======
+"
+ t
+ nil))
+ (should (ert-equal-buffer-return
+ '(rst-adornment-complete-p (rst-Ado-new-over-and-under ?=) 0)
+ "
+======
+\^@Vaudou
+===-==
+"
+ t
+ nil))
+ (should (ert-equal-buffer-return
+ '(rst-adornment-complete-p (rst-Ado-new-over-and-under ?=) 0)
+ "
+===-==
+\^@Vaudou
+======
+"
+ t
+ nil))
+ (should (ert-equal-buffer-return
+ '(rst-adornment-complete-p (rst-Ado-new-over-and-under ?=) 0)
+ "
+======
+\^@Vaudou
+
+"
+ t
+ nil))
+ (should (ert-equal-buffer-return
+ '(rst-adornment-complete-p (rst-Ado-new-over-and-under ?=) 0)
+ "
+======
+\^@Vaudou
+------
+"
+ t
+ nil))
+ (should (ert-equal-buffer-return
+ '(rst-adornment-complete-p (rst-Ado-new-over-and-under ?=) 0)
+ "
+==========
+ \^@Vaudou
+=========
+"
+ t
+ nil))
+ (should (ert-equal-buffer-return
+ '(rst-adornment-complete-p (rst-Ado-new-over-and-under ?=) 0)
+ "
+=========
+ \^@Vaudou
+==========
+"
+ t
+ nil))
+ (should (ert-equal-buffer-return
+ '(rst-adornment-complete-p (rst-Ado-new-over-and-under ?=) 0)
+ "
+==========
+ \^@Vaudou
+===-======
+"
+ t
+ nil))
+ (should (ert-equal-buffer-return
+ '(rst-adornment-complete-p (rst-Ado-new-over-and-under ?=) 0)
+ "
+===-======
+ \^@Vaudou
+==========
+"
+ t
+ nil))
+ (should (ert-equal-buffer-return
+ '(rst-adornment-complete-p (rst-Ado-new-over-and-under ?=) 0)
+ "
+==========
+ \^@Vaudou
+
+"
+ t
+ nil))
+ (should (ert-equal-buffer-return
+ '(rst-adornment-complete-p (rst-Ado-new-over-and-under ?=) 0)
+ "
+==========
+ \^@Vaudou
+----------
+"
+ t
+ nil))
+ )
+
+(ert-deftest rst-get-previous-hdr ()
+ "Tests for `rst-get-previous-hdr'."
+ (should (ert-equal-buffer-return
+ '(rst-get-previous-hdr)
+ "
+
+Previous
+--------
+
+\^@Current
+
+Next
+++++
+
+"
+ t
+ (rst-Hdr-new (rst-Ado-new-simple ?-) 0)))
+ (should (ert-equal-buffer-return
+ '(rst-get-previous-hdr)
+ "
+
+Previous
+--------
+
+Current\^@
+~~~~~~~
+
+Next
+++++
+
+"
+ t
+ (rst-Hdr-new (rst-Ado-new-simple ?-) 0)))
+ )
+
+(defun apply-ttl-match (ttl)
+ "Apply the match in TTL to the buffer and return important data.
+Puts point at the beginning of the title line. Return a list
+consisting of the `rst-Ado', the indent and the three matched
+texts. Return nil if TTL is nil. Checks whether embedded match
+groups match match group 0."
+ (when ttl
+ (let ((match (rst-Ttl-match ttl)))
+ (set-match-data match)
+ (let ((whole (match-string-no-properties 0))
+ (over (match-string-no-properties 1))
+ (text (match-string-no-properties 2))
+ (under (match-string-no-properties 3))
+ (gather ""))
+ (if over
+ (setq gather (concat gather over "\n")))
+ (if text
+ (setq gather (concat gather text "\n")))
+ (if under
+ (setq gather (concat gather under "\n")))
+ (if (not (string= (substring gather 0 -1) whole))
+ (error "Match 0 '%s' doesn't match concatenated parts '%s'"
+ whole gather))
+ (goto-char (match-beginning 2))
+ (list (rst-Ttl-ado ttl) (rst-Ttl-indent ttl) over text under)))))
+
+(defun classify-adornment (beg end)
+ "Wrapper for calling `rst-classify-adornment'."
+ (interactive "r")
+ (apply-ttl-match (rst-classify-adornment
+ (buffer-substring-no-properties beg end) end)))
+
+(defun classify-adornment-accept (beg end)
+ "Wrapper for calling `rst-classify-adornment'."
+ (interactive "r")
+ (apply-ttl-match (rst-classify-adornment
+ (buffer-substring-no-properties beg end) end t)))
+
+(ert-deftest rst-classify-adornment ()
+ "Tests for `rst-classify-adornment'."
+ (should (ert-equal-buffer-return
+ '(classify-adornment)
+ "
+
+Du bon vin tous les jours
+\^@=========================\^?
+
+"
+ nil
+ (list
+ (rst-Ado-new-simple ?=) 0
+ nil "Du bon vin tous les jours" "=========================")
+ t))
+ (should (ert-equal-buffer-return
+ '(classify-adornment)
+ "
+
+Du bon vin tous les jours
+\^@====================\^?
+
+"
+ nil
+ (list
+ (rst-Ado-new-simple ?=) 0
+ nil "Du bon vin tous les jours" "====================")
+ t))
+ (should (ert-equal-buffer-return
+ '(classify-adornment)
+ "\^@====================\^?
+Du bon vin tous les jours"
+ nil
+ nil
+ t))
+ (should (ert-equal-buffer-return
+ '(classify-adornment-accept)
+ "\^@====================\^?
+Du bon vin tous les jours"
+ nil
+ (list
+ (rst-Ado-new-over-and-under ?=) 0
+ "====================" "Du bon vin tous les jours" nil)
+ t))
+ (should (ert-equal-buffer-return
+ '(classify-adornment)
+ "
+
+ Du bon vin tous les jours
+\^@====================\^?
+
+"
+ nil
+ (list
+ (rst-Ado-new-simple ?=) 5
+ nil " Du bon vin tous les jours" "====================")
+ t))
+ (should (ert-equal-buffer-return
+ '(classify-adornment)
+ " Du bon vin tous les jours
+\^@====================\^?
+"
+ nil
+ (list
+ (rst-Ado-new-simple ?=) 5
+ nil " Du bon vin tous les jours" "====================")
+ t))
+ (should (ert-equal-buffer-return
+ '(classify-adornment)
+ "
+
+Du bon vin tous les jours
+\^@-\^?
+"
+ nil
+ nil
+ t))
+ (should (ert-equal-buffer-return
+ '(classify-adornment)
+ "
+
+Du bon vin tous les jours
+\^@--\^?
+"
+ nil
+ nil
+ t))
+ (should (ert-equal-buffer-return
+ '(classify-adornment)
+ "
+
+Du bon vin tous les jours
+\^@---\^?
+"
+ nil
+ (list
+ (rst-Ado-new-simple ?-) 0
+ nil "Du bon vin tous les jours" "---")
+ t))
+ (should (ert-equal-buffer-return
+ '(classify-adornment)
+ "
+\^@~~~~~~~~~~~~~~~~~~~~~~~~~\^?
+Du bon vin tous les jours
+~~~~~~~~~~~~~~~~~~~~~~~~~
+
+"
+ nil
+ (list
+ (rst-Ado-new-over-and-under ?~) 0
+ "~~~~~~~~~~~~~~~~~~~~~~~~~" "Du bon vin tous les jours" "~~~~~~~~~~~~~~~~~~~~~~~~~")
+ t))
+ (should (ert-equal-buffer-return
+ '(classify-adornment)
+ "~~~~~~~~~~~~~~~~~~~~~~~~~
+Du bon vin tous les jours
+\^@~~~~~~~~~~~~~~~~~~~~~~~~~\^?
+
+"
+ nil
+ (list
+ (rst-Ado-new-over-and-under ?~) 0
+ "~~~~~~~~~~~~~~~~~~~~~~~~~" "Du bon vin tous les jours" "~~~~~~~~~~~~~~~~~~~~~~~~~")
+ t))
+ (should (ert-equal-buffer-return
+ '(classify-adornment)
+ "
+\^@~~~~~~~~~~~~~~~~~~~~~~~~~\^?
+ Du bon vin tous les jours
+~~~~~~~~~~~~~~~~~~~~~~~~~
+
+"
+ nil
+ (list
+ (rst-Ado-new-over-and-under ?~) 3
+ "~~~~~~~~~~~~~~~~~~~~~~~~~" " Du bon vin tous les jours" "~~~~~~~~~~~~~~~~~~~~~~~~~")
+ t))
+ (should (ert-equal-buffer-return
+ '(classify-adornment)
+ "
+\^@~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\^?
+Du bon vin tous les jours
+~~~~~~~~~~~~~~~~~~~
+
+"
+ nil
+ (list
+ (rst-Ado-new-over-and-under ?~) 0
+ "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" "Du bon vin tous les jours" "~~~~~~~~~~~~~~~~~~~")
+ t))
+ (should (ert-equal-buffer-return
+ '(classify-adornment)
+ "
+---------------------------
+Du bon vin tous les jours
+\^@~~~~~~~~~~~~~~~~~~~~~~~~~~~\^?
+
+"
+ nil
+ nil
+ t))
+ (should (ert-equal-buffer-return
+ '(classify-adornment)
+ "\^@---------------------------\^?"
+ nil
+ (list
+ (rst-Ado-new-transition) nil
+ nil "---------------------------" nil)
+ t))
+ (should (ert-equal-buffer-return
+ '(classify-adornment)
+ "
+\^@===\^?
+"
+ nil
+ (list
+ (rst-Ado-new-transition) nil
+ nil "===" nil)
+ t))
+ (should (ert-equal-buffer-return
+ '(classify-adornment)
+ "
+\^@---------------------------\^?
+Du bon vin tous les jours
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+"
+ nil
+ nil
+ t))
+ (should (ert-equal-buffer-return
+ '(classify-adornment)
+ "
+=========================
+Du bon vin tous les jours
+\^@=========================\^?
+Du bon vin
+
+"
+ nil
+ (list
+ (rst-Ado-new-over-and-under ?=) 0
+ "=========================" "Du bon vin tous les jours" "=========================")
+ t))
+ (should (ert-equal-buffer-return
+ '(classify-adornment)
+ "
+=========================
+Du bon vin tous les jours
+=========================
+Du bon vin
+\^@----------\^?
+
+"
+ nil
+ (list
+ (rst-Ado-new-simple ?-) 0
+ nil "Du bon vin" "----------")
+ t))
+ (should (ert-equal-buffer-return
+ '(classify-adornment)
+ "
+=========================
+Du bon vin tous les jours
+=========================
+\^@----------\^?
+Du bon vin
+----------
+
+"
+ nil
+ (list
+ (rst-Ado-new-over-and-under ?-) 0
+ "----------" "Du bon vin" "----------")
+ t))
+ (should (ert-equal-buffer-return
+ '(classify-adornment)
+ "
+=========================
+Du bon vin tous les jours
+=========================
+--------------
+ Du bon vin
+\^@--------------\^?
+
+"
+ nil
+ (list
+ (rst-Ado-new-over-and-under ?-) 2
+ "--------------" " Du bon vin" "--------------")
+ t))
+ )
+
+(defun display-adornments-hierarchy ()
+ "Wrapper for calling `rst-display-hdr-hierarchy'."
+ (rst-display-hdr-hierarchy)
+ (let ((source (get-buffer "*rest section hierarchy*")))
+ (delete-region (point-min) (point-max))
+ (insert (with-current-buffer source
+ (buffer-substring (point-min) (point-max))))
+ (kill-buffer source)))
+
+(ert-deftest rst-display-hdr-hierarchy ()
+ "Tests for `rst-display-hdr-hierarchy'."
+ (should (ert-equal-buffer
+ '(display-adornments-hierarchy)
+ ""
+ "
+"
+ ))
+ (should (ert-equal-buffer
+ '(display-adornments-hierarchy)
+ "
+First
+-----
+
+Second
+======
+
+First again
+-----------
+
+Second again
+============
+
++++++
+Third
++++++
+
+"
+ "
+Section Level 1
+---------------
+
+
+Section Level 2
+===============
+
+
++++++++++++++++
+Section Level 3
++++++++++++++++
+"
+ ))
+ )
+
+(ert-deftest rst-adjust-region ()
+ "Tests for `rst-adjust-region'."
+ (let ((rst-preferred-adornments '((?= over-and-under 1)
+ (?= simple 0)
+ (?- simple 0)
+ (?~ simple 0)
+ (?+ simple 0)
+ (?` simple 0)
+ (?# simple 0)
+ (?@ simple 0))))
+ (should (ert-equal-buffer
+ '(rst-adjust-region nil)
+ "\^@\^?"
+ t
+ ))
+ (should (ert-equal-buffer
+ '(rst-adjust-region nil)
+ "
+First
+-----
+\^@
+Second
+======
+\^?
+First again
+-----------
+
+Second again
+============
+
++++++
+Third
++++++
+
+"
+ "
+First
+-----
+\^@
+Second
+------
+\^?
+First again
+-----------
+
+Second again
+============
+
++++++
+Third
++++++
+
+"
+ ))
+ (should (ert-equal-buffer
+ '(rst-adjust-region nil)
+ "
+First
+-----
+
+Second
+======
+
+First again
+-----------
+\^@
+Second again
+============
+
++++++
+Third
++++++
+\^?
+"
+ "
+First
+-----
+
+Second
+======
+
+First again
+-----------
+\^@
+Second again
+------------
+
+Third
+=====
+\^?
+"
+ ))
+ (should (ert-equal-buffer
+ '(rst-adjust-region nil)
+ "
+First
+-----
+
+Second
+======
+\^@
+First again
+-----------
+\^?
+Second again
+============
+
++++++
+Third
++++++
+
+"
+ "
+First
+-----
+
+Second
+======
+
+=============
+ First again
+=============
+
+Second again
+============
+
++++++
+Third
++++++
+
+"
+ ))
+ (should (ert-equal-buffer
+ '(rst-adjust-region t)
+ "
+First
+-----
+
+Second
+======
+\^@
+First again
+-----------
+\^?
+Second again
+============
+
++++++
+Third
++++++
+
+"
+ "
+First
+-----
+
+Second
+======
+\^@
+First again
+===========
+\^?
+Second again
+============
+
++++++
+Third
++++++
+
+"
+ ))
+ (should (ert-equal-buffer
+ '(rst-adjust-region t)
+ "
+First
+-----
+
+Second
+======
+
+First again
+-----------
+
+Second again
+============
+\^@
++++++
+Third
++++++
+\^?
+"
+ "
+First
+-----
+
+Second
+======
+
+First again
+-----------
+
+Second again
+============
+
+=======
+ Third
+=======
+
+"
+ ))
+ ))
+
+(ert-deftest rst-straighten-sections ()
+ "Tests for `rst-straighten-sections'."
+ (let ((rst-preferred-adornments '((?= over-and-under 1)
+ (?= simple 0)
+ (?- simple 0)
+ (?~ simple 0)
+ (?+ simple 0)
+ (?` simple 0)
+ (?# simple 0)
+ (?@ simple 0))))
+ (should (ert-equal-buffer
+ '(rst-straighten-sections)
+ ""
+ t
+ ))
+ (should (ert-equal-buffer
+ '(rst-straighten-sections)
+ "
+First
+-----
+
+Second
+======
+
+First again
+-----------
+
+Second again
+============
+
++++++
+Third
++++++
+
+"
+ "
+=======
+ First
+=======
+
+Second
+======
+
+=============
+ First again
+=============
+
+Second again
+============
+
+Third
+-----
+
+"
+ ))
+ ))
+
+(defun find-all-levels ()
+ "Call `rst-all-ttls-with-level' and return conses of line and level."
+ (mapcar (cl-function
+ (lambda ((ttl . level))
+ (cons (line-number-at-pos (rst-Ttl-get-title-beginning ttl))
+ level)))
+ (rst-all-ttls-with-level)))
+
+(ert-deftest rst-all-ttls-with-level ()
+ "Tests for `rst-all-ttls-with-level'."
+ (should (ert-equal-buffer-return
+ '(find-all-levels)
+ ""
+ t
+ nil
+ ))
+ (should (ert-equal-buffer-return
+ '(find-all-levels)
+ "
+ Not a valid section header because of indentation
+===================================================
+"
+ t
+ nil
+ ))
+ (should (ert-equal-buffer-return
+ '(find-all-levels)
+ "
+Valid simple section header
+===========================
+"
+ t
+ (list
+ '(2 . 0))
+ ))
+ (should (ert-equal-buffer-return
+ '(find-all-levels)
+ "
+=======================================
+ Valid over and under section header
+=======================================
+"
+ t
+ (list
+ '(3 . 0))
+ ))
+ (should (ert-equal-buffer-return
+ '(find-all-levels)
+ text-1
+ t
+ '(
+ (2 . 0)
+ (7 . 1)
+ (12 . 2)
+ (17 . 1)
+ (22 . 2)
+ (26 . 3)
+ (31 . 1))
+ ))
+ (should (ert-equal-buffer-return
+ '(find-all-levels)
+ text-2
+ t
+ '(
+ (3 . 0)
+ (6 . 1)
+ (9 . 2))
+ ))
+ (should (ert-equal-buffer-return
+ '(find-all-levels)
+ text-3
+ t
+ '(
+ (3 . 0)
+ (6 . 1))
+ ))
+ )
+
+(defun update-section (char simplep indent)
+ "Call `rst-update-section' with proper header."
+ (rst-update-section
+ (rst-Hdr-new (if simplep
+ (rst-Ado-new-simple char)
+ (rst-Ado-new-over-and-under char)) indent)))
+
+(ert-deftest rst-update-section ()
+ "Tests for `rst-update-section'."
+ (should (ert-equal-buffer
+ '(update-section ?= t 0)
+ "
+
+\^@abc
+
+"
+ "
+
+abc\^@
+===
+
+"
+
+ ))
+ (should (ert-equal-buffer
+ '(update-section ?= nil 2)
+ "
+
+\^@abc
+
+"
+ "
+
+=======
+ abc\^@
+=======
+
+"
+
+ ))
+ (should (ert-equal-buffer
+ '(update-section ?= nil 2)
+ "
+
+def
+---
+\^@abc
+
+"
+ "
+
+def
+---
+=======
+ abc\^@
+=======
+
+"
+
+ ))
+ (should (ert-equal-buffer
+ '(update-section ?= nil 2)
+ "
+
+---
+\^@abc
+
+"
+ "
+
+=======
+ abc\^@
+=======
+
+"
+
+ ))
+ (should (ert-equal-buffer
+ '(update-section ?= t 0)
+ "\^@abc
+
+"
+ "abc\^@
+===
+
+"
+
+ ))
+ (should (ert-equal-buffer
+ '(update-section ?= nil 0)
+ "\^@abc
+
+"
+ "===
+abc\^@
+===
+
+"
+
+ ))
+ (should (ert-equal-buffer
+ '(update-section ?= t 0)
+ "\^@abc"
+ "abc\^@
+===
+"
+
+ ))
+ (should (ert-equal-buffer
+ '(update-section ?= t 0)
+ "\^@abc
+"
+ "abc\^@
+===
+"
+
+ ))
+ (should (ert-equal-buffer
+ '(update-section ?= t 0)
+ "\^@abc
+ "
+ "abc\^@
+===
+ "
+
+ ))
+ (should (ert-equal-buffer
+ '(update-section ?= t 0)
+ "===
+\^@abc
+===
+"
+ "abc\^@
+===
+"
+
+ ))
+ )
--- /dev/null
+;; Tests for various functions around applying a function to an indented block -*- lexical-binding: t -*-
+
+(add-to-list 'load-path ".")
+(load "init" nil t)
+(init-rst-ert t)
+
+(ert-deftest apply-block-asserts ()
+ "Check some assertions."
+ (should (equal ert-Buf-point-char "\^@"))
+ (should (equal ert-Buf-mark-char "\^?"))
+ )
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(defun find-leftmost-column ()
+ "Call `rst-find-leftmost-column' with current region."
+ (rst-find-leftmost-column (region-beginning) (region-end)))
+
+(ert-deftest rst-find-leftmost-column ()
+ "Tests for `rst-find-leftmost-column'."
+ (should (ert-equal-buffer-return
+ '(find-leftmost-column)
+ "\^@abc
+\^?"
+ t
+ 0))
+ (should (ert-equal-buffer-return
+ '(find-leftmost-column)
+ "
+\^@abc
+\^?"
+ t
+ 0))
+ (should (ert-equal-buffer-return
+ '(find-leftmost-column)
+ "
+\^@ abc
+\^?"
+ t
+ 2))
+ (should (ert-equal-buffer-return
+ '(find-leftmost-column)
+ "
+\^@ abc
+def
+\^?"
+ t
+ 0))
+ (should (ert-equal-buffer-return
+ '(find-leftmost-column)
+ "
+\^@ abc
+ def
+\^?"
+ t
+ 2))
+ (should (ert-equal-buffer-return
+ '(find-leftmost-column)
+ "
+\^@ abc
+ def
+\^?"
+ t
+ 4))
+ (should (ert-equal-buffer-return
+ '(find-leftmost-column)
+ ; Empty lines contain spaces
+ "
+\^@
+
+ abc
+
+ def
+
+\^?"
+ t
+ 4))
+ (should (ert-equal-buffer-return
+ '(find-leftmost-column)
+ " abc\^@
+def\^?"
+ t
+ 0))
+ (should (ert-equal-buffer-return
+ '(find-leftmost-column)
+ "
+ abc\^@
+ def
+\^?"
+ t
+ 2))
+ (should (ert-equal-buffer-return
+ '(find-leftmost-column)
+ " a\^@b\^?c
+def"
+ t
+ 2))
+ (should (ert-equal-buffer-return
+ '(find-leftmost-column)
+ "
+\^@ abc
+\^? def
+"
+ t
+ 4))
+ (should (ert-equal-buffer-return
+ '(find-leftmost-column)
+ "
+\^@ abc
+ \^? def
+"
+ t
+ 2))
+ (should (ert-equal-buffer-return
+ '(find-leftmost-column)
+ "
+\^@ abc
+ d\^?ef
+"
+ t
+ 2))
+ )
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(defun bullet-list-region (all)
+ "Call `rst-bullet-list-region' with current region and ALL."
+ (rst-bullet-list-region (region-beginning) (region-end) all))
+
+(ert-deftest rst-bullet-list-region ()
+ "Tests for `rst-bullet-list-region'."
+ (let ((rst-preferred-bullets '(?*)))
+ (should (ert-equal-buffer
+ '(bullet-list-region nil)
+ "
+\^@
+eins
+one
+
+zwei
+two
+\^?"
+ "
+\^@
+* eins
+ one
+
+* zwei
+ two
+\^?"))
+ (should (ert-equal-buffer
+ '(bullet-list-region nil)
+ "
+\^@
+eins
+one
+
+ intermediate
+
+zwei
+two
+\^?"
+ "
+\^@
+* eins
+ one
+
+ intermediate
+
+* zwei
+ two
+\^?"))
+ (should (ert-equal-buffer
+ '(bullet-list-region nil)
+ "
+\^@
+eins
+one
+
+zwei
+two\^?"
+ "
+\^@
+* eins
+ one
+
+* zwei
+ two\^?"))
+ (should (ert-equal-buffer
+ '(bullet-list-region t)
+ "
+\^@
+eins
+zwei
+
+drei
+
+ vier
+\^?"
+ "
+\^@
+* eins
+* zwei
+
+* drei
+
+ vier
+\^?"))
+ ))
+
+(ert-deftest rst-bullet-list-region-error ()
+ "Tests for `rst-bullet-list-region' ending in an error."
+ (let ((rst-preferred-bullets nil))
+ (should-error (ert-equal-buffer
+ '(bullet-list-region nil)
+ ""
+ t
+ )
+ :type 'error)
+ ))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(defun enumerate-region (all)
+ "Call `rst-enumerate-region' with current region and ALL."
+ (rst-enumerate-region (region-beginning) (region-end) all))
+
+(ert-deftest rst-enumerate-region ()
+ "Tests for `rst-enumerate-region'."
+ (should (ert-equal-buffer
+ '(enumerate-region nil)
+ "
+\^@eins
+one
+
+zwei
+two
+\^?"
+ "
+\^@1. eins
+ one
+
+2. zwei
+ two
+\^?"))
+ (should (ert-equal-buffer
+ '(enumerate-region nil)
+ "
+\^@eins
+one
+
+ intermediate
+
+zwei
+two
+\^?"
+ "
+\^@1. eins
+ one
+
+ intermediate
+
+2. zwei
+ two
+\^?"))
+ (should (ert-equal-buffer
+ '(enumerate-region t)
+ "
+\^@eins
+zwei
+
+drei
+\^?"
+ "
+\^@1. eins
+2. zwei
+
+3. drei
+\^?"))
+ )
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(defun line-block-region (empty)
+ "Call `rst-line-block-region' with current region and EMPTY."
+ (rst-line-block-region (region-beginning) (region-end) empty))
+
+(ert-deftest rst-line-block-region ()
+ "Tests for `rst-line-block-region'."
+ (should (ert-equal-buffer
+ '(line-block-region nil)
+ "
+\^@
+eins
+one
+
+zwei
+\^?"
+ "
+\^@
+| eins
+| one
+
+| zwei
+\^?"))
+ (should (ert-equal-buffer
+ '(line-block-region nil)
+ "
+\^@
+eins
+ one
+
+zwei
+ two
+\^?"
+ "
+\^@
+| eins
+| one
+
+| zwei
+| two
+\^?"))
+ (should (ert-equal-buffer
+ '(line-block-region nil)
+ "
+\^@
+ eins
+ one
+
+ zwei
+ two
+\^?"
+ "
+\^@
+ | eins
+ | one
+
+ | zwei
+ | two
+\^?"))
+ (should (ert-equal-buffer
+ '(line-block-region t)
+ "
+\^@
+eins
+one
+
+zwei
+\^?"
+ "
+\^@|
+| eins
+| one
+|
+| zwei
+\^?"))
+ (should (ert-equal-buffer
+ '(line-block-region t)
+ "
+\^@
+eins
+ one
+
+zwei
+\^?"
+ "
+\^@|
+| eins
+| one
+|
+| zwei
+\^?"))
+ (should (ert-equal-buffer
+ '(line-block-region t)
+ "
+\^@
+ eins
+ one
+
+ zwei
+\^?"
+ "
+\^@ |
+ | eins
+ | one
+ |
+ | zwei
+\^?"))
+ )
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(defun apply-indented-blocks (ind &optional limit)
+ "Call `rst-apply-indented-blocks' on current region with IND.
+Stop after LIMIT calls if given. Return a list of all parameter
+packs to the callback function followed by the return value."
+ (let ((called 0)
+ params r)
+ (setq r (rst-apply-indented-blocks
+ (region-beginning) (region-end) ind
+ #'(lambda (count firstp subp supp emptyp relind)
+ (setq params
+ (append
+ params
+ (list
+ (list (current-column)
+ count firstp subp supp emptyp relind))))
+ (cl-incf called)
+ (and limit (>= called limit) called))))
+ (append params (list r))))
+
+(ert-deftest rst-apply-indented-blocks ()
+ "Tests for `rst-apply-indented-blocks'."
+ (should (ert-equal-buffer-return
+ '(apply-indented-blocks 0)
+ "\^@abc
+\^?"
+ t
+ '((0 1 t nil nil nil 0)
+ nil)))
+ (should (ert-equal-buffer-return
+ '(apply-indented-blocks 0)
+ "a\^@b\^?c"
+ t
+ '((0 1 t nil nil nil 0)
+ nil)))
+ (should (ert-equal-buffer-return
+ '(apply-indented-blocks 2)
+ "\^@
+ abc
+\^?"
+ t
+ '((2 0 nil nil nil t nil)
+ (2 1 t nil nil nil 0)
+ nil)))
+ (should (ert-equal-buffer-return
+ '(apply-indented-blocks 2)
+ "\^@
+ abc
+
+ def
+\^?"
+ t
+ '((0 0 nil nil nil t nil)
+ (2 1 t nil nil nil 0)
+ (0 1 nil nil nil t nil)
+ (4 1 nil t nil nil 2)
+ nil)))
+ (should (ert-equal-buffer-return
+ '(apply-indented-blocks 2)
+ "\^@
+ abc
+
+ def
+ ghi
+
+\^?"
+ t
+ '((0 0 nil nil nil t nil)
+ (2 1 t nil nil nil 0)
+ (0 1 nil nil nil t nil)
+ (4 1 nil t nil nil 2)
+ (6 1 nil t nil nil 4)
+ (2 1 nil t nil t nil)
+ nil)))
+ (should (ert-equal-buffer-return
+ '(apply-indented-blocks 0)
+ "\^@\^?abc"
+ t
+ '(nil)))
+ (should (ert-equal-buffer-return
+ '(apply-indented-blocks 2)
+ "\^@
+ abc
+
+ def
+ ghi
+\^?"
+ t
+ '((0 0 nil nil nil t nil)
+ (2 1 t nil nil nil 0)
+ (0 1 nil nil nil t nil)
+ (2 2 t nil nil nil 0)
+ (4 2 nil t nil nil 2)
+ nil)))
+ (should (ert-equal-buffer-return
+ '(apply-indented-blocks 2)
+ "\^@
+ abc
+
+def
+
+ ghi
+ jkl
+ mno
+\^?"
+ t
+ '((0 0 nil nil nil t nil)
+ (2 1 t nil nil nil 0)
+ (0 1 nil nil nil t nil)
+ (0 1 nil nil t nil -2)
+ (0 1 nil nil t t nil)
+ (4 1 nil t nil nil 2)
+ (2 2 t nil nil nil 0)
+ (2 2 nil nil nil nil 0)
+ nil)))
+ (should (ert-equal-buffer-return
+ '(apply-indented-blocks 2 2)
+ "\^@
+ abc
+
+ def
+\^?"
+ t
+ '((0 0 nil nil nil t nil)
+ (2 1 t nil nil nil 0)
+ 2)))
+ )
--- /dev/null
+;;; buffer.el --- Test the test support for buffers -*- lexical-binding: t -*-
+
+(add-to-list 'load-path ".")
+(load "ert-buffer" nil t)
+
+;; ****************************************************************************
+;; `ert-Buf'
+
+(defun roundtrip-ert-Buf (in)
+ (with-temp-buffer
+ (ert-Buf--to-buffer (ert-Buf-from-string in))
+ (ert-Buf-string (ert-Buf-from-buffer))))
+
+(ert-deftest ert-Buf ()
+ "Tests for functions working with `ert-Buf's."
+ (should (equal (concat ert-Buf-point-char "abc\n")
+ (roundtrip-ert-Buf (concat ert-Buf-point-char "abc\n"))))
+ (should (equal (concat "a" ert-Buf-point-char "bc\n")
+ (roundtrip-ert-Buf (concat "a" ert-Buf-point-char "bc\n"))))
+ (should (equal (concat "ab" ert-Buf-point-char "c\n")
+ (roundtrip-ert-Buf (concat "ab" ert-Buf-point-char "c\n"))))
+ (should (equal (concat "abc" ert-Buf-point-char "\n")
+ (roundtrip-ert-Buf (concat "abc" ert-Buf-point-char "\n"))))
+ (should (equal (concat "abc\n" ert-Buf-point-char)
+ (roundtrip-ert-Buf (concat "abc\n" ert-Buf-point-char))))
+ (should (equal (concat ert-Buf-point-char "abc\n" ert-Buf-mark-char "")
+ (roundtrip-ert-Buf
+ (concat ert-Buf-point-char "abc\n" ert-Buf-mark-char ""))))
+ (should (equal (concat ert-Buf-mark-char "abc\n" ert-Buf-point-char)
+ (roundtrip-ert-Buf
+ (concat ert-Buf-mark-char "abc\n" ert-Buf-point-char))))
+ (should (equal (concat "a" ert-Buf-mark-char ert-Buf-point-char "bc\n")
+ (roundtrip-ert-Buf
+ (concat "a" ert-Buf-point-char "" ert-Buf-mark-char "bc\n"))))
+ (should (equal (concat "ab" ert-Buf-mark-char "" ert-Buf-point-char "c\n")
+ (roundtrip-ert-Buf
+ (concat "ab" ert-Buf-mark-char ert-Buf-point-char "c\n"))))
+ (should-error (ert-Buf-from-string
+ (concat "ab" ert-Buf-point-char ert-Buf-point-char "c\n")))
+ (should-error (ert-Buf-from-string
+ (concat "ab" ert-Buf-mark-char ert-Buf-mark-char "c\n")))
+ )
+
+(ert-deftest ert-Buf--from-argument ()
+ "Test `ert-Buf--from-argument'."
+ (let ((marked-a (ert-Buf-from-string
+ (concat ert-Buf-point-char "a" ert-Buf-mark-char))))
+ (should (not (ert-Buf--from-argument nil nil)))
+ (should (equal (ert-Buf--from-argument ?a nil)
+ (ert-Buf-from-string "a")))
+ (should (equal (ert-Buf--from-argument ert-Buf-point-char nil)
+ (ert-Buf-from-string ert-Buf-point-char)))
+ (should (equal (ert-Buf--from-argument '("a" "b") nil)
+ (ert-Buf-from-string "ab")))
+ (should (equal (ert-Buf--from-argument `("a" ,ert-Buf-point-char "b") nil)
+ (ert-Buf-from-string (concat "a" ert-Buf-point-char "b"))))
+ (should (equal (ert-Buf--from-argument marked-a nil) marked-a))
+ (should-error (ert-Buf--from-argument -1 nil))
+ (should-error (ert-Buf--from-argument [0] nil))
+ (should-error (ert-Buf--from-argument t nil))
+ (should-error (ert-Buf--from-argument t t))
+ (should (eq (ert-Buf--from-argument t marked-a) marked-a))
+ ))
+
+;; ****************************************************************************
+;; Advice `ert-completing-read'
+
+(defvar read-fun-args nil
+ "Input for for functions reading the minibuffer.
+Consists of a list of functions and their argument lists to be
+run successively. Prompt is omitted.")
+
+(defun insert-reads ()
+ (interactive)
+ (while read-fun-args
+ (let* ((fun-arg (pop read-fun-args))
+ (result (apply (car fun-arg) "" (cdr fun-arg))))
+ (insert (if (integerp result)
+ (int-to-string result)
+ result) "\n"))))
+
+(defun test-reads (inputs fun-args result)
+ (setq read-fun-args fun-args)
+ (ert-equal-buffer '(insert-reads) "" result inputs))
+
+(ert-deftest reads ()
+ "Tests for functions using `completing-read's."
+ (should (test-reads '(5) '((read-number)) "5\n"))
+ (should (test-reads nil nil ""))
+ (should-error (test-reads '("") nil "")) ;; Too much input.
+ (should-error (test-reads '(5) '((read-number)
+ (read-number)) "")) ;; Too less input.
+ (should (test-reads '("") '((completing-read nil)) "\n"))
+ (should (test-reads '("" "") '((completing-read nil)
+ (completing-read nil)) "\n\n"))
+ (should (test-reads '("a" "b") '((completing-read nil)
+ (completing-read nil)) "a\nb\n"))
+ (should (test-reads '("a" "b") '((completing-read ("a" "b"))
+ (completing-read ("a" "b"))) "a\nb\n"))
+ (should (test-reads '("a" "b") '((completing-read ("a" "b"))
+ (completing-read ("a"))) "a\nb\n"))
+ (should-error (test-reads '("a" "b")
+ '((completing-read ("a" "b"))
+ (completing-read ("a") nil t)) "a\nb\n")) ;; Invalid input.
+ (should (test-reads '("a" "")
+ '((completing-read ("a" "b"))
+ (completing-read ("a") nil t)) "a\n\n"))
+ (should-error (test-reads '("a" "")
+ '((completing-read ("a" "b"))
+ (completing-read ("a") nil 'non-empty)) "a\n\n"))
+ (should (test-reads '("x") '((read-string)) "x\n"))
+ (should (test-reads '("") '((read-string nil nil "x")) "x\n"))
+ (should (test-reads '("y") '((read-string nil nil "x")) "y\n"))
+ (should (test-reads '("") '((read-number 5)) "5\n"))
+ (should (test-reads '(0) '((read-number 5)) "0\n"))
+ )
+
+;; ****************************************************************************
+;; Test main functions
+
+(ert-deftest ert-equal-buffer ()
+ "Tests for `ert-equal-buffer'."
+ (should (ert-equal-buffer '(insert "foo")
+ (concat ert-Buf-point-char ert-Buf-mark-char)
+ (concat ert-Buf-mark-char "foo"
+ ert-Buf-point-char)))
+ (should (ert-equal-buffer '(delete-region)
+ (concat ert-Buf-mark-char "foo"
+ ert-Buf-point-char)
+ (concat ert-Buf-point-char ert-Buf-mark-char)
+ t))
+ (should (ert-equal-buffer '(delete-region 1 4)
+ "foo"
+ ""))
+ (should-error (ert-equal-buffer '(delete-region 0 3)
+ (concat "foo")
+ "") :type 'args-out-of-range)
+ (should (ert-equal-buffer '(goto-char 4)
+ "foo"
+ (concat "foo" ert-Buf-point-char)))
+ )
+
+(ert-deftest ert-equal-buffer-return ()
+ "Tests for `ert-equal-buffer-return'."
+ (should (ert-equal-buffer-return '(buffer-substring-no-properties 4 1)
+ "foo"
+ t
+ "foo"))
+ (should (ert-equal-buffer-return '(delete-and-extract-region 1 4)
+ "foo"
+ ""
+ "foo"))
+ (should (ert-equal-buffer-return '(point)
+ ert-Buf-point-char
+ t
+ 1))
+ (should (ert-equal-buffer-return '(point)
+ (concat " " ert-Buf-point-char)
+ t
+ 2))
+ (should (ert-equal-buffer-return '(region-beginning)
+ (concat ert-Buf-point-char " "
+ ert-Buf-mark-char)
+ t
+ 1))
+ (should (ert-equal-buffer-return '(region-end)
+ (concat ert-Buf-mark-char " "
+ ert-Buf-point-char)
+ t
+ 2))
+ (should (ert-equal-buffer-return '(following-char)
+ (concat ert-Buf-point-char "A")
+ t
+ ?A))
+ (should (ert-equal-buffer-return '(following-char)
+ (concat "A" ert-Buf-point-char)
+ t
+ 0))
+ )
--- /dev/null
+;; Tests for comment handling -*- lexical-binding: t -*-
+
+(add-to-list 'load-path ".")
+(load "init" nil t)
+(init-rst-ert t)
+
+(ert-deftest comment-asserts ()
+ "Check some assertions."
+ (should (equal ert-Buf-point-char "\^@"))
+ (should (equal ert-Buf-mark-char "\^?"))
+ )
+
+(defun cmnt-insert ()
+ "Wrapper to insert comment via `comment-dwim'.
+Must be called on a line conaining at most whitespace."
+ (let ((fc fill-column))
+ (rst-mode)
+ (setq fill-column fc)
+ (comment-dwim nil)))
+
+(ert-deftest comment-insert ()
+ "Tests for inserting a comment."
+ (let ((rst-indent-width 2)
+ (rst-indent-comment 3)
+ (fill-column 20))
+ (should (ert-equal-buffer
+ '(cmnt-insert)
+ "\^@"
+ ".. \^@"
+ ))
+ (should (ert-equal-buffer
+ '(cmnt-insert)
+ "
+ \^@"
+ "
+.. \^@"
+ ))
+ (should (ert-equal-buffer
+ '(cmnt-insert)
+ "
+* bla
+
+ \^@"
+ "
+* bla
+
+ .. \^@"
+ ))
+ (should (ert-equal-buffer
+ '(cmnt-insert)
+ "
+:Field: Content
+
+\^@"
+ "
+:Field: Content
+
+ .. \^@"
+ ))
+ ))
+
+(defun cmnt-indent (continue)
+ "Wrapper for `comment-indent'."
+ (let ((fc fill-column))
+ (rst-mode)
+ (setq fill-column fc)
+ (comment-indent continue)))
+
+(ert-deftest comment-indent ()
+ "Tests for `comment-indent'."
+ (let ((rst-indent-width 2)
+ (rst-indent-comment 3)
+ (fill-column 20))
+ (should (ert-equal-buffer
+ '(cmnt-indent nil)
+ "\^@"
+ ".. \^@"
+ ))
+ (should (ert-equal-buffer
+ '(cmnt-indent nil)
+ "
+ \^@"
+ "
+.. \^@"
+ ))
+ (should (ert-equal-buffer
+ '(cmnt-indent nil)
+ ".. comment\^@"
+ ".. \^@comment"
+ ))
+ (should (ert-equal-buffer
+ '(cmnt-indent nil)
+ "
+* bla
+
+.. comment\^@"
+ "
+* bla
+
+ .. \^@comment"
+ ))
+ (should (ert-equal-buffer
+ '(cmnt-indent nil)
+ "
+:Field: Content
+
+\^@"
+ "
+:Field: Content
+
+ .. \^@"
+ ))
+ (should (ert-equal-buffer
+ '(cmnt-indent nil)
+ "
+:Field: Content
+
+.. comment\^@"
+ "
+:Field: Content
+
+ .. \^@comment"
+ ))
+ ))
+
+(defun uncmnt-region ()
+ "Wrapper for `uncomment-region'."
+ (let ((fc fill-column))
+ (rst-mode)
+ (setq fill-column fc)
+ (call-interactively 'uncomment-region)))
+
+(ert-deftest uncomment-region ()
+ "Tests for `uncomment-region'."
+ (let ((rst-indent-width 2)
+ (rst-indent-comment 3)
+ (fill-column 20))
+ (should (ert-equal-buffer
+ '(uncmnt-region)
+ "\^?..
+ com\^@ment"
+ "\^?com\^@ment"
+ ))
+ (should (ert-equal-buffer
+ '(uncmnt-region)
+ "\^?..
+ com\^@ment
+
+ bla
+"
+ "\^?com\^@ment
+
+ bla
+"
+ ))
+ (should (ert-equal-buffer
+ '(uncmnt-region)
+ "\^?..
+ comment
+
+ bl\^@a
+"
+ "\^?comment
+
+bl\^@a
+"
+ ))
+ ))
+
+(defun cmnt-region ()
+ "Wrapper for `comment-region'."
+ (let ((fc fill-column))
+ (rst-mode)
+ (setq fill-column fc)
+ (call-interactively 'comment-region)))
+
+(ert-deftest comment-region ()
+ "Tests for `comment-region'."
+ (let ((rst-indent-width 2)
+ (rst-indent-comment 3)
+ (fill-column 20))
+ (should (ert-equal-buffer
+ '(cmnt-region)
+ "\^?com\^@ment"
+ "\^?..
+ com\^@ment"
+ ))
+ (should (ert-equal-buffer
+ '(cmnt-region)
+ "\^?com\^@ment
+
+ bla
+"
+ "\^?..
+ com\^@ment
+
+ bla
+"
+ ))
+ (should (ert-equal-buffer
+ '(cmnt-region)
+ "\^?comment
+
+bl\^@a
+"
+ "\^?..
+ comment
+
+ bl\^@a
+"
+ ))
+ ))
+
+;; comment-kill could be tested but since there are no suffix comments in
+;; reStructuredText this makes little sense
--- /dev/null
+;;; ert-buffer.el --- Support functions for running ert tests on buffers -*- lexical-binding: t -*-
+
+;; Copyright (C) 2010-2012 Free Software Foundation, Inc.
+
+;; Author: Stefan Merten <smerten@oekonux.de>,
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
+
+;;; Commentary:
+;;
+;; Some functions need a buffer to run on. They may use the buffer content as
+;; well as point and mark as input and may modify all of them. In addition
+;; they may return some result. Here are some support functions to test such
+;; functions using `ert'.
+;;
+;; Use `ert-equal-buffer' and/or `ert-equal-buffer-return' for your `should'
+;; forms.
+;;
+;; You may use the constants `ert-Buf-point-char' and `ert-Buf-mark-char' in
+;; constructing comparison strings to represent point or mark, respectively.
+;;
+;; Examples:
+;;
+;; (should (ert-equal-buffer '(insert "foo")
+;; ; Insertion of "foo"...
+;; (concat ert-Buf-point-char ert-Buf-mark-char)
+;; ; ...into an empty buffer with point and mark...
+;; (concat ert-Buf-mark-char "foo"
+;; ert-Buf-point-char)))
+;; ; ...should result in a buffer containing "foo"
+;; ; with point and mark moved appropriately.
+;;
+;; (should (ert-equal-buffer '(delete-region)
+;; ; Deleting region...
+;; `(,ert-Buf-mark-char "foo" ,ert-Buf-point-char)
+;; ; ...in a region spanning the whole buffer...
+;; (concat ert-Buf-point-char ert-Buf-mark-char)
+;; ; ...should result in an empty buffer...
+;; t))
+;; ; ...when called interactively.
+;;
+;; (should (ert-equal-buffer-return '(point)
+;; ; Returning the point...
+;; ert-Buf-point-char
+;; ; ...in an empty buffer...
+;; t
+;; ; ...without changing the result buffer...
+;; 1))
+;; ; ...should return 1.
+
+;;; Code:
+
+(eval-when-compile
+ (require 'cl))
+(require 'ert)
+
+;; ****************************************************************************
+;; `ert-Buf' and related functions
+
+(defconst ert-Buf-point-char "\^@"
+ "Special character used to mark the position of point in a `ert-Buf'.")
+
+(defconst ert-Buf-mark-char "\^?"
+ "Special character used to mark the position of mark in a `ert-Buf'.")
+
+(defstruct (ert-Buf
+ (:constructor nil) ; No default constructor.
+ (:constructor ert-Buf-from-string
+ (string
+ &aux
+ (analysis (ert-Buf--parse-string string))
+ (content (car analysis))
+ (point (cadr analysis))
+ (mark (caddr analysis))))
+ (:constructor ert-Buf-from-buffer
+ (&aux
+ (content (buffer-substring-no-properties
+ (point-min) (point-max)))
+ (point (point))
+ (mark (mark t))
+ (string
+ (ert-Buf--create-string content point mark)))))
+ "Structure to hold comparable information about a buffer.
+`ert-Buf-from-string' constructs a structure from a given STRING.
+`ert-Buf-from-buffer' constructs a structure from the current
+buffer."
+ (content nil :read-only t) ; Pure string content without any special markup.
+ (point nil :read-only t) ; Position of point.
+ (mark nil :read-only t) ; Position of mark.
+ (string nil :read-only t) ; String representation.
+ )
+
+(defun ert-Buf--parse-string (string)
+ "Parse STRING and return clean results.
+Return a list consisting of the cleaned content, the position of
+point if `ert-Buf-point-char' was found and the the position of mark
+if `ert-Buf-mark-char' was found."
+ (with-temp-buffer
+ (let ((case-fold-search nil)
+ fnd point-fnd mark-fnd)
+ (insert string)
+ (goto-char (point-min))
+ (while (re-search-forward
+ (concat "[" ert-Buf-point-char ert-Buf-mark-char "]") nil t)
+ (setq fnd (match-string 0))
+ (replace-match "")
+ (cond
+ ((equal fnd ert-Buf-point-char)
+ (if point-fnd
+ (error "Duplicate point"))
+ (setq point-fnd (point)))
+ ((equal fnd ert-Buf-mark-char)
+ (if mark-fnd
+ (error "Duplicate mark"))
+ (setq mark-fnd (point)))
+ (t
+ (error "Unexpected marker found"))))
+ (list (buffer-substring-no-properties (point-min) (point-max))
+ point-fnd mark-fnd))))
+
+(defun ert-Buf--create-string (content point mark)
+ "Create a string representation from CONTENT, POINT and MARK."
+ (with-temp-buffer
+ (insert content)
+ (let (pnt-chs)
+ (if point
+ (setq pnt-chs (nconc pnt-chs (list (cons point ert-Buf-point-char)))))
+ (if mark
+ (setq pnt-chs (nconc pnt-chs (list (cons mark ert-Buf-mark-char)))))
+ ;; Sort pairs so the highest position is last.
+ (setq pnt-chs (sort pnt-chs (lambda (el1 el2) (> (car el1) (car el2)))))
+ (while pnt-chs
+ (goto-char (caar pnt-chs))
+ (insert (cdar pnt-chs))
+ (setq pnt-chs (cdr pnt-chs)))
+ (buffer-substring-no-properties (point-min) (point-max)))))
+
+(defun ert-Buf--to-buffer (buf)
+ "Set current buffer according to BUF."
+ (insert (ert-Buf-content buf))
+ (if (ert-Buf-point buf)
+ (goto-char (ert-Buf-point buf)))
+ (if (ert-Buf-mark buf)
+ (set-mark (ert-Buf-mark buf))))
+
+(defun ert-Buf--from-argument (arg other)
+ "Interpret ARG as input for an `ert-Buf', convert it and return the `ert-Buf'.
+ARG may be one of the types described in
+`ert-equal-buffer-return' or nil which is also returned."
+ (cond
+ ((not arg)
+ nil)
+ ((eq arg t)
+ (when (or (not other) (eq other t))
+ (error "First argument to `ert-Buf--from-argument' t requires a non-nil, non-t second argument"))
+ (ert-Buf--from-argument other nil))
+ ((characterp arg)
+ (ert-Buf-from-string (char-to-string arg)))
+ ((stringp arg)
+ (ert-Buf-from-string arg))
+ ((ert-Buf-p arg)
+ arg)
+ ((listp arg)
+ (ert-Buf-from-string (apply 'concat arg)))
+ (t
+ (error "Unknown type for `ert-Buf--from-argument'"))))
+
+;; ****************************************************************************
+;; Runners
+
+(defvar ert--inputs nil
+ "Variable to hold the strings to give successively to `ert-completing-read'.")
+
+(defadvice completing-read (around ert-completing-read first
+ (prompt collection &optional predicate
+ require-match initial-input hist
+ def inherit-input-method))
+ "Advice `completing-read' to accept input from `ert--inputs'."
+ (if (not ert--inputs)
+ (error "No more input strings in `ert--inputs'"))
+ (let* ((input (pop ert--inputs)))
+ (setq ad-return-value
+ (cond
+ ((eq (try-completion input collection predicate) t) ;; Perfect match.
+ input)
+ ((not require-match) ;; Non-matching input allowed.
+ input)
+ ((and (equal input "")
+ (eq require-match t)) ;; Empty input and this is allowed.
+ input)
+ (t
+ (error
+ "Input '%s' is not allowed for `completing-read' expecting %s"
+ input collection))))))
+
+(defadvice read-string (around ert-read-string first
+ (prompt &optional initial-input history
+ default-value inherit-input-method))
+ "Advice `read-string' to accept input from `ert--inputs'."
+ (if (not ert--inputs)
+ (error "No more input strings in `ert--inputs'"))
+ (let* ((input (pop ert--inputs)))
+ (setq ad-return-value
+ (if (and (equal input "") default-value)
+ default-value
+ input))))
+
+(defadvice read-number (around ert-read-number first
+ (prompt &optional default))
+ "Advice `read-number' to accept input from `ert--inputs'."
+ (if (not ert--inputs)
+ (error "No more input strings in `ert--inputs'"))
+ (let* ((input (pop ert--inputs)))
+ (setq ad-return-value
+ (if (and (equal input "") default)
+ default
+ input))))
+
+(defun ert--run-test-with-buffer (buf form interactive)
+ "With a buffer filled with `ert-Buf' BUF evaluate function form FORM.
+Return a cons consisting of the return value and a `ert-Buf'. If
+INTERACTIVE is non-nil FORM is evaluated in an interactive
+environment."
+ (with-temp-buffer
+ (ert-Buf--to-buffer buf)
+ (let ((act-return
+ (cond
+ ((not interactive)
+ (eval form))
+ ((eq interactive t)
+ (let ((current-prefix-arg (cadr form)))
+ (call-interactively (car form))))
+ ((listp interactive)
+ (setq ert--inputs interactive)
+ (ad-activate 'read-string)
+ (ad-activate 'read-number)
+ (ad-activate 'completing-read)
+ (unwind-protect
+ (let ((current-prefix-arg (cadr form)))
+ (call-interactively (car form)))
+ (progn
+ (ad-deactivate 'completing-read)
+ (ad-deactivate 'read-number)
+ (ad-deactivate 'read-string)))
+ (if ert--inputs
+ (error "%d input strings left over"
+ (length ert--inputs))))))
+ (act-buf (ert-Buf-from-buffer)))
+ (cons act-return act-buf))))
+
+(defun ert--compare-test-with-buffer (result buf ignore-return exp-return)
+ "Compare RESULT of test with expected buffer BUF.
+RESULT is a return value from `ert--run-test-with-buffer'.
+Return a list of booleans where t stands for a successful test of
+this kind:
+
+* Content of output buffer
+* Point in output buffer
+* Return value
+
+IGNORE-RETURN, EXP-RETURN are described in `ert--equal-buffer'."
+ (let ((act-return (car result))
+ (act-buf (cdr result)))
+ (list
+ (or (not buf)
+ (equal (ert-Buf-content act-buf) (ert-Buf-content buf)))
+ (or
+ (not buf)
+ (not (ert-Buf-point buf))
+ (equal (ert-Buf-point act-buf) (ert-Buf-point buf)))
+ (or ignore-return
+ (equal act-return exp-return)))))
+
+(defun ert--equal-buffer (form input exp-output ignore-return exp-return interactive)
+ "Run tests for `ert-equal-buffer-return' and `ert-equal-buffer'.
+FORM, INPUT and EXP-OUTPUT are as described for
+`ert-equal-buffer-return'. Ignore return value if IGNORE-RETURN
+or compare the return value to EXP-RETURN. INTERACTIVE is as
+described for `ert-equal-buffer-return'. Return t if equal."
+ (catch 'return
+ (dolist (elem (ert--compare-test-with-buffer
+ (ert--run-test-with-buffer
+ (ert-Buf--from-argument input exp-output) form interactive)
+ (ert-Buf--from-argument exp-output input)
+ ignore-return exp-return) t)
+ (unless elem
+ (throw 'return nil)))))
+
+(defun ert-equal-buffer-return (form input exp-output exp-return &optional interactive)
+ "Evaluate function form FORM with a buffer and compare results.
+The buffer is filled with INPUT. Compare the buffer content to
+EXP-OUTPUT if this is non-nil. Compare the return value to
+EXP-RETURN. Return t if buffer and return value are equal to the
+expected values.
+
+INPUT and EXP-OUTPUT represent the input buffer or the expected
+output buffer, respectively. They can be one of the following:
+
+* nil in which case the respective buffer is not used. Makes
+ sense only for EXP-OUTPUT.
+* t in which case the other buffer is used unchanged. The other
+ buffer must not be nil or t in this case.
+* A character which is converted to a one character string.
+* A string.
+* A list of strings which are concatenated using `concat'. This
+ can be used to shorten the form describing the buffer when used
+ with quote or backquote.
+* An `ert-Buf' object.
+
+All input variants which end up in a string are parsed by
+`ert-Buf-from-string'.
+
+If INTERACTIVE is nil FORM is evaluated with no special context.
+If INTERACTIVE is non-nil FORM is evaluated interactively and
+`current-prefix-arg' is set to the cadr of FORM (i.e\. the first
+argument in FORM) and thus must comply to the format of
+`current-prefix-arg'. If INTERACTIVE is t `call-interactively'
+is used normally. If INTERACTIVE is a list of strings the
+elements of the list are given to (advised forms of) functions
+reading from the minibuffer as user input strings. This allows
+simulating interactive user input.
+
+FORM usually needs to be quoted.
+
+Return t if buffer and return value equal the expected values."
+ (ert--equal-buffer form input exp-output nil exp-return interactive))
+
+(defun ert-equal-buffer (form input exp-output &optional interactive)
+ "Like `ert-equal-buffer-return' but the return value of FORM is ignored.
+INPUT, EXP-OUTPUT and INTERACTIVE are described in
+`ert-equal-buffer-return'."
+ (ert--equal-buffer form input exp-output t nil interactive))
+
+;; ****************************************************************************
+;; Explainers
+
+(defun ert--equal-buffer-explain (form input exp-output ignore-return exp-return interactive)
+ "Explain why `ert--equal-buffer' failed with these parameters.
+Return the explanation. FORM, INPUT, EXP-OUTPUT,
+IGNORE-RETURN, EXP-RETURN, INTERACTIVE are described in
+`ert--equal-buffer'."
+ (let ((test-result (ert--run-test-with-buffer
+ (ert-Buf--from-argument input exp-output)
+ form interactive))
+ (exp-buf (ert-Buf--from-argument exp-output input)))
+ (destructuring-bind (ok-string ok-point ok-return)
+ (ert--compare-test-with-buffer
+ test-result
+ (ert-Buf--from-argument exp-output input) ignore-return exp-return)
+ (let (result)
+ (if (not ok-return)
+ (push (list 'different-return-values
+ (ert--explain-not-equal (car test-result) exp-return))
+ result))
+ (if (not ok-point)
+ (push (list 'different-points
+ (ert-Buf-string (cdr test-result))
+ (ert-Buf-string exp-buf))
+ result))
+ (if (not ok-string)
+ (push (list 'different-buffer-contents
+ (ert--explain-not-equal
+ (ert-Buf-content (cdr test-result))
+ (ert-Buf-content exp-buf)))
+ result))
+ result))))
+
+(defun ert-equal-buffer-return-explain (form input exp-output exp-return &optional interactive)
+ "Explain why `ert-equal-buffer-return' failed with these parameters.
+Return the explanation. FORM, INPUT, EXP-OUTPUT, EXP-RETURN,
+INTERACTIVE are described in `ert--equal-buffer'."
+ (ert--equal-buffer-explain
+ form input exp-output nil exp-return interactive))
+
+(put 'ert-equal-buffer-return 'ert-explainer 'ert-equal-buffer-return-explain)
+
+(defun ert-equal-buffer-explain (form input exp-output &optional interactive)
+ "Explain why `ert-equal-buffer' failed with these parameters.
+Return the explanation. FORM, INPUT, EXP-OUTPUT, EXP-RETURN,
+INTERACTIVE are described in `ert--equal-buffer'."
+ (ert--equal-buffer-explain
+ form input exp-output t nil interactive))
+
+(put 'ert-equal-buffer 'ert-explainer 'ert-equal-buffer-explain)
+
+; LocalWords: foo minibuffer
+
+;; Local Variables:
+;; sentence-end-double-space: t
+;; End:
+
+(provide 'ert-buffer)
+
+;;; ert-buffer.el ends here
--- /dev/null
+;; Tests for functions around filling -*- lexical-binding: t -*-
+
+(add-to-list 'load-path ".")
+(load "init" nil t)
+(init-rst-ert t)
+
+(ert-deftest fill-asserts ()
+ "Check some assertions."
+ (should (equal ert-Buf-point-char "\^@"))
+ (should (equal ert-Buf-mark-char "\^?"))
+ )
+
+(defun auto-fill ()
+ "Wrapper to do auto fill."
+ (let ((fc fill-column))
+ (rst-mode)
+ (setq fill-column fc)
+ (auto-fill-mode 1)
+ (funcall auto-fill-function)))
+
+(ert-deftest auto-fill ()
+ "Tests for auto fill."
+ (let ((rst-indent-width 2)
+ (rst-indent-field 2)
+ (rst-indent-literal-normal 3)
+ (rst-indent-literal-minimized 2)
+ (rst-indent-comment 3)
+ (fill-column 20))
+ (should (ert-equal-buffer
+ '(auto-fill)
+ "
+* This is a test with a fill column of 20\^@"
+ "
+* This is a test
+ with a fill column
+ of 20\^@"
+ ))
+ (should (ert-equal-buffer
+ '(auto-fill)
+ "
+* This is a test
+ with a fill column of 20\^@"
+ "
+* This is a test
+ with a fill column
+ of 20\^@"
+ ))
+ (should (ert-equal-buffer
+ '(auto-fill)
+ "
+:Field: Does this work for fields?\^@"
+ "
+:Field: Does this
+ work for
+ fields?\^@"
+ ))
+ (should (ert-equal-buffer
+ '(auto-fill)
+ "
+:Field: Does this
+ work for fields?\^@"
+ "
+:Field: Does this
+ work for
+ fields?\^@"
+ ))
+ (should (ert-equal-buffer
+ '(auto-fill)
+ "
+.. dir:: Yes, quite fine\^@"
+ "
+.. dir:: Yes, quite
+ fine\^@"
+ ))
+ (should (ert-equal-buffer
+ '(auto-fill)
+ "
+.. dir:: Yes, quite fine\^@
+ :f: Field"
+ "
+.. dir:: Yes, quite
+ fine\^@
+ :f: Field"
+ ))
+ (should (ert-equal-buffer
+ '(auto-fill)
+ "
+.. |s| r:: Dir ectives had problems\^@"
+ "
+.. |s| r:: Dir
+ ectives
+ had
+ problems\^@"
+ ))
+ (should (ert-equal-buffer
+ '(auto-fill)
+ "
+.. |s| r:: Dir
+ ectives
+ had problems\^@"
+ "
+.. |s| r:: Dir
+ ectives
+ had
+ problems\^@"
+ ))
+ (should (ert-equal-buffer
+ '(auto-fill)
+ "
+.. [CIT] X cit is citations are also filled\^@"
+ "
+.. [CIT] X cit is
+ citations
+ are also
+ filled\^@"
+ ))
+ (should (ert-equal-buffer
+ '(auto-fill)
+ "
+.. [CIT] X cit is
+ citations
+ are also filled\^@"
+ "
+.. [CIT] X cit is
+ citations
+ are also
+ filled\^@"
+ ))
+ (should (ert-equal-buffer
+ '(auto-fill)
+ "
+.. Comments should also fill nicely\^@"
+ "
+.. Comments should
+ also fill nicely\^@"
+ ))
+ (should (ert-equal-buffer
+ '(auto-fill)
+ "
+Normal text should also fill as expected\^@"
+ "
+Normal text should
+also fill as
+expected\^@"
+ ))
+ (should (ert-equal-buffer
+ '(auto-fill)
+ "
+ Normal text should also fill as expected\^@"
+ "
+ Normal text should
+ also fill as
+ expected\^@"
+ ))
+ (should (ert-equal-buffer
+ '(auto-fill)
+ "
+Normal text should also fill \^@as expected"
+ "
+Normal text should
+also fill \^@as expected"
+ ))
+ ))
+
+(defun explicit-fill ()
+ "Wrapper for `fill-paragraph'."
+ (let ((fc fill-column))
+ (rst-mode)
+ (setq fill-column fc)
+ (fill-paragraph)
+ (untabify (point-min) (point-max))))
+
+(ert-deftest fill-paragraph ()
+ "Tests for `fill-paragraph'."
+ (let ((rst-indent-width 2)
+ (rst-indent-field 2)
+ (rst-indent-literal-normal 3)
+ (rst-indent-literal-minimized 2)
+ (rst-indent-comment 3)
+ (fill-column 20))
+ (should (ert-equal-buffer
+ '(explicit-fill)
+ "
+* This is a test with a fill column of 20\^@
+"
+ "
+* This is a test
+ with a fill column
+ of 20\^@
+"
+ ))
+ (should (ert-equal-buffer
+ '(explicit-fill)
+ "
+* This is a test \^@with a fill column
+ of 20
+"
+ "
+* This is a test
+ \^@with a fill column
+ of 20
+"
+ ))
+ (should (ert-equal-buffer
+ '(explicit-fill)
+ "
+:Field: Does this work for fields?\^@
+"
+ "
+:Field: Does this
+ work for
+ fields?\^@
+"
+ ))
+ (should (ert-equal-buffer
+ '(explicit-fill)
+ "
+:Field: Does this work\^@ for
+ fields?
+"
+ "
+:Field: Does this
+ work\^@ for
+ fields?
+"
+ ))
+ (should (ert-equal-buffer
+ '(explicit-fill)
+ "
+.. dir:: Yes, quite fine\^@
+"
+ "
+.. dir:: Yes, quite
+ fine\^@
+"
+ ))
+ (should (ert-equal-buffer
+ '(explicit-fill)
+ "
+\^@.. dir:: Yes, quite
+ fine
+"
+ "
+\^@.. dir:: Yes, quite
+ fine
+"
+ ))
+ (should (ert-equal-buffer
+ '(explicit-fill)
+ "
+.. dir:: Yes, quite fine\^@
+ :f: Field
+"
+ "
+.. dir:: Yes, quite
+ fine\^@
+ :f: Field
+"
+ ))
+ (should (ert-equal-buffer
+ '(explicit-fill)
+ "
+.. [CIT] X cit is citations are also filled\^@
+"
+ "
+.. [CIT] X cit is
+ citations
+ are also
+ filled\^@
+"
+ ))
+ (should (ert-equal-buffer
+ '(explicit-fill)
+ "
+.. [CIT] X cit is
+ citations are also filled\^@
+"
+ "
+.. [CIT] X cit is
+ citations are
+ also filled\^@
+"
+ ))
+ (should (ert-equal-buffer
+ '(explicit-fill)
+ "
+.. [CIT] X cit is
+ citations are also filled\^@
+"
+ "
+.. [CIT] X cit is
+ citations are
+ also filled\^@
+"
+ ))
+ (should (ert-equal-buffer
+ '(explicit-fill)
+ "
+.. |s| r:: Dir ectives had problems\^@
+"
+ "
+.. |s| r:: Dir
+ ectives
+ had
+ problems\^@
+"
+ ))
+ (should (ert-equal-buffer
+ '(explicit-fill)
+ "
+\^@.. |s| r:: Dir ectives had problems
+"
+ "
+\^@.. |s| r:: Dir
+ ectives
+ had
+ problems
+"
+ ))
+ (should (ert-equal-buffer
+ '(explicit-fill)
+ "
+.. |s| r:: Dir
+ ectives had problems\^@
+"
+ "
+.. |s| r:: Dir
+ ectives had
+ problems\^@
+"
+ ))
+ (should (ert-equal-buffer
+ '(explicit-fill)
+ "
+Normal \^@text should also fill as expected
+"
+ "
+Normal \^@text should
+also fill as
+expected
+"
+ ))
+ (should (ert-equal-buffer
+ '(explicit-fill)
+ "
+\^@Normal text should also fill as expected
+"
+ "
+\^@Normal text should
+also fill as
+expected
+"
+ ))
+ (should (ert-equal-buffer
+ '(explicit-fill)
+ "
+ Normal text should also fill as expected\^@
+"
+ "
+ Normal text should
+ also fill as
+ expected\^@
+"
+ ))
+ (should (ert-equal-buffer
+ '(explicit-fill)
+ "
+Normal text should also fill as expected
+
+Normal text should also fill as expected\^@
+"
+ "
+Normal text should also fill as expected
+
+Normal text should
+also fill as
+expected\^@
+"
+ ))
+ (should (ert-equal-buffer
+ '(explicit-fill)
+ "
+\^@Normal text should
+also fill as
+ expected
+"
+ "
+\^@Normal text should
+also fill as
+expected
+"
+ ))
+ ))
+
+(ert-deftest fill-paragraph-fixme ()
+ "Tests for `fill-paragraph'."
+ :expected-result :failed
+ (let ((rst-indent-width 2)
+ (rst-indent-field 2)
+ (rst-indent-literal-normal 3)
+ (rst-indent-literal-minimized 2)
+ (rst-indent-comment 3)
+ (fill-column 20))
+ (should (ert-equal-buffer
+ '(explicit-fill)
+ "
+\^@Normal text should
+ also fill as
+ expected
+"
+ "
+\^@Normal text should
+also fill as
+expected
+"
+ ))
+ ))
+
+(defun explicit-fill-region ()
+ "Wrapper for `fill-region'."
+ (let ((fc fill-column))
+ (rst-mode)
+ (setq fill-column fc)
+ (call-interactively 'fill-region)
+ (untabify (point-min) (point-max))))
+
+(ert-deftest fill-region ()
+ "Tests for `fill-region'."
+ (let ((rst-indent-width 2)
+ (rst-indent-field 2)
+ (rst-indent-literal-normal 3)
+ (rst-indent-literal-minimized 2)
+ (rst-indent-comment 3)
+ (fill-column 20))
+ (should (ert-equal-buffer
+ '(explicit-fill-region)
+ "\^@
+* This is a test with a fill column of 20
+
+* This is a test with a fill column
+ of 20
+
+:Field: Does this work for fields?
+
+:Field: Does this work for
+ fields?
+
+.. dir:: Yes, quite fine
+
+.. dir:: Yes, quite
+ fine
+
+.. dir:: Yes, quite fine
+ :f: Field for a directive
+
+.. [CIT] X cit is citations are also filled
+
+.. |s| r:: Dir ectives had problems
+
+.. |s| r:: Dir ectives had problems
+
+Normal text should also fill as expected
+
+ Normal text should also fill as expected
+\^?"
+ "\^@
+* This is a test
+ with a fill column
+ of 20
+
+* This is a test
+ with a fill column
+ of 20
+
+:Field: Does this
+ work for
+ fields?
+
+:Field: Does this
+ work for
+ fields?
+
+.. dir:: Yes, quite
+ fine
+
+.. dir:: Yes, quite
+ fine
+
+.. dir:: Yes, quite
+ fine
+ :f: Field for a
+ directive
+
+.. [CIT] X cit is
+ citations
+ are also
+ filled
+
+.. |s| r:: Dir
+ ectives
+ had
+ problems
+
+.. |s| r:: Dir
+ ectives
+ had
+ problems
+
+Normal text should
+also fill as
+expected
+
+ Normal text should
+ also fill as
+ expected
+\^?"
+ ))
+ (should (ert-equal-buffer
+ '(explicit-fill-region)
+ "\^@
+* This is a test with a fill column of 20
+* This is a test with a fill column
+ of 20
+:Field: Does this work for fields?
+:Field: Does this work for
+ fields?
+.. dir:: Yes, quite fine
+.. dir:: Yes, quite
+ fine
+.. dir:: Yes, quite fine
+ :f: Field for a directive
+.. [CIT] X cit is citations are also filled
+.. |s| r:: Dir ectives had problems
+.. |s| r:: Dir ectives had problems
+
+Normal text should also fill as expected
+
+ Normal text should also fill as expected
+\^?"
+ "\^@
+* This is a test
+ with a fill column
+ of 20
+* This is a test
+ with a fill column
+ of 20
+:Field: Does this
+ work for
+ fields?
+:Field: Does this
+ work for
+ fields?
+.. dir:: Yes, quite
+ fine
+.. dir:: Yes, quite
+ fine
+.. dir:: Yes, quite
+ fine
+ :f: Field for a
+ directive
+.. [CIT] X cit is
+ citations
+ are also
+ filled
+.. |s| r:: Dir
+ ectives
+ had
+ problems
+.. |s| r:: Dir
+ ectives
+ had
+ problems
+
+Normal text should
+also fill as
+expected
+
+ Normal text should
+ also fill as
+ expected
+\^?"
+ ))
+ ))
--- /dev/null
+;; Tests for font-locking code -*- lexical-binding: t -*-
+
+(add-to-list 'load-path ".")
+(load "init" nil t)
+(init-rst-ert t)
+
+(ert-deftest font-lock--asserts ()
+ "Check some assertions."
+ (should (equal ert-Buf-point-char "\^@"))
+ (should (equal ert-Buf-mark-char "\^?"))
+ )
+
+(ert-deftest rst-forward-indented-block ()
+ "Tests `rst-forward-indented-block'."
+ (should (ert-equal-buffer-return
+ '(rst-forward-indented-block)
+ "\^@abc"
+ t
+ nil))
+ (should (ert-equal-buffer-return
+ '(rst-forward-indented-block)
+ (concat " \^@abc
+
+def")
+ (concat " abc
+\^@
+def")
+ 7))
+ (should (ert-equal-buffer-return
+ '(rst-forward-indented-block)
+ (concat " \^@abc
+def")
+ (concat " abc
+\^@def")
+ 7))
+ (should (ert-equal-buffer-return
+ '(rst-forward-indented-block)
+ (concat " \^@abc
+ def
+ghi")
+ (concat " abc
+ def
+\^@ghi")
+ 13))
+ (should (ert-equal-buffer-return
+ '(rst-forward-indented-block)
+ (concat " \^@abc
+ def
+
+ghi")
+ (concat " abc
+ def
+\^@
+ghi")
+ 13))
+ (should (ert-equal-buffer-return
+ '(rst-forward-indented-block)
+ (concat " \^@abc
+
+ def
+
+ghi")
+ (concat " abc
+
+ def
+\^@
+ghi")
+ 14))
+ (should (ert-equal-buffer-return
+ '(rst-forward-indented-block)
+ (concat " \^@abc
+
+
+ def
+
+
+ghi")
+ (concat " abc
+
+
+ def
+\^@
+
+ghi")
+ 17))
+ (should (ert-equal-buffer-return
+ '(rst-forward-indented-block)
+ (concat " \^@abc
+ def
+ghi")
+ (concat " abc
+ def
+\^@ghi")
+ 15))
+ (should (ert-equal-buffer-return
+ '(rst-forward-indented-block)
+ (concat " \^@abc
+
+ def")
+ t
+ nil))
+ (should (ert-equal-buffer-return
+ '(rst-forward-indented-block)
+ (concat "\^@abc
+ def
+ghi
+")
+ t
+ nil))
+ (should (ert-equal-buffer-return
+ '(rst-forward-indented-block)
+ (concat "abc\^@ def
+ghi
+")
+ (concat "abc def
+\^@ghi
+")
+ 9))
+ (should (ert-equal-buffer-return
+ '(rst-forward-indented-block)
+ (concat "abc\^@ def
+ghi")
+ (concat "abc def
+\^@ghi")
+ 9))
+ (should (ert-equal-buffer-return
+ '(rst-forward-indented-block)
+ (concat ".. \^@abc
+ def
+
+ ghi
+
+jkl
+")
+ (concat ".. abc
+ def
+
+ ghi
+\^@
+jkl
+")
+ 23))
+ )
+
+(defun extend-region (beg end)
+ "Wrapper for `rst-font-lock-extend-region-internal'.
+Uses and sets region and returns t if region has been changed."
+ (interactive "r")
+ (let ((r (rst-font-lock-extend-region-internal beg end)))
+ (when r
+ (goto-char (car r))
+ (set-mark (cdr r))
+ t)))
+
+(ert-deftest rst-font-lock-extend-region-internal-indent ()
+ "Tests `rst-font-lock-extend-region-internal'."
+ (should (ert-equal-buffer-return
+ '(extend-region)
+ "\^@abc\^?"
+ t
+ nil
+ t))
+ (should (ert-equal-buffer-return
+ '(extend-region)
+ "\^@ abc\^?"
+ t
+ nil
+ t))
+ (should (ert-equal-buffer-return
+ '(extend-region)
+ " abc
+\^@ def\^?"
+ "\^@ abc
+ def\^?"
+ t
+ t))
+ (should (ert-equal-buffer-return
+ '(extend-region)
+ " abc
+\^@ def
+\^? ghi
+uvw"
+ "\^@ abc
+ def
+ ghi
+\^?uvw"
+ t
+ t))
+ (should (ert-equal-buffer-return
+ '(extend-region)
+ "xyz
+abc
+\^@ def
+\^? ghi"
+ "xyz
+\^@abc
+ def
+ ghi\^?"
+ t
+ t))
+ (should (ert-equal-buffer-return
+ '(extend-region)
+ "xyz
+ abc::
+\^@ def
+\^? ghi
+uvw"
+ "xyz
+\^@ abc::
+ def
+ ghi
+\^?uvw"
+ t
+ t))
+ (should (ert-equal-buffer-return
+ '(extend-region)
+ "xyz
+ .. abc
+\^@ def
+\^?uvw"
+ "xyz
+\^@ .. abc
+ def
+\^?uvw"
+ t
+ t))
+ (should (ert-equal-buffer-return
+ '(extend-region)
+ "xyz
+ .. abc
+ 123
+\^@ def
+\^?
+uvw"
+ "xyz
+\^@ .. abc
+ 123
+ def
+\^?
+uvw"
+ t
+ t))
+ (should (ert-equal-buffer-return
+ '(extend-region)
+ "xyz
+
+ .. abc
+
+ 123
+
+\^@ def
+\^?
+uvw"
+ "xyz
+
+\^@ .. abc
+
+ 123
+
+ def
+\^?
+uvw"
+ t
+ t))
+ )
+
+(ert-deftest rst-font-lock-extend-region-internal-adornment ()
+ "Tests `rst-font-lock-extend-region-internal'."
+ (should (ert-equal-buffer-return
+ '(extend-region)
+ "\^@===\^?"
+ t
+ nil
+ t))
+ (should (ert-equal-buffer-return
+ '(extend-region)
+ "abc
+\^@===\^?"
+ "\^@abc
+===\^?"
+ t
+ t))
+ (should (ert-equal-buffer-return ; Quite complicated without the trailing newline
+ '(extend-region)
+ "\^@abc
+\^?==="
+ t
+ nil
+ t))
+ (should (ert-equal-buffer-return
+ '(extend-region)
+ "\^@abc
+\^?===
+"
+ "\^@abc
+===
+\^?"
+ t
+ t))
+ (should (ert-equal-buffer-return
+ '(extend-region)
+ "===
+abc
+\^@===
+\^?"
+ "\^@===
+abc
+===
+\^?"
+ t
+ t))
+ (should (ert-equal-buffer-return
+ '(extend-region)
+ "\^@===
+\^?abc
+===
+"
+ "\^@===
+abc
+===
+\^?"
+ t
+ t))
+ (should (ert-equal-buffer-return
+ '(extend-region)
+ "def
+
+===
+\^@abc
+===
+\^?"
+ "def
+
+\^@===
+abc
+===
+\^?"
+ t
+ t))
+ (should (ert-equal-buffer-return
+ '(extend-region)
+ "def
+
+\^@===
+abc
+\^?===
+
+xyz"
+ "def
+
+\^@===
+abc
+===
+\^?
+xyz"
+ t
+ t))
+ )
--- /dev/null
+;; Tests for helper functions and macros. -*- lexical-binding: t -*-
+
+(add-to-list 'load-path ".")
+(load "init" nil t)
+(init-rst-ert t)
+
+(ert-deftest helpers-asserts ()
+ "Check some assertions."
+ (should (equal ert-Buf-point-char "\^@"))
+ (should (equal ert-Buf-mark-char "\^?"))
+ )
+
+(ert-deftest rst-destructuring-dolist ()
+ "Test `rst-destructuring-dolist'."
+ (should (equal nil (rst-destructuring-dolist (i nil)
+ (signal 'error nil))))
+ (should (equal t (rst-destructuring-dolist (i nil t)
+ (signal 'error nil))))
+ (should (let (res)
+ (rst-destructuring-dolist (e '(1) res)
+ (setq res (not (boundp '--rst-destructuring-dolist-var--))))))
+ (should (equal
+ '((4 . 3) (2 . 1))
+ (let (res)
+ (rst-destructuring-dolist ((l &rest r) '((1 . 2) (3 . 4)) res)
+ (push (cons r l) res)))))
+ (should (equal
+ '((6 5 4) (3 2 1))
+ (let (res)
+ (rst-destructuring-dolist ((l m r) '((1 2 3) (4 5 6)) res)
+ (push (list r m l) res)))))
+ (should (equal
+ '(3 2 1)
+ (let (res)
+ (rst-destructuring-dolist (e '(1 2 3) res)
+ (push e res)))))
+ (should (equal
+ '(30 20 10)
+ (let (res)
+ (rst-destructuring-dolist ((e &aux (a 10)) '((1) (2) (3)) res)
+ (push (* e a) res)
+ (setq a (+ a a))))))
+ (should (equal
+ '(30 20 10)
+ (let (res)
+ (rst-destructuring-dolist ((&rest e &aux (a 10)) '(1 2 3) res)
+ (push (* e a) res)
+ (setq a (+ a a))))))
+ )
+
+(ert-deftest rst-forward-line-strict ()
+ "Test `rst-forward-line-strict'."
+ (should (ert-equal-buffer-return
+ '(rst-forward-line-strict 1)
+ "\^@"
+ t
+ nil))
+ (should (ert-equal-buffer-return
+ '(rst-forward-line-strict 0)
+ "\^@"
+ t
+ t))
+ (should (ert-equal-buffer-return
+ '(rst-forward-line-strict -1)
+ "\^@"
+ t
+ nil))
+ (should (ert-equal-buffer-return
+ '(rst-forward-line-strict 1)
+ "abc\^@"
+ t
+ nil))
+ (should (ert-equal-buffer-return
+ '(rst-forward-line-strict 0)
+ "abc\^@"
+ "\^@abc"
+ t))
+ (should (ert-equal-buffer-return
+ '(rst-forward-line-strict -1)
+ "abc\^@"
+ t
+ nil))
+ (should (ert-equal-buffer-return
+ '(rst-forward-line-strict 1)
+ "abc\^@
+"
+ "abc
+\^@"
+ t))
+ (should (ert-equal-buffer-return
+ '(rst-forward-line-strict 2)
+ "abc\^@
+"
+ t
+ nil))
+ (should (ert-equal-buffer-return
+ '(rst-forward-line-strict 0)
+ "abc\^@
+"
+ "\^@abc
+"
+ t))
+ (should (ert-equal-buffer-return
+ '(rst-forward-line-strict -1)
+ "abc
+\^@"
+ "\^@abc
+"
+ t))
+ (should (ert-equal-buffer-return
+ '(rst-forward-line-strict -2)
+ "abc
+\^@"
+ t
+ nil))
+ (should (ert-equal-buffer-return
+ '(rst-forward-line-strict 1 1)
+ "\^@"
+ t
+ nil))
+ (should (ert-equal-buffer-return
+ '(rst-forward-line-strict 1 2)
+ "\^@"
+ t
+ nil))
+ (should (ert-equal-buffer-return
+ '(rst-forward-line-strict 1 4)
+ "\^@abc"
+ "abc\^@"
+ t))
+ (should (ert-equal-buffer-return
+ '(rst-forward-line-strict 1 4)
+ "abc\^@"
+ t
+ nil))
+ (should (ert-equal-buffer-return
+ '(rst-forward-line-strict 1 3)
+ "\^@abc"
+ "abc\^@"
+ t))
+ (should (ert-equal-buffer-return
+ '(rst-forward-line-strict 1 5)
+ "abc\^@
+"
+ "abc
+\^@"
+ t))
+ (should (ert-equal-buffer-return
+ '(rst-forward-line-strict 2 5)
+ "abc\^@
+"
+ t
+ nil))
+ )
+
+(defun forward-line-looking-at (n &rest rst-res)
+ "Call `rst-forward-line-looking-at'. If match is returned
+return t if `(match-beginning 0)' satisfies `(bolp)'
+and `(match-end 0)' matches mark."
+ (rst-forward-line-looking-at
+ n rst-res
+ #'(lambda (mtcd)
+ (when mtcd
+ (and (bolp)
+ (= (match-end 0) (mark)))))))
+
+(ert-deftest rst-forward-line-looking-at ()
+ "Test `rst-forward-line-looking-at'."
+ (should (ert-equal-buffer-return
+ '(forward-line-looking-at 0)
+ "\^@\^?"
+ t
+ t))
+ (should (ert-equal-buffer-return
+ '(forward-line-looking-at 1)
+ "\^@\^?"
+ t
+ nil))
+ (should (ert-equal-buffer-return
+ '(forward-line-looking-at 1)
+ "\^@
+\^?"
+ t
+ t))
+ (should (ert-equal-buffer-return
+ '(forward-line-looking-at 1)
+ "\^@
+ .. \^?"
+ t
+ nil))
+ (should (ert-equal-buffer-return
+ '(forward-line-looking-at 1 'exm-sta)
+ "\^@
+ .. \^?
+"
+ t
+ nil))
+ (should (ert-equal-buffer-return
+ '(forward-line-looking-at 1 'exm-beg)
+ "\^@
+ .. \^?
+"
+ t
+ t))
+ )
+
+(ert-deftest rst-delete-entire-line ()
+ "Test `rst-delete-entire-line'."
+ (should (ert-equal-buffer
+ '(rst-delete-entire-line 0)
+ "\^@"
+ t))
+ (should (ert-equal-buffer
+ '(rst-delete-entire-line 0)
+ " \^@"
+ "\^@"))
+ (should (ert-equal-buffer
+ '(rst-delete-entire-line 1)
+ "\^@
+abc
+"
+ "\^@
+"))
+ (should (ert-equal-buffer
+ '(rst-delete-entire-line 2)
+ "\^@
+abc
+"
+ t))
+ (should (ert-equal-buffer
+ '(rst-delete-entire-line 3)
+ "\^@
+abc
+"
+ t))
+ (should (ert-equal-buffer
+ '(rst-delete-entire-line 0)
+ "
+\^@abc
+"
+ "
+\^@"))
+ (should (ert-equal-buffer
+ '(rst-delete-entire-line -1)
+ "
+abc
+\^@"
+ "
+\^@"))
+ )
--- /dev/null
+;; Tests for rst-imenu-create-index -*- lexical-binding: t -*-
+
+(add-to-list 'load-path ".")
+(load "init" nil t)
+(init-rst-ert t)
+
+(ert-deftest imenu-asserts ()
+ "Check some assertions."
+ (should (equal ert-Buf-point-char "\^@"))
+ (should (equal ert-Buf-mark-char "\^?"))
+ )
+
+(ert-deftest rst-imenu-create-index ()
+ "Tests for `rst-imenu-create-index'."
+ (should (ert-equal-buffer-return
+ '(rst-imenu-create-index)
+ "
+"
+ t
+ nil))
+ (should (ert-equal-buffer-return
+ '(rst-imenu-create-index)
+ "
+Some normal text.
+"
+ t
+ nil))
+ (should (ert-equal-buffer-return
+ '(rst-imenu-create-index)
+ "
+Header
+======"
+ t
+ '(("=Header" . 2))))
+ (should (ert-equal-buffer-return
+ '(rst-imenu-create-index)
+ "
+============
+ Indented
+============"
+ t
+ '(("=Indented=" . 15))))
+ (should (ert-equal-buffer-return
+ '(rst-imenu-create-index)
+ "
+~~~~~~~~~~~~~~
+Over and under
+~~~~~~~~~~~~~~"
+ t
+ '(("~Over and under~" . 17))))
+ (should (ert-equal-buffer-return
+ '(rst-imenu-create-index)
+ "
+Header
+======
+
+Subheader
+---------"
+ t
+ '(("=Header"
+ ("=Header" . 2)
+ ("-Subheader" . 17)))))
+ (should (ert-equal-buffer-return
+ '(rst-imenu-create-index)
+ "
+Header
+======
+
+Subheader
+---------
+
+With space
+----------"
+ t
+ '(("=Header"
+ ("=Header" . 2)
+ ("-Subheader" . 17)
+ ("-With space" . 38)))))
+ (should (ert-equal-buffer-return
+ '(rst-imenu-create-index)
+ "
+Header
+======
+
+Subheader
+---------
+
+With space
+----------
+
+Top level again
+==============="
+ t
+ '(("=Header"
+ ("=Header" . 2)
+ ("-Subheader" . 17)
+ ("-With space" . 38))
+ ("=Top level again" . 61))))
+ (should (ert-equal-buffer-return
+ '(rst-imenu-create-index)
+ "
+Header
+======
+
+Subheader
+---------
+
+With space
+----------
+
+Sub sub
+~~~~~~~
+
+Top level again
+==============="
+ t
+ '(("=Header"
+ ("=Header" . 2)
+ ("-Subheader" . 17)
+ ("-With space"
+ ("-With space" . 38)
+ ("~Sub sub" . 61)))
+ ("=Top level again" . 78))))
+ )
+
+;; FIXME: Test missing intermediate sections.
+;; FIXME: Test document titles.
--- /dev/null
+;; Tests for functions around indentation -*- lexical-binding: t -*-
+
+(add-to-list 'load-path ".")
+(load "init" nil t)
+(init-rst-ert t)
+
+(ert-deftest indent-asserts ()
+ "Check some assertions."
+ (should (equal ert-Buf-point-char "\^@"))
+ (should (equal ert-Buf-mark-char "\^?"))
+ )
+
+(defun indent-for-tab (&optional count)
+ "Wrapper to call `indent-for-tab-command' COUNT times defaulting to 1."
+ (setq count (or count 1))
+ (rst-mode)
+ (dotimes (i count)
+ (indent-for-tab-command)))
+
+(ert-deftest indent-for-tab-command ()
+ "Tests for `indent-for-tab-command'."
+ (let ((rst-indent-width 2)
+ (rst-indent-field 2)
+ (rst-indent-literal-normal 3)
+ (rst-indent-literal-minimized 2)
+ (rst-indent-comment 3))
+ (should (ert-equal-buffer
+ '(indent-for-tab)
+ "\^@"
+ t
+ ))
+ (should (ert-equal-buffer
+ '(indent-for-tab)
+ "
+* a
+\^@"
+ "
+* a
+ \^@"
+ ))
+ (should (ert-equal-buffer
+ '(indent-for-tab)
+ "
+* a
+ \^@"
+ "
+* a
+\^@"
+ ))
+ (should (ert-equal-buffer
+ '(indent-for-tab)
+ "
+* a
+
+* b\^@"
+ "
+* a
+
+ * b\^@"
+ ))
+ (should (ert-equal-buffer
+ '(indent-for-tab)
+ "
+* a
+
+ * b\^@"
+ "
+* a
+
+* b\^@"
+ ))
+ (should (ert-equal-buffer
+ '(indent-for-tab)
+ "
+* a
+
+\^@* b"
+ "
+* a
+
+ \^@* b"
+ ))
+ (should (ert-equal-buffer
+ '(indent-for-tab)
+ "
+* a
+
+ \^@* b"
+ "
+* a
+
+\^@* b"
+ ))
+ (should (ert-equal-buffer
+ '(indent-for-tab)
+ "
+* a
+ * b
+ XV. c
+ * d
+* e
+\^@"
+ "
+* a
+ * b
+ XV. c
+ * d
+* e
+ \^@"
+ ))
+ (should (ert-equal-buffer
+ '(indent-for-tab)
+ "
+* a
+ * b
+ XV. c
+ * d
+* e
+ \^@"
+ "
+* a
+ * b
+ XV. c
+ * d
+* e
+\^@"
+ ))
+ (should (ert-equal-buffer
+ '(indent-for-tab)
+ "
+* a
+ * b
+ XV. c
+ * d
+ * e\^@"
+ "
+* a
+ * b
+ XV. c
+ * d
+ * e\^@"
+ ))
+ (should (ert-equal-buffer
+ '(indent-for-tab)
+ "
+* a
+ * b
+ XV. c
+ * d
+ * e\^@"
+ "
+* a
+ * b
+ XV. c
+ * d
+ * e\^@"
+ ))
+ (should (ert-equal-buffer
+ '(indent-for-tab)
+ "
+* a
+ * b
+ XV. c
+ * d
+ * e\^@"
+ "
+* a
+ * b
+ XV. c
+ * d
+* e\^@"
+ ))
+ (should (ert-equal-buffer
+ '(indent-for-tab)
+ "
+* a
+ * b
+ XV. c
+ * d
+* e\^@"
+ "
+* a
+ * b
+ XV. c
+ * d
+ * e\^@"
+ ))
+ (should (ert-equal-buffer
+ '(indent-for-tab)
+ "
+.. [CIT]
+
+ citation
+
+ .. |sub| dir:: Same
+
+ * a
+
+ * b
+
+ :f: val::
+ \^@"
+ "
+.. [CIT]
+
+ citation
+
+ .. |sub| dir:: Same
+
+ * a
+
+ * b
+
+ :f: val::
+ \^@"
+ ))
+ (should (ert-equal-buffer
+ '(indent-for-tab)
+ "
+.. [CIT]
+
+ citation
+
+ .. |sub| dir:: Same
+
+ * a
+
+ * b
+
+ :f: val::
+ \^@"
+ "
+.. [CIT]
+
+ citation
+
+ .. |sub| dir:: Same
+
+ * a
+
+ * b
+
+ :f: val::
+ \^@"
+ ))
+ (should (ert-equal-buffer
+ '(indent-for-tab)
+ "
+.. [CIT]
+
+ citation
+
+ .. |sub| dir:: Same
+
+ * a
+
+ * b
+
+ :f: val::
+ \^@"
+ "
+.. [CIT]
+
+ citation
+
+ .. |sub| dir:: Same
+
+ * a
+
+ * b
+
+ :f: val::
+ \^@"
+ ))
+ (should (ert-equal-buffer
+ '(indent-for-tab)
+ "
+.. [CIT]
+
+ citation
+
+ .. |sub| dir:: Same
+
+ * a
+
+ * b
+
+ :f: val::
+ \^@"
+ "
+.. [CIT]
+
+ citation
+
+ .. |sub| dir:: Same
+
+ * a
+
+ * b
+
+ :f: val::
+ \^@"
+ ))
+ (should (ert-equal-buffer
+ '(indent-for-tab)
+ "
+.. [CIT]
+
+ citation
+
+ .. |sub| dir:: Same
+
+ * a
+
+ * b
+
+ :f: val::
+ \^@"
+ "
+.. [CIT]
+
+ citation
+
+ .. |sub| dir:: Same
+
+ * a
+
+ * b
+
+ :f: val::
+ \^@"
+ ))
+ (should (ert-equal-buffer
+ '(indent-for-tab)
+ "
+.. [CIT]
+
+ citation
+
+ .. |sub| dir:: Same
+
+ * a
+
+ * b
+
+ :f: val::
+ \^@"
+ "
+.. [CIT]
+
+ citation
+
+ .. |sub| dir:: Same
+
+ * a
+
+ * b
+
+ :f: val::
+ \^@"
+ ))
+ (should (ert-equal-buffer
+ '(indent-for-tab)
+ "
+.. [CIT]
+
+ citation
+
+ .. |sub| dir:: Same
+
+ * a
+
+ * b
+
+ :f: val::
+ \^@"
+ "
+.. [CIT]
+
+ citation
+
+ .. |sub| dir:: Same
+
+ * a
+
+ * b
+
+ :f: val::
+ \^@"
+ ))
+ (should (ert-equal-buffer
+ '(indent-for-tab)
+ "
+.. [CIT]
+
+ citation
+
+ .. |sub| dir:: Same
+
+ * a
+
+ * b
+
+ :f: val::
+ \^@"
+ "
+.. [CIT]
+
+ citation
+
+ .. |sub| dir:: Same
+
+ * a
+
+ * b
+
+ :f: val::
+ \^@"
+ ))
+ (should (ert-equal-buffer
+ '(indent-for-tab)
+ "
+.. [CIT]
+
+ citation
+
+ .. |sub| dir:: Same
+
+ * a
+
+ * b
+
+ :f: val::
+ \^@"
+ "
+.. [CIT]
+
+ citation
+
+ .. |sub| dir:: Same
+
+ * a
+
+ * b
+
+ :f: val::
+\^@"
+ ))
+ ))
+
+(ert-deftest indent-for-tab-command-BUGS ()
+ "Exposes bugs for `indent-for-tab-command'."
+ :expected-result :failed ;; These are bugs
+ (let ((rst-indent-width 2)
+ (rst-indent-field 2)
+ (rst-indent-literal-normal 3)
+ (rst-indent-literal-minimized 2)
+ (rst-indent-comment 3))
+ ;; Bug https://sourceforge.net/p/docutils/bugs/299/
+ (should (ert-equal-buffer
+ '(indent-for-tab)
+ "
+Lorem ipsum dolor sit amet, consectetur adipisicing elit
+:other:`something` sed do eiusmod tempor incididunt ut
+\^@"
+ "
+Lorem ipsum dolor sit amet, consectetur adipisicing elit
+:other:`something` sed do eiusmod tempor incididunt ut
+\^@"
+ ))))
--- /dev/null
+;; Initialize tests -*- lexical-binding: t -*-
+
+(defun init-rst-ert (&optional with-buffer)
+ "Initialize tests.
+Prepare for buffer using tests if WITH-BUFFER."
+ (when with-buffer
+ (add-to-list 'load-path ".")
+ (load "ert-buffer" nil t)
+ (if (equal (car load-path) ".")
+ (setq load-path (cdr load-path))))
+
+ (add-to-list 'load-path "..")
+ (load "rst.el" nil t)
+ (if (equal (car load-path) "..")
+ (setq load-path (cdr load-path)))
+
+ ;; Emacs 24 should have a patch in `testcover-after` declaring a
+ ;; `gv-expander'.
+ (if (< emacs-major-version 24)
+ ;; Define a setf-method for `testcover-after' so `ert' tests can be run
+ ;; without problems.
+ (defsetf testcover-after (idx val) (store)
+ (list 'progn
+ (list 'testcover-after idx val)
+ ;; FIXME: Though it solves the problem it is not really correct
+ ;; because `val' is only a temporary variable here.
+ (list 'setf val store)))))
+
+;; Clean up `load-path' if set caller just to load this file.
+(if (equal (car load-path) ".")
+ (setq load-path (cdr load-path)))
--- /dev/null
+;; Tests for operations on list items -*- lexical-binding: t -*-
+
+(add-to-list 'load-path ".")
+(load "init" nil t)
+(init-rst-ert t)
+
+(ert-deftest items-asserts ()
+ "Check some assertions."
+ (should (equal ert-Buf-point-char "\^@"))
+ (should (equal ert-Buf-mark-char "\^?"))
+ )
+
+(defun find-begs (beg-re)
+ (rst-find-begs (region-beginning) (region-end) beg-re))
+
+(ert-deftest rst-find-begs ()
+ "Tests `rst-find-begs'."
+ (should (ert-equal-buffer-return
+ '(find-begs 'itmany-beg-1)
+ "\^@1 Normal paragraph.
+
+* 22 A bullet
+
+* 37 Another bullet
+
+58 Another normal paragraph.
+
+\^?"
+ t '((22 . 0)
+ (37 . 0))))
+ (should (ert-equal-buffer-return
+ '(find-begs 'itmany-beg-1)
+ "1 Normal paragraph.
+
+\^?* 22 A bullet
+
+* 37 Another bullet
+
+\^@58 Another normal paragraph.
+
+"
+ t '((22 . 0)
+ (37 . 0))))
+ (should (ert-equal-buffer-return
+ '(find-begs 'itmany-beg-1)
+ "1 Normal paragraph.
+
+\^?* 22 A bullet
+
+* 37 Another bullet
+
+1. 58 An enum.
+
+2. 74 Another enum.
+
+\^@95 Another normal paragraph.
+
+"
+ t '((22 . 0)
+ (37 . 0)
+ (58 . 0)
+ (74 . 0))))
+ (should (ert-equal-buffer-return
+ '(find-begs 'bul-beg)
+ "\^@
+- 2 one
++ 10 two
+* 19 three
+\^?"
+ t '((2 . 0)
+ (10 . 0)
+ (19 . 0))))
+ (should (ert-equal-buffer-return
+ '(find-begs 'bul-beg)
+ "
+- 2 one\^@
++ 10 two
+* 19 three
+\^?"
+ t '((2 . 0)
+ (10 . 0)
+ (19 . 0))))
+ (should (ert-equal-buffer-return
+ '(find-begs 'bul-beg)
+ "+ 1 zero
+\^@- 10 one
++ 19 two
+* 28 three\^?
+"
+ t '((10 . 0)
+ (19 . 0)
+ (28 . 0))))
+ (should (ert-equal-buffer-return
+ '(find-begs 'bul-beg)
+ "\^@
+- 2 one
+
+ + 11 two
+
+* 23 three
+\^?"
+ t '((2 . 0)
+ (13 . 2)
+ (23 . 0))))
+ (should (ert-equal-buffer-return
+ '(find-begs 'bul-beg)
+ "\^@Normal paragraph
+
+* 19 bullet
+
+ * 32 three
+
+Another normal paragraph
+\^?"
+ t '((19 . 0)
+ (34 . 2))))
+ )
+
+(ert-deftest rst-find-begs-BUGS ()
+ "Exposes bugs in `rst-find-begs'."
+ :expected-result :failed ;; These are bugs
+ (should (ert-equal-buffer-return
+ '(find-begs 'bul-beg)
+ "\^@Normal paragraph
+* 18 bullet
+ * 30 three
+Another normal paragraph
+\^?"
+ t '((18 . 0)
+ (32 . 2))))
+ (should (ert-equal-buffer-return
+ '(find-begs 'bul-beg)
+ "\^@
+- 2 one
+ + 10 two
+* 21 three
+\^?"
+ t '((2 . 0)
+ (12 . 2)
+ (19 . 0))))
+ )
+
+(ert-deftest rst-convert-bullets-to-enumeration ()
+ "Tests `rst-convert-bullets-to-enumeration'."
+ (should (ert-equal-buffer
+ '(rst-convert-bullets-to-enumeration)
+"\^@Normal paragraph.
+
+* A bullet
+
+* Another bullet
+
+Another normal paragraph.
+
+\^?"
+"\^@Normal paragraph.
+
+1. A bullet
+
+2. Another bullet
+
+Another normal paragraph.
+
+\^?" t))
+ (should (ert-equal-buffer
+ '(rst-convert-bullets-to-enumeration)
+"Normal paragraph.
+
+\^?* A bullet
+
+* Another bullet
+
+\^@Another normal paragraph.
+
+"
+"Normal paragraph.
+
+\^?1. A bullet
+
+2. Another bullet
+
+\^@Another normal paragraph.
+
+" t))
+ (should (ert-equal-buffer
+ '(rst-convert-bullets-to-enumeration)
+"Normal paragraph.
+
+\^?* A bullet
+
+* Another bullet
+
+1. A bullet
+
+2. Another bullet
+
+\^@Another normal paragraph.
+
+"
+
+"Normal paragraph.
+
+\^?1. A bullet
+
+2. Another bullet
+
+3. A bullet
+
+4. Another bullet
+
+\^@Another normal paragraph.
+
+" t))
+ )
+
+(ert-deftest rst-convert-bullets-to-enumeration-BUGS ()
+ "Exposes bugs in `rst-convert-bullets-to-enumeration'."
+ :expected-result :failed ;; These are bugs
+ (should (ert-equal-buffer
+ '(rst-convert-bullets-to-enumeration)
+"\^@Normal paragraph.
+
+* A bullet
+
+* Another bullet
+
+ * A bullet
+
+ * Another bullet
+
+Another normal paragraph.
+
+\^?"
+"\^@Normal paragraph.
+
+1. A bullet
+
+2. Another bullet
+
+ * A bullet
+
+ * Another bullet
+
+Another normal paragraph.
+
+\^?" t))
+ )
+
+(ert-deftest rst-insert-list-continue ()
+ "Tests `rst-insert-list' when continuing a list."
+ (should (ert-equal-buffer
+ '(rst-insert-list)
+"* Some text\^@\n"
+"* Some text
+* \^@\n"))
+ (should (ert-equal-buffer
+ '(rst-insert-list)
+"* Some \^@text\n"
+"* Some text
+* \^@\n"))
+ (should (ert-equal-buffer
+ '(rst-insert-list)
+"* \^@Some text\n"
+"* Some text
+* \^@\n"))
+ (should (ert-equal-buffer
+ '(rst-insert-list)
+"* Some text
+ - A deeper hyphen bullet\^@\n"
+"* Some text
+ - A deeper hyphen bullet
+ - \^@\n"))
+ (should (ert-equal-buffer
+ '(rst-insert-list)
+"* Some text
+ - \^@Some text\n"
+"* Some text
+ - Some text
+ - \^@\n"))
+ (should (ert-equal-buffer
+ '(rst-insert-list)
+"1. Some text\^@\n"
+"1. Some text
+2. \^@\n"))
+ (should (ert-equal-buffer
+ '(rst-insert-list)
+"2. Some text\^@\n"
+"2. Some text
+3. \^@\n"))
+ (should (ert-equal-buffer
+ '(rst-insert-list)
+"a) Some text\^@\n"
+"a) Some text
+b) \^@\n"))
+ (should (ert-equal-buffer
+ '(rst-insert-list)
+"(A) Some text\^@\n"
+"(A) Some text
+\(B) \^@\n"))
+ (should (ert-equal-buffer
+ '(rst-insert-list)
+"(I) Some text\^@\n"
+"(I) Some text
+\(J) \^@\n"))
+ (should (ert-equal-buffer
+ '(rst-insert-list)
+"(I) Some text\^@\n"
+"(I) Some text
+\(J) \^@\n"))
+ (should (ert-equal-buffer
+ '(rst-insert-list)
+"(h) Some text
+\(i) Some text\^@\n"
+"(h) Some text
+\(i) Some text
+\(j) \^@\n"))
+ (should (ert-equal-buffer
+ '(rst-insert-list t)
+"(i) Some text\^@\n"
+"(i) Some text
+\(ii) \^@\n"))
+ (should (ert-equal-buffer
+ '(rst-insert-list)
+"(IV) Some text
+\(V) Some text\^@\n"
+"(IV) Some text
+\(V) Some text
+\(VI) \^@\n"))
+ )
+
+(ert-deftest rst-insert-list-continue-BUGS ()
+ "Exposes bugs in `rst-insert-list-continue'."
+ :expected-result :failed ;; These are bugs
+ (should (ert-equal-buffer
+ '(rst-insert-list)
+"(iv) Some text
+
+\(v) Some text\^@\n"
+"(iv) Some text
+
+\(v) Some text
+\(vi) \^@\n")))
+
+(ert-deftest rst-insert-list-new ()
+ "Tests `rst-insert-list' when inserting a new list."
+ (should (ert-equal-buffer
+ '(rst-insert-list)
+"\^@
+"
+"* \^@
+" '("*")))
+ (should (ert-equal-buffer
+ '(rst-insert-list)
+"
+\^@
+"
+"
+- \^@
+" '("-")))
+ (should (ert-equal-buffer
+ '(rst-insert-list)
+"
+\^@
+
+"
+"
+#. \^@
+
+" '("#.")))
+ (should (ert-equal-buffer
+ '(rst-insert-list)
+"\^@
+"
+"5) \^@
+" '("1)" 5)))
+ (should (ert-equal-buffer
+ '(rst-insert-list)
+"\^@
+"
+"(i) \^@
+" '("(i)" "")))
+ (should (ert-equal-buffer
+ '(rst-insert-list)
+"\^@
+"
+"IV. \^@
+" '("I." 4)))
+ (should (ert-equal-buffer
+ '(rst-insert-list)
+"Some line\^@
+"
+"Some line
+
+c. \^@
+" '("a." "c")))
+ (should (ert-equal-buffer
+ '(rst-insert-list)
+"Some line
+\^@
+"
+"Some line
+
+B) \^@
+" '("A)" "B")))
+ (should (ert-equal-buffer
+ '(rst-insert-list)
+"Some line
+
+\^@
+"
+"Some line
+
+IV. \^@
+" '("I." 4)))
+ (should (ert-equal-buffer
+ '(rst-insert-list)
+"Some line
+\^@Another line
+"
+"Some line
+Another line
+
+* \^@
+" '("*")))
+ )
+
+(ert-deftest rst-insert-list-new-BUGS ()
+ "Exposes bugs in `rst-insert-list' when inserting a new list."
+ :expected-result :failed ;; These are bugs
+ (should (ert-equal-buffer
+ '(rst-insert-list)
+"\^@ \n"
+"* \^@
+" '("*")))
+ (should (ert-equal-buffer
+ '(rst-insert-list)
+"Some line
+\^@
+Another line
+"
+"Some line
+
+* \^@
+
+Another line
+" '("*")))
+ )
+
+(ert-deftest rst-straighten-bullets-region ()
+ "Tests `rst-straighten-bullets-region'."
+ (let ((rst-preferred-bullets '(?* ?-)))
+ (should (ert-equal-buffer
+ '(rst-straighten-bullets-region)
+ "\^@\^?"
+ "\^@\^?"
+ t))
+ (should (ert-equal-buffer
+ '(rst-straighten-bullets-region)
+ "\^@
+- one
++ two
+* three
+\^?"
+ "\^@
+* one
+* two
+* three
+\^?"
+ t))
+ (should (ert-equal-buffer
+ '(rst-straighten-bullets-region)
+ "- one\^@
++ two\^?"
+ "* one\^@
+* two\^?"
+ t))
+ (should (ert-equal-buffer
+ '(rst-straighten-bullets-region)
+ "+ zero
+\^@- one
++ two
+* three\^?
+- four"
+ "+ zero
+\^@* one
+* two
+* three\^?
+- four"
+ t))
+ (should (ert-equal-buffer
+ '(rst-straighten-bullets-region)
+ "\^@
+- one
+
+ + two
+
+* three
+\^?"
+ "\^@
+* one
+
+ - two
+
+* three
+\^?"
+ t))
+ (should (ert-equal-buffer
+ '(rst-straighten-bullets-region)
+ "\^@
+- one
+
+ - two
+
+* three
+\^?"
+ "\^@
+* one
+
+ - two
+
+* three
+\^?"
+ t))
+ (should (ert-equal-buffer
+ '(rst-straighten-bullets-region)
+ "\^@
++ one
+
+ * two
+
++ three
+\^?"
+ "\^@
+* one
+
+ - two
+
+* three
+\^?"
+ t))
+ )
+ (let ((rst-preferred-bullets nil))
+ (should (ert-equal-buffer
+ '(rst-straighten-bullets-region)
+ "\^@
+- one
++ two
+* three
+\^?"
+ "\^@
+- one
++ two
+* three
+\^?"
+ t))
+ ))
+
+(ert-deftest rst-straighten-bullets-region-BUGS ()
+ "Tests `rst-straighten-bullets-region'."
+ :expected-result :failed ;; These are bugs
+ (let ((rst-preferred-bullets '(?* ?-)))
+ (should (ert-equal-buffer
+ '(rst-straighten-bullets-region)
+ "\^@
+- one
+ + two
+* three
+\^?"
+ "\^@
+* one
+ - two
+* three
+\^?"
+ t))
+ (should (ert-equal-buffer
+ '(rst-straighten-bullets-region)
+ "\^@
+- one
+ + two
+* three
+\^?"
+ "\^@
+* one
+ - two
+* three
+\^?"
+ t))
+ (should (ert-equal-buffer
+ '(rst-straighten-bullets-region)
+ "\^@
++ one
+ * two
++ three
+\^?"
+ "\^@
+* one
+ - two
+* three
+\^?"
+ t))
+ ))
+
+(defun arabic-roman-roundtrip (arabic roman)
+ "Convert ARABIC to roman, compare it to ROMAN and convert this back.
+Return t if roundtrip is correct."
+ (let ((cvt-roman (rst-arabic-to-roman arabic))
+ (cvt-arabic (rst-roman-to-arabic roman)))
+ (and (equal roman cvt-roman) (equal arabic cvt-arabic))))
+
+(ert-deftest arabic-roman-roundtrip ()
+ "Test `rst-arabic-to-roman' and `rst-roman-to-arabic'."
+
+ ;; Test invalid arabic numbers.
+ (should-error (arabic-roman-roundtrip -1 "I")
+ :type 'wrong-type-argument)
+ (should-error (arabic-roman-roundtrip 0 "I")
+ :type 'wrong-type-argument)
+ (should-error (arabic-roman-roundtrip nil "I")
+ :type 'wrong-type-argument)
+
+ ;; Test invalid roman numbers.
+ (should-error (arabic-roman-roundtrip 1 nil)
+ :type 'wrong-type-argument)
+ (should-error (arabic-roman-roundtrip 1 "NoRoman")
+ :type 'wrong-type-argument)
+ (should-error (arabic-roman-roundtrip 1 "")
+ :type 'wrong-type-argument)
+
+ ;; Test values.
+ (should (arabic-roman-roundtrip 1 "I"))
+ (should (arabic-roman-roundtrip 4 "IV"))
+ (should (arabic-roman-roundtrip 5 "V"))
+ (should (arabic-roman-roundtrip 10 "X"))
+ (should (arabic-roman-roundtrip 20 "XX"))
+ (should (arabic-roman-roundtrip 1999 "MCMXCIX"))
+ (should (arabic-roman-roundtrip 2000 "MM"))
+ (should (arabic-roman-roundtrip 3333 "MMMCCCXXXIII"))
+ (should (arabic-roman-roundtrip 444 "CDXLIV"))
+ )
--- /dev/null
+;; Tests for various movement commands -*- lexical-binding: t -*-
+
+(add-to-list 'load-path ".")
+(load "init" nil t)
+(init-rst-ert t)
+
+(ert-deftest movement-asserts ()
+ "Check some assertions."
+ (should (equal ert-Buf-point-char "\^@"))
+ (should (equal ert-Buf-mark-char "\^?"))
+ )
+
+(defun fwd-para ()
+ "Wrapper to call `forward-paragraph'."
+ (rst-mode)
+ (forward-paragraph))
+
+(ert-deftest forward-paragraph ()
+ "Tests for `forward-paragraph'."
+ (should (ert-equal-buffer-return
+ '(fwd-para)
+ "
+:Field: Content
+\^@
+ More content
+ over several
+
+ * An item
+ with multi
+"
+ "
+:Field: Content
+
+ More content
+ over several
+\^@
+ * An item
+ with multi
+"
+ 0
+ ))
+
+
+ (should (ert-equal-buffer-return
+ '(fwd-para)
+ "\^@
+This is
+a short
+para"
+ "
+This is
+a short
+para\^@"
+ 0
+ ))
+ (should (ert-equal-buffer-return
+ '(fwd-para)
+ "\^@
+This is
+a short
+para
+"
+ "
+This is
+a short
+para
+\^@"
+ 0
+ ))
+ (should (ert-equal-buffer-return
+ '(fwd-para)
+ "\^@
+This is
+a short
+para
+
+"
+ "
+This is
+a short
+para
+\^@
+"
+ 0
+ ))
+ (should (ert-equal-buffer-return
+ '(fwd-para)
+ "\^@
+This is
+a short
+para
+
+
+"
+ "
+This is
+a short
+para
+\^@
+
+"
+ 0
+ ))
+ (should (ert-equal-buffer-return
+ '(fwd-para)
+ "
+\^@This is
+a short
+para
+
+"
+ "
+This is
+a short
+para
+\^@
+"
+ 0
+ ))
+ (should (ert-equal-buffer-return
+ '(fwd-para)
+ "
+This is
+a short
+\^@para
+
+"
+ "
+This is
+a short
+para
+\^@
+"
+ 0
+ ))
+ (should (ert-equal-buffer-return
+ '(fwd-para)
+ "
+This is
+a short
+\^@para
+
+"
+ "
+This is
+a short
+para
+\^@
+"
+ 0
+ ))
+ (should (ert-equal-buffer-return
+ '(fwd-para)
+ "
+This is
+\^@a short
+ para
+
+"
+ "
+This is
+a short
+ para
+\^@
+"
+ 0
+ ))
+ (should (ert-equal-buffer-return
+ '(fwd-para)
+ "
+This is
+a short
+\^@para
+
+This is
+a short
+para
+
+"
+ "
+This is
+a short
+para
+\^@
+This is
+a short
+para
+
+"
+ 0
+ ))
+ (should (ert-equal-buffer-return
+ '(fwd-para)
+ "
+\^@* An item
+
+* Another item
+"
+ "
+* An item
+\^@
+* Another item
+"
+ 0
+ ))
+ (should (ert-equal-buffer-return
+ '(fwd-para)
+ "
+\^@* An item
+* Another item
+"
+ "
+* An item
+\^@* Another item
+"
+ 0
+ ))
+ (should (ert-equal-buffer-return
+ '(fwd-para)
+ "
+\^@:Field: Content
+
+ More content
+ over several
+
+ * An item
+ with multi
+"
+ "
+:Field: Content
+\^@
+ More content
+ over several
+
+ * An item
+ with multi
+"
+ 0
+ ))
+ (should (ert-equal-buffer-return
+ '(fwd-para)
+ "
+:Field: Content
+\^@
+ More content
+ over several
+
+ * An item
+ with multi
+"
+ "
+:Field: Content
+
+ More content
+ over several
+\^@
+ * An item
+ with multi
+"
+ 0
+ ))
+ (should (ert-equal-buffer-return
+ '(fwd-para)
+ "
+:Field: Content
+
+ More content
+ over several
+\^@
+ * An item
+ with multi
+"
+ "
+:Field: Content
+
+ More content
+ over several
+
+ * An item
+ with multi
+\^@"
+ 0
+ ))
+ (should (ert-equal-buffer-return
+ '(fwd-para)
+ "\^@
+.. |s| d::
+ :F: Content
+
+ More content
+ over several
+ * An item
+ with multi
+"
+ "
+.. |s| d::
+\^@ :F: Content
+
+ More content
+ over several
+ * An item
+ with multi
+"
+ 0
+ ))
+ (should (ert-equal-buffer-return
+ '(fwd-para)
+ "
+.. |s| d::
+\^@ :F: Content
+
+ More content
+ over several
+ * An item
+ with multi
+"
+ "
+.. |s| d::
+ :F: Content
+\^@
+ More content
+ over several
+ * An item
+ with multi
+"
+ 0
+ ))
+ (should (ert-equal-buffer-return
+ '(fwd-para)
+ "
+.. |s| d::
+ :F: Content
+\^@
+ More content
+ over several
+ * An item
+ with multi
+"
+ "
+.. |s| d::
+ :F: Content
+
+ More content
+ over several
+\^@ * An item
+ with multi
+"
+ 0
+ ))
+ (should (ert-equal-buffer-return
+ '(fwd-para)
+ "
+.. |s| d::
+ :F: Content
+
+ More content
+ over several
+\^@ * An item
+ with multi
+"
+ "
+.. |s| d::
+ :F: Content
+
+ More content
+ over several
+ * An item
+ with multi
+\^@"
+ 0
+ ))
+ )
+
+(ert-deftest rst-forward-section ()
+ "Tests for `rst-forward-section'."
+ (should (ert-equal-buffer
+ '(rst-forward-section -1)
+ "
+========
+\^@Header 1
+========
+
+Some text
+
+Header 2
+========
+"
+ "\^@
+========
+Header 1
+========
+
+Some text
+
+Header 2
+========
+"
+ ))
+ (should (ert-equal-buffer
+ '(rst-forward-section 1)
+ "\^@"
+ "\^@"))
+ (should (ert-equal-buffer
+ '(rst-forward-section 1)
+ "
+Some text\^@
+
+More text
+"
+ "
+Some text
+
+More text
+\^@"
+ ))
+ (should (ert-equal-buffer
+ '(rst-forward-section 1)
+ "
+Some text
+
+More text
+\^@"
+ "
+Some text
+
+More text
+\^@"
+ ))
+ (should (ert-equal-buffer
+ '(rst-forward-section -1)
+ "
+Some text
+
+More text
+\^@"
+ "\^@
+Some text
+
+More text
+"
+ ))
+ (should (ert-equal-buffer
+ '(rst-forward-section 1)
+ "
+\^@Header 1
+========
+
+Some text
+"
+ "
+Header 1
+========
+
+Some text
+\^@"
+ ))
+ (should (ert-equal-buffer
+ '(rst-forward-section 1)
+ "
+Header 1\^@
+========
+
+Some text
+"
+ "
+Header 1
+========
+
+Some text
+\^@"
+ ))
+ (should (ert-equal-buffer
+ '(rst-forward-section 1)
+ "
+Header 1
+===\^@=====
+
+Some text
+"
+ "
+Header 1
+========
+
+Some text
+\^@"
+ ))
+ (should (ert-equal-buffer
+ '(rst-forward-section 1)
+ "
+Header 1\^@
+========
+
+Some text
+
+Header 2
+========
+"
+ "
+Header 1
+========
+
+Some text
+
+\^@Header 2
+========
+"
+ ))
+ (should (ert-equal-buffer
+ '(rst-forward-section 1)
+ "
+Header 1
+========
+
+\^@Some text
+
+Header 2
+========
+"
+ "
+Header 1
+========
+
+Some text
+
+\^@Header 2
+========
+"
+ ))
+ (should (ert-equal-buffer
+ '(rst-forward-section 1)
+ "
+Header 1
+========\^@
+
+Some text
+
+Header 2
+========
+"
+ "
+Header 1
+========
+
+Some text
+
+\^@Header 2
+========
+"
+ ))
+ (should (ert-equal-buffer
+ '(rst-forward-section 1)
+ "
+========
+\^@Header 1
+========
+
+Some text
+
+Header 2
+========
+"
+ "
+========
+Header 1
+========
+
+Some text
+
+\^@Header 2
+========
+"
+ ))
+ (should (ert-equal-buffer
+ '(rst-forward-section 1)
+ "
+\^@========
+Header 1
+========
+
+Some text
+
+Header 2
+========
+"
+ "
+========
+Header 1
+========
+
+Some text
+
+\^@Header 2
+========
+"
+ ))
+ (should (ert-equal-buffer
+ '(rst-forward-section -1)
+ "
+========
+Header 1
+========
+
+Some text
+
+\^@Header 2
+========
+"
+ "
+========
+\^@Header 1
+========
+
+Some text
+
+Header 2
+========
+"
+ ))
+
+; ****
+
+ (should (ert-equal-buffer
+ '(rst-forward-section 2)
+ "\^@
+========
+Header 1
+========
+
+Some text
+
+Header 2
+========
+"
+ "
+========
+Header 1
+========
+
+Some text
+
+\^@Header 2
+========
+"
+ ))
+ (should (ert-equal-buffer
+ '(rst-forward-section 3)
+ "
+========
+\^@Header 1
+========
+
+Some text
+
+Header 2
+========
+
+Header 3
+========
+
+Header 4
+========
+"
+ "
+========
+Header 1
+========
+
+Some text
+
+Header 2
+========
+
+Header 3
+========
+
+\^@Header 4
+========
+"
+ ))
+ (should (ert-equal-buffer
+ '(rst-forward-section 3)
+ "\^@
+========
+Header 1
+========
+
+Some text
+
+Header 2
+========
+"
+ "
+========
+Header 1
+========
+
+Some text
+
+Header 2
+========
+\^@"
+ ))
+ (should (ert-equal-buffer
+ '(rst-forward-section 0)
+ "
+========
+Header 1\^@
+========
+
+Some text
+
+Header 2
+========
+"
+ "
+========
+\^@Header 1
+========
+
+Some text
+
+Header 2
+========
+"
+ ))
+ (should (ert-equal-buffer
+ '(rst-forward-section 0)
+ "
+========\^@
+Header 1
+========
+
+Some text
+
+Header 2
+========
+"
+ "
+========
+\^@Header 1
+========
+
+Some text
+
+Header 2
+========
+"
+ ))
+ (should (ert-equal-buffer
+ '(rst-forward-section 0)
+ "
+========
+Header 1
+========\^@
+
+Some text
+
+Header 2
+========
+"
+ "
+========
+\^@Header 1
+========
+
+Some text
+
+Header 2
+========
+"
+ ))
+ (should (ert-equal-buffer
+ '(rst-forward-section 0)
+ "
+========
+Header 1
+========
+
+Some text\^@
+
+Header 2
+========
+"
+ "
+========
+Header 1
+========
+
+Some text\^@
+
+Header 2
+========
+"
+ ))
+ (should (ert-equal-buffer
+ '(rst-forward-section -)
+ "
+========
+Header 1
+========
+
+Some text
+
+\^@Header 2
+========
+"
+ "
+========
+\^@Header 1
+========
+
+Some text
+
+Header 2
+========
+"
+ t))
+ (should (ert-equal-buffer
+ '(rst-forward-section nil)
+ "
+========
+\^@Header 1
+========
+
+Some text
+
+Header 2
+========
+"
+ "
+========
+Header 1
+========
+
+Some text
+
+\^@Header 2
+========
+"
+ t
+ ))
+ (should (ert-equal-buffer
+ '(rst-forward-section (4))
+ "\^@
+========
+Header 1
+========
+
+Some text
+
+Header 2
+========
+"
+ "
+========
+Header 1
+========
+
+Some text
+
+Header 2
+========
+\^@"
+ t))
+ (should (ert-equal-buffer
+ '(rst-backward-section nil)
+ "
+========
+Header 1
+========
+
+Some text
+
+\^@Header 2
+========
+"
+ "
+========
+\^@Header 1
+========
+
+Some text
+
+Header 2
+========
+"
+ t))
+ )
--- /dev/null
+;; Tests for the regular expression builder -*- lexical-binding: t -*-
+
+(add-to-list 'load-path ".")
+(load "init" nil t)
+(init-rst-ert t)
+
+(ert-deftest rst-re ()
+ "Tests `rst-re'."
+ (should (equal (rst-re "xy") "xy"))
+ (should (equal (rst-re ?A) "A"))
+ (should (equal (rst-re ?$) "\\$"))
+ (should (equal (rst-re 'exm-tag) "\\.\\."))
+ (should (equal (rst-re "xy" ?A ?$ 'exm-tag) "xyA\\$\\.\\."))
+ (should (equal (rst-re '(:seq "xy" ?A ?$ exm-tag)) "xyA\\$\\.\\."))
+ (should (equal (rst-re '(:shy "xy" ?A ?$ exm-tag)) "\\(?:xyA\\$\\.\\.\\)"))
+ (should (equal (rst-re '(:grp "xy" ?A ?$ exm-tag)) "\\(xyA\\$\\.\\.\\)"))
+ (should (equal (rst-re '(:alt "xy" ?A ?$ exm-tag))
+ "\\(?:xy\\|A\\|\\$\\|\\.\\.\\)"))
+ (should (equal (rst-re '(:seq (:seq "xy" ?A ?$ exm-tag))) "xyA\\$\\.\\."))
+ (should (equal (rst-re '(:grp (:alt "xy" ?A ?$ exm-tag)))
+ "\\(\\(?:xy\\|A\\|\\$\\|\\.\\.\\)\\)"))
+ (should (equal (rst-re '(:alt (:grp "xy" ?A ?$ exm-tag)))
+ "\\(?:\\(xyA\\$\\.\\.\\)\\)"))
+ (should (equal (rst-re '(:alt "xy" ?A) '(:grp ?$ exm-tag))
+ "\\(?:xy\\|A\\)\\(\\$\\.\\.\\)"))
+ (should-error (rst-re '(:unknown "xy")))
+ (should-error (rst-re [1]))
+ )
+
+(defun re-equal-modify-orig (orig loc refactored repls)
+ (let ((case-fold-search nil))
+ (while (string-match "\\[ \t]" orig)
+ ;; Transpose horizontal whitespace
+ (setq orig (replace-match "[\t ]" t nil orig)))
+ (while (string-match "\\\\s \\*\\$" orig)
+ ;; Replace symbolic whitespace
+ (setq orig (replace-match "[\t ]*$" t nil orig)))
+ (dolist (regex-repl repls)
+ (if (string-match (car regex-repl) orig)
+ (setq orig (replace-match (cdr regex-repl) t t orig))
+ (error "Replacement regex /%s/ didn't match in '%s' for location '%s'"
+ (car regex-repl) orig loc)))
+ orig))
+
+
+(defun re-equal (orig loc refactored &rest repls)
+ "Compare regex ORIG at location LOC to REFACTORED.
+REPLS starts with a list of cons cells telling where regex in car
+is replaced by cdr in ORIG."
+ (equal (re-equal-modify-orig orig loc refactored repls) refactored))
+
+(defun re-equal-explain (orig loc refactored &rest repls)
+ (setq orig (re-equal-modify-orig orig loc refactored repls))
+ (ert--explain-not-equal orig refactored))
+
+(put 're-equal 'ert-explainer 're-equal-explain)
+
+(defun re-check-matches (orig loc refactored s pairs)
+ "Check matches and return those pairs which didn't work"
+ (let ((case-fold-search nil)
+ failed)
+ (dolist (pair pairs failed)
+ (let ((orig-mtc (if (string-match orig s)
+ (match-string (car pair) s)))
+ (refa-mtc (if (string-match refactored s)
+ (match-string (cdr pair) s))))
+ (if (not orig-mtc)
+ (error "Original regex '%s' didn't match string '%s' for location '%s'"
+ orig s loc)
+ (if (not refa-mtc)
+ (error "Refactored regex '%s' didn't match string '%s' for location '%s'"
+ refactored s loc)
+ (if (not (equal orig-mtc refa-mtc))
+ (push pair failed))))))))
+
+(defun re-equal-matches (orig loc refactored matches &rest repls)
+ "Like `re-equal'. However, if MATCHES is non-nil it must be a
+list with a string and cons cells each consisting of two numbers.
+For each cons cell the string is matched with ORIG and REFACTORED
+and the numbered matches are compared."
+ (and (equal (re-equal-modify-orig orig loc refactored repls) refactored)
+ (not (re-check-matches orig loc refactored
+ (car matches) (cdr matches)))))
+
+(defun re-equal-matches-explain (orig loc refactored matches &rest repls)
+ (if (not (equal (re-equal-modify-orig orig loc refactored repls) refactored))
+ (apply 're-equal-explain orig loc refactored repls)
+ (let (result)
+ (dolist (failed (re-check-matches orig loc refactored
+ (car matches) (cdr matches)) result)
+ (push (list 'matchers-didnt-match (car failed) (cdr failed))
+ result)))))
+
+(put 're-equal-matches 'ert-explainer 're-equal-matches-explain)
+
+(ert-deftest rst-re-refactoring ()
+ "Test the refactorings done based on rst_el_1_68."
+ ;; Any comment or string "=== rst.el.~rst_el_1_68~:..." gives the line number
+ ;; of the refactored code in the original file for the previous expression.
+ (let* ((rst-bullets
+ '(?- ?* ?+))
+ ;; === rst.el.~rst_el_1_68~:451
+ (rst-re-bullets
+ (format "\\([%s][ \t]\\)[^ \t]" (regexp-quote (concat rst-bullets))))
+ ;; === rst.el.~rst_el_1_68~:1604
+ ;; More parameters
+ (c ?*)
+ (len 10)
+ (char ?+)
+ (adornment "$$$$")
+ (ado-re (regexp-quote adornment))
+ (fromchar ?.)
+ )
+ (should (re-equal
+ "^\\.\\. "
+ "=== rst.el.~rst_el_1_68~:398"
+ (rst-re "^" 'exm-sta)
+ (cons " $" "[ ]+") ;; Any whitespace may follow
+ ))
+ (should (re-equal
+ "^[ \t]*\\S *\\w\\S *"
+ "=== rst.el.~rst_el_1_68~:567"
+ (rst-re 'lin-beg "\\S *\\w\\S *")
+ ))
+ (should (re-equal
+ "::[ \t]*$"
+ "=== rst.el.~rst_el_1_68~:591"
+ (rst-re 'dcl-tag 'lin-end)
+ ))
+ (should (re-equal
+ "\\.\\.\\.[ \t]*$"
+ "=== rst.el.~rst_el_1_68~:592"
+ (rst-re 'ell-tag 'lin-end)
+ ))
+ (should (re-equal
+ ".[ \t]*$"
+ "=== rst.el.~rst_el_1_68~:594"
+ (rst-re "." 'lin-end)
+ ))
+ (should (re-equal
+ "^[ \t]+"
+ "=== rst.el.~rst_el_1_68~:605"
+ (rst-re 'hws-sta)
+ (cons "^^" "") ;; No need to anchor for looking-at
+ ))
+ (should (re-equal
+ "^[ \t]*$"
+ "=== rst.el.~rst_el_1_68~:744"
+ (rst-re 'lin-end)
+ (cons "^^" "") ;; No need to anchor for looking-at
+ ))
+ (should (re-equal
+ "^[ \t]*$"
+ "=== rst.el.~rst_el_1_68~:1517"
+ (rst-re 'lin-end)
+ (cons "^^" "") ;; No need to anchor for looking-at
+ ))
+ (should (re-equal
+ "^[ \t]*$"
+ "=== rst.el.~rst_el_1_68~:1545"
+ (rst-re 'lin-end)
+ (cons "^^" "") ;; No need to anchor for looking-at
+ ))
+ (should (re-equal
+ "^[ \t]*$"
+ "=== rst.el.~rst_el_1_68~:1548"
+ (rst-re 'lin-end)
+ (cons "^^" "") ;; No need to anchor for looking-at
+ ))
+ (should (re-equal
+ "[0-9]+"
+ "=== rst.el.~rst_el_1_68~:1657"
+ (rst-re 'num-tag)
+ ))
+ (should (re-equal
+ "[IVXLCDMivxlcdm]+"
+ "=== rst.el.~rst_el_1_68~:1661"
+ (rst-re 'rom-tag)
+ ))
+ (should (re-equal
+ "[IVXLCDMivxlcdm]+"
+ "=== rst.el.~rst_el_1_68~:1677"
+ (rst-re 'rom-tag)
+ ))
+ (should (re-equal
+ "[a-zA-Z]"
+ "=== rst.el.~rst_el_1_68~:1685"
+ (rst-re 'ltr-tag)
+ ))
+ (should (re-equal
+ "[ \t\n]*\\'"
+ "=== rst.el.~rst_el_1_68~:1762"
+ (rst-re "[ \t\n]*\\'")
+ ))
+ (should (re-equal
+ "\\S .*\\S "
+ "=== rst.el.~rst_el_1_68~:1767"
+ (rst-re "\\S .*\\S ")
+ ))
+ (should (re-equal
+ "[ \t]*$"
+ "=== rst.el.~rst_el_1_68~:2066"
+ (rst-re 'lin-end)
+ ))
+ (should (re-equal
+ "[ \t]*$"
+ "=== rst.el.~rst_el_1_68~:2366"
+ (rst-re 'lin-end)
+ ))
+ (should (re-equal
+ "^[ \t]*$"
+ "=== rst.el.~rst_el_1_68~:2414"
+ (rst-re 'lin-end)
+ (cons "^^" "") ;; No need to anchor for looking-at
+ ))
+ (should (re-equal
+ "[ \t]*$"
+ "=== rst.el.~rst_el_1_68~:2610"
+ (rst-re 'lin-end)
+ ))
+ (should (re-equal
+ "[ \t]*$"
+ "=== rst.el.~rst_el_1_68~:2612"
+ (rst-re 'lin-end)
+ ))
+ (should (re-equal
+ "[ \t]*$"
+ "=== rst.el.~rst_el_1_68~:2645"
+ (rst-re 'lin-end)
+ ))
+ (should (re-equal
+ "[^ \t]\\|[ \t]*\\.\\.[^ \t]\\|.*::$"
+ "=== rst.el.~rst_el_1_68~:3177"
+ (rst-re '(:alt
+ "[^ \t]"
+ (:seq hws-tag exm-tag "[^ \t]")
+ (:seq ".*" dcl-tag lin-end)))
+ (cons "^" "\\(?:") (cons "$" "\\)") ;; Add outermost shy group
+ (cons "::\\$" "::[ ]*$") ;; Allow trailing space after double
+ ;; colon
+ ))
+ (should (re-equal
+ "\\s *$"
+ "=== rst.el.~rst_el_1_68~:3209"
+ (rst-re 'lin-end)
+ ))
+ (should (re-equal
+ "^\\s *$"
+ "=== rst.el.~rst_el_1_68~:3215"
+ (rst-re 'linemp-tag)
+ ))
+ (should (re-equal
+ "\\s *$"
+ "=== rst.el.~rst_el_1_68~:3253"
+ (rst-re 'lin-end)
+ ))
+ (should (re-equal
+ "\\s *"
+ "=== rst.el.~rst_el_1_68~:3256"
+ (rst-re 'hws-tag)
+ (cons "\\\\s \\*" "[\t ]*") ;; Replace symbolic by real whitespace
+ ))
+ (should (re-equal
+ "\\s *$"
+ "=== rst.el.~rst_el_1_68~:3261"
+ (rst-re 'lin-end)
+ ))
+ (should (re-equal
+ "\\s *"
+ "=== rst.el.~rst_el_1_68~:3268"
+ (rst-re 'hws-tag)
+ (cons "\\\\s \\*" "[\t ]*") ;; Replace symbolic by real whitespace
+ ))
+ (should (re-equal
+ (regexp-quote adornment)
+ "=== rst.el.~rst_el_1_68~:3346"
+ (rst-re (regexp-quote adornment))
+ ))
+ (should (re-equal
+ "\\s *$"
+ "=== rst.el.~rst_el_1_68~:3354"
+ (rst-re 'lin-end)
+ ))
+ (should (re-equal
+ "\\s *$"
+ "=== rst.el.~rst_el_1_68~:3358"
+ (rst-re 'lin-end)
+ ))
+ (should (re-equal
+ "\\s *$"
+ "=== rst.el.~rst_el_1_68~:3374"
+ (rst-re 'lin-end)
+ ))
+ (should (re-equal
+ (concat "\\(" ado-re "\\)\\s *$")
+ "=== rst.el.~rst_el_1_68~:3377"
+ (rst-re (list :grp
+ ado-re)
+ 'lin-end)
+ ))
+ (should (re-equal
+ (concat "\\(" ado-re "\\)\\s *$")
+ "=== rst.el.~rst_el_1_68~:3393"
+ (rst-re (list :grp
+ ado-re)
+ 'lin-end)
+ ))
+ (should (re-equal
+ (concat "^" (regexp-quote (string fromchar)) "+\\( *\\)$")
+ "=== rst.el.~rst_el_1_68~:3590"
+ (rst-re "^" fromchar "+\\( *\\)$")
+ ))
+ (should (re-equal
+ "\f\\|>*[ \t]*$\\|>*[ \t]*[-+*] \\|>*[ \t]*[0-9#]+\\. "
+ "=== rst.el.~rst_el_1_68~:391"
+ (rst-re '(:alt
+ "\f"
+ lin-end
+ (:seq hws-tag itmany-sta-1)))
+ (cons "^" "\\(?:") (cons "$" "\\)") ;; Add outermost shy group
+ (cons (regexp-quote "[-+*] \\|>*[ ]*[0-9#]+\\. ")
+ "\\(\\(?:\\(?:\\(?:[a-zA-Z]\\|[0-9]+\\|[IVXLCDMivxlcdm]+\\|#\\)\\.\\|(?\\(?:[a-zA-Z]\\|[0-9]+\\|[IVXLCDMivxlcdm]+\\|#\\))\\)\\|[-*+\u2022\u2023\u2043]\\)\\)[ ]+"
+ ) ;; Now matches all items
+ (cons ">\\*" "") ;; Remove ">" prefix
+ (cons ">\\*" "") ;; Remove another ">" prefix
+ (cons "\\[\t ]\\+" "\\(?:[\t ]+\\|$\\)") ;; Item tag needs no
+ ;; trailing whitespace
+ ))
+ (should (re-equal
+ (format "[%s]+[ \t]*$" (char-to-string c))
+ "=== rst.el.~rst_el_1_68~:587"
+ (rst-re c "+" 'lin-end)
+ (cons "\\[\\*]" "\\*") ;; Use quoting instead of char class
+ ))
+ (should (re-equal
+ (concat "^"
+ (regexp-quote (make-string len char))
+ "$")
+ "=== rst.el.~rst_el_1_68~:941"
+ (rst-re "^" char (format "\\{%d\\}" len) "$")
+ (cons "\\(\\\\\\+\\)\\{9\\}\\$"
+ "\\{10\\}$") ;; Use regex repeat instead of explicit repeat
+ ))
+ (should (re-equal
+ (format "#.\\|[%s]"
+ (regexp-quote (concat rst-bullets)))
+ "=== rst.el.~rst_el_1_68~:1653"
+ (rst-re '(:alt
+ enmaut-tag
+ bul-tag))
+ (cons "^" "\\(?:") (cons "$" "\\)") ;; Add outermost shy group
+ (cons (regexp-quote "[-\\*\\+]")
+ "[-*+\u2022\u2023\u2043]") ;; Wrongly quoted characters in
+ ;; class and more bullets
+ (cons "#\\." "\\(?:#\\.\\|(?#)\\)") ;; Use all auto enumerators
+ ))
+ (should (re-equal
+ "[a-zA-Z]+"
+ "=== rst.el.~rst_el_1_68~:1672"
+ (rst-re 'ltr-tag)
+ (cons "\\+$" "") ;; Wrong in source
+ ))
+ (should (re-equal
+ rst-re-bullets
+ "=== rst.el.~rst_el_1_68~:1735"
+ (rst-re 'bul-sta)
+ (cons (regexp-quote "[-\\*\\+]")
+ "[-*+\u2022\u2023\u2043]") ;; Wrongly quoted characters in
+ ;; class and more bullets
+ (cons "\\[^ \t]" "") ;; Accept bullets without content
+ (cons "^\\\\(" "") (cons "\\\\)" "") ;; Remove superfluous group
+ (cons "$" "+") ;; Allow more whitespace
+ (cons "\\[\t ]\\+" "\\(?:[\t ]+\\|$\\)") ;; Item tag needs no
+ ;; trailing whitespace
+ ))
+ (should (re-equal
+ "^\\.\\. contents[ \t]*::\\(.*\\)\n\\([ \t]+:\\w+:.*\n\\)*\\.\\."
+ "=== rst.el.~rst_el_1_68~:2056"
+ (rst-re "^" 'exm-sta "contents" 'dcl-tag ".*\n"
+ "\\(?:" 'hws-sta 'fld-tag ".*\n\\)*" 'exm-tag)
+ (cons " contents\\[\t ]\\*"
+ "[\t ]+contents") ;; Any whitespace before but no after
+ (cons "\\\\(\\.\\*\\\\)" ".*") ;; Remove superfluous group
+ (cons "\\\\(" "\\(?:") ;; Make group shy
+ (cons ":\\\\w\\+:" ":\\(?:[^:\n]\\|\\\\:\\)+:") ;; Use improved
+ ;; field tag
+ ))
+ (should (re-equal
+ "[ \t]+[^ \t]"
+ "=== rst.el.~rst_el_1_68~:2065"
+ (rst-re 'hws-sta "\\S ")
+ (cons "\\[^ \t]" "\\S ") ;; Require non-whitespace instead
+ ;; of only non-horizontal whitespace
+ ))
+ ))
+
+(ert-deftest rst-re-refactoring-complicated ()
+ "Try to test complicated refactorings done based on rst_el_1_68."
+ :expected-result :failed ;; These have been reviewed logically and are ok
+ (let* ((rst-bullets
+ '(?- ?* ?+))
+ ;; === rst.el.~rst_el_1_68~:451
+ (rst-re-enumerator "\\(?:[a-zA-Z]\\|[0-9IVXLCDMivxlcdm]+\\)")
+ ;; === rst.el.~rst_el_1_68~:1608
+ (rst-re-enumerations
+ (format "^[ \t]*\\(%s.\\|(?%s)\\)[ \t]"
+ rst-re-enumerator
+ rst-re-enumerator))
+ ;; === rst.el.~rst_el_1_68~:1610
+ (rst-re-items
+ (format "^[ \t]*\\([%s]\\|\\(#\\|%s\\)\\.\\|(?%s)\\)[ \t]"
+ (regexp-quote (concat rst-bullets))
+ rst-re-enumerator
+ rst-re-enumerator))
+ ;; === rst.el.~rst_el_1_68~:1616
+ ;; More parameters
+ (char ?+)
+ )
+ (should (re-equal
+ rst-re-items
+ "=== rst.el.~rst_el_1_68~:2718"
+ (rst-re 'itmany-sta-1)
+ (cons "^^\\[\t ]\\*" "") ;; Wrongly anchored at the beginning of
+ ;; the line
+ (cons (regexp-quote "\\(#\\|\\(?:[a-zA-Z]\\|[0-9IVXLCDMivxlcdm]+\\)\\)")
+ "\\(?:[a-zA-Z]\\|[0-9]+\\|[IVXLCDMivxlcdm]+\\|#\\)"
+ ) ;; Replace counter for "\\."
+ (cons (regexp-quote "\\(?:[a-zA-Z]\\|[0-9IVXLCDMivxlcdm]+\\)")
+ "\\(?:[a-zA-Z]\\|[0-9]+\\|[IVXLCDMivxlcdm]+\\|#\\)"
+ ) ;; Replace counter for "(?)"
+ (cons "$" "+") ;; Allow more whitespace
+ (cons "^\\\\(" "\\(\\(?:") (cons "\\[\t ]\\+$" "\\)[\t ]+"
+ ) ;; Add superfluous shy group
+ (cons (regexp-quote "[-\\*\\+]\\|") "") ;; Remove wrongly quoted
+ ;; characters
+ (cons (regexp-quote "\\)\\)[\t ]+")
+ "\\|[-*+\u2022\u2023\u2043]\\)\\)[\t ]+"
+ ) ;; Re-add bullets
+ ))
+ (should (re-equal
+ rst-re-items
+ "=== rst.el.~rst_el_1_68~:2724"
+ (rst-re 'itmany-beg-1)
+ ))
+ (should (re-equal
+ rst-re-items
+ "=== rst.el.~rst_el_1_68~:1649"
+ (rst-re 'itmany-beg-1)
+ ))
+ (should (re-equal
+ rst-re-enumerations
+ "=== rst.el.~rst_el_1_68~:1671"
+ (rst-re 'enmexp-beg)
+ ))
+ (should (re-equal
+ rst-re-items
+ "=== rst.el.~rst_el_1_68~:1719"
+ (rst-re 'itmany-beg-1)
+ ))
+ (should (re-equal
+ (concat
+ "\\(?:"
+ "\\(\\(?:[0-9a-zA-Z#]\\{1,3\\}[.):-]\\|[*+-]\\)[ \t]+\\)[^ \t\n]"
+ "\\|"
+ (format "\\(%s%s+[ \t]+\\)[^ \t\n]"
+ (regexp-quote (char-to-string char))
+ (regexp-quote (char-to-string char)))
+ "\\)")
+ "=== rst.el.~rst_el_1_68~:2430"
+ (rst-re
+ `(:grp
+ (:alt
+ itmany-tag
+ (:seq ,(char-after) "\\{2,\\}"))
+ hws-sta)
+ "\\S ")
+ (cons "^\\\\(\\?:" "") (cons "\\\\)$" "") ;; Remove superfluous
+ ;; shy group
+ (cons (regexp-quote "[0-9a-zA-Z#]\\{1,3\\}[.):-]\\|[*+-]")
+ "\\(\\(?:\\(?:\\(?:[a-zA-Z]\\|[0-9]+\\|[IVXLCDMivxlcdm]+\\|#\\)\\.\\|(?\\(?:[a-zA-Z]\\|[0-9]+\\|[IVXLCDMivxlcdm]+\\|#\\))\\)\\|[-*+\u2022\u2023\u2043]\\)\\)"
+ ) ;; Replace wrong item tag by correct one
+ (cons (regexp-quote "\\+\\++")
+ "\\+\\{2,\\}") ;; Use regex repeat instead of explicit repeat
+ (cons "\\[^ \t\n]" "\\S ") ;; Use symbolic non-whitespace
+ (cons "\\[^ \t\n]" "\\S ") ;; Use symbolic non-whitespace again
+ (cons "\\\\S " "") ;; Factor out symbolic non-whitespace
+ ))
+ ))
+
+(ert-deftest rst-re-refactoring-font-lock ()
+ "Test the refactorings in font-lock done based on rst_el_1_68."
+ ;; Any comment or string "=== rst.el.~rst_el_1_68~:..." gives the line number
+ ;; of the refactored code in the original file for the previous expression.
+ (let* ((rst-use-char-classes t)
+ (rst-use-unicode t)
+ ;; horizontal white space
+ (re-hws "[\t ]")
+ ;; beginning of line with possible indentation
+ (re-bol (concat "^" re-hws "*"))
+ ;; Separates block lead-ins from their content
+ (re-blksep1 (concat "\\(" re-hws "+\\|$\\)"))
+ ;; explicit markup tag
+ (re-emt "\\.\\.")
+ ;; explicit markup start
+ (re-ems (concat re-emt re-hws "+"))
+ ;; inline markup prefix
+ (re-imp1 (concat "\\(^\\|" re-hws "\\|[-'\"([{<"
+ (if rst-use-unicode
+ "\u2018\u201c\u00ab\u2019"
+ "")
+ "/:]\\)"))
+ ;; inline markup suffix
+ (re-ims1 (concat "\\(" re-hws "\\|[]-'\")}>"
+ (if rst-use-unicode
+ "\u2019\u201d\u00bb"
+ "")
+ "/:.,;!?\\]\\|$\\)"))
+ ;; symbol character
+ (re-sym1 "\\(\\sw\\|\\s_\\)")
+ ;; inline markup content begin
+ (re-imbeg2 "\\(\\S \\|\\S \\([^")
+
+ ;; There seems to be a bug leading to error "Stack overflow in regexp
+ ;; matcher" when "|" or "\\*" are the characters searched for
+ (re-imendbegbeg
+ (if (< emacs-major-version 21)
+ "]"
+ "\\]\\|\\\\."))
+ ;; inline markup content end
+ (re-imendbeg (concat re-imendbegbeg "\\)\\{0,"
+ (format "%d" rst-max-inline-length)
+ "\\}[^\t "))
+ (re-imendend "\\\\]\\)")
+ ;; inline markup content without asterisk
+ (re-ima2 (concat re-imbeg2 "*" re-imendbeg "*" re-imendend))
+ ;; inline markup content without backquote
+ (re-imb2 (concat re-imbeg2 "`" re-imendbeg "`" re-imendend))
+ ;; inline markup content without vertical bar
+ (re-imv2 (concat re-imbeg2 "|" re-imendbeg "|" re-imendend))
+ ;; Supported URI schemes
+ (re-uris1 "\\(acap\\|cid\\|data\\|dav\\|fax\\|file\\|ftp\\|gopher\\|http\\|https\\|imap\\|ldap\\|mailto\\|mid\\|modem\\|news\\|nfs\\|nntp\\|pop\\|prospero\\|rtsp\\|service\\|sip\\|tel\\|telnet\\|tip\\|urn\\|vemmi\\|wais\\)")
+ ;; Line starting with adornment and optional whitespace; complete
+ ;; adornment is in (match-string 1); there must be at least 3
+ ;; characters because otherwise explicit markup start would be
+ ;; recognized
+ (re-ado2 (concat "^\\(\\(["
+ (if rst-use-char-classes
+ "^[:word:][:space:][:cntrl:]"
+ "^\\w \t\x00-\x1F")
+ "]\\)\\2\\2+\\)" re-hws "*$"))
+ )
+ (should (re-equal-matches
+ ;; `Bullet Lists`_
+ (concat re-bol "\\([-*+]" re-blksep1 "\\)")
+ "=== rst.el.~rst_el_1_68~:3011"
+ (rst-re 'lin-beg '(:grp bul-sta))
+ (list "*"
+ (cons 1 1))
+ (cons (regexp-quote "[-*+]")
+ "[-*+\u2022\u2023\u2043]") ;; More bullets
+ (cons "\\\\(\\[\t " "\\(?:[\t ") ;; Make a group shy
+ ))
+ (should (re-equal-matches
+ ;; `Enumerated Lists`_
+ (concat re-bol "\\((?\\(#\\|[0-9]+\\|[A-Za-z]\\|[IVXLCMivxlcm]+\\)[.)]"
+ re-blksep1 "\\)")
+ "=== rst.el.~rst_el_1_68~:3015"
+ (rst-re 'lin-beg '(:grp enmany-sta))
+ (list " (#) Item"
+ (cons 1 1))
+ (cons (regexp-quote
+ "(?\\(#\\|[0-9]+\\|[A-Za-z]\\|[IVXLCMivxlcm]+\\)[.)]")
+ "\\(?:\\(?:[a-zA-Z]\\|[0-9]+\\|[IVXLCDMivxlcdm]+\\|#\\)\\.\\|(?\\(?:[a-zA-Z]\\|[0-9]+\\|[IVXLCDMivxlcdm]+\\|#\\))\\)"
+ ) ;; Enumeration tags are more sophisticated
+ (cons "\\\\(\\[\t " "\\(?:[\t ") ;; Make a group shy
+ ))
+ (should (re-equal-matches
+ ;; `Field Lists`_
+ (concat re-bol "\\(:[^:\n]+:\\)" re-blksep1)
+ "=== rst.el.~rst_el_1_68~:3021"
+ (rst-re 'lin-beg '(:grp fld-tag) 'bli-sfx)
+ (list " :some field: "
+ (cons 1 1))
+ (cons "\\[^:\n]" "\\(?:[^:\n]\\|\\\\:\\)") ;; Field name more
+ ;; sophisticated
+ (cons "\\\\(\\[\t " "\\(?:[\t ") ;; Make a group shy
+ ))
+ (should (re-equal-matches
+ ;; `Option Lists`_
+ (concat re-bol "\\(\\(\\(\\([-+/]\\|--\\)\\sw\\(-\\|\\sw\\)*"
+ "\\([ =]\\S +\\)?\\)\\(,[\t ]\\)?\\)+\\)\\($\\|[\t ]\\{2\\}\\)")
+ "=== rst.el.~rst_el_1_68~:3025"
+ (rst-re 'lin-beg '(:grp opt-tag (:shy optsep-tag opt-tag) "*")
+ '(:alt "$" (:seq hws-prt "\\{2\\}")))
+ (list " --len=length, -l length Explanation"
+ (cons 1 1))
+ (cons (regexp-quote "\\(\\(\\(\\([-+/]\\|--\\)\\sw\\(-\\|\\sw\\)*\\([ =]\\S +\\)?\\)\\(,[ ]\\)?\\)+\\)")
+ "\\(\\(?:\\(?:[-+/]\\|--\\)\\sw\\(?:-\\|\\sw\\)*\\(?:[ =]\\S +\\)?\\)\\(?:\\(?:,[ ]\\)\\(?:\\(?:[-+/]\\|--\\)\\sw\\(?:-\\|\\sw\\)*\\(?:[ =]\\S +\\)?\\)\\)*\\)"
+ ) ;; Option recognition more sophisticated
+ (cons "\\\\(\\$" "\\(?:$") ;; Make a group shy
+ ))
+ (should (re-equal-matches
+ ;; `Line Blocks`_
+ (concat re-bol "\\(|" re-blksep1 "\\)[^|\n]*$")
+ "=== rst.el.~rst_el_1_68~:3030"
+ (rst-re 'lin-beg '(:grp "|" bli-sfx) "[^|\n]*$")
+ (list " | Some text"
+ (cons 1 1))
+ (cons "\\\\(\\[\t " "\\(?:[\t ") ;; Make a group shy
+ ))
+ (should (re-equal-matches
+ ;; `Footnotes`_ / `Citations`_
+ (concat re-bol "\\(" re-ems "\\[[^[\n]+\\]\\)" re-blksep1)
+ "=== rst.el.~rst_el_1_68~:3038"
+ (rst-re 'lin-beg '(:grp exm-sta fnc-tag) 'bli-sfx)
+ (list ".. [#]"
+ (cons 1 1))
+ (cons "\\[^\\[" "[^]") ;; Error correction in old code
+ (cons "\\\\]" "]") ;; Remove superfluous quote
+ (cons "\\\\(\\[\t " "\\(?:[\t ") ;; Make a group shy
+ ))
+ (should (re-equal-matches
+ ;; `Directives`_ / `Substitution Definitions`_
+ (concat re-bol "\\(" re-ems "\\)\\(\\(|[^|\n]+|[\t ]+\\)?\\)\\("
+ re-sym1 "+::\\)" re-blksep1)
+ "=== rst.el.~rst_el_1_68~:3042"
+ (rst-re 'lin-beg '(:grp exm-sta)
+ '(:grp (:shy subdef-tag hws-sta) "?")
+ '(:grp sym-tag dcl-tag) 'bli-sfx)
+ (list ".. |attr| replace:: val"
+ (cons 1 1)
+ (cons 2 2)
+ (cons 4 3))
+ (cons "\\\\(|" "\\(?:|") ;; Make a group shy
+ (cons "\\[^|\n]\\+" "\\(?:\\S \\|\\S \\(?:[^|\\\n]\\|\\\\.\\)\\{0,1000\\}[^ |\\]\\)"
+ ) ;; Symbol name more sophisticated
+ (cons (regexp-quote "\\(\\sw\\|\\s_\\)+")
+ "\\(?:\\sw+\\(?:[-+.:_]\\sw+\\)*\\)") ;; New syntax for
+ ;; symbols
+ (cons "\\\\(\\[\t " "\\(?:[\t ") ;; Make a group shy
+ ))
+ (should (re-equal-matches
+ ;; `Hyperlink Targets`_
+ (concat re-bol "\\(" re-ems "_\\([^:\\`\n]\\|\\\\.\\|`[^`\n]+`\\)+:\\)"
+ re-blksep1)
+ "=== rst.el.~rst_el_1_68~:3049"
+ (rst-re 'lin-beg
+ '(:grp exm-sta "_" (:alt
+ (:seq "`" ilcbkqdef-tag "`")
+ (:seq (:alt "[^:\\\n]" "\\\\.") "+")) ":")
+ 'bli-sfx)
+ (list ".. _`some\\: target`:"
+ (cons 1 1))
+ (cons (regexp-quote "\\([^:\\`\n]\\|\\\\.\\|`[^`\n]+`\\)+")
+ "\\(?:`\\(?:\\S \\|\\S \\(?:[^`\\\n]\\|\\\\.\\)\\{0,1000\\}[^ `\\]\\)`\\|\\(?:[^:\\\n]\\|\\\\.\\)+\\)"
+ ) ;; Hyperlink name recognition more sophisticated
+ (cons "\\\\(\\[\t " "\\(?:[\t ") ;; Make a group shy
+ ))
+ (should (re-equal-matches
+ ;; `Hyperlink Targets`_
+ (concat re-bol "\\(__\\)" re-blksep1)
+ "=== rst.el.~rst_el_1_68~:3053"
+ (rst-re 'lin-beg '(:grp "__") 'bli-sfx)
+ (list " __"
+ (cons 1 1))
+ (cons "\\\\(\\[\t " "\\(?:[\t ") ;; Make a group shy
+ ))
+ (should (re-equal-matches
+ ;; `Strong Emphasis`_
+ (concat re-imp1 "\\(\\*\\*" re-ima2 "\\*\\*\\)" re-ims1)
+ "=== rst.el.~rst_el_1_68~:3062"
+ (rst-re 'ilm-pfx '(:grp "\\*\\*" ilcast-tag "\\*\\*") 'ilm-sfx)
+ (list "abc **def** ghi"
+ (cons 2 1))
+ (cons "^\\\\(" "\\(?:") ;; Make a group shy
+ (cons "\\\\(\\\\S" "\\(?:\\S") ;; Make a group shy
+ (cons "\\\\(\\[^" "\\(?:[^") ;; Make a group shy
+ (cons (regexp-quote "\\\\]") "\\]") ;; Remove superfluous quote
+ (cons (regexp-quote "\\|$") "")
+ (cons (regexp-quote "\\([\t ]")
+ "\\(?:$\\|[\t ]") ;; Move "$" in regex and make a group shy
+ ))
+ (should (re-equal-matches
+ ;; `Emphasis`_
+ (concat re-imp1 "\\(\\*" re-ima2 "\\*\\)" re-ims1)
+ "=== rst.el.~rst_el_1_68~:3066"
+ (rst-re 'ilm-pfx '(:grp "\\*" ilcast-tag "\\*") 'ilm-sfx)
+ (list "*x*"
+ (cons 2 1))
+ (cons "^\\\\(" "\\(?:") ;; Make a group shy
+ (cons "\\\\(\\\\S" "\\(?:\\S") ;; Make a group shy
+ (cons "\\\\(\\[^" "\\(?:[^") ;; Make a group shy
+ (cons (regexp-quote "\\\\]") "\\]") ;; Remove superfluous quote
+ (cons (regexp-quote "\\|$") "")
+ (cons (regexp-quote "\\([\t ]")
+ "\\(?:$\\|[\t ]") ;; Move "$" in regex and make a group shy
+ ))
+ (should (re-equal-matches
+ ;; `Inline Literals`_
+ (concat re-imp1 "\\(``" re-imb2 "``\\)" re-ims1)
+ "=== rst.el.~rst_el_1_68~:3070"
+ (rst-re 'ilm-pfx '(:grp "``" ilcbkq-tag "``") 'ilm-sfx)
+ (list "``co de``"
+ (cons 2 1))
+ (cons "^\\\\(" "\\(?:") ;; Make a group shy
+ (cons "\\\\(\\\\S" "\\(?:\\S") ;; Make a group shy
+ (cons "\\\\(\\[^" "\\(?:[^") ;; Make a group shy
+ (cons (regexp-quote "\\\\]") "\\]") ;; Remove superfluous quote
+ (cons (regexp-quote "\\|$") "")
+ (cons (regexp-quote "\\([\t ]")
+ "\\(?:$\\|[\t ]") ;; Move "$" in regex and make a group shy
+ ))
+ (should (re-equal-matches
+ ;; `Inline Internal Targets`_
+ (concat re-imp1 "\\(_`" re-imb2 "`\\)" re-ims1)
+ "=== rst.el.~rst_el_1_68~:3074"
+ (rst-re 'ilm-pfx '(:grp "_`" ilcbkq-tag "`") 'ilm-sfx)
+ (list "_`Inline\ntarget`"
+ (cons 2 1))
+ (cons "^\\\\(" "\\(?:") ;; Make a group shy
+ (cons "\\\\(\\\\S" "\\(?:\\S") ;; Make a group shy
+ (cons "\\\\(\\[^" "\\(?:[^") ;; Make a group shy
+ (cons (regexp-quote "\\\\]") "\\]") ;; Remove superfluous quote
+ (cons (regexp-quote "\\|$") "")
+ (cons (regexp-quote "\\([\t ]")
+ "\\(?:$\\|[\t ]") ;; Move "$" in regex and make a group shy
+ ))
+ (should (re-equal-matches
+ ;; `Hyperlink References`_
+ (concat re-imp1 "\\(\\(`" re-imb2 "`\\|\\(\\sw\\(\\sw\\|-\\)+\\sw\\)\\)__?\\)" re-ims1)
+ "=== rst.el.~rst_el_1_68~:3079"
+ (rst-re 'ilm-pfx '(:grp (:alt (:seq "`" ilcbkq-tag "`")
+ (:seq "\\sw" (:alt "\\sw" "-") "+\\sw"))
+ "__?") 'ilm-sfx)
+ (list "<`xxx`__>"
+ (cons 2 1))
+ (cons "^\\\\(" "\\(?:") ;; Make a group shy
+ (cons "\\\\(\\\\S" "\\(?:\\S") ;; Make a group shy
+ (cons "\\\\(\\[^" "\\(?:[^") ;; Make a group shy
+ (cons (regexp-quote "\\\\]") "\\]") ;; Remove superfluous quote
+ (cons (regexp-quote "\\|$") "")
+ (cons (regexp-quote "\\([\t ]")
+ "\\(?:$\\|[\t ]") ;; Move "$" in regex and make a group shy
+ (cons "\\\\(`" "\\(?:`") ;; Make a group shy
+ (cons "\\\\(\\\\sw" "\\sw")
+ (cons "\\\\sw\\\\)" "\\sw") ;; Remove a group
+ (cons "sw\\\\(\\\\sw" "sw\\(?:\\sw") ;; Make a group shy
+ ))
+ (should (re-equal-matches
+ ;; `Interpreted Text`_
+ (concat re-imp1 "\\(\\(:" re-sym1 "+:\\)?\\)\\(`" re-imb2 "`\\)\\(\\(:"
+ re-sym1 "+:\\)?\\)" re-ims1)
+ "=== rst.el.~rst_el_1_68~:3083"
+ (rst-re 'ilm-pfx '(:grp (:shy ":" sym-tag ":") "?")
+ '(:grp "`" ilcbkq-tag "`")
+ '(:grp (:shy ":" sym-tag ":") "?") 'ilm-sfx)
+ (list "`Interpreted`"
+ (cons 2 1)
+ (cons 5 2)
+ (cons 8 3))
+ (cons "^\\\\(" "\\(?:") ;; Make a group shy
+ (cons "\\\\(\\\\S" "\\(?:\\S") ;; Make a group shy
+ (cons "\\\\(\\[^" "\\(?:[^") ;; Make a group shy
+ (cons "\\\\(:" "\\(?::") ;; Make a group shy
+ (cons "\\\\(:" "\\(?::") ;; Make a group shy
+ (cons (regexp-quote "\\(\\sw\\|\\s_\\)+")
+ "\\(?:\\sw+\\(?:[-+.:_]\\sw+\\)*\\)") ;; New syntax for
+ ;; symbols
+ (cons (regexp-quote "\\(\\sw\\|\\s_\\)+")
+ "\\(?:\\sw+\\(?:[-+.:_]\\sw+\\)*\\)") ;; New syntax for
+ ;; symbols
+ (cons (regexp-quote "\\\\]") "\\]") ;; Remove superfluous quote
+ (cons (regexp-quote "\\|$") "")
+ (cons (regexp-quote "\\([\t ]")
+ "\\(?:$\\|[\t ]") ;; Move "$" in regex and make a group shy
+ ))
+ (should (re-equal-matches
+ ;; `Footnote References`_ / `Citation References`_
+ (concat re-imp1 "\\(\\[[^]]+\\]_\\)" re-ims1)
+ "=== rst.el.~rst_el_1_68~:3090"
+ (rst-re 'ilm-pfx '(:grp fnc-tag "_") 'ilm-sfx)
+ (list "[1]_"
+ (cons 2 1))
+ (cons "^\\\\(" "\\(?:") ;; Make a group shy
+ (cons "]]" "]\n]") ;; A reference may not contain \n
+ (cons "\\\\]" "]") ;; Remove superfluous quote
+ (cons (regexp-quote "\\|$") "")
+ (cons (regexp-quote "\\([\t ]")
+ "\\(?:$\\|[\t ]") ;; Move "$" in regex and make a group shy
+ ))
+ (should (re-equal-matches
+ ;; `Substitution References`_
+ (concat re-imp1 "\\(|" re-imv2 "|\\)" re-ims1)
+ "=== rst.el.~rst_el_1_68~:3094"
+ (rst-re 'ilm-pfx '(:grp sub-tag) 'ilm-sfx)
+ (list "|attr|"
+ (cons 2 1))
+ (cons "^\\\\(" "\\(?:") ;; Make a group shy
+ (cons "\\\\(\\\\S" "\\(?:\\S") ;; Make a group shy
+ (cons (regexp-quote "\\([^|") "\\(?:[^|") ;; Make a group shy
+ (cons "\\\\]" "]") ;; Remove superfluous quote
+ (cons "\\\\]" "]") ;; Remove superfluous quote
+ (cons "\\[^|]" "[^|\\]") ;; Improve recognition
+ (cons (regexp-quote "\\|$") "")
+ (cons (regexp-quote "\\([\t ]")
+ "\\(?:$\\|[\t ]") ;; Move "$" in regex and make a group shy
+ ))
+ (should (re-equal-matches
+ ;; `Standalone Hyperlinks`_
+ (concat re-imp1 "\\(" re-uris1 ":\\S +\\)" re-ims1)
+ "=== rst.el.~rst_el_1_68~:3099"
+ (rst-re 'ilm-pfx '(:grp uri-tag ":\\S +") 'ilm-sfx)
+ (list "http://example.com/"
+ (cons 2 1))
+ (cons "^\\\\(" "\\(?:") ;; Make a group shy
+ (cons "\\\\(acap" "\\(?:acap") ;; Make a group shy
+ (cons (regexp-quote "\\|$") "")
+ (cons (regexp-quote "\\([\t ]")
+ "\\(?:$\\|[\t ]") ;; Move "$" in regex and make a group shy
+ ))
+ (should (re-equal-matches
+ ;; `Standalone Hyperlinks`_
+ (concat re-imp1 "\\(" re-sym1 "+@" re-sym1 "+\\)" re-ims1)
+ "=== rst.el.~rst_el_1_68~:3102"
+ (rst-re 'ilm-pfx '(:grp sym-tag "@" sym-tag ) 'ilm-sfx)
+ (list "someone@example"
+ (cons 2 1))
+ (cons "^\\\\(" "\\(?:") ;; Make a group shy
+ (cons (regexp-quote "\\(\\sw\\|\\s_\\)+")
+ "\\(?:\\sw+\\(?:[-+.:_]\\sw+\\)*\\)") ;; New syntax for
+ ;; symbols
+ (cons (regexp-quote "\\(\\sw\\|\\s_\\)+")
+ "\\(?:\\sw+\\(?:[-+.:_]\\sw+\\)*\\)") ;; New syntax for
+ ;; symbols
+ (cons (regexp-quote "\\|$") "")
+ (cons (regexp-quote "\\([\t ]")
+ "\\(?:$\\|[\t ]") ;; Move "$" in regex and make a group shy
+ ))
+ (should (re-equal
+ ;; Sections_ / Transitions_
+ re-ado2
+ "=== rst.el.~rst_el_1_68~:3109"
+ (rst-re 'ado-beg-2-1)
+ (cons "\\^\\[:word:]\\[:space:]\\[:cntrl:]"
+ "]!\"#$%&'()*+,./:;<=>?@[\\^_`{|}~-") ;; Use real adornment
+ ;; characters
+ (cons "2\\+" "{2,\\}") ;; Use repeat count
+ ))
+ (should (re-equal
+ ;; `Comments`_
+ (concat re-bol "\\(" re-ems "\\)\[^[|_\n]\\([^:\n]\\|:\\([^:\n]\\|$\\)\\)*$")
+ "=== rst.el.~rst_el_1_68~:3128"
+ (rst-re 'lin-beg '(:grp exm-sta) "[^\[|_\n]"
+ '(:alt "[^:\n]" (:seq ":" (:alt "[^:\n]" "$"))) "*$")
+ (cons "\\\\(\\[^:" "\\(?:[^:") ;; Make a group shy
+ (cons "\\\\(\\[^:" "\\(?:[^:") ;; Make a group shy
+ ))
+ (should (re-equal-matches
+ ;; `Comments`_
+ (concat re-bol "\\(" re-emt "\\)\\(\\s *\\)$")
+ "=== rst.el.~rst_el_1_68~:3135"
+ (rst-re 'lin-beg '(:grp exm-tag) '(:grp hws-tag) "$")
+ (list ".. "
+ (cons 1 1)
+ (cons 2 2))
+ (cons "\\\\s " "[\t ]") ;; Only horizontal space
+ ))
+ (should (re-equal-matches
+ ;; `Literal Blocks`_
+ (concat re-bol "\\(\\([^.\n]\\|\\.[^.\n]\\).*\\)?\\(::\\)$")
+ "=== rst.el.~rst_el_1_68~:3145"
+ (rst-re 'lin-beg '(:shy (:alt "[^.\n]" "\\.[^.\n]") ".*") "?"
+ '(:grp dcl-tag) "$")
+ (list "Some text ::"
+ (cons 3 1))
+ (cons "\\\\(\\\\(" "\\(?:\\(?:") ;; Make two groups shy
+ ))
+ (should (re-equal-matches
+ ;; `Doctest Blocks`_
+ (concat re-bol "\\(>>>\\|\\.\\.\\.\\)\\(.+\\)")
+ "=== rst.el.~rst_el_1_68~:3154"
+ (rst-re 'lin-beg '(:grp (:alt ">>>" ell-tag)) '(:grp ".+"))
+ (list ">>> content"
+ (cons 1 1)
+ (cons 2 2))
+ (cons ">>>" "\\(?:>>>") (cons "\\.\\\\)" ".\\)\\)") ;; Add a shy
+ ;; group
+ ))
+ ))
--- /dev/null
+;; Tests for various functions around shifting text -*- lexical-binding: t -*-
+
+(add-to-list 'load-path ".")
+(load "init" nil t)
+(init-rst-ert t)
+
+(ert-deftest shift-asserts ()
+ "Check some assertions."
+ (should (equal ert-Buf-point-char "\^@"))
+ (should (equal ert-Buf-mark-char "\^?"))
+ )
+
+(defun string-insert (s col char)
+ "Insert CHAR at position COL in S. Return S."
+ (let ((l (length s))
+ (c (char-to-string char)))
+ (if (<= l col)
+ (concat s (make-string (- col l) ? ) c)
+ (concat (substring s 0 col) c (substring s (1+ col))))))
+
+(defun line-tabs ()
+ "Wrapper to call `rst-line-tabs' creating a readable result."
+ (let ((tabs (rst-line-tabs))
+ (s "")
+ (cnt 0)
+ c)
+ (delete-region (point-min) (point-max))
+ (dolist (tab tabs)
+ (setq c (+ ?A cnt))
+ (if (cdr tab) (setq c (+ c (- ?a ?A))))
+ (setq s (string-insert s (car tab) c))
+ (setq cnt (1+ cnt)))
+ (insert "\n" s)))
+
+(ert-deftest rst-line-tabs ()
+ "Tests for `rst-line-tabs'."
+ (let ((rst-indent-width 2)
+ (rst-indent-field 2)
+ (rst-indent-literal-normal 3)
+ (rst-indent-literal-minimized 2)
+ (rst-indent-comment 3))
+ (should (ert-equal-buffer
+ '(line-tabs)
+ "\^@"
+ "
+"
+ ))
+ (should (ert-equal-buffer
+ '(line-tabs)
+ "
+* a\^@"
+ "
+B a"
+ ))
+ (should (ert-equal-buffer
+ '(line-tabs)
+ "
+ * b\^@"
+ "
+ B a"
+ ))
+ (should (ert-equal-buffer
+ '(line-tabs)
+ "
+ XV. c\^@"
+ "
+ B a"
+ ))
+ (should (ert-equal-buffer
+ '(line-tabs)
+ "
+* \^@"
+ "
+A"
+ ))
+ (should (ert-equal-buffer
+ '(line-tabs)
+ "
+ *\tb\^@"
+ "
+ B a"
+ ))
+ (should (ert-equal-buffer
+ '(line-tabs)
+ "Some para\^@"
+ "
+A"
+ ))
+ (should (ert-equal-buffer
+ '(line-tabs)
+ " A quoted block\^@"
+ "
+ A"
+ ))
+ (should (ert-equal-buffer
+ '(line-tabs)
+ "
+:Field: Content on same line\^@"
+ "
+C b a"
+ ))
+ (should (ert-equal-buffer
+ '(line-tabs)
+ "
+:Field: \^@"
+ "
+B a"
+ ))
+ (let ((rst-indent-field 0))
+ (should (ert-equal-buffer
+ '(line-tabs)
+ "
+:Field: Content on same line\^@"
+ "
+B a"
+ ))
+ (should (ert-equal-buffer
+ '(line-tabs)
+ "
+:Field: \^@"
+ "
+B a"
+ )))
+ (should (ert-equal-buffer
+ '(line-tabs)
+ "
+.. dir:: Content on same line\^@"
+ "
+C b a"
+ ))
+ (should (ert-equal-buffer
+ '(line-tabs)
+ "
+.. dir:: \^@"
+ "
+B a"
+ ))
+ (should (ert-equal-buffer
+ '(line-tabs)
+ "
+.. |sub| dir:: Content on same line\^@"
+ "
+D c b a"
+ ))
+ (should (ert-equal-buffer
+ '(line-tabs)
+ "
+.. |sub| dir::\^@"
+ "
+C b a"
+ ))
+ (should (ert-equal-buffer
+ '(line-tabs)
+ "
+.. [CIT] citation\^@"
+ "
+C b a"
+ ))
+ (should (ert-equal-buffer
+ '(line-tabs)
+ "
+.. [#FN] Footnote\^@"
+ "
+C b a"
+ ))
+ (should (ert-equal-buffer
+ '(line-tabs)
+ "
+.. [CIT]\^@"
+ "
+B a"
+ ))
+ (should (ert-equal-buffer
+ '(line-tabs)
+ "
+Some text::\^@"
+ "
+B a"
+ ))
+ (should (ert-equal-buffer
+ '(line-tabs)
+ "
+::\^@"
+ "
+B a"
+ ))
+ (should (ert-equal-buffer
+ '(line-tabs)
+ "
+ ::\^@"
+ "
+ B a"
+ ))
+ (should (ert-equal-buffer
+ '(line-tabs)
+ "
+.. First comment\^@"
+ "
+B a"
+ ))
+ (should (ert-equal-buffer
+ '(line-tabs)
+ "
+ XV. c::\^@"
+ "
+ C b a"
+ ))
+ (should (ert-equal-buffer
+ '(line-tabs)
+ "
+ :f: val::\^@"
+ "
+ D c b a"
+ ))
+ ))
+
+(defun compute-tabs ()
+ "Wrapper to call `rst-compute-tabs' creating a readable result."
+ (let ((tabs (rst-compute-tabs (point)))
+ (s "")
+ (cnt 0))
+ (delete-region (point-min) (point-max))
+ (dolist (tab tabs)
+ (setq s (string-insert s tab (+ ?A cnt)))
+ (setq cnt (1+ cnt)))
+ (insert "\n" s)))
+
+(ert-deftest rst-compute-tabs ()
+ "Tests for `rst-compute-tabs'."
+ (let ((rst-indent-width 2)
+ (rst-indent-field 2)
+ (rst-indent-literal-normal 3)
+ (rst-indent-literal-minimized 2)
+ (rst-indent-comment 3))
+ (should (ert-equal-buffer
+ '(compute-tabs)
+ "\^@"
+ "
+"
+ ))
+ (should (ert-equal-buffer
+ '(compute-tabs)
+ "
+* a
+\^@"
+ "
+B A"
+ ))
+ (should (ert-equal-buffer
+ '(compute-tabs)
+ "
+* a
+ * b
+\^@"
+ "
+C B A"
+ ))
+ (should (ert-equal-buffer
+ '(compute-tabs)
+ "
+* a
+ * b
+ XV. c
+\^@"
+ "
+D C B A"
+ ))
+ (should (ert-equal-buffer
+ '(compute-tabs)
+ "
+* a
+ XV. c
+\^@"
+ "
+D C B A"
+ ))
+ (should (ert-equal-buffer
+ '(compute-tabs)
+ "
+*
+ XV. c
+\^@"
+ "
+C B A"
+ ))
+ (should (ert-equal-buffer
+ '(compute-tabs)
+ "
+* a
+ * b
+ XV. c
+ * d
+\^@"
+ "
+C B A"
+ ))
+ (should (ert-equal-buffer
+ '(compute-tabs)
+ "
+* a
+ * b
+ XV. c
+ * d
+* e
+\^@"
+ "
+B A"
+ ))
+ (should (ert-equal-buffer
+ '(compute-tabs)
+ "
+ * a
+ * b
+ XV. c
+\^@"
+ "
+ D C B A"
+ ))
+ (should (ert-equal-buffer
+ '(compute-tabs)
+ "
+* a
+ *\tb
+\^@"
+ "
+C B A"
+ ))
+ (should (ert-equal-buffer
+ '(compute-tabs)
+ "* a
+\^@"
+ "
+B A"
+ ))
+ (should (ert-equal-buffer
+ '(compute-tabs)
+ " * a
+ * b
+ XV. c
+\^@"
+ "
+ D C B A"
+ ))
+ (should (ert-equal-buffer
+ '(compute-tabs)
+ "Some para
+
+ A quoted block
+
+ Quoting again
+\^@"
+ "
+C B A"
+ ))
+ (should (ert-equal-buffer
+ '(compute-tabs)
+ "
+:Field: Content on same line
+\^@"
+ "
+C B A"
+ ))
+ (should (ert-equal-buffer
+ '(compute-tabs)
+ "
+:Field: Content on same line
+ but continued differently
+\^@"
+ "
+D CA B"
+ ))
+ (should (ert-equal-buffer
+ '(compute-tabs)
+ "
+:Field: Content on same line
+ but continued differently
+\^@"
+ "
+D C B A"
+ ))
+ (should (ert-equal-buffer
+ '(compute-tabs)
+ "
+:Field:
+
+ Content on next line
+\^@"
+ "
+C BA"
+ ))
+ (should (ert-equal-buffer
+ '(compute-tabs)
+ "
+:Field: Starts on same line
+
+ Content on next line
+\^@"
+ "
+C A B"
+ ))
+ (should (ert-equal-buffer
+ '(compute-tabs)
+ "
+.. dir:: Content on same line
+\^@"
+ "
+C B A"
+ ))
+ (should (ert-equal-buffer
+ '(compute-tabs)
+ "
+.. dir::
+
+ Content on next line
+\^@"
+ "
+B A"
+ ))
+ (should (ert-equal-buffer
+ '(compute-tabs)
+ "
+.. dir::
+
+ Content on next line
+\^@"
+ "
+C B A"
+ ))
+ (should (ert-equal-buffer
+ '(compute-tabs)
+ "
+.. dir:: Same
+
+ Content on next line
+\^@"
+ "
+D C A B"
+ ))
+ (should (ert-equal-buffer
+ '(compute-tabs)
+ "
+.. |sub| dir:: Content on same line
+\^@"
+ "
+D C B A"
+ ))
+ (should (ert-equal-buffer
+ '(compute-tabs)
+ "
+.. |sub| dir::
+
+ Content on next line
+\^@"
+ "
+C A B"
+ ))
+ (should (ert-equal-buffer
+ '(compute-tabs)
+ "
+.. |sub| dir::
+
+ Content on next line
+\^@"
+ "
+D C A B"
+ ))
+ (should (ert-equal-buffer
+ '(compute-tabs)
+ "
+.. |sub| dir:: Same
+
+ Content on next line
+\^@"
+ "
+E D A C B"
+ ))
+ (should (ert-equal-buffer
+ '(compute-tabs)
+ "
+.. |sub| dir:: Same
+
+ :par: val
+
+ Content on next line
+\^@"
+ "
+E DC A B"
+ ))
+ (should (ert-equal-buffer
+ '(compute-tabs)
+ "
+.. |sub| dir::
+
+ :par: val
+
+ Content on next line
+\^@"
+ "
+C A B"
+ ))
+ (should (ert-equal-buffer
+ '(compute-tabs)
+ "
+.. |sub| dir:: Same
+
+ :f: val
+
+ Content on next line
+\^@"
+ "
+E DAC B"
+ ))
+ (should (ert-equal-buffer
+ '(compute-tabs)
+ "
+.. |sub| dir:: Same
+
+ :f: val
+
+ Content on next line
+\^@"
+ "
+D A C B"
+ ))
+ (should (ert-equal-buffer
+ '(compute-tabs)
+ "
+.. |sub| dir:: Same
+
+ :f: val
+
+ * Item
+\^@"
+ "
+C B A"
+ ))
+ (should (ert-equal-buffer
+ '(compute-tabs)
+ "
+.. |sub| dir:: Same
+
+ :f: val
+
+ * Item
+
+ 1. Enumerated
+\^@"
+ "
+D C B A"
+ ))
+ (should (ert-equal-buffer
+ '(compute-tabs)
+ "
+.. [CIT] citation
+\^@"
+ "
+C B A"
+ ))
+ (should (ert-equal-buffer
+ '(compute-tabs)
+ "
+.. [#FN] Footnote
+\^@"
+ "
+C B A"
+ ))
+ (should (ert-equal-buffer
+ '(compute-tabs)
+ "
+.. [CIT]
+
+ citation
+\^@"
+ "
+B A"
+ ))
+ (should (ert-equal-buffer
+ '(compute-tabs)
+ "
+.. [CIT]
+
+ citation
+\^@"
+ "
+C B A"
+ ))
+ (should (ert-equal-buffer
+ '(compute-tabs)
+ "
+.. [CIT]
+
+ citation
+
+ .. |sub| dir:: Same
+
+ :f: val
+
+ * Item
+
+ 1. Enumerated
+\^@"
+ "
+E D C B A"
+ ))
+ (should (ert-equal-buffer
+ '(compute-tabs)
+ "
+Some text::
+\^@"
+ "
+B A"
+ ))
+ (should (ert-equal-buffer
+ '(compute-tabs)
+ "
+No text
+
+::
+\^@"
+ "
+B A"
+ ))
+ (should (ert-equal-buffer
+ '(compute-tabs)
+ "
+No text
+
+ ::
+\^@"
+ "
+C B A"
+ ))
+ (should (ert-equal-buffer
+ '(compute-tabs)
+ "
+.. [CIT]
+
+ citation
+
+ .. |sub| dir:: Same
+
+ :f: val
+
+ No text
+
+ ::
+\^@"
+ "
+E D C B A"
+ ))
+ (should (ert-equal-buffer
+ '(compute-tabs)
+ "
+.. First comment
+\^@"
+ "
+B A"
+ ))
+ (should (ert-equal-buffer
+ '(compute-tabs)
+ "
+* a
+ XV. c::
+\^@"
+ "
+E D C B A"
+ ))
+ (should (ert-equal-buffer
+ '(compute-tabs)
+ "
+.. [CIT]
+
+ citation
+
+ .. |sub| dir:: Same
+
+ :f: val::
+\^@"
+ "
+F E D C B A"
+ ))
+ ))
+
+(ert-deftest rst-shift-region-right ()
+ "Tests for `rst-shift-region' to the right."
+ (let ((rst-indent-width 2)) ; Set relevant variables
+ (should (ert-equal-buffer
+ '(rst-shift-region 1)
+ "
+\^@a
+\^?"
+ "
+\^@ a
+\^?"
+ t))
+ (should (ert-equal-buffer
+ '(rst-shift-region 1)
+ "
+\^@ a
+\^?"
+ "
+\^@ a
+\^?"
+ t))
+ (should (ert-equal-buffer
+ '(rst-shift-region 1)
+ "\^@
+a
+b
+\^?"
+ "\^@
+ a
+ b
+\^?"
+ t))
+ (should (ert-equal-buffer
+ '(rst-shift-region 1)
+ "* x
+\^@
+a
+b
+\^?"
+ "* x
+\^@
+ a
+ b
+\^?"
+ t))
+ (should (ert-equal-buffer
+ '(rst-shift-region 1)
+ "* x
+\^@
+ a
+ b
+\^?"
+ "* x
+\^@
+ a
+ b
+\^?"
+ t))
+ (should (ert-equal-buffer
+ '(rst-shift-region 1)
+ "* x
+ * y
+\^@
+ a
+ b
+\^?"
+ "* x
+ * y
+\^@
+ a
+ b
+\^?"
+ t))
+ (should (ert-equal-buffer
+ '(rst-shift-region 1)
+ "* x
+\^?
+a
+b
+\^@"
+ "* x
+\^?
+ a
+ b
+\^@"
+ t))
+ (should (ert-equal-buffer
+ '(rst-shift-region 2)
+ "* x
+\^?
+a
+b
+\^@"
+ "* x
+\^?
+ a
+ b
+\^@"
+ t))
+ ))
+
+(ert-deftest rst-shift-region-left ()
+ "Tests for `rst-shift-region' to the left."
+ (let ((rst-indent-width 2)) ; Set relevant variables
+ (should (ert-equal-buffer
+ '(rst-shift-region -1)
+ "* x
+\^@
+ a
+ b
+\^?"
+ "* x
+\^@
+ a
+ b
+\^?"
+ t))
+ (should (ert-equal-buffer
+ '(rst-shift-region -1)
+ "
+\^@ a
+\^?"
+ "
+\^@a
+\^?"
+ t))
+ (should (ert-equal-buffer
+ '(rst-shift-region -1)
+ "
+\^@ a
+\^?"
+ "
+\^@ a
+\^?"
+ t))
+ (should (ert-equal-buffer
+ '(rst-shift-region -1)
+ "\^@
+ a
+ b
+\^?"
+ "\^@
+a
+b
+\^?"
+ t))
+ (should (ert-equal-buffer
+ '(rst-shift-region -1)
+ "* x
+\^@
+ a
+ b
+\^?"
+ "* x
+\^@
+a
+b
+\^?"
+ t))
+ (should (ert-equal-buffer
+ '(rst-shift-region -1)
+ "* x
+ * y
+\^@
+ a
+ b
+\^?"
+ "* x
+ * y
+\^@
+ a
+ b
+\^?"
+ t))
+ (should (ert-equal-buffer
+ '(rst-shift-region -1)
+ "* x
+\^?
+ a
+ b
+\^@"
+ "* x
+\^?
+a
+b
+\^@"
+ t))
+ (should (ert-equal-buffer
+ '(rst-shift-region 0)
+ "* x
+ * y
+\^@
+ a
+ b
+\^?"
+ "* x
+ * y
+\^@
+a
+b
+\^?"
+ t))
+ (should (ert-equal-buffer
+ '(rst-shift-region -1)
+ "\^@* x
+ * y
+
+ a
+ b
+\^?"
+ "\^@* x
+ * y
+
+ a
+ b
+\^?"
+ t))
+ (should (ert-equal-buffer
+ '(rst-shift-region -2)
+ "* x
+ * y
+\^@
+ a
+ b
+\^?"
+ "* x
+ * y
+\^@
+ a
+ b
+\^?"
+ t))
+ ))
--- /dev/null
+;; Tests for operations on toc -*- lexical-binding: t -*-
+
+(add-to-list 'load-path ".")
+(load "init" nil t)
+(init-rst-ert t)
+
+(ert-deftest toc-asserts ()
+ "Check some assertions."
+ (should (equal ert-Buf-point-char "\^@"))
+ (should (equal ert-Buf-mark-char "\^?"))
+ )
+
+(setq title "=====
+Title
+=====
+
+"
+ headers "Header A
+========
+
+Header B
+========
+
+Subheader B.a
+-------------
+
+SubSubheader B.a.1
+~~~~~~~~~~~~~~~~~~
+
+Subheader B.b
+-------------
+
+Header C
+========")
+
+(ert-deftest rst-toc-insert ()
+ "Tests `rst-toc-insert'."
+ ;; Set customizable variables to defaults
+ (let ((rst-toc-indent 2)
+ (rst-toc-insert-style 'fixed)
+ (rst-toc-insert-number-separator " - ")
+ (rst-toc-insert-max-level nil)
+ (indent-tabs-mode nil))
+ (should (ert-equal-buffer
+ '(rst-toc-insert)
+ ""
+ t))
+ ;; Can't identify a title so do nothing - that's actually a (MIS-)FEATURE
+ (should (ert-equal-buffer
+ '(rst-toc-insert)
+ (concat "\^@" headers)
+ t))
+ ;; Can't identify a title so do nothing - that's actually a (MIS-)FEATURE
+ (should (ert-equal-buffer
+ (rst-toc-insert)
+ (concat "\^@\n" headers)
+ t))
+ ;; Won't work on a section title
+ (should (ert-equal-buffer
+ '(rst-toc-insert)
+ (concat title "\^@" headers)
+ t))
+ ;; No indentation
+ (let ((rst-toc-indent 1))
+ (should (ert-equal-buffer
+ '(rst-toc-insert)
+ (concat title "\^@THIS IS DELETED\n\n" headers)
+ (concat title "1 - Header A
+2 - Header B
+ 2.1 - Subheader B.a
+ 2.1.1 - SubSubheader B.a.1
+ 2.2 - Subheader B.b
+3 - Header C\^@
+
+" headers))))
+ ;; Indentation
+ (let ((rst-toc-insert-style 'listed)
+ (rst-preferred-bullets '(?+))
+ (rst-toc-indent 1))
+ (should (ert-equal-buffer
+ '(rst-toc-insert)
+ (concat title " \^@\n\n" headers)
+ (concat title " + Header A
+ + Header B
+ + Subheader B.a
+ + SubSubheader B.a.1
+ + Subheader B.b
+ + Header C\^@
+
+" headers))))
+ ;; Only first level
+ (let ((rst-toc-insert-style 'plain))
+ (should (ert-equal-buffer
+ '(rst-toc-insert 1)
+ (concat title " \^@\n\n" headers)
+ (concat title " Header A
+ Header B
+ Header C\^@
+
+" headers))))
+ ;; Prefix and indentation
+ (let ((rst-toc-insert-style 'aligned)
+ (headers-add "
+
+C_1
+---
+
+C_2
+---
+
+C_3
+---
+
+C_4
+---
+
+C_5
+---
+
+C_6
+---
+
+C_7
+---
+
+C_8
+---
+
+C_9
+---
+
+C_10
+----
+"))
+ (should (ert-equal-buffer
+ '(rst-toc-insert)
+ (concat title ".. \^@\n\n" headers headers-add)
+ (concat title ".. 1 - Header A
+ 2 - Header B
+ 2.1 - Subheader B.a
+ 2.1.1 - SubSubheader B.a.1
+ 2.2 - Subheader B.b
+ 3 - Header C
+ 3. 1 - C_1
+ 3. 2 - C_2
+ 3. 3 - C_3
+ 3. 4 - C_4
+ 3. 5 - C_5
+ 3. 6 - C_6
+ 3. 7 - C_7
+ 3. 8 - C_8
+ 3. 9 - C_9
+ 3.10 - C_10\^@
+
+" headers headers-add))))
+ )
+ )
+
+(ert-deftest rst-toc-update ()
+ "Tests `rst-toc-update'."
+ (let ((contents ".. contents:: Inhalt\n")
+ (fields " :bla: blub\n :local:\n")
+ (old ".. 1 Header A
+ 2 Header B
+ 3 Header C")
+ (new "..
+ 1 Header A
+ 2 Header B
+ 2.1 Subheader B.a
+ 2.1.1 SubSubheader B.a.1
+ 2.2 Subheader B.b
+ 3 Header C")
+ (indent-tabs-mode nil))
+ ;; Set customizable variables to defaults
+ (let ((rst-toc-indent 2)
+ (rst-toc-insert-style 'fixed)
+ (rst-toc-insert-number-separator " ")
+ (rst-toc-insert-max-level nil))
+ (should (ert-equal-buffer
+ '(rst-toc-update)
+ (concat title contents fields old "\n\n" headers "\^@")
+ (concat title contents fields new "\n\n" headers "\^@")))
+ (should (ert-equal-buffer
+ '(rst-toc-update)
+ (concat title contents old "\n\n" headers "\^@")
+ (concat title contents new "\n\n" headers "\^@")))
+ (should (ert-equal-buffer
+ '(rst-toc-update)
+ (concat title contents ".." "\n\n" headers "\^@")
+ (concat title contents new "\n\n" headers "\^@")))
+ (should (ert-equal-buffer
+ '(rst-toc-update)
+ (concat title contents ".." "\^@")
+ (concat title contents ".." "\^@")))
+ )
+ ))
+
+(defun toc ()
+ "Call `rst-toc' and copy special buffer to target buffer.
+Return line number link is pointing to in original buffer or nil for no link."
+ (rst-toc)
+ (let ((txt (buffer-substring-no-properties (point-min) (point-max)))
+ (pt (point))
+ (mrk (mark t))
+ (lnk (condition-case nil
+ (progn
+ (rst-toc-mode-follow-link-kill)
+ t)
+ (error nil))))
+ (setq lnk (and lnk (line-number-at-pos)))
+ (delete-region (point-min) (point-max))
+ (insert txt)
+ (set-mark mrk)
+ (goto-char pt)
+ lnk))
+
+(ert-deftest rst-toc ()
+ "Tests `rst-toc'."
+ ;; Set customizable variables to defaults
+ (let ((rst-toc-indent 2)
+ (indent-tabs-mode nil))
+ (should (ert-equal-buffer
+ '(toc)
+ "No section title at all
+\^@"
+ "\^@"
+ ))
+ (should (ert-equal-buffer-return
+ '(toc)
+ (concat title headers "\n\^@")
+ "Title
+ Header A
+ Header B
+ Subheader B.a
+ SubSubheader B.a.1
+ Subheader B.b
+\^@ Header C
+"
+ 20))
+ (should (ert-equal-buffer-return
+ '(toc)
+ (concat title "Header A
+========
+
+Header B
+========
+
+Subh\^@eader B.a
+-------------
+
+SubSubheader B.a.1
+~~~~~~~~~~~~~~~~~~
+
+Subheader B.b
+-------------
+
+Header C
+========
+")
+ "Title
+ Header A
+ Header B
+\^@ Subheader B.a
+ SubSubheader B.a.1
+ Subheader B.b
+ Header C
+"
+ 11))
+ (should (ert-equal-buffer-return
+ '(toc)
+ (concat "\^@\n\n" title headers "\n")
+ "\^@Title
+ Header A
+ Header B
+ Subheader B.a
+ SubSubheader B.a.1
+ Subheader B.b
+ Header C
+"
+ 4))
+ (should (ert-equal-buffer-return
+ '(toc)
+ (concat title "Header A
+========
+
+Header B
+========
+
+Subheader B.a
+-------------
+
+SubSubheader B.a.1
+~~~~~~~~~~~~~~~~~~
+\^@
+Subheader B.b
+-------------
+
+Header C
+========
+")
+ "Title
+ Header A
+ Header B
+ Subheader B.a
+\^@ SubSubheader B.a.1
+ Subheader B.b
+ Header C
+"
+ 14))
+ ))
+
+(defun toc-follow (level)
+ (rst-toc-insert level)
+ (back-to-indentation)
+ (call-interactively #'rst-toc-follow-link))
+
+(ert-deftest rst-toc-follow-link ()
+ "Tests `rst-toc-follow-link'."
+ (let ((rst-toc-insert-style 'plain))
+ (should-error (ert-equal-buffer
+ '(toc-follow 1)
+ ""
+ "")
+ :type 'error)
+ (should (ert-equal-buffer
+ '(toc-follow 1)
+ (concat title " \^@\n\n" headers)
+ (concat title " Header A
+ Header B
+ Header C
+
+Header A
+========
+
+Header B
+========
+
+Subheader B.a
+-------------
+
+SubSubheader B.a.1
+~~~~~~~~~~~~~~~~~~
+
+Subheader B.b
+-------------
+
+\^@Header C
+========")))
+ ))
+
+(defun toc-mode-return (kill)
+ (rst-toc)
+ (rst-toc-mode-return kill)
+ (let ((buf (get-buffer rst-toc-buffer-name)))
+ (when buf
+ (kill-buffer buf)
+ t)))
+
+(ert-deftest rst-toc-mode-return ()
+ "Tests `rst-toc-mode-return'."
+ (should-error (ert-equal-buffer
+ '(rst-toc-mode-return)
+ ""
+ t)
+ :type 'error)
+ (should (ert-equal-buffer-return
+ '(toc-mode-return nil)
+ (concat title " \^@\n\n" headers)
+ t
+ t))
+ (should (ert-equal-buffer-return
+ '(toc-mode-return t)
+ (concat title " \^@\n\n" headers)
+ t
+ nil))
+ )
--- /dev/null
+;; Tests for `rst-all-stn' and relatives -*- lexical-binding: t -*-
+
+(add-to-list 'load-path ".")
+(load "init" nil t)
+(init-rst-ert t)
+
+(ert-deftest toc-asserts ()
+ "Check some assertions."
+ (should (equal ert-Buf-point-char "\^@"))
+ (should (equal ert-Buf-mark-char "\^?"))
+ )
+
+(ert-deftest rst-all-stn ()
+ "Tests `rst-all-stn'."
+ (let* ((title "=====
+Title
+=====
+
+")
+ (headers "Header A
+========
+
+Header B
+========
+
+Subheader B.a
+-------------
+
+SubSubheader B.a.1
+~~~~~~~~~~~~~~~~~~
+
+Header C
+========
+
+Missing node C.a.1
+~~~~~~~~~~~~~~~~~~
+")
+ (ado-T (rst-Ado-new-over-and-under ?=))
+ (ttl-T (rst-Ttl--new ado-T '(1 18 1 6 7 12 13 18) 0
+ "Title"))
+ (ado-A (rst-Ado-new-simple ?=))
+ (ttl-A (rst-Ttl--new ado-A '(20 37 nil nil 20 28 29 37) 0
+ "Header A"))
+ (ttl-B (rst-Ttl--new ado-A '(39 56 nil nil 39 47 48 56) 0
+ "Header B"))
+ (ado-Ba (rst-Ado-new-simple ?-))
+ (ttl-Ba (rst-Ttl--new ado-Ba '(58 85 nil nil 58 71 72 85) 0
+ "Subheader B.a"))
+ (ado-Ba1 (rst-Ado-new-simple ?~))
+ (ttl-Ba1 (rst-Ttl--new ado-Ba1 '(87 124 nil nil 87 105 106 124) 0
+ "SubSubheader B.a.1"))
+ (ttl-C (rst-Ttl--new ado-A '(126 143 nil nil 126 134 135 143) 0
+ "Header C"))
+ (ttl-Ca nil)
+ (ttl-Ca1 (rst-Ttl--new ado-Ba1 '(145 182 nil nil 145 163 164 182) 0
+ "Missing node C.a.1")))
+ (let* ((stn-Ca (rst-Stn-new
+ ttl-Ca 2
+ (list (rst-Stn-new ttl-Ca1 3 nil))))
+ (stn-C (rst-Stn-new
+ ttl-C 1
+ (list stn-Ca)))
+ (stn-A (rst-Stn-new ttl-A 1 nil))
+ (stn-B (rst-Stn-new
+ ttl-B 1
+ (list (rst-Stn-new
+ ttl-Ba 2
+ (list (rst-Stn-new ttl-Ba1 3 nil))))))
+ (stn-T (rst-Stn-new
+ ttl-T 0
+ (list stn-A
+ stn-B
+ stn-C))))
+ (should (ert-equal-buffer-return
+ '(rst-all-stn)
+ ""
+ t
+ nil
+ ))
+ (should (ert-equal-buffer-return
+ '(rst-all-stn)
+ title
+ t
+ (rst-Stn-new
+ nil -1
+ (list (rst-Stn-new ttl-T 0 nil)))
+ ))
+ (should (ert-equal-buffer-return
+ '(rst-all-stn)
+ (concat title headers)
+ t
+ (rst-Stn-new
+ nil -1
+ (list stn-T))
+ ))
+ )))
+
+(ert-deftest rst-stn-containing-point ()
+ "Tests `rst-stn-containing-point'."
+ (let* (;; "
+ ;; =====
+ ;; Title
+ ;; =====
+ ;;
+ ;; Header A
+ ;; ========
+ ;;
+ ;; Header B
+ ;; ========
+ ;;
+ ;; Subheader B.a
+ ;; -------------
+ ;;
+ ;; SubSubheader B.a.1
+ ;; ~~~~~~~~~~~~~~~~~~
+ ;;
+ ;; Subheader B.b
+ ;; -------------
+ ;;
+ ;; Header C
+ ;; ========
+ ;;
+ ;; Missing node C.a.1
+ ;; ~~~~~~~~~~~~~~~~~~
+ ;; "
+ (title "=====
+Title
+=====
+
+")
+ (ado-T (rst-Ado-new-over-and-under ?=))
+ (ttl-T (rst-Ttl--new ado-T '(1 18 1 6 7 12 13 18) 0
+ "Title"))
+ (ado-A (rst-Ado-new-simple ?=))
+ (ttl-A (rst-Ttl--new ado-A '(20 37 nil nil 20 28 29 37) 0
+ "Header A"))
+ (ttl-B (rst-Ttl--new ado-A '(39 56 nil nil 39 47 48 56) 0
+ "Header B"))
+ (ado-Ba (rst-Ado-new-simple ?-))
+ (ttl-Ba (rst-Ttl--new ado-Ba '(58 85 nil nil 58 71 72 85) 0
+ "Subheader B.a"))
+ (ado-Ba1 (rst-Ado-new-simple ?~))
+ (ttl-Ba1 (rst-Ttl--new ado-Ba1 '(87 124 nil nil 87 105 106 124) 0
+ "SubSubheader B.a.1"))
+ (ttl-Bb (rst-Ttl--new ado-Ba '(126 153 nil nil 126 139 140 153) 0
+ "Subheader B.b"))
+ (ttl-C (rst-Ttl--new ado-A '(155 172 nil nil 155 163 164 172) 0
+ "Header C"))
+ (ttl-Ca nil)
+ (ttl-Ca1 (rst-Ttl--new ado-Ba1 '(164 211 nil nil 164 192 193 211) 0
+ "Missing node C.a.1")))
+ (let* ((stn-Ca (rst-Stn-new
+ ttl-Ca 2
+ (list (rst-Stn-new ttl-Ca1 3 nil))))
+ (stn-C (rst-Stn-new
+ ttl-C 1
+ (list stn-Ca)))
+ (stn-A (rst-Stn-new ttl-A 1 nil))
+ (stn-Ba (rst-Stn-new
+ ttl-Ba 2
+ (list (rst-Stn-new ttl-Ba1 3 nil))))
+ (stn-Bb (rst-Stn-new ttl-Bb 2 nil))
+ (stn-B (rst-Stn-new
+ ttl-B 1
+ (list stn-Ba
+ stn-Bb)))
+ (stn-T (rst-Stn-new
+ ttl-T 0
+ (list stn-A
+ stn-B
+ stn-C))))
+ (should (ert-equal-buffer-return
+ '(rst-stn-containing-point (rst-all-stn))
+ "\^@"
+ t
+ nil
+ ))
+ (should (ert-equal-buffer-return
+ '(rst-stn-containing-point (rst-all-stn))
+ (concat "\^@" title)
+ t
+ nil
+ ))
+ (should (ert-equal-buffer-return
+ '(rst-stn-containing-point (rst-all-stn))
+ (concat title "\^@")
+ t
+ (rst-Stn-new ttl-T 0 nil)
+ ))
+ (should (ert-equal-buffer-return
+ '(rst-stn-containing-point (rst-all-stn))
+ (concat title "\^@Header A
+========
+
+Header B
+========
+
+Subheader B.a
+-------------
+
+SubSubheader B.a.1
+~~~~~~~~~~~~~~~~~~
+
+Subheader B.b
+-------------
+
+Header C
+========")
+ t
+ stn-A
+ ))
+ (should (ert-equal-buffer-return
+ '(rst-stn-containing-point (rst-all-stn))
+ (concat title "Header A
+========
+
+Header B
+========
+\^@
+Subheader B.a
+-------------
+
+SubSubheader B.a.1
+~~~~~~~~~~~~~~~~~~
+
+Subheader B.b
+-------------
+
+Header C
+========")
+ t
+ stn-B
+ ))
+ (should (ert-equal-buffer-return
+ '(rst-stn-containing-point (rst-all-stn))
+ (concat title "Header A
+========
+
+Header B
+========
+
+Subheader B.a\^@
+-------------
+
+SubSubheader B.a.1
+~~~~~~~~~~~~~~~~~~
+
+Subheader B.b
+-------------
+
+Header C
+========")
+ t
+ stn-Ba
+ ))
+ (should (ert-equal-buffer-return
+ '(rst-stn-containing-point (rst-all-stn))
+ (concat title "Header A
+========
+
+Header B
+========
+
+Subheader B.a
+-------------
+
+SubSubheader B.a.1
+~~~~~~~~~~~~~~~~~~
+
+S\^@ubheader B.b
+-------------
+
+Header C
+========")
+ t
+ stn-Bb
+ ))
+ )))
--- /dev/null
+#!/usr/bin/env python
+
+# $Id: quicktest.py 8346 2019-08-26 12:11:32Z milde $
+# Authors: Garth Kidd <garth@deadlybloodyserious.com>;
+# David Goodger <goodger@python.org>
+# Copyright: This module has been placed in the public domain.
+
+from __future__ import print_function
+try:
+ import locale
+ locale.setlocale(locale.LC_ALL, '')
+except:
+ pass
+
+import sys
+import os
+import getopt
+import docutils
+from docutils.frontend import OptionParser
+from docutils.utils import new_document
+from docutils.parsers.rst import Parser
+
+
+usage_header = """\
+quicktest.py: Quickly test the reStructuredText parser. This is not an
+interface to the full functionality of Docutils. Use one of the ``rst2*.py``
+front-end tools instead.
+
+Usage::
+
+ quicktest.py [options] [<source> [<destination>]]
+
+``source`` is the name of the file to use as input (default is stdin).
+``destination`` is the name of the file to create as output (default is
+stdout).
+
+Options:
+"""
+
+options = [('pretty', 'p',
+ 'output pretty pseudo-xml: no "&abc;" entities (default)'),
+ ('test', 't', 'output test-ready data (input & expected output, '
+ 'ready to be copied to a parser test module)'),
+ ('rawxml', 'r', 'output raw XML'),
+ ('styledxml=', 's', 'output raw XML with XSL style sheet '
+ 'reference (filename supplied in the option argument)'),
+ ('xml', 'x', 'output pretty XML (indented)'),
+ ('attributes', 'A', 'dump document attributes after processing'),
+ ('debug', 'd', 'debug mode (lots of output)'),
+ ('version', 'V', 'show Docutils version then exit'),
+ ('help', 'h', 'show help text then exit')]
+"""See ``distutils.fancy_getopt.FancyGetopt.__init__`` for a description of
+the data structure: (long option, short option, description)."""
+
+def usage():
+ print(usage_header)
+ for longopt, shortopt, description in options:
+ if longopt[-1:] == '=':
+ opts = '-%s arg, --%sarg' % (shortopt, longopt)
+ else:
+ opts = '-%s, --%s' % (shortopt, longopt)
+ sys.stdout.write('%-15s' % opts)
+ if len(opts) > 14:
+ sys.stdout.write('%-16s' % '\n')
+ while len(description) > 60:
+ limit = description.rindex(' ', 0, 60)
+ print(description[:limit].strip())
+ description = description[limit + 1:]
+ sys.stdout.write('%-15s' % ' ')
+ print(description)
+
+def _pretty(input, document, optargs):
+ return document.pformat()
+
+def _rawxml(input, document, optargs):
+ return document.asdom().toxml()
+
+def _styledxml(input, document, optargs):
+ docnode = document.asdom().childNodes[0]
+ return '%s\n%s\n%s' % (
+ '<?xml version="1.0" encoding="ISO-8859-1"?>',
+ '<?xml-stylesheet type="text/xsl" href="%s"?>'
+ % optargs['styledxml'], docnode.toxml())
+
+def _prettyxml(input, document, optargs):
+ return document.asdom().toprettyxml(' ', '\n')
+
+def _test(input, document, optargs):
+ tq = '"""'
+ output = document.pformat() # same as _pretty()
+ return """\
+ totest['change_this_test_name'] = [
+[%s\\
+%s
+%s,
+%s\\
+%s
+%s],
+]
+""" % ( tq, escape(input.rstrip()), tq, tq, escape(output.rstrip()), tq )
+
+def escape(text):
+ """
+ Return `text` in triple-double-quoted Python string form.
+ """
+ text = text.replace('\\', '\\\\') # escape backslashes
+ text = text.replace('"""', '""\\"') # break up triple-double-quotes
+ text = text.replace(' \n', ' \\n\\\n') # protect trailing whitespace
+ return text
+
+_outputFormatters = {
+ 'rawxml': _rawxml,
+ 'styledxml': _styledxml,
+ 'xml': _prettyxml,
+ 'pretty' : _pretty,
+ 'test': _test
+ }
+
+def format(outputFormat, input, document, optargs):
+ formatter = _outputFormatters[outputFormat]
+ return formatter(input, document, optargs)
+
+def getArgs():
+ if os.name == 'mac' and len(sys.argv) <= 1:
+ return macGetArgs()
+ else:
+ return posixGetArgs(sys.argv[1:])
+
+def posixGetArgs(argv):
+ outputFormat = 'pretty'
+ # convert fancy_getopt style option list to getopt.getopt() arguments
+ shortopts = ''.join([option[1] + ':' * (option[0][-1:] == '=')
+ for option in options if option[1]])
+ longopts = [option[0] for option in options if option[0]]
+ try:
+ opts, args = getopt.getopt(argv, shortopts, longopts)
+ except getopt.GetoptError:
+ usage()
+ sys.exit(2)
+ optargs = {'debug': 0, 'attributes': 0}
+ for o, a in opts:
+ if o in ['-h', '--help']:
+ usage()
+ sys.exit()
+ elif o in ['-V', '--version']:
+ sys.stderr.write('quicktest.py (Docutils %s%s)\n' %
+ (docutils.__version__,
+ docutils.__version_details__ and
+ ' [%s]'%docutils.__version_details__ or ''))
+ sys.exit()
+ elif o in ['-r', '--rawxml']:
+ outputFormat = 'rawxml'
+ elif o in ['-s', '--styledxml']:
+ outputFormat = 'styledxml'
+ optargs['styledxml'] = a
+ elif o in ['-x', '--xml']:
+ outputFormat = 'xml'
+ elif o in ['-p', '--pretty']:
+ outputFormat = 'pretty'
+ elif o in ['-t', '--test']:
+ outputFormat = 'test'
+ elif o in ['--attributes', '-A']:
+ optargs['attributes'] = 1
+ elif o in ['-d', '--debug']:
+ optargs['debug'] = 1
+ else:
+ raise getopt.GetoptError("getopt should have saved us!")
+ if len(args) > 2:
+ print('Maximum 2 arguments allowed.')
+ usage()
+ sys.exit(1)
+ inputFile = sys.stdin
+ outputFile = sys.stdout
+ if args:
+ inputFile = open(args.pop(0))
+ if args:
+ outputFile = open(args.pop(0), 'w')
+ return inputFile, outputFile, outputFormat, optargs
+
+def macGetArgs():
+ import EasyDialogs
+ EasyDialogs.Message("""\
+Use the next dialog to build a command line:
+
+1. Choose an output format from the [Option] list
+2. Click [Add]
+3. Choose an input file: [Add existing file...]
+4. Save the output: [Add new file...]
+5. [OK]""")
+ optionlist = [(longopt, description)
+ for (longopt, shortopt, description) in options]
+ argv = EasyDialogs.GetArgv(optionlist=optionlist, addfolder=0)
+ return posixGetArgs(argv)
+
+def main():
+ # process cmdline arguments:
+ inputFile, outputFile, outputFormat, optargs = getArgs()
+ settings = OptionParser(components=(Parser,)).get_default_values()
+ settings.debug = optargs['debug']
+ parser = Parser()
+ input = inputFile.read()
+ document = new_document(inputFile.name, settings)
+ parser.parse(input, document)
+ output = format(outputFormat, input, document, optargs)
+ outputFile.write(output)
+ if optargs['attributes']:
+ import pprint
+ pprint.pprint(document.__dict__)
+
+
+if __name__ == '__main__':
+ sys.stderr = sys.stdout
+ main()
--- /dev/null
+#!/usr/bin/env python
+
+# $Id: rst2html.py 4564 2006-05-21 20:44:42Z wiemann $
+# Author: David Goodger <goodger@python.org>
+# Copyright: This module has been placed in the public domain.
+
+"""
+A minimal front end to the Docutils Publisher, producing HTML.
+"""
+
+try:
+ import locale
+ locale.setlocale(locale.LC_ALL, '')
+except:
+ pass
+
+from docutils.core import publish_cmdline, default_description
+
+
+description = ('Generates (X)HTML documents from standalone reStructuredText '
+ 'sources. ' + default_description)
+
+publish_cmdline(writer_name='html', description=description)
--- /dev/null
+#!/usr/bin/env python
+
+# $Id: rst2html4.py 7994 2016-12-10 17:41:45Z milde $
+# Author: David Goodger <goodger@python.org>
+# Copyright: This module has been placed in the public domain.
+
+"""
+A minimal front end to the Docutils Publisher, producing (X)HTML.
+
+The output conforms to XHTML 1.0 transitional
+and almost to HTML 4.01 transitional (except for closing empty tags).
+"""
+
+try:
+ import locale
+ locale.setlocale(locale.LC_ALL, '')
+except:
+ pass
+
+from docutils.core import publish_cmdline, default_description
+
+
+description = ('Generates (X)HTML documents from standalone reStructuredText '
+ 'sources. ' + default_description)
+
+publish_cmdline(writer_name='html4', description=description)
--- /dev/null
+#!/usr/bin/env python
+# -*- coding: utf8 -*-
+# :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
+#
+# Revision: $Revision: 8410 $
+# Date: $Date: 2019-11-04 22:14:43 +0100 (Mo, 04. Nov 2019) $
+
+"""
+A minimal front end to the Docutils Publisher, producing HTML 5 documents.
+
+The output also conforms to XHTML 1.0 transitional
+(except for the doctype declaration).
+"""
+
+try:
+ import locale # module missing in Jython
+ locale.setlocale(locale.LC_ALL, '')
+except locale.Error:
+ pass
+
+from docutils.core import publish_cmdline, default_description
+
+description = (u'Generates HTML 5 documents from standalone '
+ u'reStructuredText sources '
+ + default_description)
+
+publish_cmdline(writer_name='html5', description=description)
--- /dev/null
+#!/usr/bin/env python
+
+# $Id: rst2latex.py 5905 2009-04-16 12:04:49Z milde $
+# Author: David Goodger <goodger@python.org>
+# Copyright: This module has been placed in the public domain.
+
+"""
+A minimal front end to the Docutils Publisher, producing LaTeX.
+"""
+
+try:
+ import locale
+ locale.setlocale(locale.LC_ALL, '')
+except:
+ pass
+
+from docutils.core import publish_cmdline
+
+description = ('Generates LaTeX documents from standalone reStructuredText '
+ 'sources. '
+ 'Reads from <source> (default is stdin) and writes to '
+ '<destination> (default is stdout). See '
+ '<http://docutils.sourceforge.net/docs/user/latex.html> for '
+ 'the full reference.')
+
+publish_cmdline(writer_name='latex', description=description)
--- /dev/null
+#!/usr/bin/env python
+
+# Author:
+# Contact: grubert@users.sf.net
+# Copyright: This module has been placed in the public domain.
+
+"""
+man.py
+======
+
+This module provides a simple command line interface that uses the
+man page writer to output from ReStructuredText source.
+"""
+
+import locale
+try:
+ locale.setlocale(locale.LC_ALL, '')
+except:
+ pass
+
+from docutils.core import publish_cmdline, default_description
+from docutils.writers import manpage
+
+description = ("Generates plain unix manual documents. " + default_description)
+
+publish_cmdline(writer=manpage.Writer(), description=description)
--- /dev/null
+#!/usr/bin/env python
+
+# $Id: rst2odt.py 5839 2009-01-07 19:09:28Z dkuhlman $
+# Author: Dave Kuhlman <dkuhlman@rexx.com>
+# Copyright: This module has been placed in the public domain.
+
+"""
+A front end to the Docutils Publisher, producing OpenOffice documents.
+"""
+
+import sys
+try:
+ import locale
+ locale.setlocale(locale.LC_ALL, '')
+except:
+ pass
+
+from docutils.core import publish_cmdline_to_binary, default_description
+from docutils.writers.odf_odt import Writer, Reader
+
+
+description = ('Generates OpenDocument/OpenOffice/ODF documents from '
+ 'standalone reStructuredText sources. ' + default_description)
+
+
+writer = Writer()
+reader = Reader()
+output = publish_cmdline_to_binary(reader=reader, writer=writer,
+ description=description)
+
--- /dev/null
+#!/usr/bin/env python
+
+# $Id: rst2odt_prepstyles.py 8346 2019-08-26 12:11:32Z milde $
+# Author: Dave Kuhlman <dkuhlman@rexx.com>
+# Copyright: This module has been placed in the public domain.
+
+"""
+Fix a word-processor-generated styles.odt for odtwriter use: Drop page size
+specifications from styles.xml in STYLE_FILE.odt.
+"""
+
+# Author: Michael Schutte <michi@uiae.at>
+
+from __future__ import print_function
+
+from lxml import 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.read("styles.xml")
+
+ root = etree.fromstring(styles)
+ for el in root.xpath("//style:page-layout-properties",
+ namespaces=NAMESPACES):
+ for attr in el.attrib:
+ if attr.startswith("{%s}" % NAMESPACES["fo"]):
+ del el.attrib[attr]
+
+ tempname = mkstemp()
+ zout = zipfile.ZipFile(os.fdopen(tempname[0], "w"), "w",
+ zipfile.ZIP_DEFLATED)
+
+ for item in zin.infolist():
+ if item.filename == "styles.xml":
+ zout.writestr(item, etree.tostring(root))
+ 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:
+ 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()
--- /dev/null
+#!/usr/bin/env python
+
+# $Id: rst2pseudoxml.py 4564 2006-05-21 20:44:42Z wiemann $
+# Author: David Goodger <goodger@python.org>
+# Copyright: This module has been placed in the public domain.
+
+"""
+A minimal front end to the Docutils Publisher, producing pseudo-XML.
+"""
+
+try:
+ import locale
+ locale.setlocale(locale.LC_ALL, '')
+except:
+ pass
+
+from docutils.core import publish_cmdline, default_description
+
+
+description = ('Generates pseudo-XML from standalone reStructuredText '
+ 'sources (for testing purposes). ' + default_description)
+
+publish_cmdline(description=description)
--- /dev/null
+#!/usr/bin/env python
+
+# $Id: rst2s5.py 4564 2006-05-21 20:44:42Z wiemann $
+# Author: Chris Liechti <cliechti@gmx.net>
+# Copyright: This module has been placed in the public domain.
+
+"""
+A minimal front end to the Docutils Publisher, producing HTML slides using
+the S5 template system.
+"""
+
+try:
+ import locale
+ locale.setlocale(locale.LC_ALL, '')
+except:
+ pass
+
+from docutils.core import publish_cmdline, default_description
+
+
+description = ('Generates S5 (X)HTML slideshow documents from standalone '
+ 'reStructuredText sources. ' + default_description)
+
+publish_cmdline(writer_name='s5', description=description)
--- /dev/null
+#!/usr/bin/env python
+
+# $Id: rst2xetex.py 7847 2015-03-17 17:30:47Z milde $
+# Author: Guenter Milde
+# Copyright: This module has been placed in the public domain.
+
+"""
+A minimal front end to the Docutils Publisher, producing Lua/XeLaTeX code.
+"""
+
+try:
+ import locale
+ locale.setlocale(locale.LC_ALL, '')
+except:
+ pass
+
+from docutils.core import publish_cmdline
+
+description = ('Generates LaTeX documents from standalone reStructuredText '
+ 'sources for compilation with the Unicode-aware TeX variants '
+ 'XeLaTeX or LuaLaTeX. '
+ 'Reads from <source> (default is stdin) and writes to '
+ '<destination> (default is stdout). See '
+ '<http://docutils.sourceforge.net/docs/user/latex.html> for '
+ 'the full reference.')
+
+publish_cmdline(writer_name='xetex', description=description)
--- /dev/null
+#!/usr/bin/env python
+
+# $Id: rst2xml.py 4564 2006-05-21 20:44:42Z wiemann $
+# Author: David Goodger <goodger@python.org>
+# Copyright: This module has been placed in the public domain.
+
+"""
+A minimal front end to the Docutils Publisher, producing Docutils XML.
+"""
+
+try:
+ import locale
+ locale.setlocale(locale.LC_ALL, '')
+except:
+ pass
+
+from docutils.core import publish_cmdline, default_description
+
+
+description = ('Generates Docutils-native XML from standalone '
+ 'reStructuredText sources. ' + default_description)
+
+publish_cmdline(writer_name='xml', description=description)
--- /dev/null
+#!/usr/bin/env python
+
+# $Id: rstpep2html.py 4564 2006-05-21 20:44:42Z wiemann $
+# Author: David Goodger <goodger@python.org>
+# Copyright: This module has been placed in the public domain.
+
+"""
+A minimal front end to the Docutils Publisher, producing HTML from PEP
+(Python Enhancement Proposal) documents.
+"""
+
+try:
+ import locale
+ locale.setlocale(locale.LC_ALL, '')
+except:
+ pass
+
+from docutils.core import publish_cmdline, default_description
+
+
+description = ('Generates (X)HTML from reStructuredText-format PEP files. '
+ + default_description)
+
+publish_cmdline(reader_name='pep', writer_name='pep_html',
+ description=description)
--- /dev/null
+#!/usr/bin/env python
+
+# $Id: test_buildhtml.py 8376 2019-08-27 19:49:29Z milde $
+# Author: engelbert gruber <grubert@users.sourceforge.net>
+# Copyright: This module has been placed in the public domain.
+
+"""
+test buildhtml options, because ``--local`` is broken.
+
+Build-HTML Options
+------------------
+--recurse Recursively scan subdirectories for files to process.
+ This is the default.
+--local Do not scan subdirectories for files to process.
+--prune=<directory> Do not process files in <directory>. This option may
+ be used more than once to specify multiple
+ directories.
+--ignore=<patterns> Recursively ignore files or directories matching any
+ of the given wildcard (shell globbing) patterns
+ (separated by colons). Default: ".svn:CVS"
+--silent Work silently (no progress messages). Independent of
+ "--quiet".
+"""
+
+import unittest
+import os
+from subprocess import Popen, PIPE, STDOUT
+import tempfile
+
+
+buildhtml_path = os.path.abspath(os.path.join(
+ os.path.dirname(__file__) or os.curdir,
+ '..', 'buildhtml.py'))
+
+def process_and_return_filelist(options):
+ dirs = []
+ files = []
+ try:
+ p = Popen(buildhtml_path+" "+options, shell=True,
+ stdin=PIPE, stdout=PIPE, stderr=STDOUT, close_fds=True)
+ (cin, cout) = (p.stdin, p.stdout)
+ except NameError:
+ cin, cout = os.popen4(buildhtml_path+" "+options)
+ while True:
+ line = cout.readline()
+ if not line:
+ break
+ # in Py 3x, cout.readline() returns `bytes` and the processing fails
+ line = line.decode('ascii', 'replace')
+ # BUG no colon in filename/path allowed
+ item = line.split(": ")[-1].strip()
+ if line.startswith(" "):
+ files.append(item)
+ else:
+ dirs.append(item)
+ cin.close()
+ cout.close()
+ return (dirs, files)
+
+class BuildHtmlTests(unittest.TestCase):
+ tree = ( "_tmp_test_tree",
+ "_tmp_test_tree/one.txt",
+ "_tmp_test_tree/two.txt",
+ "_tmp_test_tree/dir1",
+ "_tmp_test_tree/dir1/one.txt",
+ "_tmp_test_tree/dir1/two.txt",
+ "_tmp_test_tree/dir2",
+ "_tmp_test_tree/dir2/one.txt",
+ "_tmp_test_tree/dir2/two.txt",
+ "_tmp_test_tree/dir2/sub",
+ "_tmp_test_tree/dir2/sub/one.txt",
+ "_tmp_test_tree/dir2/sub/two.txt",
+ )
+
+ def setUp(self):
+ try:
+ self.root = tempfile.mkdtemp()
+ except NameError:
+ self.root = os.tempnam()
+ os.mkdir(self.root)
+
+ for s in self.tree:
+ s = os.path.join(self.root, s)
+ if not "." in s:
+ os.mkdir(s)
+ else:
+ fd_s = open(s, "w")
+ fd_s.write("dummy")
+ fd_s.close()
+
+ def tearDown(self):
+ for i in range(len(self.tree) - 1, -1, -1):
+ s = os.path.join(self.root, self.tree[i])
+ if not "." in s:
+ os.rmdir(s)
+ else:
+ os.remove(s)
+ os.rmdir(self.root)
+
+ def test_1(self):
+ opts = "--dry-run "+ self.root
+ dirs, files = process_and_return_filelist( opts )
+ self.assertEqual(files.count("one.txt"), 4)
+
+ def test_local(self):
+ opts = "--dry-run --local "+ self.root
+ dirs, files = process_and_return_filelist( opts )
+ self.assertEqual( len(dirs), 1)
+ self.assertEqual( files, [])
+
+if __name__ == '__main__':
+ unittest.main()