branch develop updated (c531e37 -> d44412e)
This is an automated email from the git hooks/post-receive script. New change to branch develop in repository jrst. See https://gitlab.nuiton.org/nuiton/jrst.git from c531e37 Fix build new 4d580f6 Update commons-io new 7a41cc4 Update commons-lang3 new 3ed2b95 Update nuiton-i18n new 1c5672d Update guava new f8b9494 Update flyingsaucer new 498cd5e Update nuiton-config new 36b5822 Update nuiton-utils new 53fec2f Update docbook-xsl new 67c4473 Update doxia and plexus new 6076986 fixes #4148: Update docutils codebase to 0.13.1 new 5181b34 fixes #3633: JRST plugin should not load file from remote repositories new e577d30 fixes #3529: Fix tests broken since doxia 1.6 update new d44412e Remove myself from copyright The 13 revisions listed above as "new" are entirely new to this repository and will be described in separate emails. The revisions listed as "adds" were already present in the repository and have only been added to this reference. Detailed log of new commits: commit d44412e65ed2fdd70fbd2e30ccbe705883d1756d Author: Eric Chatellier <eric.chatellier@gmail.com> Date: Sun Feb 12 17:15:41 2017 +0100 Remove myself from copyright commit e577d3087bd53a1ad11f5fe0bfc4741200f2195c Author: Eric Chatellier <eric.chatellier@gmail.com> Date: Sun Feb 12 17:13:38 2017 +0100 fixes #3529: Fix tests broken since doxia 1.6 update commit 5181b343dd3af915bab2c2713764577d353ce55d Author: Eric Chatellier <eric.chatellier@gmail.com> Date: Sun Feb 12 16:43:04 2017 +0100 fixes #3633: JRST plugin should not load file from remote repositories commit 6076986ca0c874f5d598df9f3ac11461dc43d0aa Author: Eric Chatellier <eric.chatellier@gmail.com> Date: Sun Feb 12 16:03:13 2017 +0100 fixes #4148: Update docutils codebase to 0.13.1 commit 67c4473c0f5c6612079427ddfebac2d34e363eeb Author: Eric Chatellier <eric.chatellier@gmail.com> Date: Sun Feb 12 15:55:38 2017 +0100 Update doxia and plexus commit 53fec2f23d497ee9f3051e0d8bc2d343b57e6d0d Author: Eric Chatellier <eric.chatellier@gmail.com> Date: Sun Feb 12 15:49:00 2017 +0100 Update docbook-xsl commit 36b582280b94d13137f3751c2bc0cc63cb0c538f Author: Eric Chatellier <eric.chatellier@gmail.com> Date: Sun Feb 12 15:46:32 2017 +0100 Update nuiton-utils commit 498cd5e130dba599520986b8a870891942ee6efa Author: Eric Chatellier <eric.chatellier@gmail.com> Date: Sun Feb 12 15:45:45 2017 +0100 Update nuiton-config commit f8b9494b43ed4cfbc8fe327a13036e12741075bc Author: Eric Chatellier <eric.chatellier@gmail.com> Date: Sun Feb 12 15:40:39 2017 +0100 Update flyingsaucer commit 1c5672dceb7714a65036f0f8bde21e06d8421307 Author: Eric Chatellier <eric.chatellier@gmail.com> Date: Sun Feb 12 15:39:01 2017 +0100 Update guava commit 3ed2b951c68d3d53a4d5cee302b1d83981488af0 Author: Eric Chatellier <eric.chatellier@gmail.com> Date: Sun Feb 12 15:25:27 2017 +0100 Update nuiton-i18n commit 7a41cc40382caaceb4f2893836a278b7b177b87c Author: Eric Chatellier <eric.chatellier@gmail.com> Date: Sun Feb 12 15:23:04 2017 +0100 Update commons-lang3 commit 4d580f61f3b5cf988e3956a53cfbcfe571af0f57 Author: Eric Chatellier <eric.chatellier@gmail.com> Date: Sun Feb 12 15:22:45 2017 +0100 Update commons-io Summary of changes: .../main/resources/docutils/docutils/__init__.py | 4 +- .../src/main/resources/docutils/docutils/io.py | 6 +- .../resources/docutils/docutils/languages/fa.py | 61 ++ .../resources/docutils/docutils/languages/lt.py | 67 +- .../resources/docutils/docutils/languages/lv.py | 60 + .../src/main/resources/docutils/docutils/nodes.py | 4 +- .../docutils/docutils/parsers/rst/__init__.py | 25 +- .../docutils/parsers/rst/directives/__init__.py | 14 +- .../docutils/parsers/rst/directives/misc.py | 22 +- .../docutils/parsers/rst/directives/tables.py | 81 +- .../docutils/docutils/parsers/rst/languages/fa.py | 102 ++ .../docutils/docutils/parsers/rst/languages/lv.py | 108 ++ .../docutils/docutils/parsers/rst/roles.py | 7 +- .../docutils/docutils/parsers/rst/states.py | 273 ++--- .../docutils/docutils/parsers/rst/tableparser.py | 4 +- .../docutils/docutils/transforms/frontmatter.py | 6 +- .../resources/docutils/docutils/transforms/peps.py | 6 +- .../docutils/docutils/transforms/universal.py | 6 +- .../docutils/docutils/transforms/writer_aux.py | 2 +- .../docutils/docutils/utils/code_analyzer.py | 4 +- .../docutils/docutils/utils/error_reporting.py | 26 +- .../docutils/docutils/utils/math/__init__.py | 7 +- .../docutils/docutils/utils/math/latex2mathml.py | 13 +- .../docutils/docutils/utils/math/math2html.py | 402 ++++--- .../docutils/utils/math/tex2mathml_extern.py | 147 +++ .../docutils/docutils/utils/smartquotes.py | 4 +- .../docutils/docutils/utils/urischemes.py | 4 +- .../docutils/docutils/writers/__init__.py | 13 +- .../{html4css1/__init__.py => _html_base.py} | 982 +++++++---------- .../docutils/docutils/writers/docutils_xml.py | 22 +- .../docutils/writers/html4css1/__init__.py | 1157 +++----------------- .../docutils/writers/html4css1/html4css1.css | 28 +- .../docutils/writers/html5_polyglot/__init__.py | 200 ++++ .../writers/{html4css1 => html5_polyglot}/math.css | 0 .../docutils/writers/html5_polyglot/minimal.css | 260 +++++ .../docutils/writers/html5_polyglot/plain.css | 288 +++++ .../{html4css1 => html5_polyglot}/template.txt | 0 .../docutils/docutils/writers/latex2e/__init__.py | 460 ++++---- .../docutils/docutils/writers/latex2e/xelatex.tex | 3 +- .../docutils/docutils/writers/odf_odt/__init__.py | 32 +- .../docutils/docutils/writers/pep_html/pep.css | 2 +- .../docutils/docutils/writers/xetex/__init__.py | 15 +- doxia-module-jrst-legacy/pom.xml | 8 +- .../src/main/java/org/nuiton/jrst/JrstParser.java | 4 +- .../test/java/org/nuiton/jrst/JrstParserTest.java | 7 +- doxia-module-jrst/pom.xml | 8 +- .../src/main/java/org/nuiton/jrst/JrstParser.java | 4 +- .../test/java/org/nuiton/jrst/JrstParserTest.java | 7 +- jrst-site-util/pom.xml | 3 +- .../java/org/nuiton/jrst/AbstractJrstParser.java | 7 +- jrst/pom.xml | 7 +- jrst/src/main/assembly/jrst.sh | 2 +- jrst/src/main/java/org/nuiton/jrst/JRST.java | 2 +- jrst/src/main/java/org/nuiton/jrst/JRSTConfig.java | 2 +- .../java/org/nuiton/jrst/JRSTConfigAction.java | 2 +- .../java/org/nuiton/jrst/JRSTConfigOption.java | 2 +- ...ctnumDirective.java => JRSTEntityResolver.java} | 44 +- .../main/java/org/nuiton/jrst/JRSTInterface.java | 2 +- .../org/nuiton/jrst/JRSTToXmlStrategyDocutils.java | 50 +- .../java/org/nuiton/jrst/legacy/JRSTLexer.java | 2 +- jrst/src/main/resources/dtd/docutils.dtd | 621 +++++++++++ jrst/src/main/resources/dtd/soextblx.dtd | 312 ++++++ jrst/src/main/resources/xsl/rst2xhtml.xsl | 2 +- .../java/org/nuiton/jrst/bugs/DirectiveTest.java | 2 +- .../test/java/org/nuiton/jrst/bugs/HtmlTest.java | 2 +- .../test/java/org/nuiton/jrst/bugs/TableTest.java | 2 +- .../test/java/org/nuiton/jrst/bugs/TextTest.java | 2 +- .../test/java/org/nuiton/jrst/bugs/TitlesTest.java | 2 +- pom.xml | 60 +- 69 files changed, 3752 insertions(+), 2343 deletions(-) create mode 100644 docutils/src/main/resources/docutils/docutils/languages/fa.py create mode 100644 docutils/src/main/resources/docutils/docutils/languages/lv.py create mode 100644 docutils/src/main/resources/docutils/docutils/parsers/rst/languages/fa.py create mode 100644 docutils/src/main/resources/docutils/docutils/parsers/rst/languages/lv.py create mode 100644 docutils/src/main/resources/docutils/docutils/utils/math/tex2mathml_extern.py copy docutils/src/main/resources/docutils/docutils/writers/{html4css1/__init__.py => _html_base.py} (62%) create mode 100644 docutils/src/main/resources/docutils/docutils/writers/html5_polyglot/__init__.py rename docutils/src/main/resources/docutils/docutils/writers/{html4css1 => html5_polyglot}/math.css (100%) create mode 100644 docutils/src/main/resources/docutils/docutils/writers/html5_polyglot/minimal.css create mode 100644 docutils/src/main/resources/docutils/docutils/writers/html5_polyglot/plain.css copy docutils/src/main/resources/docutils/docutils/writers/{html4css1 => html5_polyglot}/template.txt (100%) copy jrst/src/main/java/org/nuiton/jrst/{legacy/directive/SectnumDirective.java => JRSTEntityResolver.java} (50%) create mode 100644 jrst/src/main/resources/dtd/docutils.dtd create mode 100644 jrst/src/main/resources/dtd/soextblx.dtd -- To stop receiving notification emails like this one, please contact nuiton.org SCM administrator <admin+scm@nuiton.org>.
This is an automated email from the git hooks/post-receive script. New commit to branch develop in repository jrst. See https://gitlab.nuiton.org/nuiton/jrst.git commit 4d580f61f3b5cf988e3956a53cfbcfe571af0f57 Author: Eric Chatellier <eric.chatellier@gmail.com> Date: Sun Feb 12 15:22:45 2017 +0100 Update commons-io --- jrst/pom.xml | 5 ----- pom.xml | 9 +-------- 2 files changed, 1 insertion(+), 13 deletions(-) diff --git a/jrst/pom.xml b/jrst/pom.xml index 7ff453d..0b41f3b 100644 --- a/jrst/pom.xml +++ b/jrst/pom.xml @@ -79,11 +79,6 @@ <artifactId>jaxx-runtime</artifactId> </dependency> - <!--dependency> - <groupId>org.nuiton.jaxx</groupId> - <artifactId>jaxx-widgets</artifactId> - </dependency--> - <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-lang3</artifactId> diff --git a/pom.xml b/pom.xml index 2e7dfc1..ccd6b75 100644 --- a/pom.xml +++ b/pom.xml @@ -451,7 +451,6 @@ <version>2.1.7</version> </dependency> - <!-- jaxx dependencies --> <dependency> <groupId>org.nuiton.jaxx</groupId> @@ -465,12 +464,6 @@ <version>${jaxxVersion}</version> </dependency> - <dependency> - <groupId>org.nuiton.jaxx</groupId> - <artifactId>jaxx-widgets</artifactId> - <version>${jaxxVersion}</version> - </dependency> - <!-- swing widgets --> <dependency> <groupId>org.nuiton</groupId> @@ -501,7 +494,7 @@ <dependency> <groupId>commons-io</groupId> <artifactId>commons-io</artifactId> - <version>2.4</version> + <version>2.5</version> </dependency> <dependency> -- To stop receiving notification emails like this one, please contact nuiton.org SCM administrator <admin+scm@nuiton.org>.
This is an automated email from the git hooks/post-receive script. New commit to branch develop in repository jrst. See https://gitlab.nuiton.org/nuiton/jrst.git commit 7a41cc40382caaceb4f2893836a278b7b177b87c Author: Eric Chatellier <eric.chatellier@gmail.com> Date: Sun Feb 12 15:23:04 2017 +0100 Update commons-lang3 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index ccd6b75..df613d4 100644 --- a/pom.xml +++ b/pom.xml @@ -512,7 +512,7 @@ <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-lang3</artifactId> - <version>3.4</version> + <version>3.5</version> </dependency> <dependency> -- To stop receiving notification emails like this one, please contact nuiton.org SCM administrator <admin+scm@nuiton.org>.
This is an automated email from the git hooks/post-receive script. New commit to branch develop in repository jrst. See https://gitlab.nuiton.org/nuiton/jrst.git commit 3ed2b951c68d3d53a4d5cee302b1d83981488af0 Author: Eric Chatellier <eric.chatellier@gmail.com> Date: Sun Feb 12 15:25:27 2017 +0100 Update nuiton-i18n --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index df613d4..ef780e0 100644 --- a/pom.xml +++ b/pom.xml @@ -112,7 +112,7 @@ <doxiaVersion>1.7</doxiaVersion> <doxiaSitetoolsVersion>1.7</doxiaSitetoolsVersion> - <nuitonI18nVersion>3.3</nuitonI18nVersion> + <nuitonI18nVersion>3.6.3</nuitonI18nVersion> <xalanVersion>2.7.1</xalanVersion> <jaxxVersion>2.28.2</jaxxVersion> <mavenVersion>3.3.9</mavenVersion> -- To stop receiving notification emails like this one, please contact nuiton.org SCM administrator <admin+scm@nuiton.org>.
This is an automated email from the git hooks/post-receive script. New commit to branch develop in repository jrst. See https://gitlab.nuiton.org/nuiton/jrst.git commit 1c5672dceb7714a65036f0f8bde21e06d8421307 Author: Eric Chatellier <eric.chatellier@gmail.com> Date: Sun Feb 12 15:39:01 2017 +0100 Update guava --- pom.xml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pom.xml b/pom.xml index ef780e0..22058d1 100644 --- a/pom.xml +++ b/pom.xml @@ -3,7 +3,7 @@ #%L JRst %% - Copyright (C) 2004 - 2016 CodeLutin, Chatellier Eric + Copyright (C) 2004 - 2017 CodeLutin %% This program is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as @@ -26,7 +26,7 @@ <parent> <groupId>org.nuiton</groupId> <artifactId>nuitonpom</artifactId> - <version>10.2</version> + <version>10.5</version> </parent> <artifactId>jrst</artifactId> @@ -114,7 +114,7 @@ <doxiaSitetoolsVersion>1.7</doxiaSitetoolsVersion> <nuitonI18nVersion>3.6.3</nuitonI18nVersion> <xalanVersion>2.7.1</xalanVersion> - <jaxxVersion>2.28.2</jaxxVersion> + <jaxxVersion>2.40</jaxxVersion> <mavenVersion>3.3.9</mavenVersion> <!-- site configuration --> @@ -482,7 +482,7 @@ <dependency> <groupId>com.google.guava</groupId> <artifactId>guava</artifactId> - <version>19.0</version> + <version>20.0</version> </dependency> <dependency> -- To stop receiving notification emails like this one, please contact nuiton.org SCM administrator <admin+scm@nuiton.org>.
This is an automated email from the git hooks/post-receive script. New commit to branch develop in repository jrst. See https://gitlab.nuiton.org/nuiton/jrst.git commit f8b9494b43ed4cfbc8fe327a13036e12741075bc Author: Eric Chatellier <eric.chatellier@gmail.com> Date: Sun Feb 12 15:40:39 2017 +0100 Update flyingsaucer --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 22058d1..5bec8ad 100644 --- a/pom.xml +++ b/pom.xml @@ -437,12 +437,12 @@ <dependency> <groupId>org.xhtmlrenderer</groupId> <artifactId>flying-saucer-pdf</artifactId> - <version>9.0.8</version> + <version>9.1.1</version> </dependency> <dependency> <groupId>org.xhtmlrenderer</groupId> <artifactId>flying-saucer-core</artifactId> - <version>9.0.8</version> + <version>9.1.1</version> </dependency> <dependency> -- To stop receiving notification emails like this one, please contact nuiton.org SCM administrator <admin+scm@nuiton.org>.
This is an automated email from the git hooks/post-receive script. New commit to branch develop in repository jrst. See https://gitlab.nuiton.org/nuiton/jrst.git commit 498cd5e130dba599520986b8a870891942ee6efa Author: Eric Chatellier <eric.chatellier@gmail.com> Date: Sun Feb 12 15:45:45 2017 +0100 Update nuiton-config --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 5bec8ad..5a0b8a4 100644 --- a/pom.xml +++ b/pom.xml @@ -137,7 +137,7 @@ <dependency> <groupId>org.nuiton</groupId> <artifactId>nuiton-config</artifactId> - <version>3.0-rc-3</version> + <version>3.2</version> <scope>compile</scope> </dependency> -- To stop receiving notification emails like this one, please contact nuiton.org SCM administrator <admin+scm@nuiton.org>.
This is an automated email from the git hooks/post-receive script. New commit to branch develop in repository jrst. See https://gitlab.nuiton.org/nuiton/jrst.git commit 36b582280b94d13137f3751c2bc0cc63cb0c538f Author: Eric Chatellier <eric.chatellier@gmail.com> Date: Sun Feb 12 15:46:32 2017 +0100 Update nuiton-utils --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 5a0b8a4..c2e4066 100644 --- a/pom.xml +++ b/pom.xml @@ -130,7 +130,7 @@ <dependency> <groupId>org.nuiton</groupId> <artifactId>nuiton-utils</artifactId> - <version>3.0-rc-11</version> + <version>3.0-rc-18</version> <scope>compile</scope> </dependency> -- To stop receiving notification emails like this one, please contact nuiton.org SCM administrator <admin+scm@nuiton.org>.
This is an automated email from the git hooks/post-receive script. New commit to branch develop in repository jrst. See https://gitlab.nuiton.org/nuiton/jrst.git commit 53fec2f23d497ee9f3051e0d8bc2d343b57e6d0d Author: Eric Chatellier <eric.chatellier@gmail.com> Date: Sun Feb 12 15:49:00 2017 +0100 Update docbook-xsl --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index c2e4066..2442e14 100644 --- a/pom.xml +++ b/pom.xml @@ -299,7 +299,7 @@ <dependency> <groupId>net.sf.docbook</groupId> <artifactId>docbook-xsl</artifactId> - <version>1.78.1</version> + <version>1.79.1</version> <type>zip</type> <classifier>resources</classifier> <scope>provided</scope> -- To stop receiving notification emails like this one, please contact nuiton.org SCM administrator <admin+scm@nuiton.org>.
This is an automated email from the git hooks/post-receive script. New commit to branch develop in repository jrst. See https://gitlab.nuiton.org/nuiton/jrst.git commit 67c4473c0f5c6612079427ddfebac2d34e363eeb Author: Eric Chatellier <eric.chatellier@gmail.com> Date: Sun Feb 12 15:55:38 2017 +0100 Update doxia and plexus --- pom.xml | 26 ++++++++++++-------------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/pom.xml b/pom.xml index 2442e14..1f91507 100644 --- a/pom.xml +++ b/pom.xml @@ -110,8 +110,6 @@ <signatureArtifactId>java17</signatureArtifactId> <signatureVersion>1.0</signatureVersion> - <doxiaVersion>1.7</doxiaVersion> - <doxiaSitetoolsVersion>1.7</doxiaSitetoolsVersion> <nuitonI18nVersion>3.6.3</nuitonI18nVersion> <xalanVersion>2.7.1</xalanVersion> <jaxxVersion>2.40</jaxxVersion> @@ -232,13 +230,13 @@ <dependency> <groupId>org.codehaus.plexus</groupId> <artifactId>plexus-utils</artifactId> - <version>3.0.22</version> + <version>3.0.24</version> </dependency> <dependency> <groupId>org.codehaus.plexus</groupId> <artifactId>plexus-component-annotations</artifactId> - <version>1.6</version> + <version>1.7.1</version> </dependency> <dependency> @@ -328,41 +326,41 @@ <dependency> <groupId>org.apache.maven.doxia</groupId> <artifactId>doxia-module-xdoc</artifactId> - <version>${doxiaVersion}</version> + <version>1.7</version> <scope>provided</scope> </dependency> <dependency> <groupId>org.apache.maven.doxia</groupId> <artifactId>doxia-core</artifactId> - <version>${doxiaVersion}</version> + <version>1.7</version> <scope>provided</scope> </dependency> <dependency> <groupId>org.apache.maven.doxia</groupId> <artifactId>doxia-sink-api</artifactId> - <version>${doxiaVersion}</version> + <version>1.7</version> <scope>provided</scope> </dependency> <dependency> <groupId>org.apache.maven.doxia</groupId> <artifactId>doxia-logging-api</artifactId> - <version>${doxiaVersion}</version> + <version>1.7</version> <scope>provided</scope> </dependency> <dependency> <groupId>org.apache.maven.doxia</groupId> <artifactId>doxia-decoration-model</artifactId> - <version>1.6</version> + <version>1.7.4</version> </dependency> <dependency> <groupId>org.codehaus.plexus</groupId> <artifactId>plexus-container-default</artifactId> - <version>1.6</version> + <version>1.7.1</version> <scope>provided</scope> </dependency> @@ -375,7 +373,7 @@ <dependency> <groupId>org.codehaus.plexus</groupId> <artifactId>plexus-velocity</artifactId> - <version>1.1.8</version> + <version>1.2</version> <exclusions> <exclusion> <groupId>org.codehaus.plexus</groupId> @@ -404,14 +402,14 @@ <groupId>org.apache.maven.doxia</groupId> <artifactId>doxia-core</artifactId> <type>test-jar</type> - <version>${doxiaVersion}</version> + <version>1.7</version> <scope>test</scope> </dependency> <dependency> <groupId>org.apache.maven.doxia</groupId> <artifactId>doxia-site-renderer</artifactId> - <version>${doxiaSitetoolsVersion}</version> + <version>1.7.4</version> </dependency> <dependency> @@ -423,7 +421,7 @@ <dependency> <groupId>org.eclipse.sisu</groupId> <artifactId>org.eclipse.sisu.plexus</artifactId> - <version>0.3.2</version> + <version>0.3.3</version> <scope>provided</scope> </dependency> -- To stop receiving notification emails like this one, please contact nuiton.org SCM administrator <admin+scm@nuiton.org>.
This is an automated email from the git hooks/post-receive script. New commit to branch develop in repository jrst. See https://gitlab.nuiton.org/nuiton/jrst.git commit 6076986ca0c874f5d598df9f3ac11461dc43d0aa Author: Eric Chatellier <eric.chatellier@gmail.com> Date: Sun Feb 12 16:03:13 2017 +0100 fixes #4148: Update docutils codebase to 0.13.1 --- .../main/resources/docutils/docutils/__init__.py | 4 +- .../src/main/resources/docutils/docutils/io.py | 6 +- .../resources/docutils/docutils/languages/fa.py | 61 ++ .../resources/docutils/docutils/languages/lt.py | 67 +- .../resources/docutils/docutils/languages/lv.py | 60 + .../src/main/resources/docutils/docutils/nodes.py | 4 +- .../docutils/docutils/parsers/rst/__init__.py | 25 +- .../docutils/parsers/rst/directives/__init__.py | 14 +- .../docutils/parsers/rst/directives/misc.py | 22 +- .../docutils/parsers/rst/directives/tables.py | 81 +- .../docutils/docutils/parsers/rst/languages/fa.py | 102 ++ .../docutils/docutils/parsers/rst/languages/lv.py | 108 ++ .../docutils/docutils/parsers/rst/roles.py | 7 +- .../docutils/docutils/parsers/rst/states.py | 273 ++--- .../docutils/docutils/parsers/rst/tableparser.py | 4 +- .../docutils/docutils/transforms/frontmatter.py | 6 +- .../resources/docutils/docutils/transforms/peps.py | 6 +- .../docutils/docutils/transforms/universal.py | 6 +- .../docutils/docutils/transforms/writer_aux.py | 2 +- .../docutils/docutils/utils/code_analyzer.py | 4 +- .../docutils/docutils/utils/error_reporting.py | 26 +- .../docutils/docutils/utils/math/__init__.py | 7 +- .../docutils/docutils/utils/math/latex2mathml.py | 13 +- .../docutils/docutils/utils/math/math2html.py | 402 ++++--- .../docutils/utils/math/tex2mathml_extern.py | 147 +++ .../docutils/docutils/utils/smartquotes.py | 4 +- .../docutils/docutils/utils/urischemes.py | 4 +- .../docutils/docutils/writers/__init__.py | 13 +- .../{html4css1/__init__.py => _html_base.py} | 982 +++++++---------- .../docutils/docutils/writers/docutils_xml.py | 22 +- .../docutils/writers/html4css1/__init__.py | 1157 +++----------------- .../docutils/writers/html4css1/html4css1.css | 28 +- .../docutils/writers/html5_polyglot/__init__.py | 200 ++++ .../writers/{html4css1 => html5_polyglot}/math.css | 0 .../docutils/writers/html5_polyglot/minimal.css | 260 +++++ .../docutils/writers/html5_polyglot/plain.css | 288 +++++ .../docutils/writers/html5_polyglot/template.txt | 8 + .../docutils/docutils/writers/latex2e/__init__.py | 460 ++++---- .../docutils/docutils/writers/latex2e/xelatex.tex | 3 +- .../docutils/docutils/writers/odf_odt/__init__.py | 32 +- .../docutils/docutils/writers/pep_html/pep.css | 2 +- .../docutils/docutils/writers/xetex/__init__.py | 15 +- 42 files changed, 2693 insertions(+), 2242 deletions(-) diff --git a/docutils/src/main/resources/docutils/docutils/__init__.py b/docutils/src/main/resources/docutils/docutils/__init__.py index 270b883..79ed8fb 100644 --- a/docutils/src/main/resources/docutils/docutils/__init__.py +++ b/docutils/src/main/resources/docutils/docutils/__init__.py @@ -1,4 +1,4 @@ -# $Id: __init__.py 7756 2014-07-06 11:48:05Z grubert $ +# $Id: __init__.py 7984 2016-12-09 09:48:27Z grubert $ # Author: David Goodger <goodger@python.org> # Copyright: This module has been placed in the public domain. @@ -52,7 +52,7 @@ Subpackages: __docformat__ = 'reStructuredText' -__version__ = '0.12' +__version__ = '0.13.1' """``major.minor.micro`` version number. The micro number is bumped for API changes, for new functionality, and for interim project releases. The minor number is bumped whenever there is a significant project release. The major diff --git a/docutils/src/main/resources/docutils/docutils/io.py b/docutils/src/main/resources/docutils/docutils/io.py index 1a14ac0..234e14c 100644 --- a/docutils/src/main/resources/docutils/docutils/io.py +++ b/docutils/src/main/resources/docutils/docutils/io.py @@ -1,4 +1,4 @@ -# $Id: io.py 7596 2013-01-25 13:42:17Z milde $ +# $Id: io.py 7864 2015-04-12 09:57:05Z milde $ # Author: David Goodger <goodger@python.org> # Copyright: This module has been placed in the public domain. @@ -369,9 +369,9 @@ class FileOutput(Output): if ('b' not in self.mode and sys.version_info < (3,0) or check_encoding(self.destination, self.encoding) is False ): - if sys.version_info >= (3,0) and os.linesep != '\n': - data = data.replace('\n', os.linesep) # fix endings data = self.encode(data) + if sys.version_info >= (3,0) and os.linesep != '\n': + data = data.replace(b('\n'), b(os.linesep)) # fix endings try: # In Python < 2.5, try...except has to be nested in try...finally. try: diff --git a/docutils/src/main/resources/docutils/docutils/languages/fa.py b/docutils/src/main/resources/docutils/docutils/languages/fa.py new file mode 100644 index 0000000..48aa588 --- /dev/null +++ b/docutils/src/main/resources/docutils/docutils/languages/fa.py @@ -0,0 +1,61 @@ +# -*- 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.""" diff --git a/docutils/src/main/resources/docutils/docutils/languages/lt.py b/docutils/src/main/resources/docutils/docutils/languages/lt.py index 7e1569c..c5c3fdc 100644 --- a/docutils/src/main/resources/docutils/docutils/languages/lt.py +++ b/docutils/src/main/resources/docutils/docutils/languages/lt.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# $Id: lt.py 7668 2013-06-04 12:46:30Z milde $ +# $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. @@ -9,7 +9,7 @@ # docutils/parsers/rst/languages. """ -English-language mappings for language-dependent features of Docutils. +Lithuanian language mappings for language-dependent features of Docutils. """ __docformat__ = 'reStructuredText' @@ -54,68 +54,7 @@ bibliographic_fields = { 'autoriaus teisės': 'copyright', 'dedikacija': 'dedication', 'santrauka': 'abstract'} -"""English (lowcased) to canonical name mapping for bibliographic fields.""" - -author_separators = [';', ','] -"""List of separator strings for the 'Authors' bibliographic field. Tried in -order.""" -# -*- coding: utf-8 -*- -# $Id: lt.py 7668 2013-06-04 12:46:30Z 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': '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'} -"""English (lowcased) to canonical name mapping for bibliographic fields.""" +"""Lithuanian (lowcased) to canonical name mapping for bibliographic fields.""" author_separators = [';', ','] """List of separator strings for the 'Authors' bibliographic field. Tried in diff --git a/docutils/src/main/resources/docutils/docutils/languages/lv.py b/docutils/src/main/resources/docutils/docutils/languages/lv.py new file mode 100644 index 0000000..f8125d4 --- /dev/null +++ b/docutils/src/main/resources/docutils/docutils/languages/lv.py @@ -0,0 +1,60 @@ +# -*- 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.""" diff --git a/docutils/src/main/resources/docutils/docutils/nodes.py b/docutils/src/main/resources/docutils/docutils/nodes.py index 7c172ee..8628e9c 100644 --- a/docutils/src/main/resources/docutils/docutils/nodes.py +++ b/docutils/src/main/resources/docutils/docutils/nodes.py @@ -1,4 +1,4 @@ -# $Id: nodes.py 7595 2013-01-21 17:33:56Z milde $ +# $Id: nodes.py 7788 2015-02-16 22:10:52Z milde $ # Author: David Goodger <goodger@python.org> # Maintainer: docutils-develop@lists.sourceforge.net # Copyright: This module has been placed in the public domain. @@ -533,7 +533,7 @@ class Element(Node): parts = [self.tagname] for name, value in self.attlist(): if value is None: # boolean attribute - parts.append(name) + parts.append('%s="True"' % name) continue if isinstance(value, list): values = [serial_escape('%s' % (v,)) for v in value] diff --git a/docutils/src/main/resources/docutils/docutils/parsers/rst/__init__.py b/docutils/src/main/resources/docutils/docutils/parsers/rst/__init__.py index ed70e0e..6bf1e52 100644 --- a/docutils/src/main/resources/docutils/docutils/parsers/rst/__init__.py +++ b/docutils/src/main/resources/docutils/docutils/parsers/rst/__init__.py @@ -1,4 +1,4 @@ -# $Id: __init__.py 7598 2013-01-30 12:39:24Z milde $ +# $Id: __init__.py 7961 2016-07-28 22:02:47Z milde $ # Author: David Goodger <goodger@python.org> # Copyright: This module has been placed in the public domain. @@ -101,9 +101,9 @@ class Parser(docutils.parsers.Parser): ('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://www.faqs.org/rfcs/").', + ('Base URL for RFC references (default "http://tools.ietf.org/html/").', ['--rfc-base-url'], - {'metavar': '<URL>', 'default': 'http://www.faqs.org/rfcs/', + {'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'], @@ -142,6 +142,19 @@ class Parser(docutils.parsers.Parser): 'one of "yes", "no", "alt[ernative]" (default "no").', ['--smart-quotes'], {'default': False, 'validator': frontend.validate_ternary}), + ('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' @@ -249,12 +262,6 @@ class Directive(object): - ``lineno`` is the absolute line number of the first line of the directive. - - ``src`` is the name (or path) of the rst source of the directive. - - - ``srcline`` is the line number of the first line of the directive - in its source. It may differ from ``lineno``, if the main source - includes other sources with the ``.. include::`` 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. diff --git a/docutils/src/main/resources/docutils/docutils/parsers/rst/directives/__init__.py b/docutils/src/main/resources/docutils/docutils/parsers/rst/directives/__init__.py index 6e843b8..b1ede9c 100644 --- a/docutils/src/main/resources/docutils/docutils/parsers/rst/directives/__init__.py +++ b/docutils/src/main/resources/docutils/docutils/parsers/rst/directives/__init__.py @@ -1,4 +1,4 @@ -# $Id: __init__.py 7621 2013-03-04 13:20:49Z milde $ +# $Id: __init__.py 7785 2015-02-08 23:51:45Z grubert $ # Author: David Goodger <goodger@python.org> # Copyright: This module has been placed in the public domain. @@ -402,3 +402,15 @@ def choice(argument, 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 + diff --git a/docutils/src/main/resources/docutils/docutils/parsers/rst/directives/misc.py b/docutils/src/main/resources/docutils/docutils/parsers/rst/directives/misc.py index 643bc70..f843bdc 100644 --- a/docutils/src/main/resources/docutils/docutils/parsers/rst/directives/misc.py +++ b/docutils/src/main/resources/docutils/docutils/parsers/rst/directives/misc.py @@ -1,4 +1,4 @@ -# $Id: misc.py 7487 2012-07-22 21:20:28Z milde $ +# $Id: misc.py 7961 2016-07-28 22:02:47Z milde $ # Authors: David Goodger <goodger@python.org>; Dethe Elza # Copyright: This module has been placed in the public domain. @@ -231,7 +231,7 @@ class Raw(Directive): 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, + encoding=encoding, error_handler=e_handler) try: text = raw_file.read() @@ -477,6 +477,24 @@ class Date(Directive): 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, + # no actual use case! + # + # 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 + # and self.state.document.settings.use_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: diff --git a/docutils/src/main/resources/docutils/docutils/parsers/rst/directives/tables.py b/docutils/src/main/resources/docutils/docutils/parsers/rst/directives/tables.py index 67fda63..0e890b6 100644 --- a/docutils/src/main/resources/docutils/docutils/parsers/rst/directives/tables.py +++ b/docutils/src/main/resources/docutils/docutils/parsers/rst/directives/tables.py @@ -1,4 +1,4 @@ -# $Id: tables.py 7747 2014-03-20 10:51:10Z milde $ +# $Id: tables.py 7958 2016-07-28 21:52:14Z milde $ # Authors: David Goodger <goodger@python.org>; David Priest # Copyright: This module has been placed in the public domain. @@ -20,6 +20,10 @@ 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): """ @@ -29,7 +33,10 @@ class Table(Directive): optional_arguments = 1 final_argument_whitespace = True option_spec = {'class': directives.class_option, - 'name': directives.unchanged} + 'name': directives.unchanged, + 'align': align, + 'widths': directives.value_or(('auto', 'grid'), + directives.positive_int_list)} has_content = True def make_title(self): @@ -85,15 +92,19 @@ class Table(Directive): self.block_text, self.block_text), line=self.lineno) raise SystemMessagePropagation(error) + @property + def widths(self): + return self.options.get('widths', '') + def get_column_widths(self, max_cols): - if 'widths' in self.options: - col_widths = self.options['widths'] - if len(col_widths) != max_cols: + if type(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: @@ -101,7 +112,13 @@ class Table(Directive): '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 + if self.widths == 'auto': + widths = 'auto' + elif self.widths: # "grid" or list of integers + widths = 'given' + else: + widths = self.widths + return widths, col_widths def extend_short_rows_with_empty_cells(self, columns, parts): for part in parts: @@ -130,6 +147,21 @@ class RSTTable(Table): return [error] table_node = node[0] table_node['classes'] += self.options.get('class', []) + if 'align' in self.options: + table_node['align'] = self.options.get('align') + tgroup = table_node[0] + if type(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) @@ -141,12 +173,14 @@ class CSVTable(Table): option_spec = {'header-rows': directives.nonnegative_int, 'stub-columns': directives.nonnegative_int, 'header': directives.unchanged, - 'widths': directives.positive_int_list, + '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 @@ -219,7 +253,7 @@ class CSVTable(Table): 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) + widths, col_widths = self.get_column_widths(max_cols) self.extend_short_rows_with_empty_cells(max_cols, (table_head, table_body)) except SystemMessagePropagation, detail: @@ -235,8 +269,10 @@ class CSVTable(Table): return [error] table = (col_widths, table_head, table_body) table_node = self.state.build_table(table, self.content_offset, - stub_columns) + stub_columns, widths=widths) table_node['classes'] += self.options.get('class', []) + if 'align' in self.options: + table_node['align'] = self.options.get('align') self.add_name(table_node) if title: table_node.insert(0, title) @@ -356,13 +392,15 @@ 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, - 'widths': directives.positive_int_list, + 'widths': directives.value_or(('auto', ), + directives.positive_int_list), 'class': directives.class_option, - 'name': directives.unchanged} + 'name': directives.unchanged, + 'align': align} def run(self): if not self.content: @@ -375,7 +413,7 @@ class ListTable(Table): 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) + num_cols, widths, 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) @@ -383,8 +421,10 @@ class ListTable(Table): self.check_table_dimensions(table_data, header_rows, stub_columns) except SystemMessagePropagation, detail: return [detail.args[0]] - table_node = self.build_table_from_list(table_data, col_widths, + table_node = self.build_table_from_list(table_data, widths, 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.add_name(table_node) if title: @@ -427,15 +467,20 @@ class ListTable(Table): raise SystemMessagePropagation(error) else: num_cols = len(item[0]) - col_widths = self.get_column_widths(num_cols) - return num_cols, col_widths + widths, col_widths = self.get_column_widths(num_cols) + return num_cols, widths, col_widths - def build_table_from_list(self, table_data, col_widths, header_rows, stub_columns): + def build_table_from_list(self, table_data, widths, col_widths, header_rows, + stub_columns): table = nodes.table() + if widths: + table['classes'] += ['colwidths-%s' % widths] tgroup = nodes.tgroup(cols=len(col_widths)) table += tgroup for col_width in col_widths: - colspec = nodes.colspec(colwidth=col_width) + colspec = nodes.colspec() + if col_width is not None: + colspec.attributes['colwidth'] = col_width if stub_columns: colspec.attributes['stub'] = 1 stub_columns -= 1 diff --git a/docutils/src/main/resources/docutils/docutils/parsers/rst/languages/fa.py b/docutils/src/main/resources/docutils/docutils/parsers/rst/languages/fa.py new file mode 100644 index 0000000..5547759 --- /dev/null +++ b/docutils/src/main/resources/docutils/docutils/parsers/rst/languages/fa.py @@ -0,0 +1,102 @@ +# -*- 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. +""" diff --git a/docutils/src/main/resources/docutils/docutils/parsers/rst/languages/lv.py b/docutils/src/main/resources/docutils/docutils/parsers/rst/languages/lv.py new file mode 100644 index 0000000..3f8313c --- /dev/null +++ b/docutils/src/main/resources/docutils/docutils/parsers/rst/languages/lv.py @@ -0,0 +1,108 @@ +# -*- 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. +""" diff --git a/docutils/src/main/resources/docutils/docutils/parsers/rst/roles.py b/docutils/src/main/resources/docutils/docutils/parsers/rst/roles.py index b6dca44..7fa8c1f 100644 --- a/docutils/src/main/resources/docutils/docutils/parsers/rst/roles.py +++ b/docutils/src/main/resources/docutils/docutils/parsers/rst/roles.py @@ -1,4 +1,4 @@ -# $Id: roles.py 7514 2012-09-14 14:27:12Z milde $ +# $Id: roles.py 7937 2016-05-24 10:48:48Z milde $ # Author: Edward Loper <edloper@gradient.cis.upenn.edu> # Copyright: This module has been placed in the public domain. @@ -334,7 +334,7 @@ def code_role(role, rawtext, text, lineno, inliner, options={}, content=[]): node = nodes.literal(rawtext, '', classes=classes) - # analyze content and add nodes for every token + # analyse content and add nodes for every token for classes, value in tokens: # print (classes, value) if classes: @@ -351,9 +351,10 @@ code_role.options = {'class': directives.class_option, 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) + node = nodes.math(rawtext, text, **options) return [node], [] register_canonical_role('math', math_role) diff --git a/docutils/src/main/resources/docutils/docutils/parsers/rst/states.py b/docutils/src/main/resources/docutils/docutils/parsers/rst/states.py index 30f48df..35de9d2 100644 --- a/docutils/src/main/resources/docutils/docutils/parsers/rst/states.py +++ b/docutils/src/main/resources/docutils/docutils/parsers/rst/states.py @@ -1,4 +1,4 @@ -# $Id: states.py 7640 2013-03-25 20:57:52Z milde $ +# $Id: states.py 7958 2016-07-28 21:52:14Z milde $ # Author: David Goodger <goodger@python.org> # Copyright: This module has been placed in the public domain. @@ -225,7 +225,6 @@ class RSTState(StateWS): # 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 - # print "adding get_source_and_line to reporter", self.state_machine.input_offset def goto_line(self, abs_line_offset): @@ -464,12 +463,142 @@ class Inliner: """ def __init__(self): + pass + + def init_customizations(self, settings): + # lookahead and look-behind expressions for inline markup rules + if settings.character_level_inline_markup: + 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.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), + target=re.compile(self.non_whitespace_escape_before + + r'(`)' + end_string_suffix), + substitution_ref=re.compile(self.non_whitespace_escape_before + + r'(\|_{0,2})' + + end_string_suffix), + 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 = [(self.patterns.uri, self.standalone_uri),] """List of (pattern, bound method) tuples, used by `self.implicit_inline`.""" - def init_customizations(self, settings): - """Setting-based customizations; run when parsing begins.""" if settings.pep_references: self.implicit_dispatch.append((self.patterns.pep, self.pep_reference)) @@ -527,14 +656,6 @@ class Inliner: # Inline object recognition # ------------------------- - # lookahead and look-behind expressions for inline markup rules - 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)) # print start_string_prefix.encode('utf8') # TODO: support non-ASCII whitespace in the following 4 patterns? non_whitespace_before = r'(?<![ \n])' @@ -560,118 +681,6 @@ class Inliner: %(emailc)s+(?:\.%(emailc)s*)* # host %(uri_end)s # final URI char """ - parts = ('initial_inline', start_string_prefix, '', - [('start', '', 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>__?)' % simplename, - ('footnotelabel', r'\[', r'(?P<fnend>\]_)', - [r'[0-9]+', # manually numbered - r'\#(%s)?' % simplename, # auto-numbered (w/ label?) - r'\*', # auto-symbol - r'(?P<citationlabel>%s)' % simplename] # citation reference - ) - ] - ), - ('backquote', # interpreted text or phrase reference - '(?P<role>(:%s:)?)' % simplename, # optional role - non_whitespace_after, - ['`(?!`)'] # but not literal - ) - ] - ) - patterns = Struct( - initial=build_regexp(parts), - emphasis=re.compile(non_whitespace_escape_before - + r'(\*)' + end_string_suffix, re.UNICODE), - strong=re.compile(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 - """ % locals(), re.VERBOSE | re.UNICODE), - embedded_link=re.compile( - r""" - ( - (?:[ \n]+|^) # spaces or beginning of line/string - < # open bracket - %(non_whitespace_after)s - ([^<>\x00]+(\x00_)?) # anything but angle brackets & nulls - # except escaped trailing low line - %(non_whitespace_before)s - > # close bracket w/o whitespace before - ) - $ # end of string - """ % locals(), re.VERBOSE | re.UNICODE), - literal=re.compile(non_whitespace_before + '(``)' - + end_string_suffix), - target=re.compile(non_whitespace_escape_before - + r'(`)' + end_string_suffix), - substitution_ref=re.compile(non_whitespace_escape_before - + r'(\|_{0,2})' - + end_string_suffix), - email=re.compile(email_pattern % locals() + '$', - 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 - """ + email_pattern + r""" - ) - ) - %(end_string_suffix)s - """) % locals(), 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""" % locals(), re.VERBOSE | re.UNICODE), - rfc=re.compile( - r""" - %(start_string_prefix)s - (RFC(-|\s+)?(?P<rfcnum>\d+)) - %(end_string_suffix)s""" % locals(), re.VERBOSE | re.UNICODE)) def quoted_start(self, match): """Test if inline markup start-string is 'quoted'. @@ -787,8 +796,10 @@ class Inliner: match = self.patterns.embedded_link.search(escaped) if match: # embedded <URI> or <alias_> text = unescape(escaped[:match.start(0)]) - aliastext = unescape(match.group(2), restore_backslashes=True) - if aliastext.endswith('_') and not (aliastext.endswith(r'\_') + aliastext = match.group(2) + underscore_escaped = aliastext.endswith('\x00_') + aliastext = unescape(aliastext) + if aliastext.endswith('_') and not (underscore_escaped or self.patterns.uri.match(aliastext)): aliastype = 'name' alias = normalize_name(aliastext[:-1]) @@ -1230,6 +1241,8 @@ class Body(RSTState): 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()) @@ -1460,6 +1473,7 @@ class Body(RSTState): 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, error: @@ -1547,6 +1561,9 @@ class Body(RSTState): 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, [] @@ -1747,9 +1764,11 @@ class Body(RSTState): line=startline+offset) return [error] - def build_table(self, tabledata, tableline, stub_columns=0): + def build_table(self, tabledata, tableline, stub_columns=0, widths=None): colwidths, headrows, bodyrows = tabledata table = nodes.table() + if widths: + table['classes'] += ['colwidths-%s' % widths] tgroup = nodes.tgroup(cols=len(colwidths)) table += tgroup for colwidth in colwidths: diff --git a/docutils/src/main/resources/docutils/docutils/parsers/rst/tableparser.py b/docutils/src/main/resources/docutils/docutils/parsers/rst/tableparser.py index 2cd3879..e19388b 100644 --- a/docutils/src/main/resources/docutils/docutils/parsers/rst/tableparser.py +++ b/docutils/src/main/resources/docutils/docutils/parsers/rst/tableparser.py @@ -1,4 +1,4 @@ -# $Id: tableparser.py 7320 2012-01-19 22:33:02Z milde $ +# $Id: tableparser.py 7898 2015-05-29 20:49:28Z milde $ # Author: David Goodger <goodger@python.org> # Copyright: This module has been placed in the public domain. @@ -511,8 +511,8 @@ class SimpleTableParser(TableParser): if i == lastcol and line[end:].strip(): text = line[start:].rstrip() new_end = start + len(text) - columns[i] = (start, new_end) 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(): diff --git a/docutils/src/main/resources/docutils/docutils/transforms/frontmatter.py b/docutils/src/main/resources/docutils/docutils/transforms/frontmatter.py index b39ce11..8bfc64f 100644 --- a/docutils/src/main/resources/docutils/docutils/transforms/frontmatter.py +++ b/docutils/src/main/resources/docutils/docutils/transforms/frontmatter.py @@ -1,4 +1,4 @@ -# $Id: frontmatter.py 7595 2013-01-21 17:33:56Z milde $ +# $Id: frontmatter.py 7897 2015-05-29 11:48:20Z milde $ # Author: David Goodger, Ueli Schlaepfer <goodger@python.org> # Copyright: This module has been placed in the public domain. @@ -403,7 +403,7 @@ class DocInfo(Transform): for field in field_list: try: name = field[0][0].astext() - normedname = nodes.fully_normalize_name(name) + normedname = nodes.make_id(name) if not (len(field) == 2 and normedname in bibliofields and self.check_empty_biblio_field(field, name)): raise TransformError @@ -433,6 +433,8 @@ class DocInfo(Transform): and isinstance(field[-1][0], nodes.paragraph): utils.clean_rcs_keywords( field[-1][0], self.rcs_keyword_substitutions) + if normedname and normedname not in bibliofields: + field['classes'].append(normedname) docinfo.append(field) nodelist = [] if len(docinfo) != 0: diff --git a/docutils/src/main/resources/docutils/docutils/transforms/peps.py b/docutils/src/main/resources/docutils/docutils/transforms/peps.py index 821cbcc..519a707 100644 --- a/docutils/src/main/resources/docutils/docutils/transforms/peps.py +++ b/docutils/src/main/resources/docutils/docutils/transforms/peps.py @@ -1,4 +1,4 @@ -# $Id: peps.py 6433 2010-09-28 08:21:25Z milde $ +# $Id: peps.py 7773 2014-10-08 15:08:29Z grubert $ # Author: David Goodger <goodger@python.org> # Copyright: This module has been placed in the public domain. @@ -32,8 +32,8 @@ class Headers(Transform): default_priority = 360 pep_url = 'pep-%04d' - pep_cvs_url = ('http://svn.python.org/view/*checkout*' - '/peps/trunk/pep-%04d.txt') + 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'),) diff --git a/docutils/src/main/resources/docutils/docutils/transforms/universal.py b/docutils/src/main/resources/docutils/docutils/transforms/universal.py index 3f3b55f..c485d72 100644 --- a/docutils/src/main/resources/docutils/docutils/transforms/universal.py +++ b/docutils/src/main/resources/docutils/docutils/transforms/universal.py @@ -1,4 +1,4 @@ -# $Id: universal.py 7668 2013-06-04 12:46:30Z milde $ +# $Id: universal.py 7957 2016-07-28 20:59:14Z milde $ # -*- coding: utf-8 -*- # Authors: David Goodger <goodger@python.org>; Ueli Schlaepfer; Günter Milde # Maintainer: docutils-develop@lists.sourceforge.net @@ -49,6 +49,10 @@ class Decorations(Transform): 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: diff --git a/docutils/src/main/resources/docutils/docutils/transforms/writer_aux.py b/docutils/src/main/resources/docutils/docutils/transforms/writer_aux.py index ab26b0b..c5818d9 100644 --- a/docutils/src/main/resources/docutils/docutils/transforms/writer_aux.py +++ b/docutils/src/main/resources/docutils/docutils/transforms/writer_aux.py @@ -1,4 +1,4 @@ -# $Id: writer_aux.py 7320 2012-01-19 22:33:02Z milde $ +# $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. diff --git a/docutils/src/main/resources/docutils/docutils/utils/code_analyzer.py b/docutils/src/main/resources/docutils/docutils/utils/code_analyzer.py index be23a19..c0f3109 100644 --- a/docutils/src/main/resources/docutils/docutils/utils/code_analyzer.py +++ b/docutils/src/main/resources/docutils/docutils/utils/code_analyzer.py @@ -4,7 +4,7 @@ """Lexical analysis of formal languages (i.e. code) using Pygments.""" # :Author: Georg Brandl; Felix Wiemann; Günter Milde -# :Date: $Date: 2011-12-20 15:14:21 +0100 (Die, 20. Dez 2011) $ +# :Date: $Date: 2015-04-20 16:05:27 +0200 (Mo, 20. Apr 2015) $ # :Copyright: This module has been placed in the public domain. from docutils import ApplicationError @@ -13,7 +13,7 @@ try: from pygments.lexers import get_lexer_by_name from pygments.formatters.html import _get_ttype_class with_pygments = True -except ImportError: +except (ImportError, SyntaxError): # pygments 2.0.1 fails with Py 3.1 and 3.2 with_pygments = False # Filter the following token types from the list of class arguments: diff --git a/docutils/src/main/resources/docutils/docutils/utils/error_reporting.py b/docutils/src/main/resources/docutils/docutils/utils/error_reporting.py index 19348bf..a893d21 100644 --- a/docutils/src/main/resources/docutils/docutils/utils/error_reporting.py +++ b/docutils/src/main/resources/docutils/docutils/utils/error_reporting.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # -*- coding: utf-8 -*- -# :Id: $Id: error_reporting.py 7668 2013-06-04 12:46:30Z milde $ +# :Id: $Id: error_reporting.py 7947 2016-07-22 08:49:52Z milde $ # :Copyright: © 2011 Günter Milde. # :License: Released under the terms of the `2-Clause BSD license`_, in short: # @@ -44,10 +44,18 @@ try: except ImportError: locale_encoding = None else: - 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-t...) + 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-t...) + except ValueError, 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" + except: # any other problems determining the locale -> use None + locale_encoding = None try: codecs.lookup(locale_encoding or '') # None -> '' except LookupError: @@ -72,7 +80,7 @@ class SafeString(object): def __str__(self): try: return str(self.data) - except UnicodeEncodeError, err: + except UnicodeEncodeError: if isinstance(self.data, Exception): args = [str(SafeString(arg, self.encoding, self.encoding_errors)) @@ -189,7 +197,11 @@ class ErrorOutput(object): self.stream.write(data) except UnicodeEncodeError: self.stream.write(data.encode(self.encoding, self.encoding_errors)) - except TypeError: # in Python 3, stderr expects unicode + 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: diff --git a/docutils/src/main/resources/docutils/docutils/utils/math/__init__.py b/docutils/src/main/resources/docutils/docutils/utils/math/__init__.py index 0508e4f..673f93e 100644 --- a/docutils/src/main/resources/docutils/docutils/utils/math/__init__.py +++ b/docutils/src/main/resources/docutils/docutils/utils/math/__init__.py @@ -1,4 +1,4 @@ -# :Id: $Id: __init__.py 7218 2011-11-08 17:42:40Z milde $ +# :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: # @@ -17,8 +17,9 @@ It contains various modules for conversion between different math formats :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 +: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 diff --git a/docutils/src/main/resources/docutils/docutils/utils/math/latex2mathml.py b/docutils/src/main/resources/docutils/docutils/utils/math/latex2mathml.py index 7bbdbdd..9927e43 100644 --- a/docutils/src/main/resources/docutils/docutils/utils/math/latex2mathml.py +++ b/docutils/src/main/resources/docutils/docutils/utils/math/latex2mathml.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # -*- coding: utf-8 -*- -# :Id: $Id: latex2mathml.py 7668 2013-06-04 12:46:30Z milde $ +# :Id: $Id: latex2mathml.py 7865 2015-04-12 10:06:43Z milde $ # :Copyright: © 2010 Günter Milde. # Based on rst2mathml.py from the latex_math sandbox project # © 2005 Jens Jørgen Mortensen @@ -558,3 +558,14 @@ def handle_keyword(name, node, string): 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()) + + diff --git a/docutils/src/main/resources/docutils/docutils/utils/math/math2html.py b/docutils/src/main/resources/docutils/docutils/utils/math/math2html.py index 2d3149e..c65485b 100644 --- a/docutils/src/main/resources/docutils/docutils/utils/math/math2html.py +++ b/docutils/src/main/resources/docutils/docutils/utils/math/math2html.py @@ -14,7 +14,7 @@ # .. _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/ +# http://alexfernandez.github.io/elyxer/ # --end-- # Alex 20101110 @@ -112,7 +112,7 @@ class BibStylesConfig(object): 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>$journal</i>,{ pp. $pages,} $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.}', @@ -245,7 +245,8 @@ class ContainerConfig(object): 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 space':u'Space', + 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', @@ -291,7 +292,7 @@ class EscapeConfig(object): "Configuration class from elyxer.config file" chars = { - u'\n':u'', u' -- ':u' — ', u'\'':u'’', u'---':u'—', u'`':u'‘', + u'\n':u'', u' -- ':u' — ', u' --- ':u' — ', u'\'':u'’', u'`':u'‘', } commands = { @@ -324,21 +325,24 @@ class FormulaConfig(object): alphacommands = { u'\\AA':u'Å', u'\\AE':u'Æ', - u'\\AmS':u'<span class="versalitas">AmS</span>', u'\\DH':u'Ð', - u'\\L':u'Ł', u'\\O':u'Ø', u'\\OE':u'Œ', u'\\TH':u'Þ', u'\\aa':u'å', - u'\\ae':u'æ', u'\\alpha':u'α', u'\\beta':u'β', u'\\delta':u'δ', - u'\\dh':u'ð', u'\\epsilon':u'ϵ', u'\\eta':u'η', u'\\gamma':u'γ', - u'\\i':u'ı', u'\\imath':u'ı', u'\\iota':u'ι', u'\\j':u'ȷ', - u'\\jmath':u'ȷ', u'\\kappa':u'κ', u'\\l':u'ł', u'\\lambda':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'\\sigma':u'σ', u'\\ss':u'ß', u'\\tau':u'τ', u'\\textcrh':u'ħ', - u'\\th':u'þ', u'\\theta':u'θ', u'\\upsilon':u'υ', u'\\varDelta':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'\\varepsilon':u'ε', u'\\varkappa':u'ϰ', u'\\varphi':u'φ', - u'\\varpi':u'ϖ', u'\\varrho':u'ϱ', u'\\varsigma':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'ζ', } @@ -376,59 +380,75 @@ class FormulaConfig(object): commands = { u'\\ ':u' ', u'\\!':u'', u'\\#':u'#', u'\\$':u'$', u'\\%':u'%', - u'\\&':u'&', u'\\,':u' ', u'\\:':u' ', u'\\;':u' ', - u'\\APLdownarrowbox':u'⍗', u'\\APLleftarrowbox':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'\\CheckedBox':u'☑', - u'\\Circle':u'○', u'\\Coloneqq':u'⩴', u'\\Corresponds':u'≙', - u'\\Cup':u'⋓', u'\\Delta':u'Δ', u'\\Diamond':u'◇', u'\\Downarrow':u'⇓', - u'\\EUR':u'€', u'\\Game':u'⅁', u'\\Gamma':u'Γ', u'\\Im':u'ℑ', - u'\\Join':u'⨝', u'\\LEFTCIRCLE':u'◖', u'\\LEFTcircle':u'◐', - u'\\Lambda':u'Λ', u'\\Leftarrow':u'⇐', u'\\Lleftarrow':u'⇚', - u'\\Longleftarrow':u'⟸', u'\\Longleftrightarrow':u'⟺', - u'\\Longrightarrow':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'\\RIGHTCIRCLE':u'◗', - u'\\RIGHTcircle':u'◑', u'\\Re':u'ℜ', u'\\Rrightarrow':u'⇛', - u'\\Rsh':u'↱', u'\\S':u'§', u'\\Sigma':u'Σ', u'\\Square':u'☐', - u'\\Subset':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'\\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'\\ast':u'∗', u'\\asymp':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'\\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'\\blacklozenge':u'⧫', - u'\\blacksmiley':u'☻', u'\\blacksquare':u'■', u'\\blacktriangle':u'▲', - u'\\blacktriangledown':u'▼', u'\\blacktriangleright':u'▶', u'\\bot':u'⊥', - u'\\bowtie':u'⋈', u'\\box':u'▫', u'\\boxdot':u'⊡', u'\\bullet':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'\\cdot':u'⋅', u'\\cdots':u'⋯', u'\\centerdot':u'∙', - u'\\checkmark':u'✓', u'\\chi':u'χ', u'\\circ':u'○', u'\\circeq':u'≗', - u'\\circledR':u'®', u'\\circledast':u'⊛', u'\\circledcirc':u'⊚', - u'\\circleddash':u'⊝', u'\\clubsuit':u'♣', u'\\coloneqq':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'\\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'\\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'\\earth':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'\\female':u'♀', u'\\flat':u'♭', - u'\\forall':u'∀', u'\\frown':u'⌢', u'\\frownie':u'☹', u'\\gcd':u'gcd', + 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'⋚', @@ -439,41 +459,44 @@ class FormulaConfig(object): 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'\\invneg':u'⌐', u'\\jmath':u'ȷ', - u'\\jupiter':u'♃', u'\\ker':u'ker', u'\\land':u'∧', - u'\\landupint':u'<span class="bigsymbol">∱</span>', u'\\langle':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'\\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'\\lhd':u'⊲', - u'\\libra':u'♎', u'\\lightning':u'↯', u'\\liminf':u'liminf', - u'\\limsup':u'limsup', u'\\ll':u'≪', u'\\lll':u'⋘', u'\\ln':u'ln', + 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'\\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'\\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'\\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'⋬', @@ -485,31 +508,40 @@ class FormulaConfig(object): 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'\\perp':u'⊥', - u'\\pisces':u'♓', u'\\pitchfork':u'⋔', u'\\pluto':u'♇', u'\\pm':u'±', - u'\\pointer':u'➪', u'\\pounds':u'£', u'\\prec':u'≺', - u'\\preccurlyeq':u'≼', u'\\preceq':u'≼', u'\\precsim':u'≾', - u'\\prime':u'′', u'\\prompto':u'∝', u'\\qquad':u' ', u'\\quad':u' ', - u'\\quarternote':u'♩', u'\\rangle':u'⟩', u'\\rbrace':u'}', - u'\\rbrace)':u'}', u'\\rbrack':u']', u'\\rceil':u'⌉', u'\\rfloor':u'⌋', - u'\\rhd':u'⊳', u'\\rightarrow)':u'→', u'\\rightarrowtail':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'\\risingdotseq':u'≓', u'\\rtimes':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'\\setminus':u'∖', u'\\sharp':u'♯', - u'\\simeq':u'≃', u'\\sin':u'sin', u'\\sinh':u'sinh', u'\\slash':u'∕', - u'\\smile':u'⌣', u'\\smiley':u'☺', u'\\spadesuit':u'♠', - u'\\sphericalangle':u'∢', u'\\sqcap':u'⊓', u'\\sqcup':u'⊔', - u'\\sqsubset':u'⊏', u'\\sqsubseteq':u'⊑', u'\\sqsupset':u'⊐', - u'\\sqsupseteq':u'⊒', u'\\square':u'□', u'\\star':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'\\tan':u'tan', + 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'…', @@ -520,20 +552,21 @@ class FormulaConfig(object): u'\\textregistered':u'®', u'\\textrightarrow':u'→', u'\\textsection':u'§', u'\\texttrademark':u'™', u'\\texttwosuperior':u'²', u'\\textvisiblespace':u' ', - u'\\therefore':u'∴', u'\\top':u'⊤', u'\\triangle':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'\\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'\\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'\\wedge':u'∧', u'\\wedge)':u'∧', - u'\\wp':u'℘', u'\\wr':u'≀', u'\\yen':u'¥', u'\\{':u'{', u'\\|':u'∥', - u'\\}':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 = { @@ -580,7 +613,9 @@ class FormulaConfig(object): } 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"',], @@ -589,15 +624,21 @@ class FormulaConfig(object): 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;"',], @@ -610,6 +651,7 @@ class FormulaConfig(object): 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"',], @@ -627,24 +669,24 @@ class FormulaConfig(object): } limitcommands = { - u'\\int':u'∫', u'\\intop':u'∫', u'\\lim':u'lim', u'\\prod':u'∏', - u'\\smallint':u'∫', u'\\sum':u'∑', + 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'⨡', } - # TODO: setting for simple enlarged vs. piecewise symbols - for key in (u'\\int', u'\\intop', u'\\prod', u'\\sum'): - limitcommands[key] = '<span class="symbol">%s</span>' % limitcommands[key] 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'\\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'\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 = { @@ -664,13 +706,58 @@ class FormulaConfig(object): } spacedcommands = { - u'\\Leftrightarrow':u'⇔', u'\\Rightarrow':u'⇒', u'\\approx':u'≈', - u'\\dashrightarrow':u'⇢', u'\\equiv':u'≡', u'\\ge':u'≥', u'\\geq':u'≥', + 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'\\leq':u'≤', u'\\ne':u'≠', u'\\neq':u'≠', u'\\not\\in':u'∉', - u'\\propto':u'∝', u'\\rightarrow':u'→', u'\\rightsquigarrow':u'⇝', - u'\\sim':u'~', u'\\subset':u'⊂', u'\\subseteq':u'⊆', u'\\supset':u'⊃', - u'\\supseteq':u'⊇', u'\\times':u'×', u'\\to':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 = { @@ -695,7 +782,7 @@ class FormulaConfig(object): unmodified = { - u'characters':[u'.',u'*',u'€',u'(',u')',u'[',u']',u':',u'·',u'!',u';',u'|',u'§',u'"',], + u'characters':[u'.',u'*',u'€',u'(',u')',u'[',u']',u'·',u'!',u';',u'|',u'§',u'"',], } urls = { @@ -706,7 +793,7 @@ class GeneralConfig(object): "Configuration class from elyxer.config file" version = { - u'date':u'2011-06-27', u'lyxformat':u'413', u'number':u'1.2.3', + u'date':u'2015-02-26', u'lyxformat':u'413', u'number':u'1.2.5', } class HeaderConfig(object): @@ -735,6 +822,7 @@ class ImageConfig(object): 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 = { @@ -860,6 +948,10 @@ class TagConfig(object): 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"', } @@ -889,7 +981,8 @@ class TranslationConfig(object): 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'spanish':u'es', + u'english':u'en', u'french':u'fr', u'ngerman':u'de', u'russian':u'ru', + u'spanish':u'es', } @@ -936,7 +1029,7 @@ class CommandLineParser(object): initial = args[0] del args[0] return key, self.readquoted(args, initial) - value = args[0] + value = args[0].decode('utf-8') del args[0] if isinstance(current, list): current.append(value) @@ -945,8 +1038,10 @@ class CommandLineParser(object): 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('--'): @@ -983,6 +1078,7 @@ class Options(object): unicode = False iso885915 = False css = [] + favicon = '' title = None directory = None destdirectory = None @@ -1062,6 +1158,8 @@ class Options(object): 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: @@ -1069,6 +1167,8 @@ class Options(object): 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'): @@ -1088,6 +1188,7 @@ class Options(object): return Options.marginfoot = False Options.letterfoot = False + Options.hoverfoot = False options = Options.footnotes.split(',') for option in options: footoption = option + 'foot' @@ -1113,7 +1214,8 @@ class Options(object): 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 elyxer.a CSS file into the output') + 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') @@ -1143,8 +1245,8 @@ class Options(object): 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(' --jsmath "URL": use jsMath from elyxer.the given URL to display equations') - Trace.error(' --mathjax "URL": use MathJax from elyxer.the given URL to display equations') + 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') @@ -1152,6 +1254,7 @@ class Options(object): 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): @@ -3536,11 +3639,17 @@ class BarredText(TaggedText): return self.output.tag = TagConfig.barred[self.type] -class LangLine(BlackBox): +class LangLine(TaggedText): "A line with language information" def process(self): - self.lang = self.header[1] + "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." @@ -3908,8 +4017,7 @@ class Reference(Link): 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: - if '$' in self.formatted: - Trace.error('No title in ' + unicode(partkey)) + # there is a $ left, but it should go away on preprocessing self.contents = [Constant(self.formatted)] return pieces = self.formatted.split('$') @@ -4481,6 +4589,8 @@ class BeginCommand(CommandBit): FormulaCommand.types += [BeginCommand] +import datetime + class CombiningFunction(OneParamFunction): @@ -4697,6 +4807,16 @@ class BracketProcessor(MathsProcessor): 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, diff --git a/docutils/src/main/resources/docutils/docutils/utils/math/tex2mathml_extern.py b/docutils/src/main/resources/docutils/docutils/utils/math/tex2mathml_extern.py new file mode 100644 index 0000000..ccc5593 --- /dev/null +++ b/docutils/src/main/resources/docutils/docutils/utils/math/tex2mathml_extern.py @@ -0,0 +1,147 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# :Id: $Id: tex2mathml_extern.py 7861 2015-04-10 23:48:51Z 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 +# ===================================================== + +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') + + print err + 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 = ur'\frac{\partial \sin^2(\alpha)}{\partial \vec r} \varpi \, \text{Grüße}' + # print latexml(example).encode('utf8') + # print ttm(example)#.encode('utf8') + print blahtexml(example).encode('utf8') diff --git a/docutils/src/main/resources/docutils/docutils/utils/smartquotes.py b/docutils/src/main/resources/docutils/docutils/utils/smartquotes.py index 68b1e83..ae5ccc4 100644 --- a/docutils/src/main/resources/docutils/docutils/utils/smartquotes.py +++ b/docutils/src/main/resources/docutils/docutils/utils/smartquotes.py @@ -1,7 +1,7 @@ #!/usr/bin/python # -*- coding: utf-8 -*- -# :Id: $Id: smartquotes.py 7716 2013-08-21 21:54:57Z milde $ +# :Id: $Id: smartquotes.py 7933 2016-01-13 21:09:13Z milde $ # :Copyright: © 2010 Günter Milde, # original `SmartyPants`_: © 2003 John Gruber # smartypants.py: © 2004, 2007 Chad Miller @@ -43,7 +43,7 @@ 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 +Adapted to Docutils_ by Günter Milde. Additional Credits ================== diff --git a/docutils/src/main/resources/docutils/docutils/utils/urischemes.py b/docutils/src/main/resources/docutils/docutils/utils/urischemes.py index 53d76eb..253bc5f 100644 --- a/docutils/src/main/resources/docutils/docutils/utils/urischemes.py +++ b/docutils/src/main/resources/docutils/docutils/utils/urischemes.py @@ -1,4 +1,4 @@ -# $Id: urischemes.py 7464 2012-06-25 13:16:03Z milde $ +# $Id: urischemes.py 7922 2015-09-22 15:28:09Z milde $ # Author: David Goodger <goodger@python.org> # Copyright: This module has been placed in the public domain. @@ -113,7 +113,7 @@ schemes = { '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 2806.'), + 'RFC 3966.'), 'telephone': 'telephone', 'telnet': 'Reference to interactive sessions; RFC 4248', 'tftp': 'Trivial File Transfer Protocol; RFC 3617', diff --git a/docutils/src/main/resources/docutils/docutils/writers/__init__.py b/docutils/src/main/resources/docutils/docutils/writers/__init__.py index 5e254e1..3208c8a 100644 --- a/docutils/src/main/resources/docutils/docutils/writers/__init__.py +++ b/docutils/src/main/resources/docutils/docutils/writers/__init__.py @@ -1,4 +1,4 @@ -# $Id: __init__.py 7648 2013-04-18 07:36:22Z milde $ +# $Id: __init__.py 7969 2016-08-18 21:40:00Z milde $ # Author: David Goodger <goodger@python.org> # Copyright: This module has been placed in the public domain. @@ -120,13 +120,18 @@ class UnfilteredWriter(Writer): _writer_aliases = { - 'html': 'html4css1', + 'html': 'html4css1', # may change to html5 some day + 'html4': 'html4css1', + 'html5': 'html5_polyglot', 'latex': 'latex2e', 'pprint': 'pseudoxml', 'pformat': 'pseudoxml', 'pdf': 'rlpdf', - 'xml': 'docutils_xml', - 's5': 's5_html'} + '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.""" diff --git a/docutils/src/main/resources/docutils/docutils/writers/html4css1/__init__.py b/docutils/src/main/resources/docutils/docutils/writers/_html_base.py similarity index 62% copy from docutils/src/main/resources/docutils/docutils/writers/html4css1/__init__.py copy to docutils/src/main/resources/docutils/docutils/writers/_html_base.py index 1af053e..a03231c 100644 --- a/docutils/src/main/resources/docutils/docutils/writers/html4css1/__init__.py +++ b/docutils/src/main/resources/docutils/docutils/writers/_html_base.py @@ -1,24 +1,26 @@ -# $Id: __init__.py 7753 2014-06-24 14:52:59Z 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' - +#!/usr/bin/env python +# -*- coding: utf8 -*- +# :Author: David Goodger, Günter Milde +# Based on the html4css1 writer by David Goodger. +# :Maintainer: docutils-develop@lists.sourceforge.net +# :Revision: $Revision: 7977 $ +# :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 + + +# _html_base.py: common definitions for Docutils HTML writers +# ============================================================ import sys -import os import os.path -import time import re import urllib try: # check for the Python Imaging Library @@ -31,130 +33,27 @@ except ImportError: except ImportError: PIL = None import docutils -from docutils import frontend, nodes, utils, writers, languages, io +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 -from docutils.utils.math.latex2mathml import parse_latex_math +from docutils.utils.math import (unichar2tex, pick_math_environment, + math2html, latex2mathml, tex2mathml_extern) + class Writer(writers.Writer): - supported = ('html', 'html4css1', 'xhtml') + supported = ('html', 'xhtml') # update in subclass """Formats this writer supports.""" - default_stylesheet = 'html4css1.css' - default_stylesheet_dirs = ['.', utils.relative_path( - os.path.join(os.getcwd(), 'dummy'), os.path.dirname(__file__))] - + # default_stylesheets = [] # set in subclass! + # default_stylesheet_dirs = ['.'] # set in subclass! 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 = ( - '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"' % default_stylesheet, - ['--stylesheet-path'], - {'metavar': '<file[,file,...]>', 'overrides': 'stylesheet', - 'validator': frontend.validate_comma_separated_list, - 'default': [default_stylesheet]}), - ('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}),)) + # default_template_path = ... # set in subclass! + # settings_spec = ... # set in subclass! settings_defaults = {'output_encoding_error_handler': 'xmlcharrefreplace'} - config_section = 'html4css1 writer' + # config_section = ... # set in subclass! config_section_dependencies = ('writers',) visitor_attributes = ( @@ -167,10 +66,6 @@ class Writer(writers.Writer): def get_transforms(self): return writers.Writer.get_transforms(self) + [writer_aux.Admonitions] - def __init__(self): - writers.Writer.__init__(self) - self.translator_class = HTMLTranslator - def translate(self): self.visitor = visitor = self.translator_class(self.document) self.document.walkabout(visitor) @@ -200,62 +95,21 @@ class Writer(writers.Writer): self.parts[part] = ''.join(getattr(self, part)) -class HTMLTranslator(nodes.NodeVisitor): - - """ - This HTML 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 browsers (although they really - shouldn't). - - 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). +class HTMLTranslator(nodes.NodeVisitor): - - 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. + """Generic Docutils to HTML translator. - The ``no_compact_lists`` setting (``--no-compact-lists`` command-line - option) disables list whitespace optimization. - """ + See the html4css1 and html5_polyglott for writers for full featured HTML + writers. """ xml_declaration = '<?xml version="1.0" encoding="%s" ?>\n' - doctype = ( - '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"' - ' "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">\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 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') - + content_type = ('<meta charset="%s"/>\n') generator = ('<meta name="generator" content="Docutils %s: ' 'http://docutils.sourceforge.net/" />\n') @@ -264,9 +118,9 @@ class HTMLTranslator(nodes.NodeVisitor): # The latest version of MathJax from the distributed server: # avaliable to the public under the `MathJax CDN Terms of Service`__ # __http://www.mathjax.org/download/mathjax-cdn-terms-of-service/ - mathjax_url = ('http://cdn.mathjax.org/mathjax/latest/MathJax.js?' - 'config=TeX-AMS-MML_HTMLorMML') # may be overwritten by custom URL appended to "mathjax" + mathjax_url = ('https://cdn.mathjax.org/mathjax/latest/MathJax.js?' + 'config=TeX-AMS_CHTML') stylesheet_link = '<link rel="stylesheet" href="%s" type="text/css" />\n' embedded_stylesheet = '<style type="text/css">\n\n%s\n</style>\n' @@ -274,6 +128,14 @@ class HTMLTranslator(nodes.NodeVisitor): sollbruchstelle = re.compile(r'.+\W\W.+|[-?].+', re.U) # wrap point inside word 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 @@ -285,6 +147,7 @@ class HTMLTranslator(nodes.NodeVisitor): 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[:] @@ -308,13 +171,15 @@ class HTMLTranslator(nodes.NodeVisitor): # A heterogenous stack used in conjunction with the tree traversal. # Make sure that the pops correspond to the pushes: self.context = [] - self.topic_classes = [] + + 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 = [] @@ -325,7 +190,7 @@ class HTMLTranslator(nodes.NodeVisitor): self.html_body = [] self.in_document_title = 0 # len(self.body) or 0 self.in_mailto = False - self.author_in_authors = False + self.author_in_authors = False # for html4css1 self.math_header = [] def astext(self): @@ -336,16 +201,11 @@ class HTMLTranslator(nodes.NodeVisitor): 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({ - ord('&'): u'&', - ord('<'): u'<', - ord('"'): u'"', - ord('>'): u'>', - ord('@'): u'@', # may thwart some address harvesters - # TODO: convert non-breaking space only if needed? - 0xa0: u' '}) # non-breaking space + return text.translate(self.special_characters) def cloak_mailto(self, uri): """Try to hide a mailto: URL from harvesters.""" @@ -428,8 +288,11 @@ class HTMLTranslator(nodes.NodeVisitor): # 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: - # Empty tag. Insert target right in front of element. + if empty or isinstance(node, + (nodes.bullet_list, nodes.enumerated_list, + nodes.definition_list, nodes.field_list, + nodes.option_list, nodes.docinfo)): + # Insert target right in front of element. prefix.append('<span id="%s"></span>' % id) else: # Non-empty tag. Place the auxiliary <span> tag @@ -471,10 +334,6 @@ class HTMLTranslator(nodes.NodeVisitor): return child['classes'].append(class_) - def set_first_last(self, node): - self.set_class_on_child(node, 'first', 0) - self.set_class_on_child(node, 'last', -1) - def visit_Text(self, node): text = node.astext() encoded = self.encode(text) @@ -501,20 +360,21 @@ class HTMLTranslator(nodes.NodeVisitor): def visit_address(self, node): self.visit_docinfo_item(node, 'address', meta=False) - self.body.append(self.starttag(node, 'pre', CLASS='address')) + 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')) - self.set_first_last(node) def depart_admonition(self, node=None): self.body.append('</div>\n') - attribution_formats = {'dash': ('—', ''), + attribution_formats = {'dash': (u'\u2014', ''), 'parentheses': ('(', ')'), 'parens': ('(', ')'), 'none': ('', '')} @@ -529,21 +389,19 @@ class HTMLTranslator(nodes.NodeVisitor): self.body.append(self.context.pop() + '</p>\n') def visit_author(self, node): - if isinstance(node.parent, nodes.authors): - if self.author_in_authors: - self.body.append('\n<br />') - else: + 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.author_in_authors = True + self.body.append('\n') 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() @@ -560,17 +418,38 @@ class HTMLTranslator(nodes.NodeVisitor): try: node.walk(visitor) except nodes.NodeFound: - return None + return False else: - return 1 + 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): - 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'] - or self.check_simple_list(node)))) + # print "is_compactable %s ?" % node.__class__, + # 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): + # print "`compact-field-lists` is False" + return False + if (isinstance(node, (nodes.enumerated_list, nodes.bullet_list)) + and not self.settings.compact_lists): + # print "`compact-lists` is False" + 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 = {} @@ -592,18 +471,22 @@ class HTMLTranslator(nodes.NodeVisitor): 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): - 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) + 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('</td></tr>\n' - '</tbody>\n</table>\n') + 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 = '#' @@ -619,8 +502,11 @@ class HTMLTranslator(nodes.NodeVisitor): 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(' <span class="classifier-delimiter">:</span> ') self.body.append(self.starttag(node, 'span', '', CLASS='classifier')) def depart_classifier(self, node): @@ -632,17 +518,21 @@ class HTMLTranslator(nodes.NodeVisitor): node.parent.stubs.append(node.attributes.get('stub')) def depart_colspec(self, node): - pass - - def write_colspecs(self): - width = 0 - for node in self.colspecs: - width += node['colwidth'] + # 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 / width + 0.5) + colwidth = int(node['colwidth'] * 100.0 / total_width + 0.5) self.body.append(self.emptytag(node, 'col', - width='%i%%' % colwidth)) - self.colspecs = [] + style='width: %i%%' % colwidth)) + self.body.append('</colgroup>\n') def visit_comment(self, node, sub=re.compile('-(?=-)').sub): @@ -663,7 +553,7 @@ class HTMLTranslator(nodes.NodeVisitor): self.body.append('</div>\n') def visit_container(self, node): - self.body.append(self.starttag(node, 'div', CLASS='container')) + self.body.append(self.starttag(node, 'div', CLASS='docutils container')) def depart_container(self, node): self.body.append('</div>\n') @@ -695,66 +585,61 @@ class HTMLTranslator(nodes.NodeVisitor): def visit_definition(self, node): self.body.append('</dt>\n') self.body.append(self.starttag(node, 'dd', '')) - self.set_first_last(node) def depart_definition(self, node): self.body.append('</dd>\n') def visit_definition_list(self, node): - self.body.append(self.starttag(node, 'dl', CLASS='docutils')) + 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 + # 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, 'td', '')) - self.set_first_last(node) + self.body.append(self.starttag(node, 'dd', '')) def depart_description(self, node): - self.body.append('</td>') + self.body.append('</dd>\n') 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 + 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('</tbody>\n</table>\n') - self.in_docinfo = False - start = self.context.pop() - self.docinfo = self.body[start:] - self.body = [] + self.body.append('</dl>\n') 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') + 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('</td></tr>\n') + self.body.append('</dd>\n') def visit_doctest_block(self, node): - self.body.append(self.starttag(node, 'pre', CLASS='doctest-block')) + self.body.append(self.starttag(node, 'pre', suffix='', + CLASS='code python doctest')) def depart_doctest_block(self, node): self.body.append('\n</pre>\n') @@ -812,110 +697,61 @@ class HTMLTranslator(nodes.NodeVisitor): node.parent.column += node['morecols'] self.body.append(self.starttag(node, tagname, '', **atts)) self.context.append('</%s>\n' % tagname.lower()) - if len(node) == 0: # empty cell - self.body.append(' ') - self.set_first_last(node) + # 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): - """ - The 'start' attribute does not conform to HTML 4.01's strict.dtd, but - CSS1 doesn't help. CSS2 isn't widely enough supported yet to be - usable. - """ 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: + 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.compact_simple, self.compact_p = self.context.pop() self.body.append('</ol>\n') - 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_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 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_list(self, node): + self.body.append('</dl>\n') - def depart_field_body(self, node): - self.body.append('</td>\n') + def visit_field(self, node): + pass - 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(self, node): + pass - def depart_field_list(self, node): - self.body.append('</tbody>\n</table>\n') - self.compact_field_list, self.compact_p = self.context.pop() + # as field is ignored, pass class arguments to field-name and field-body: 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)) + self.body.append(self.starttag(node, 'dt', '', + CLASS=''.join(node.parent['classes']))) def depart_field_name(self, node): - self.body.append(':</th>') - self.body.append(self.context.pop()) + 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'} @@ -928,6 +764,7 @@ class HTMLTranslator(nodes.NodeVisitor): 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)) @@ -941,65 +778,43 @@ class HTMLTranslator(nodes.NodeVisitor): 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): - 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: - i = 1 - for backref in backrefs: - backlinks.append('<a class="fn-backref" href="#%s">%s</a>' - % (backref, i)) - i += 1 - 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') + 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('</td></tr>\n' - '</tbody>\n</table>\n') + 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'] - 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)) + 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(self.context.pop() + '</a>') + self.body.append('</a>') + # Docutils-generated text: put section numbers in a span for CSS styling: def visit_generated(self, node): - pass + if 'sectnum' in node['classes']: + # get section number (strip trailing no-break-spaces) + sectnum = node.astext().rstrip(u' ') + # print sectnum.encode('utf-8') + self.body.append('<span class="sectnum">%s</span> ' + % self.encode(sectnum)) + # Content already processed: + raise nodes.SkipNode def depart_generated(self, node): pass @@ -1016,16 +831,16 @@ class HTMLTranslator(nodes.NodeVisitor): 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'] - # place SVG and SWF images in an <object> element - types = {'.svg': 'image/svg+xml', - '.swf': 'application/x-shockwave-flash'} ext = os.path.splitext(uri)[1].lower() - if ext in ('.svg', '.swf'): + if ext in self.object_image_types: atts['data'] = uri - atts['type'] = types[ext] + atts['type'] = self.object_image_types[ext] else: atts['src'] = uri atts['alt'] = node.get('alt', uri) @@ -1077,8 +892,7 @@ class HTMLTranslator(nodes.NodeVisitor): suffix = '\n' if 'align' in node: atts['class'] = 'align-%s' % node['align'] - self.context.append('') - if ext in ('.svg', '.swf'): # place in an object element, + 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) @@ -1086,7 +900,8 @@ class HTMLTranslator(nodes.NodeVisitor): self.body.append(self.emptytag(node, 'img', suffix, **atts)) def depart_image(self, node): - self.body.append(self.context.pop()) + # self.body.append(self.context.pop()) + pass def visit_inline(self, node): self.body.append(self.starttag(node, 'span', '')) @@ -1094,14 +909,35 @@ class HTMLTranslator(nodes.NodeVisitor): def depart_inline(self, node): self.body.append('</span>') + # footnote and citation labels: def visit_label(self, node): - # Context added in footnote_backrefs. - self.body.append(self.starttag(node, 'td', '%s[' % self.context.pop(), - CLASS='label')) + 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): - # Context added in footnote_backrefs. - self.body.append(']%s</td><td>%s' % (self.context.pop(), self.context.pop())) + 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: + # Python 2.4 fails with enumerate(backrefs, 1) + backlinks = ['<a href="#%s">%s</a>' % (ref, i+1) + for (i, ref) in enumerate(backrefs)] + 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')) @@ -1125,12 +961,11 @@ class HTMLTranslator(nodes.NodeVisitor): def visit_list_item(self, node): self.body.append(self.starttag(node, 'li', '')) - if len(node): - node[0]['classes'].append('first') def depart_list_item(self, node): self.body.append('</li>\n') + # inline literal def visit_literal(self, node): # special case: "code" role classes = node.get('classes', []) @@ -1140,24 +975,20 @@ class HTMLTranslator(nodes.NodeVisitor): self.body.append(self.starttag(node, 'code', '')) return self.body.append( - self.starttag(node, 'tt', '', CLASS='docutils literal')) + 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(): - # Protect text like "--an-option" and the regular expression - # ``[+]?(\d+(\.\d*)?|\.\d+)`` from bad line wrapping - if self.sollbruchstelle.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) + if token.strip() and self.sollbruchstelle.search(token): + self.body.append('<span class="pre">%s</span>' + % self.encode(token)) else: - # Protect runs of multiple spaces; the last space can wrap: - self.body.append(' ' * (len(token) - 1) + ' ') - self.body.append('</tt>') + self.body.append(self.encode(token)) + self.body.append('</span>') # Content already processed: raise nodes.SkipNode @@ -1166,46 +997,55 @@ class HTMLTranslator(nodes.NodeVisitor): self.body.append('</code>') def visit_literal_block(self, node): - self.body.append(self.starttag(node, 'pre', CLASS='literal-block')) + 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): - self.body.append('\n</pre>\n') + 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 != ''. - # As there is no native HTML math support, we provide alternatives: - # LaTeX and MathJax math_output modes simply wrap the content, - # HTML and MathML math_output modes also convert the math_code. - if self.math_output not in ('mathml', 'html', 'mathjax', 'latex'): + 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' - # - # HTML container - tags = {# math_output: (block, inline, class-arguments) - 'mathml': ('div', '', ''), - 'html': ('div', 'span', 'formula'), - 'mathjax': ('div', 'span', 'math'), - 'latex': ('pre', 'tt', 'math'), - } - tag = tags[self.math_output][math_env == ''] - clsarg = tags[self.math_output][2] + 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': (None, None), + 'mathml': ('$%s$', u'\\begin{%s}\n%s\n\\end{%s}'), 'html': ('$%s$', u'\\begin{%s}\n%s\n\\end{%s}'), 'mathjax': ('\(%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 and math_env: - math_code = wrapper % (math_env, math_code, math_env) - elif wrapper: - math_code = wrapper % math_code + 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) @@ -1222,11 +1062,29 @@ class HTMLTranslator(nodes.NodeVisitor): math2html.DocumentParameters.displaymode = (math_env != '') math_code = math2html.math2html(math_code) elif self.math_output == 'mathml': - self.doctype = self.doctype_mathml - self.content_type = self.content_type_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: - mathml_tree = parse_latex_math(math_code, inline=not(math_env)) - math_code = ''.join(mathml_tree.xml()) + 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, err: err_node = self.document.reporter.error(err, base_node=node) self.visit_system_message(err_node) @@ -1265,6 +1123,8 @@ class HTMLTranslator(nodes.NodeVisitor): 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) @@ -1277,13 +1137,13 @@ class HTMLTranslator(nodes.NodeVisitor): self.head.append(tag) def visit_option(self, node): - if self.context[-1]: - self.body.append(', ') self.body.append(self.starttag(node, 'span', '', CLASS='option')) def depart_option(self, node): self.body.append('</span>') - self.context[-1] += 1 + 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', ' ')) @@ -1293,39 +1153,24 @@ class HTMLTranslator(nodes.NodeVisitor): self.body.append('</var>') 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(self.starttag(node, 'dt', '')) 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()) + self.body.append('</kbd></dt>\n') 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') + self.starttag(node, 'dl', CLASS='option-list')) def depart_option_list(self, node): - self.body.append('</tbody>\n</table>\n') + self.body.append('</dl>\n') def visit_option_list_item(self, node): - self.body.append(self.starttag(node, 'tr', '')) + pass def depart_option_list_item(self, node): - self.body.append('</tr>\n') + pass def visit_option_string(self, node): pass @@ -1339,45 +1184,29 @@ class HTMLTranslator(nodes.NodeVisitor): def depart_organization(self, node): self.depart_docinfo_item() - 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 + # 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): - if self.should_be_compact_paragraph(node): - self.context.append('') - else: - self.body.append(self.starttag(node, 'p', '')) - self.context.append('</p>\n') + self.body.append(self.starttag(node, 'p', '')) def depart_paragraph(self, node): - self.body.append(self.context.pop()) + 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'): @@ -1446,6 +1275,7 @@ class HTMLTranslator(nodes.NodeVisitor): 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( @@ -1455,10 +1285,10 @@ class HTMLTranslator(nodes.NodeVisitor): 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.set_first_last(node) self.in_sidebar = True def depart_sidebar(self, node): @@ -1490,24 +1320,22 @@ class HTMLTranslator(nodes.NodeVisitor): 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): - self.body.append(self.starttag(node, 'p', '', - CLASS='sidebar-subtitle')) - self.context.append('</p>\n') + classes = 'sidebar-subtitle' elif isinstance(node.parent, nodes.document): - self.body.append(self.starttag(node, 'h2', '', CLASS='subtitle')) - self.context.append('</h2>\n') + classes = 'subtitle' 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) + classes = 'section-subtitle' + self.body.append(self.starttag(node, 'p', '', CLASS=classes)) def depart_subtitle(self, node): - self.body.append(self.context.pop()) + self.body.append('</p>\n') if self.in_document_title: self.subtitle = self.body[self.in_document_title:-1] self.in_document_title = 0 @@ -1543,22 +1371,26 @@ class HTMLTranslator(nodes.NodeVisitor): else: line = '' self.body.append('System Message: %s/%s ' - '(<tt class="docutils">%s</tt>%s)%s</p>\n' + '(<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') + # tables + # ------ + # no hard-coded border setting in the table head:: + def visit_table(self, node): - self.context.append(self.compact_p) - self.compact_p = True - classes = ' '.join(['docutils', self.settings.table_style]).strip() - self.body.append( - self.starttag(node, 'table', CLASS=classes, border="1")) + classes = [cls.strip(u' \t\n') + for cls in self.settings.table_style.split(',')] + if 'align' in node: + classes.append('align-%s' % node['align']) + tag = self.starttag(node, 'table', CLASS=' '.join(classes)) + self.body.append(tag) def depart_table(self, node): - self.compact_p = self.context.pop() self.body.append('</table>\n') def visit_target(self, node): @@ -1572,10 +1404,9 @@ class HTMLTranslator(nodes.NodeVisitor): 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.write_colspecs() - self.body.append(self.context.pop()) # '</colgroup>\n' or '' - self.body.append(self.starttag(node, 'tbody', valign='top')) + self.body.append(self.starttag(node, 'tbody')) def depart_tbody(self, node): self.body.append('</tbody>\n') @@ -1591,21 +1422,14 @@ class HTMLTranslator(nodes.NodeVisitor): pass def visit_tgroup(self, node): - # Mozilla needs <colgroup>: - self.body.append(self.starttag(node, 'colgroup')) - # Appended by thead or tbody: - self.context.append('</colgroup>\n') + self.colspecs = [] node.stubs = [] def depart_tgroup(self, node): pass def visit_thead(self, node): - self.write_colspecs() - self.body.append(self.context.pop()) # '</colgroup>\n' - # There may or may not be a <thead>; this is for <tbody> to use: - self.context.append('') - self.body.append(self.starttag(node, 'thead', valign='bottom')) + self.body.append(self.starttag(node, 'thead')) def depart_thead(self, node): self.body.append('</thead>\n') @@ -1666,13 +1490,17 @@ class HTMLTranslator(nodes.NodeVisitor): 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')) @@ -1698,39 +1526,73 @@ class SimpleListChecker(nodes.GenericNodeVisitor): 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_bullet_list(self, node): - pass - - def visit_enumerated_list(self, node): - pass - def visit_list_item(self, node): - children = [] - for child in node.children: - if not isinstance(child, nodes.Invisible): - children.append(child) + # print "visiting list item", node.__class__ + children = [child for child in node.children + if not isinstance(child, nodes.Invisible)] + # print "has %s visible children" % len(children) if (children and isinstance(children[0], nodes.paragraph) - and (isinstance(children[-1], nodes.bullet_list) - or isinstance(children[-1], nodes.enumerated_list))): + and (isinstance(children[-1], nodes.bullet_list) or + isinstance(children[-1], nodes.enumerated_list) or + isinstance(children[-1], nodes.field_list))): children.pop() + # print "%s children remain" % len(children) if len(children) <= 1: return else: + # print "found", child.__class__, "in", node.__class__ raise nodes.NodeFound - def visit_paragraph(self, node): - raise nodes.SkipNode + def pass_node(self, node): + pass - def invisible_visit(self, node): - """Invisible nodes should be ignored.""" + def ignore_node(self, node): + # ignore nodes that are never complex (can contain only inline nodes) raise nodes.SkipNode - visit_comment = invisible_visit - visit_substitution_definition = invisible_visit - visit_target = invisible_visit - visit_pending = invisible_visit + # 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 diff --git a/docutils/src/main/resources/docutils/docutils/writers/docutils_xml.py b/docutils/src/main/resources/docutils/docutils/writers/docutils_xml.py index 036817b..79f3dbd 100644 --- a/docutils/src/main/resources/docutils/docutils/writers/docutils_xml.py +++ b/docutils/src/main/resources/docutils/docutils/writers/docutils_xml.py @@ -1,4 +1,4 @@ -# $Id: docutils_xml.py 7497 2012-08-16 15:17:29Z milde $ +# $Id: docutils_xml.py 7966 2016-08-18 13:06:09Z milde $ # Author: David Goodger, Paul Tremblay, Guenter Milde # Maintainer: docutils-develop@lists.sourceforge.net # Copyright: This module has been placed in the public domain. @@ -46,7 +46,7 @@ class Writer(writers.Writer): ['--newlines'], {'action': 'store_true', 'validator': frontend.validate_boolean}), ('Generate XML with indents and newlines.', - ['--indents'], + ['--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'], @@ -105,9 +105,10 @@ class XMLTranslator(nodes.GenericNodeVisitor): self.newline = '\n' if settings.indents: self.newline = '\n' - self.indent = ' ' + 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 = [] @@ -125,13 +126,19 @@ class XMLTranslator(nodes.GenericNodeVisitor): # 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 - if isinstance(node, nodes.TextElement): + # @@ 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) @@ -142,7 +149,9 @@ class XMLTranslator(nodes.GenericNodeVisitor): if not self.in_simple: self.output.append(self.indent*self.level) self.output.append(node.endtag()) - if isinstance(node, nodes.TextElement): + 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) @@ -153,6 +162,9 @@ class XMLTranslator(nodes.GenericNodeVisitor): 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): diff --git a/docutils/src/main/resources/docutils/docutils/writers/html4css1/__init__.py b/docutils/src/main/resources/docutils/docutils/writers/html4css1/__init__.py index 1af053e..7853496 100644 --- a/docutils/src/main/resources/docutils/docutils/writers/html4css1/__init__.py +++ b/docutils/src/main/resources/docutils/docutils/writers/html4css1/__init__.py @@ -1,4 +1,4 @@ -# $Id: __init__.py 7753 2014-06-24 14:52:59Z milde $ +# $Id: __init__.py 7977 2016-11-29 12:00:39Z milde $ # Author: David Goodger # Maintainer: docutils-develop@lists.sourceforge.net # Copyright: This module has been placed in the public domain. @@ -14,43 +14,28 @@ for proper viewing with a modern graphical browser. __docformat__ = 'reStructuredText' - -import sys -import os import os.path -import time -import re -import urllib -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 frontend, nodes, utils, writers, languages, io -from docutils.utils.error_reporting import SafeString +from docutils import frontend, nodes, writers, io from docutils.transforms import writer_aux -from docutils.utils.math import unichar2tex, pick_math_environment, math2html -from docutils.utils.math.latex2mathml import parse_latex_math +from docutils.writers import _html_base -class Writer(writers.Writer): +class Writer(writers._html_base.Writer): - supported = ('html', 'html4css1', 'xhtml') + supported = ('html', 'html4', 'html4css1', 'xhtml', 'xhtml10') """Formats this writer supports.""" - default_stylesheet = 'html4css1.css' - default_stylesheet_dirs = ['.', utils.relative_path( - os.path.join(os.getcwd(), 'dummy'), os.path.dirname(__file__))] + 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 = utils.relative_path( - os.path.join(os.getcwd(), 'dummy'), - os.path.join(os.path.dirname(__file__), default_template)) + default_template_path = os.path.join( + os.path.dirname(os.path.abspath(__file__)), default_template) settings_spec = ( 'HTML-Specific Options', @@ -68,11 +53,11 @@ class Writer(writers.Writer): '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"' % default_stylesheet, + 'Default: "%s"' % ','.join(default_stylesheets), ['--stylesheet-path'], {'metavar': '<file[,file,...]>', 'overrides': 'stylesheet', 'validator': frontend.validate_comma_separated_list, - 'default': [default_stylesheet]}), + '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'], @@ -152,65 +137,24 @@ class Writer(writers.Writer): ['--cloak-email-addresses'], {'action': 'store_true', 'validator': frontend.validate_boolean}),)) - settings_defaults = {'output_encoding_error_handler': 'xmlcharrefreplace'} - config_section = 'html4css1 writer' - config_section_dependencies = ('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 __init__(self): - writers.Writer.__init__(self) + self.parts = {} self.translator_class = HTMLTranslator - 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): +class HTMLTranslator(writers._html_base.HTMLTranslator): """ - This HTML writer has been optimized to produce visually compact + 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 browsers (although they really + 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: @@ -243,291 +187,46 @@ class HTMLTranslator(nodes.NodeVisitor): option) disables list whitespace optimization. """ - xml_declaration = '<?xml version="1.0" encoding="%s" ?>\n' + # 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') - 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 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') - 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' - # The latest version of MathJax from the distributed server: - # avaliable to the public under the `MathJax CDN Terms of Service`__ - # __http://www.mathjax.org/download/mathjax-cdn-terms-of-service/ - mathjax_url = ('http://cdn.mathjax.org/mathjax/latest/MathJax.js?' - 'config=TeX-AMS-MML_HTMLorMML') - # may be overwritten by custom URL appended to "mathjax" - - 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'\S+| +|\n') - sollbruchstelle = re.compile(r'.+\W\W.+|[-?].+', re.U) # wrap point inside word - lang_attribute = 'lang' # name changes to 'xml:lang' in XHTML 1.1 - - 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) - # 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() - - # A heterogenous stack used in conjunction with the tree traversal. - # Make sure that the pops correspond to the pushes: - self.context = [] - self.topic_classes = [] - self.colspecs = [] - self.compact_p = True - self.compact_simple = False - self.compact_field_list = False - self.in_docinfo = False - self.in_sidebar = 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 - 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.""" - # @@@ A codec to do these and all other HTML entities would be nice. - text = unicode(text) - return text.translate({ - ord('&'): u'&', - ord('<'): u'<', - ord('"'): u'"', - ord('>'): u'>', - ord('@'): u'@', # may thwart some address harvesters - # TODO: convert non-breaking space only if needed? - 0xa0: u' '}) # non-breaking space - - 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, 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: - # Empty tag. 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 = atts.items() - attlist.sort() - 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 + # encode also non-breaking space + special_characters = dict(_html_base.HTMLTranslator.special_characters) + special_characters[0xa0] = u' ' - 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_) + # 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) - 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>') - + # add newline after opening tag def visit_address(self, node): self.visit_docinfo_item(node, 'address', meta=False) self.body.append(self.starttag(node, 'pre', CLASS='address')) - def depart_address(self, node): - self.body.append('\n</pre>\n') - self.depart_docinfo_item() + # ersatz for first/last pseudo-classes def visit_admonition(self, node): + node['classes'].insert(0, 'admonition') self.body.append(self.starttag(node, 'div')) self.set_first_last(node) - def depart_admonition(self, node=None): - self.body.append('</div>\n') - - attribution_formats = {'dash': ('—', ''), - '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') - + # author, authors: use <br> instead of paragraphs def visit_author(self, node): if isinstance(node.parent, nodes.authors): if self.author_in_authors: @@ -548,21 +247,8 @@ class HTMLTranslator(nodes.NodeVisitor): 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 None - else: - return 1 + # Compact lists: + # exclude definition lists and field lists (non-compact by default) def is_compactable(self, node): return ('compact' in node['classes'] @@ -570,28 +256,10 @@ class HTMLTranslator(nodes.NodeVisitor): 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)))) - 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 table for bibliographic references. def visit_citation(self, node): self.body.append(self.starttag(node, 'table', CLASS='docutils citation', @@ -605,32 +273,12 @@ class HTMLTranslator(nodes.NodeVisitor): self.body.append('</td></tr>\n' '</tbody>\n</table>\n') - def visit_citation_reference(self, node): - href = '#' - if 'refid' in node: - href += node['refid'] - elif 'refname' in node: - href += self.document.nameids[node['refname']] - # 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>') - + # insert classifier-delimiter (not required with CSS2) def visit_classifier(self, node): self.body.append(' <span class="classifier-delimiter">:</span> ') self.body.append(self.starttag(node, 'span', '', CLASS='classifier')) - def depart_classifier(self, node): - self.body.append('</span>') - - 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')) - + # rewritten in _html_base (support for "auto" width) def depart_colspec(self, node): pass @@ -644,74 +292,17 @@ class HTMLTranslator(nodes.NodeVisitor): width='%i%%' % colwidth)) self.colspecs = [] - 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='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 - + # 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) - def depart_definition(self, node): - self.body.append('</dd>\n') - + # don't add "simple" class value def visit_definition_list(self, node): self.body.append(self.starttag(node, 'dl', CLASS='docutils')) - def depart_definition_list(self, node): - self.body.append('</dl>\n') - - def visit_definition_list_item(self, node): - pass - - def depart_definition_list_item(self, node): - pass - + # use a table for description lists def visit_description(self, node): self.body.append(self.starttag(node, 'td', '')) self.set_first_last(node) @@ -719,6 +310,7 @@ class HTMLTranslator(nodes.NodeVisitor): 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', @@ -753,77 +345,22 @@ class HTMLTranslator(nodes.NodeVisitor): def depart_docinfo_item(self): self.body.append('</td></tr>\n') + # add newline after opening tag def visit_doctest_block(self, node): self.body.append(self.starttag(node, 'pre', CLASS='doctest-block')) - def depart_doctest_block(self, node): - self.body.append('\n</pre>\n') - - def visit_document(self, node): - self.head.append('<title>%s</title>\n' - % self.encode(node.get('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 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>') - + # insert an NBSP into empty cells, ersatz for first/last 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()) + writers._html_base.HTMLTranslator.visit_entry(self, node) if len(node) == 0: # empty cell self.body.append(' ') self.set_first_last(node) - def depart_entry(self, node): - self.body.append(self.context.pop()) - + # ersatz for first/last pseudo-classes def visit_enumerated_list(self, node): """ The 'start' attribute does not conform to HTML 4.01's strict.dtd, but - CSS1 doesn't help. CSS2 isn't widely enough supported yet to be - usable. + cannot be emulated in CSS1 (HTML 5 reincludes it). """ atts = {} if 'start' in node: @@ -844,6 +381,7 @@ class HTMLTranslator(nodes.NodeVisitor): 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')) @@ -906,7 +444,7 @@ class HTMLTranslator(nodes.NodeVisitor): and len(node.astext()) > self.settings.field_name_limit): atts['colspan'] = 2 self.context.append('</tr>\n' - + self.starttag(node.parent, 'tr', '', + + self.starttag(node.parent, 'tr', '', CLASS='field') + '<td> </td>') else: @@ -917,30 +455,7 @@ class HTMLTranslator(nodes.NodeVisitor): self.body.append(':</th>') self.body.append(self.context.pop()) - 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') - - 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:] - + # use table for footnote text def visit_footnote(self, node): self.body.append(self.starttag(node, 'table', CLASS='docutils footnote', @@ -960,11 +475,10 @@ class HTMLTranslator(nodes.NodeVisitor): self.context.append('<a class="fn-backref" href="#%s">' % backrefs[0]) else: - i = 1 - for backref in backrefs: + # Python 2.4 fails with enumerate(backrefs, 1) + for (i, backref) in enumerate(backrefs): backlinks.append('<a class="fn-backref" href="#%s">%s</a>' - % (backref, i)) - i += 1 + % (backref, i+1)) self.context.append('<em>(%s)</em> ' % ', '.join(backlinks)) self.context += ['', ''] else: @@ -982,6 +496,7 @@ class HTMLTranslator(nodes.NodeVisitor): 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 @@ -998,139 +513,34 @@ class HTMLTranslator(nodes.NodeVisitor): def depart_footnote_reference(self, node): self.body.append(self.context.pop() + '</a>') + # just pass on generated text def visit_generated(self, node): pass - 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:] - - def visit_image(self, node): - atts = {} - uri = node['uri'] - # place SVG and SWF images in an <object> element - types = {'.svg': 'image/svg+xml', - '.swf': 'application/x-shockwave-flash'} - ext = os.path.splitext(uri)[1].lower() - if ext in ('.svg', '.swf'): - atts['data'] = uri - atts['type'] = 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 = urllib.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'] - self.context.append('') - if ext in ('.svg', '.swf'): # place in an object element, - # 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): - self.body.append(self.context.pop()) - - def visit_inline(self, node): - self.body.append(self.starttag(node, 'span', '')) - - def depart_inline(self, node): - self.body.append('</span>') + # 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): - # Context added in footnote_backrefs. self.body.append(self.starttag(node, 'td', '%s[' % self.context.pop(), CLASS='label')) def depart_label(self, node): - # Context added in footnote_backrefs. self.body.append(']%s</td><td>%s' % (self.context.pop(), self.context.pop())) - 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') + # ersatz for first/last pseudo-classes def visit_list_item(self, node): self.body.append(self.starttag(node, 'li', '')) if len(node): node[0]['classes'].append('first') - def depart_list_item(self, node): - self.body.append('</li>\n') - + # use <tt> (not supported by HTML5), + # cater for limited styling options in CSS1 using hard-coded NBSPs def visit_literal(self, node): # special case: "code" role classes = node.get('classes', []) @@ -1161,137 +571,15 @@ class HTMLTranslator(nodes.NodeVisitor): # Content already processed: raise nodes.SkipNode - def depart_literal(self, node): - # skipped unless literal element is from "code" role: - self.body.append('</code>') - + # add newline after 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') - def visit_math(self, node, math_env=''): - # If the method is called from visit_math_block(), math_env != ''. - - # As there is no native HTML math support, we provide alternatives: - # LaTeX and MathJax math_output modes simply wrap the content, - # HTML and MathML math_output modes also convert the math_code. - if self.math_output not in ('mathml', 'html', 'mathjax', 'latex'): - self.document.reporter.error( - 'math-output format "%s" not supported ' - 'falling back to "latex"'% self.math_output) - self.math_output = 'latex' - # - # HTML container - tags = {# math_output: (block, inline, class-arguments) - 'mathml': ('div', '', ''), - 'html': ('div', 'span', 'formula'), - 'mathjax': ('div', 'span', 'math'), - 'latex': ('pre', 'tt', 'math'), - } - tag = tags[self.math_output][math_env == ''] - clsarg = tags[self.math_output][2] - # LaTeX container - wrappers = {# math_mode: (inline, block) - 'mathml': (None, None), - 'html': ('$%s$', u'\\begin{%s}\n%s\n\\end{%s}'), - 'mathjax': ('\(%s\)', u'\\begin{%s}\n%s\n\\end{%s}'), - 'latex': (None, None), - } - wrapper = wrappers[self.math_output][math_env != ''] - # get and wrap content - math_code = node.astext().translate(unichar2tex.uni2tex_table) - if wrapper and math_env: - math_code = wrapper % (math_env, math_code, math_env) - elif wrapper: - 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: - if self.math_output_options: - self.mathjax_url = self.math_output_options[0] - 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': - self.doctype = self.doctype_mathml - self.content_type = self.content_type_mathml - try: - mathml_tree = parse_latex_math(math_code, inline=not(math_env)) - math_code = ''.join(mathml_tree.xml()) - except SyntaxError, 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): - # print node.astext().encode('utf8') - 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_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): - if self.context[-1]: - self.body.append(', ') - self.body.append(self.starttag(node, 'span', '', CLASS='option')) - - def depart_option(self, node): - self.body.append('</span>') - self.context[-1] += 1 - - 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>') - + # use table for option list def visit_option_group(self, node): atts = {} if ( self.settings.option_limit @@ -1327,18 +615,8 @@ class HTMLTranslator(nodes.NodeVisitor): def depart_option_list_item(self, node): self.body.append('</tr>\n') - 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() - + # 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. @@ -1379,117 +657,28 @@ class HTMLTranslator(nodes.NodeVisitor): def depart_paragraph(self, node): self.body.append(self.context.pop()) - 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') - - 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') - + # ersatz for first/last pseudo-classes def visit_sidebar(self, node): self.body.append( self.starttag(node, 'div', CLASS='sidebar')) self.set_first_last(node) self.in_sidebar = True - def depart_sidebar(self, node): - self.body.append('</div>\n') - self.in_sidebar = False - - 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>') - + # <sub> not allowed in <pre> def visit_subscript(self, node): - self.body.append(self.starttag(node, 'sub', '')) + 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): - 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) + 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', '', @@ -1515,12 +704,21 @@ class HTMLTranslator(nodes.NodeVisitor): self.html_subtitle.extend(self.body) del self.body[:] + # <sup> not allowed in <pre> in HTML 4 def visit_superscript(self, node): - self.body.append(self.starttag(node, 'sup', '')) + 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): - self.body.append('</sup>') + 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">') @@ -1547,59 +745,34 @@ class HTMLTranslator(nodes.NodeVisitor): % (node['type'], node['level'], self.encode(node['source']), line, backref_text)) - def depart_system_message(self, node): - self.body.append('</div>\n') - + # "hard coded" border setting def visit_table(self, node): self.context.append(self.compact_p) self.compact_p = True - classes = ' '.join(['docutils', self.settings.table_style]).strip() + classes = ['docutils', self.settings.table_style] + if 'align' in node: + classes.append('align-%s' % node['align']) self.body.append( - self.starttag(node, 'table', CLASS=classes, border="1")) + self.starttag(node, 'table', CLASS=' '.join(classes), border="1")) def depart_table(self, node): self.compact_p = self.context.pop() 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()) - + # hard-coded vertical alignment def visit_tbody(self, node): self.write_colspecs() self.body.append(self.context.pop()) # '</colgroup>\n' or '' self.body.append(self.starttag(node, 'tbody', valign='top')) - 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 - + # rewritten in _html_base def visit_tgroup(self, node): - # Mozilla needs <colgroup>: self.body.append(self.starttag(node, 'colgroup')) # Appended by thead or tbody: self.context.append('</colgroup>\n') node.stubs = [] - def depart_tgroup(self, node): - pass - + # rewritten in _html_base def visit_thead(self, node): self.write_colspecs() self.body.append(self.context.pop()) # '</colgroup>\n' @@ -1607,91 +780,8 @@ class HTMLTranslator(nodes.NodeVisitor): self.context.append('') self.body.append(self.starttag(node, 'thead', valign='bottom')) - def depart_thead(self, node): - self.body.append('</thead>\n') - - def visit_title(self, node): - """Only 6 section levels are supported by HTML.""" - check_id = 0 # TODO: is this a bool (False) or a counter? - close_tag = '</p>\n' - if isinstance(node.parent, nodes.topic): - self.body.append( - self.starttag(node, 'p', '', CLASS='topic-title first')) - 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>') - - def visit_topic(self, node): - self.body.append(self.starttag(node, 'div', CLASS='topic')) - self.topic_classes = node['classes'] - - def depart_topic(self, node): - self.body.append('</div>\n') - self.topic_classes = [] - - 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): +class SimpleListChecker(writers._html_base.SimpleListChecker): """ Raise `nodes.NodeFound` if non-simple list item is encountered. @@ -1700,15 +790,6 @@ class SimpleListChecker(nodes.GenericNodeVisitor): paragraph, a simple list, or a paragraph followed by a simple list. """ - def default_visit(self, node): - raise nodes.NodeFound - - def visit_bullet_list(self, node): - pass - - def visit_enumerated_list(self, node): - pass - def visit_list_item(self, node): children = [] for child in node.children: @@ -1723,14 +804,20 @@ class SimpleListChecker(nodes.GenericNodeVisitor): else: raise nodes.NodeFound - def visit_paragraph(self, node): - raise nodes.SkipNode + # def visit_bullet_list(self, node): + # pass - def invisible_visit(self, node): - """Invisible nodes should be ignored.""" - raise nodes.SkipNode + # def visit_enumerated_list(self, node): + # pass - visit_comment = invisible_visit - visit_substitution_definition = invisible_visit - visit_target = invisible_visit - visit_pending = invisible_visit + # 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 + + def visit_definition_list(self, node): + raise nodes.NodeFound diff --git a/docutils/src/main/resources/docutils/docutils/writers/html4css1/html4css1.css b/docutils/src/main/resources/docutils/docutils/writers/html4css1/html4css1.css index 39a0369..427d33e 100644 --- a/docutils/src/main/resources/docutils/docutils/writers/html4css1/html4css1.css +++ b/docutils/src/main/resources/docutils/docutils/writers/html4css1/html4css1.css @@ -1,6 +1,6 @@ /* :Author: David Goodger (goodger@python.org) -:Id: $Id: html4css1.css 7614 2013-02-21 15:55:51Z milde $ +: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. @@ -28,6 +28,14 @@ table.borderless td, table.borderless th { .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 } @@ -152,12 +160,12 @@ h2.subtitle { hr.docutils { width: 75% } -img.align-left, .figure.align-left, object.align-left { +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 { +img.align-right, .figure.align-right, object.align-right, table.align-right { clear: right ; float: right ; margin-left: 1em } @@ -168,6 +176,11 @@ img.align-center, .figure.align-center, object.align-center { margin-right: auto; } +table.align-center { + margin-left: auto; + margin-right: auto; +} + .align-left { text-align: left } @@ -185,6 +198,15 @@ div.align-right { /* 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 } diff --git a/docutils/src/main/resources/docutils/docutils/writers/html5_polyglot/__init__.py b/docutils/src/main/resources/docutils/docutils/writers/html5_polyglot/__init__.py new file mode 100644 index 0000000..c14c5ee --- /dev/null +++ b/docutils/src/main/resources/docutils/docutils/writers/html5_polyglot/__init__.py @@ -0,0 +1,200 @@ +# .. coding: utf8 +# :Author: Günter Milde <milde@users.sf.net> +# Based on the html4css1 writer by David Goodger. +# :Maintainer: docutils-develop@lists.sourceforge.net +# :Revision: $Revision: 7977 $ +# :Date: $Date: 2005-06-28$ +# :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 = 'html-plain writer' + + def __init__(self): + self.parts = {} + self.translator_class = HTMLTranslator + + +class HTMLTranslator(writers._html_base.HTMLTranslator): + """ + This writer generates `polyglot markup`: HTML 5 that is also valid XML. + """ + # def __init__(self, document): + # writers._html_base.HTMLTranslator.__init__(self, document) + + + # <acronym> tag not supported 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 meta tag in HTML 5 + def visit_authors(self, node): + self.visit_docinfo_item(node, 'authors', meta=False) + + def visit_copyright(self, node): + self.visit_docinfo_item(node, 'copyright', meta=False) + + # no meta tag in HTML 5 + def visit_date(self, node): + self.visit_docinfo_item(node, 'date', meta=False) + + # TODO: use HTML 5 <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): + + # 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) + + # no meta tag in HTML 5 + def visit_organization(self, node): + self.visit_docinfo_item(node, 'organization', meta=False) + + # TODO: use the new HTML 5 element <section>? + # def visit_section(self, node): + + # TODO: use the new HTML5 element <aside>? + # def visit_topic(self, node): diff --git a/docutils/src/main/resources/docutils/docutils/writers/html4css1/math.css b/docutils/src/main/resources/docutils/docutils/writers/html5_polyglot/math.css similarity index 100% rename from docutils/src/main/resources/docutils/docutils/writers/html4css1/math.css rename to docutils/src/main/resources/docutils/docutils/writers/html5_polyglot/math.css diff --git a/docutils/src/main/resources/docutils/docutils/writers/html5_polyglot/minimal.css b/docutils/src/main/resources/docutils/docutils/writers/html5_polyglot/minimal.css new file mode 100644 index 0000000..5eb5b3d --- /dev/null +++ b/docutils/src/main/resources/docutils/docutils/writers/html5_polyglot/minimal.css @@ -0,0 +1,260 @@ +/* Minimal style sheet for the HTML output of Docutils. */ +/* */ +/* :Author: Günter Milde, based on html4css1.css by David Goodger */ +/* :Id: $Id: minimal.css 7952 2016-07-26 18:15:59Z 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.admonition-title, +p.topic-title, +p.sidebar-title, +p.rubric, +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; } +ul.auto-toc { + 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: 40px; } +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, +img.align-left, +object.align-left, +table.align-left { + margin-right: auto; +} +.figure.align-center, +img.align-center, +object.align-center { + margin-left: auto; + margin-right: auto; + display: block; +} +table.align-center { + margin-left: auto; + margin-right: auto; +} +.figure.align-right, +img.align-right, +object.align-right, +table.align-right { + margin-left: auto; +} +/* reset inner alignment in figures and tables */ +div.align-left, div.align-center, div.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{ + margin: 40px; + border: medium outset; + padding-right: 1em; + padding-left: 1em; +} + +/* Sidebar */ +div.sidebar { + width: 30%; + max-width: 26em; + float: right; + clear: right; +} + +/* Text Blocks */ +div.topic, +pre.literal-block, +pre.doctest-block, +pre.math, +pre.code { + margin-right: 40px; + margin-left: 40px; +} +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 */ +} diff --git a/docutils/src/main/resources/docutils/docutils/writers/html5_polyglot/plain.css b/docutils/src/main/resources/docutils/docutils/writers/html5_polyglot/plain.css new file mode 100644 index 0000000..aeccf7a --- /dev/null +++ b/docutils/src/main/resources/docutils/docutils/writers/html5_polyglot/plain.css @@ -0,0 +1,288 @@ +/* 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 7952 2016-07-26 18:15:59Z 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 { + padding: 0 5%; + margin: 8px 0; +} +div.document { + 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; + margin: auto; +} + +/* 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, +table{ + margin-top: 0.5em; + margin-bottom: 0.5em; +} +h1, h2, h3, h4, h5, h6, +dl > dd { + margin-bottom: 0.5em; +} + +/* Lists */ +/* ========== */ + +/* Definition Lists */ + +dl > dd p:first-child { margin-top: 0; } +/* :last-child is not part of CSS 2.1 (introduced in CSS 3) */ +/* dl > dd p:last-child { margin-bottom: 0; } */ + +/* lists nested in definition lists */ +/* :only-child is not part of CSS 2.1 (introduced 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 { + margin-left: 1.5em; + margin-right: 1.5em +} + +/* Block Quotes */ + +blockquote, +div.topic { + margin-left: 1.5em; + margin-right: 1.5em +} +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, +img.align-left, +object.align-left { + display: block; + clear: left; + float: left; + margin-right: 1em +} +.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 into the margin. In a layout with fixed margins, */ +/* it can be moved into the margin completely. */ +div.sidebar { + width: 30%; + max-width: 26em; + margin-left: 1em; + margin-right: -5.5%; + background-color: #ffffee ; +} + +/* Code */ + +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 */ + +div.footer, div.header { + clear: both; + font-size: smaller; +} + +/* 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 */ diff --git a/docutils/src/main/resources/docutils/docutils/writers/html5_polyglot/template.txt b/docutils/src/main/resources/docutils/docutils/writers/html5_polyglot/template.txt new file mode 100644 index 0000000..2591bce --- /dev/null +++ b/docutils/src/main/resources/docutils/docutils/writers/html5_polyglot/template.txt @@ -0,0 +1,8 @@ +%(head_prefix)s +%(head)s +%(stylesheet)s +%(body_prefix)s +%(body_pre_docinfo)s +%(docinfo)s +%(body)s +%(body_suffix)s diff --git a/docutils/src/main/resources/docutils/docutils/writers/latex2e/__init__.py b/docutils/src/main/resources/docutils/docutils/writers/latex2e/__init__.py index 0d23218..112bc76 100644 --- a/docutils/src/main/resources/docutils/docutils/writers/latex2e/__init__.py +++ b/docutils/src/main/resources/docutils/docutils/writers/latex2e/__init__.py @@ -1,5 +1,5 @@ # .. coding: utf-8 -# $Id: __init__.py 7745 2014-02-28 14:15:59Z milde $ +# $Id: __init__.py 7971 2016-09-13 19:11:48Z milde $ # Author: Engelbert Gruber, Günter Milde # Maintainer: docutils-develop@lists.sourceforge.net # Copyright: This module has been placed in the public domain. @@ -34,12 +34,14 @@ class Writer(writers.Writer): """Formats this writer supports.""" default_template = 'default.tex' - default_template_path = os.path.dirname(__file__) - + 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, @@ -54,14 +56,6 @@ class Writer(writers.Writer): ['--docutils-footnotes'], {'default': True, 'action': 'store_true', 'validator': frontend.validate_boolean}), - ('Alias for --docutils-footnotes (deprecated)', - ['--use-latex-footnotes'], - {'action': 'store_true', - 'validator': frontend.validate_boolean}), - ('Use figure floats for footnote text (deprecated)', - ['--figure-footnotes'], - {'action': 'store_true', - 'validator': frontend.validate_boolean}), ('Format for footnote references: one of "superscript" or ' '"brackets". Default is "superscript".', ['--footnote-references'], @@ -190,9 +184,11 @@ class Writer(writers.Writer): 'above and below the table and below the header or "borderless". ' 'Default: "standard"', ['--table-style'], - {'choices': ['standard', 'booktabs','nolines', 'borderless'], - 'default': 'standard', - 'metavar': '<format>'}), + {'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. ' @@ -490,7 +486,7 @@ PreambleCmds.admonition = r""" \csname DUadmonition#1\endcsname{#2}% \else \begin{center} - \fbox{\parbox{0.9\textwidth}{#2}} + \fbox{\parbox{0.9\linewidth}{#2}} \end{center} \fi }""" @@ -509,7 +505,7 @@ PreambleCmds.color = r"""\usepackage{color}""" PreambleCmds.docinfo = r""" % docinfo (width of docinfo table) -\DUprovidelength{\DUdocinfowidth}{0.9\textwidth}""" +\DUprovidelength{\DUdocinfowidth}{0.9\linewidth}""" # PreambleCmds.docinfo._depends = 'providelength' PreambleCmds.dedication = r""" @@ -546,17 +542,6 @@ PreambleCmds.footnotes = r"""% numeric or symbol footnotes with hyperlinks \endgroup% }""" -PreambleCmds.footnote_floats = r"""% settings for footnotes as floats: -\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}""" - PreambleCmds.graphicx_auto = r"""% Check output format \ifx\pdftexversion\undefined \usepackage{graphicx} @@ -612,6 +597,7 @@ PreambleCmds.linking = r""" %% hyperlinks: \ifthenelse{\isundefined{\hypersetup}}{ \usepackage[%s]{hyperref} + \usepackage{bookmark} \urlstyle{same} %% normal text font (alternatives: tt, rm, sf) }{}""" @@ -650,7 +636,7 @@ PreambleCmds.sidebar = r""" % sidebar (text outside the main text flow) \providecommand{\DUsidebar}[2][class-arg]{% \begin{center} - \colorbox[gray]{0.80}{\parbox{0.9\textwidth}{#2}} + \colorbox[gray]{0.80}{\parbox{0.9\linewidth}{#2}} \end{center} }""" @@ -711,7 +697,13 @@ PreambleCmds.transition = r""" class CharMaps(object): """LaTeX representations for active and Unicode characters.""" - # characters that always need escaping: + # characters that need escaping even in `alltt` environments: + alltt = { + ord('\\'): ur'\textbackslash{}', + ord('{'): ur'\{', + ord('}'): ur'\}', + } + # characters that normally need escaping: special = { ord('#'): ur'\#', ord('$'): ur'\$', @@ -720,9 +712,6 @@ class CharMaps(object): ord('~'): ur'\textasciitilde{}', ord('_'): ur'\_', ord('^'): ur'\textasciicircum{}', - ord('\\'): ur'\textbackslash{}', - ord('{'): ur'\{', - ord('}'): ur'\}', # straight double quotes are 'active' in many languages ord('"'): ur'\textquotedbl{}', # Square brackets are ordinary chars and cannot be escaped with '\', @@ -752,9 +741,9 @@ class CharMaps(object): } # Unicode chars that are recognized by LaTeX's utf8 encoding utf8_supported_unicode = { - 0x00AB: ur'\guillemotleft', # LEFT-POINTING DOUBLE ANGLE QUOTATION MARK - 0x00bb: ur'\guillemotright', # RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK - 0x200C: ur'\textcompwordmark', # ZERO WIDTH NON-JOINER + 0x00AB: ur'\guillemotleft{}', # LEFT-POINTING DOUBLE ANGLE QUOTATION MARK + 0x00bb: ur'\guillemotright{}', # RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK + 0x200C: ur'\textcompwordmark{}', # ZERO WIDTH NON-JOINER 0x2013: ur'\textendash{}', 0x2014: ur'\textemdash{}', 0x2018: ur'\textquoteleft{}', @@ -901,17 +890,20 @@ class Table(object): :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,table_style): + def __init__(self, translator, latex_type): self._translator = translator self._latex_type = latex_type - self._table_style = table_style 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): @@ -926,13 +918,23 @@ class Table(object): self.caption = [] self._attrs = {} self.stubs = [] + self.colwidths_auto = False + def is_open(self): return self._open - def set_table_style(self, table_style): - if not table_style in ('standard','booktabs','borderless','nolines'): - return - self._table_style = table_style + 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: @@ -948,20 +950,26 @@ class Table(object): return None def get_vertical_bar(self): - if self._table_style == 'standard': + if self.borders == 'standard': return '|' return '' # horizontal lines are drawn below a row, def get_opening(self): - return '\n'.join([r'\setlength{\DUtablewidth}{\linewidth}', - r'\begin{%s}[c]' % self.get_latex_type()]) + 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}{\linewidth}') + return '\n'.join(opening) def get_closing(self): closing = [] - if self._table_style == 'booktabs': + if self.borders == 'booktabs': closing.append(r'\bottomrule') - # elif self._table_style == 'standard': + # elif self.borders == 'standard': # closing.append(r'\hline') closing.append(r'\end{%s}' % self.get_latex_type()) return '\n'.join(closing) @@ -971,7 +979,7 @@ class Table(object): # "stubs" list is an attribute of the tgroup element: self.stubs.append(node.attributes.get('stub')) - def get_colspecs(self): + def get_colspecs(self, node): """Return column specification for longtable. Assumes reST line length being 80 characters. @@ -983,38 +991,45 @@ class Table(object): 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 - self._col_width = [] - self._rowspan = [] # donot make it full linewidth factor = 0.93 if total_width > 1.0: factor /= total_width - bar = self.get_vertical_bar() latex_table_spec = '' for node in self._col_specs: colwidth = factor * float(node['colwidth']+1) / width self._col_width.append(colwidth+0.005) - self._rowspan.append(0) 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).""" - return '%.2f\\DUtablewidth' % self._col_width[self._cell_in_row-1] + 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.""" - mc_width = sum([width - for width in ([self._col_width[start + co - 1] - for co in range (len_)])]) - return '%.2f\\DUtablewidth' % mc_width + 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: @@ -1031,17 +1046,17 @@ class Table(object): def visit_thead(self): self._in_thead += 1 - if self._table_style == 'standard': + if self.borders == 'standard': return ['\\hline\n'] - elif self._table_style == 'booktabs': + elif self.borders == 'booktabs': return ['\\toprule\n'] return [] def depart_thead(self): a = [] - #if self._table_style == 'standard': + #if self.borders == 'standard': # a.append('\\hline\n') - if self._table_style == 'booktabs': + if self.borders == 'booktabs': a.append('\\midrule\n') if self._latex_type == 'longtable': if 1 == self._translator.thead_depth(): @@ -1054,8 +1069,10 @@ class Table(object): # 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 @@ -1063,7 +1080,7 @@ class Table(object): if (self._rowspan[i]>0): self._rowspan[i] -= 1 - if self._table_style == 'standard': + 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): @@ -1086,18 +1103,22 @@ class Table(object): 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-1] + return self.stubs[self._cell_in_row] return False @@ -1142,7 +1163,7 @@ class LaTeXTranslator(nodes.NodeVisitor): 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) @@ -1167,7 +1188,7 @@ class LaTeXTranslator(nodes.NodeVisitor): self.section_enumerator_separator = ( settings.section_enumerator_separator.replace('_', r'\_')) # literal blocks: - self.literal_block_env = '' + self.literal_block_env = 'alltt' self.literal_block_options = '' if settings.literal_block_env != '': (none, @@ -1204,16 +1225,10 @@ class LaTeXTranslator(nodes.NodeVisitor): self.settings.graphicx_option) # footnotes: self.docutils_footnotes = settings.docutils_footnotes - if settings.use_latex_footnotes: - self.docutils_footnotes = True - self.warn('`use_latex_footnotes` is deprecated. ' - 'The setting has been renamed to `docutils_footnotes` ' - 'and the alias will be removed in a future version.') - self.figure_footnotes = settings.figure_footnotes - if self.figure_footnotes: - self.docutils_footnotes = True - self.warn('The "figure footnotes" workaround/setting is strongly ' - 'deprecated and will be removed in a future version.') + # @@ 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 # ~~~~~~~~~~~~~~~~~~~~~~~~ @@ -1271,7 +1286,7 @@ class LaTeXTranslator(nodes.NodeVisitor): # object for a table while proccessing. self.table_stack = [] - self.active_table = Table(self, 'longtable', settings.table_style) + self.active_table = Table(self, 'longtable') # Where to collect the output of visitor methods (default: body) self.out = self.body @@ -1447,16 +1462,17 @@ class LaTeXTranslator(nodes.NodeVisitor): def encode(self, text): """Return text with 'problematic' characters escaped. - * Escape the ten special printing characters ``# $ % & ~ _ ^ \ { }``, + * 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.special.copy() + table = CharMaps.alltt.copy() + if not self.alltt: + table.update(CharMaps.special) # keep the underscore in citation references if self.inside_citation_reference_label: del(table[ord('_')]) @@ -1854,7 +1870,7 @@ class LaTeXTranslator(nodes.NodeVisitor): raise nodes.SkipNode self.out.append('\\textbf{%s}: &\n\t' % self.language_label(name)) if name == 'address': - self.insert_newline = 1 + self.insert_newline = True self.out.append('{\\raggedright\n') self.context.append(' } \\\\\n') else: @@ -1954,78 +1970,74 @@ class LaTeXTranslator(nodes.NodeVisitor): 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): - self.active_table.visit_entry() # cell separation - # BUG: the following fails, with more than one multirow - # starting in the second column (or later) see - # ../../../test/functional/input/data/latex.txt - if self.active_table.get_entry_number() == 1: - # if the first row is a multirow, this actually is the second row. - # this gets hairy if rowspans follow each other. - if self.active_table.get_rowspan(0): - count = 0 - while self.active_table.get_rowspan(count): - count += 1 - self.out.append(' & ') - self.active_table.visit_entry() # increment cell count + if self.active_table.get_entry_number() == 0: + self.insert_additional_table_colum_delimiters() else: self.out.append(' & ') + # multirow, multicolumn - # IN WORK BUG TODO HACK continues here - # 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 and 'morecols' in node: raise NotImplementedError('Cells that ' - 'span multiple rows *and* columns are not supported, sorry.') + '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-tabl... + # 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}' - count = node['morerows'] + 1 + mrows = node['morerows'] + 1 self.active_table.set_rowspan( - self.active_table.get_entry_number()-1,count) - # TODO why does multirow end on % ? needs to be checked for below - self.out.append('\\multirow{%d}{%s}{%%' % - (count,self.active_table.get_column_width())) + 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() == 1: + if self.active_table.get_entry_number() == 0: bar1 = self.active_table.get_vertical_bar() else: bar1 = '' - count = node['morecols'] + 1 - self.out.append('\\multicolumn{%d}{%sp{%s}%s}{' % - (count, 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(), - count), + mcols), self.active_table.get_vertical_bar())) self.context.append('}') else: self.context.append('') - # header / not header - if isinstance(node.parent.parent, nodes.thead): - if self.out[-1].endswith("%"): - self.out.append("\n") - self.out.append('\\textbf{%') - self.context.append('}') - elif self.active_table.is_stub_column(): - if self.out[-1].endswith("%"): - self.out.append("\n") + # 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("{"): + 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 - # if following row is spanned from above. - if self.active_table.get_rowspan(self.active_table.get_entry_number()): - self.out.append(' & ') - self.active_table.visit_entry() # increment cell count + # 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() @@ -2034,59 +2046,63 @@ class LaTeXTranslator(nodes.NodeVisitor): self.out.extend(self.active_table.depart_row()) def visit_enumerated_list(self, node): - # We create our own enumeration list environment. - # This allows to set the style and starting value - # and unlimited nesting. - enum_style = {'arabic':'arabic', - 'loweralpha':'alph', - 'upperalpha':'Alph', - 'lowerroman':'roman', - 'upperroman':'Roman' } - enum_suffix = '' - if 'suffix' in node: - enum_suffix = node['suffix'] - enum_prefix = '' - if 'prefix' in node: - enum_prefix = node['prefix'] + # 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: - pref = '' - if self.section_prefix_for_enumerators and self.section_level: - for i in range(self.section_level): - pref += '%d.' % self._section_number[i] - pref = pref[:-1] + self.section_enumerator_separator - enum_prefix += pref - for ctype, cname in self._enumeration_counters: - enum_prefix += '\\%s{%s}.' % (ctype, cname) - enum_type = 'arabic' - if 'enumtype' in node: - enum_type = node['enumtype'] - if enum_type in enum_style: - enum_type = enum_style[enum_type] - - counter_name = 'listcnt%d' % len(self._enumeration_counters) - self._enumeration_counters.append((enum_type, counter_name)) - # If we haven't used this counter name before, then create a - # new counter; otherwise, reset & reuse the old counter. - if len(self._enumeration_counters) > self._max_enumeration_counters: - self._max_enumeration_counters = len(self._enumeration_counters) - self.out.append('\\newcounter{%s}\n' % counter_name) + 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) + + if enumeration_level <= 4: + self.out.append('\\begin{enumerate}\n') + if (prefix, enumtype, suffix + ) != labels[enumeration_level-1]: + self.out.append('\\renewcommand{\\label%s}{%s}\n' % + (counter_name, label)) else: - self.out.append('\\setcounter{%s}{0}\n' % counter_name) - - self.out.append('\\begin{list}{%s\\%s{%s}%s}\n' % - (enum_prefix,enum_type,counter_name,enum_suffix)) - self.out.append('{\n') - self.out.append('\\usecounter{%s}\n' % counter_name) - # set start after usecounter, because it initializes to zero. + self.fallbacks[counter_name] = '\\newcounter{%s}' % counter_name + self.out.append('\\begin{list}') + self.out.append('{%s}' % label) + self.out.append('{\\usecounter{%s}}\n' % counter_name) if 'start' in node: - self.out.append('\\addtocounter{%s}{%d}\n' % + self.out.append('\\setcounter{%s}{%d}\n' % (counter_name,node['start']-1)) - ## set rightmargin equal to leftmargin - self.out.append('\\setlength{\\rightmargin}{\\leftmargin}\n') - self.out.append('}\n') + # ## set rightmargin equal to leftmargin + # self.out.append('\\setlength{\\rightmargin}{\\leftmargin}\n') + + def depart_enumerated_list(self, node): - self.out.append('\\end{list}\n') + if len(self._enumeration_counters) <= 4: + self.out.append('\\end{enumerate}\n') + else: + self.out.append('\\end{list}\n') self._enumeration_counters.pop() def visit_field(self, node): @@ -2139,7 +2155,7 @@ class LaTeXTranslator(nodes.NodeVisitor): # 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 textwidth, + # 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('\n\\begin{figure} %% align = "%s"\n' % alignment) @@ -2165,30 +2181,22 @@ class LaTeXTranslator(nodes.NodeVisitor): backref = node['backrefs'][0] except IndexError: backref = node['ids'][0] # no backref, use self-ref instead - if self.settings.figure_footnotes: - self.requirements['~fnt_floats'] = PreambleCmds.footnote_floats - self.out.append('\\begin{figure}[b]') - self.append_hypertargets(node) - if node.get('id') == node.get('name'): # explicite label - self.out += self.ids_to_labels(node) - elif self.docutils_footnotes: + if self.docutils_footnotes: self.fallbacks['footnotes'] = PreambleCmds.footnotes - num,text = node.astext().split(None,1) + 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: - self.out.append('%') + # mask newline to prevent spurious whitespace if paragraph follows: + if node[1:] and isinstance(node[1], nodes.paragraph): + self.out.append('%') ## else: # TODO: "real" LaTeX \footnote{}s def depart_footnote(self, node): - if self.figure_footnotes: - self.out.append('\\end{figure}\n') - else: - self.out.append('}\n') + self.out.append('}\n') def visit_footnote_reference(self, node): href = '' @@ -2223,12 +2231,7 @@ class LaTeXTranslator(nodes.NodeVisitor): # footnote/citation label def label_delim(self, node, bracket, superscript): if isinstance(node.parent, nodes.footnote): - if not self.figure_footnotes: - raise nodes.SkipNode - if self.settings.footnote_references == 'brackets': - self.out.append(bracket) - else: - self.out.append(superscript) + raise nodes.SkipNode else: assert isinstance(node.parent, nodes.citation) if not self._use_latex_citations: @@ -2306,7 +2309,7 @@ class LaTeXTranslator(nodes.NodeVisitor): 'middle': (r'\raisebox{-0.5\height}{', '}'), 'top': (r'\raisebox{-\height}{', '}'), # block level images: - 'center': (r'\noindent\makebox[\textwidth][c]{', '}'), + 'center': (r'\noindent\makebox[\linewidth][c]{', '}'), 'left': (r'\noindent{', r'\hfill}'), 'right': (r'\noindent{\hfill', '}'),} if 'align' in attrs: @@ -2442,27 +2445,37 @@ class LaTeXTranslator(nodes.NodeVisitor): def visit_literal_block(self, node): """Render a literal block.""" # environments and packages to typeset literal blocks - packages = {'listing': r'\usepackage{moreverb}', + packages = {'alltt': r'\usepackage{alltt}', + 'listing': r'\usepackage{moreverb}', 'lstlisting': r'\usepackage{listings}', 'Verbatim': r'\usepackage{fancyvrb}', # 'verbatim': '', 'verbatimtab': r'\usepackage{moreverb}'} + if node.get('ids'): + self.out += ['\n'] + self.ids_to_labels(node) + if not self.active_table.is_open(): # no quote inside tables, to avoid vertical space between # table border and literal block. - # BUG: fails if normal text precedes the literal block. - self.out.append('%\n\\begin{quote}') + # TODO: fails if normal text precedes the literal block. + # check parent node instead? + self.out.append('%\n\\begin{quote}\n') self.context.append('\n\\end{quote}\n') else: self.out.append('\n') self.context.append('\n') - if self.literal_block_env != '' and self.is_plaintext(node): - self.requirements['literal_block'] = packages.get( - self.literal_block_env, '') - self.verbatim = True - self.out.append('\\begin{%s}%s\n' % (self.literal_block_env, - self.literal_block_options)) + + if self.is_plaintext(node): + environment = self.literal_block_env + self.requirements['literal_block'] = packages.get(environment, '') + if environment == 'alltt': + self.alltt = True + else: + self.verbatim = True + self.out.append('\\begin{%s}%s\n' % + (environment, self.literal_block_options)) + self.context.append('\n\\end{%s}' % environment) else: self.literal = True self.insert_newline = True @@ -2472,16 +2485,15 @@ class LaTeXTranslator(nodes.NodeVisitor): self.requirements['color'] = PreambleCmds.color self.fallbacks['code'] = PreambleCmds.highlight_rules self.out.append('{\\ttfamily \\raggedright \\noindent\n') + self.context.append('\n}') def depart_literal_block(self, node): - if self.verbatim: - self.out.append('\n\\end{%s}\n' % self.literal_block_env) - self.verbatim = False - else: - self.out.append('\n}') - self.insert_non_breaking_blanks = False - self.insert_newline = False - self.literal = False + 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()) ## def visit_meta(self, node): @@ -2509,7 +2521,10 @@ class LaTeXTranslator(nodes.NodeVisitor): if node.get('ids'): math_code = '\n'.join([math_code] + self.ids_to_labels(node)) if math_env == '$': - wrapper = u'$%s$' + if self.alltt: + wrapper = u'\(%s\)' + else: + wrapper = u'$%s$' else: wrapper = u'\n'.join(['%%', r'\begin{%s}' % math_env, @@ -2586,8 +2601,10 @@ class LaTeXTranslator(nodes.NodeVisitor): self.depart_docinfo_item(node) def visit_paragraph(self, node): - # insert blank line, if the paragraph is not first in a list item - # nor follows a non-paragraph node in a compound + # insert blank line, unless + # * the paragraph is first in a list item, + # * 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) or isinstance(node.parent, nodes.description))): @@ -2596,6 +2613,12 @@ class LaTeXTranslator(nodes.NodeVisitor): 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'): @@ -2606,7 +2629,8 @@ class LaTeXTranslator(nodes.NodeVisitor): def depart_paragraph(self, node): if node['classes']: self.depart_inline(node) - self.out.append('\n') + if not self.active_table.colwidths_auto: + self.out.append('\n') def visit_problematic(self, node): self.requirements['color'] = PreambleCmds.color @@ -2797,7 +2821,7 @@ class LaTeXTranslator(nodes.NodeVisitor): 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',self.settings.table_style) + 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 @@ -2806,9 +2830,11 @@ class LaTeXTranslator(nodes.NodeVisitor): self.d_class.section(self.section_level).find('paragraph') != -1): self.out.append('\\leavevmode') self.active_table.open() - for cls in node['classes']: - self.active_table.set_table_style(cls) - if self.active_table._table_style == 'booktabs': + 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([]) @@ -2822,8 +2848,6 @@ class LaTeXTranslator(nodes.NodeVisitor): self.active_table.close() if len(self.table_stack)>0: self.active_table = self.table_stack.pop() - else: - self.active_table.set_table_style(self.settings.table_style) # Insert hyperlabel after (long)table, as # other places (beginning, caption) result in LaTeX errors. if node.get('ids'): @@ -2850,7 +2874,7 @@ class LaTeXTranslator(nodes.NodeVisitor): # BUG write preamble if not yet done (colspecs not []) # for tables without heads. if not self.active_table.get('preamble written'): - self.visit_thead(None) + self.visit_thead(node) self.depart_thead(None) def depart_tbody(self, node): @@ -2882,7 +2906,7 @@ class LaTeXTranslator(nodes.NodeVisitor): def visit_thead(self, node): self._thead_depth += 1 if 1 == self.thead_depth(): - self.out.append('{%s}\n' % self.active_table.get_colspecs()) + 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()) diff --git a/docutils/src/main/resources/docutils/docutils/writers/latex2e/xelatex.tex b/docutils/src/main/resources/docutils/docutils/writers/latex2e/xelatex.tex index 06eecfd..39df6f9 100644 --- a/docutils/src/main/resources/docutils/docutils/writers/latex2e/xelatex.tex +++ b/docutils/src/main/resources/docutils/docutils/writers/latex2e/xelatex.tex @@ -1,6 +1,7 @@ $head_prefix% generated by Docutils <http://docutils.sourceforge.net/> % rubber: set program xelatex -\usepackage[no-sscript]{xltxtra} % loads fixltx2e, metalogo, xunicode, fontspec +\usepackage{fixltx2e} +\usepackage{fontspec} % \defaultfontfeatures{Scale=MatchLowercase} $requirements %%% Custom LaTeX preamble diff --git a/docutils/src/main/resources/docutils/docutils/writers/odf_odt/__init__.py b/docutils/src/main/resources/docutils/docutils/writers/odf_odt/__init__.py index 5670900..3b29e3b 100644 --- a/docutils/src/main/resources/docutils/docutils/writers/odf_odt/__init__.py +++ b/docutils/src/main/resources/docutils/docutils/writers/odf_odt/__init__.py @@ -1,4 +1,4 @@ -# $Id: __init__.py 7717 2013-08-21 22:01:21Z milde $ +# $Id: __init__.py 7899 2015-06-03 22:02:46Z timehorse $ # Author: Dave Kuhlman <dkuhlman@rexx.com> # Copyright: This module has been placed in the public domain. @@ -58,7 +58,7 @@ try: import pygments.lexers from pygmentsformatter import OdtPygmentsProgFormatter, \ OdtPygmentsLaTeXFormatter -except ImportError, exp: +except (ImportError, SyntaxError), exp: pygments = None # check for the Python Imaging Library @@ -594,9 +594,7 @@ class Writer(writers.Writer): if source is None: continue try: - # encode/decode - destination1 = destination.decode('latin-1').encode('utf-8') - zfile.write(source, destination1) + zfile.write(source, destination) except OSError, e: self.document.reporter.warning( "Can't open file %s." % (source, )) @@ -872,6 +870,8 @@ class ODFTranslator(nodes.GenericNodeVisitor): 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 @@ -2399,14 +2399,26 @@ class ODFTranslator(nodes.GenericNodeVisitor): def visit_inline(self, node): styles = node.attributes.get('classes', ()) - if len(styles) > 0: - inline_style = styles[0] - el = SubElement(self.current_element, 'text:span', - attrib={'text:style-name': self.rststyle(inline_style)}) + 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): - self.set_to_parent() + 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 diff --git a/docutils/src/main/resources/docutils/docutils/writers/pep_html/pep.css b/docutils/src/main/resources/docutils/docutils/writers/pep_html/pep.css index fc2715f..7d6fcaf 100644 --- a/docutils/src/main/resources/docutils/docutils/writers/pep_html/pep.css +++ b/docutils/src/main/resources/docutils/docutils/writers/pep_html/pep.css @@ -1,7 +1,7 @@ /* :Author: David Goodger :Contact: goodger@python.org -:date: $Date: 2006-05-21 22:44:42 +0200 (Son, 21. Mai 2006) $ +: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. diff --git a/docutils/src/main/resources/docutils/docutils/writers/xetex/__init__.py b/docutils/src/main/resources/docutils/docutils/writers/xetex/__init__.py index 113fee5..e5ecf1d 100644 --- a/docutils/src/main/resources/docutils/docutils/writers/xetex/__init__.py +++ b/docutils/src/main/resources/docutils/docutils/writers/xetex/__init__.py @@ -2,8 +2,8 @@ # -*- coding: utf-8 -*- # :Author: Günter Milde <milde@users.sourceforge.net> -# :Revision: $Revision: 7668 $ -# :Date: $Date: 2013-06-04 14:46:30 +0200 (Die, 04. Jun 2013) $ +# :Revision: $Revision: 7852 $ +# :Date: $Date: 2015-03-21 17:07:49 +0100 (Sa, 21. Mär 2015) $ # :Copyright: © 2010 Günter Milde. # :License: Released under the terms of the `2-Clause BSD license`_, in short: # @@ -17,8 +17,9 @@ """ XeLaTeX document tree Writer. -A variant of Docutils' standard 'latex2e' writer producing output -suited for processing with XeLaTeX (http://tug.org/xetex/). +A variant of Docutils' standard 'latex2e' writer producing LaTeX output +suited for processing with the Unicode-aware TeX engines +LuaTeX and XeTeX. """ __docformat__ = 'reStructuredText' @@ -32,9 +33,9 @@ from docutils import frontend, nodes, utils, writers, languages from docutils.writers import latex2e class Writer(latex2e.Writer): - """A writer for Unicode-based LaTeX variants (XeTeX, LuaTeX)""" + """A writer for Unicode-aware LaTeX variants (XeTeX, LuaTeX)""" - supported = ('xetex','xelatex','luatex') + supported = ('lxtex', 'xetex','xelatex','luatex', 'lualatex') """Formats this writer supports.""" default_template = 'xelatex.tex' @@ -54,7 +55,7 @@ class Writer(latex2e.Writer): template=('Template file. Default: "%s".' % default_template, ['--template'], {'default': default_template, 'metavar': '<file>'}), latex_preamble=('Customization by LaTeX code in the preamble. ' - 'Default: select PDF standard fonts (Times, Helvetica, Courier).', + 'Default: select "Linux Libertine" fonts.', ['--latex-preamble'], {'default': default_preamble}), ) -- To stop receiving notification emails like this one, please contact nuiton.org SCM administrator <admin+scm@nuiton.org>.
This is an automated email from the git hooks/post-receive script. New commit to branch develop in repository jrst. See https://gitlab.nuiton.org/nuiton/jrst.git commit 5181b343dd3af915bab2c2713764577d353ce55d Author: Eric Chatellier <eric.chatellier@gmail.com> Date: Sun Feb 12 16:43:04 2017 +0100 fixes #3633: JRST plugin should not load file from remote repositories --- .../java/org/nuiton/jrst/JRSTEntityResolver.java | 45 ++ .../org/nuiton/jrst/JRSTToXmlStrategyDocutils.java | 50 +- jrst/src/main/resources/dtd/docutils.dtd | 621 +++++++++++++++++++++ jrst/src/main/resources/dtd/soextblx.dtd | 312 +++++++++++ 4 files changed, 1026 insertions(+), 2 deletions(-) diff --git a/jrst/src/main/java/org/nuiton/jrst/JRSTEntityResolver.java b/jrst/src/main/java/org/nuiton/jrst/JRSTEntityResolver.java new file mode 100644 index 0000000..7587669 --- /dev/null +++ b/jrst/src/main/java/org/nuiton/jrst/JRSTEntityResolver.java @@ -0,0 +1,45 @@ +/* + * #%L + * JRst :: Api + * %% + * Copyright (C) 2017 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jrst; + +import org.xml.sax.EntityResolver; +import org.xml.sax.InputSource; +import org.xml.sax.SAXException; + +import java.io.IOException; + +/** + * Entity resolver that forbid resolution over internet. + */ +public class JRSTEntityResolver implements EntityResolver { + + @Override + public InputSource resolveEntity(String publicId, String systemId) throws SAXException, IOException { + InputSource result = null; + if (systemId.endsWith("docutils.dtd")) { + result = new InputSource(getClass().getResourceAsStream("/dtd/docutils.dtd")); + } else if (systemId.endsWith("soextblx.dtd")) { + result = new InputSource(getClass().getResourceAsStream("/dtd/soextblx.dtd")); + } + return result; + } +} diff --git a/jrst/src/main/java/org/nuiton/jrst/JRSTToXmlStrategyDocutils.java b/jrst/src/main/java/org/nuiton/jrst/JRSTToXmlStrategyDocutils.java index 44a8af9..56d2940 100644 --- a/jrst/src/main/java/org/nuiton/jrst/JRSTToXmlStrategyDocutils.java +++ b/jrst/src/main/java/org/nuiton/jrst/JRSTToXmlStrategyDocutils.java @@ -2,7 +2,7 @@ * #%L * JRst :: Api * %% - * Copyright (C) 2004 - 2015 CodeLutin + * Copyright (C) 2004 - 2017 CodeLutin * %% * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as @@ -27,12 +27,16 @@ import org.codehaus.plexus.component.annotations.Component; import org.dom4j.Document; import org.dom4j.DocumentException; import org.dom4j.DocumentHelper; +import org.dom4j.io.SAXReader; import org.nuiton.jrst.legacy.JRSTReader; import org.python.util.PythonInterpreter; +import org.xml.sax.InputSource; import java.io.ByteArrayOutputStream; import java.io.File; +import java.io.StringReader; import java.net.URL; +import java.util.StringTokenizer; /** * Old mecanism to transform rst file to xml format using {@link JRSTReader}. @@ -110,7 +114,7 @@ public class JRSTToXmlStrategyDocutils implements JRSTToXmlStrategy { Document doc = null; try { - doc = DocumentHelper.parseText(xmlString); + doc = parseText(xmlString); } catch (DocumentException e) { log.error("Error during the creation of the document", e); } @@ -123,4 +127,46 @@ public class JRSTToXmlStrategyDocutils implements JRSTToXmlStrategy { } } } + + // copied and adapted from DocumentHelper#parseText(String) + protected Document parseText(String text) throws DocumentException { + SAXReader reader = new SAXReader(); + reader.setEntityResolver(new JRSTEntityResolver()); + InputSource source = new InputSource(new StringReader(text)); + String encoding = getEncoding(text); + source.setEncoding(encoding); + + Document result = reader.read(source); + if (result.getXMLEncoding() == null) { + result.setXMLEncoding(encoding); + } + return result; + } + + // copied from DocumentHelper#getEncoding(String) + private static String getEncoding(String text) { + String result = null; + + String xml = text.trim(); + + if (xml.startsWith("<?xml")) { + int end = xml.indexOf("?>"); + String sub = xml.substring(0, end); + StringTokenizer tokens = new StringTokenizer(sub, " =\"\'"); + + while (tokens.hasMoreTokens()) { + String token = tokens.nextToken(); + + if ("encoding".equals(token)) { + if (tokens.hasMoreTokens()) { + result = tokens.nextToken(); + } + + break; + } + } + } + + return result; + } } diff --git a/jrst/src/main/resources/dtd/docutils.dtd b/jrst/src/main/resources/dtd/docutils.dtd new file mode 100644 index 0000000..c844f72 --- /dev/null +++ b/jrst/src/main/resources/dtd/docutils.dtd @@ -0,0 +1,621 @@ +<!-- +====================================================================== + Docutils Generic DTD +====================================================================== +:Author: David Goodger +:Contact: docutils-develop@lists.sourceforge.net +:Revision: $Revision: 7978 $ +:Date: $Date: 2016-11-29 12:03:44 +0000 (Tue, 29 Nov 2016) $ +: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. +--> + +<!-- Attributes +================================================================== --> + +<!-- 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. --> +<!ENTITY % measure "NMTOKEN"> + +<!ENTITY % additional.basic.atts ""> +<!-- +Attributes shared by all elements in this DTD: + +- `id` is a unique identifier, typically assigned by the system. +- `name` is an identifier 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 NMTOKENS #IMPLIED + names CDATA #IMPLIED + dupnames CDATA #IMPLIED + source CDATA #IMPLIED + classes NMTOKENS #IMPLIED + %additional.basic.atts; "> + +<!-- External reference to a URI/URL. --> +<!ENTITY % refuri.att + " refuri CDATA #IMPLIED "> + +<!-- Internal reference to the `id` attribute of an element. --> +<!ENTITY % refid.att + " refid IDREF #IMPLIED "> + +<!-- Space-separated list of id references, for backlinks. --> +<!ENTITY % backrefs.att + " backrefs IDREFS #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 NMTOKENS #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; + %align-h.att; + morecols %number; #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: +--> diff --git a/jrst/src/main/resources/dtd/soextblx.dtd b/jrst/src/main/resources/dtd/soextblx.dtd new file mode 100644 index 0000000..56ba311 --- /dev/null +++ b/jrst/src/main/resources/dtd/soextblx.dtd @@ -0,0 +1,312 @@ +<!-- +=========================================================================== + 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; +> -- To stop receiving notification emails like this one, please contact nuiton.org SCM administrator <admin+scm@nuiton.org>.
This is an automated email from the git hooks/post-receive script. New commit to branch develop in repository jrst. See https://gitlab.nuiton.org/nuiton/jrst.git commit e577d3087bd53a1ad11f5fe0bfc4741200f2195c Author: Eric Chatellier <eric.chatellier@gmail.com> Date: Sun Feb 12 17:13:38 2017 +0100 fixes #3529: Fix tests broken since doxia 1.6 update --- doxia-module-jrst-legacy/pom.xml | 8 +++++++- .../src/main/java/org/nuiton/jrst/JrstParser.java | 4 ++-- .../src/test/java/org/nuiton/jrst/JrstParserTest.java | 7 ++----- doxia-module-jrst/pom.xml | 8 +++++++- doxia-module-jrst/src/main/java/org/nuiton/jrst/JrstParser.java | 4 ++-- .../src/test/java/org/nuiton/jrst/JrstParserTest.java | 7 ++----- jrst-site-util/pom.xml | 3 +-- .../src/main/java/org/nuiton/jrst/AbstractJrstParser.java | 7 +++---- pom.xml | 3 ++- 9 files changed, 28 insertions(+), 23 deletions(-) diff --git a/doxia-module-jrst-legacy/pom.xml b/doxia-module-jrst-legacy/pom.xml index 56c768e..1e8d8a3 100644 --- a/doxia-module-jrst-legacy/pom.xml +++ b/doxia-module-jrst-legacy/pom.xml @@ -3,7 +3,7 @@ #%L JRst :: Doxia module %% - Copyright (C) 2009 - 2012 CodeLutin, Chemit tony + Copyright (C) 2009 - 2017 CodeLutin, Chemit tony %% This program is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as @@ -114,6 +114,12 @@ </dependency> <dependency> + <groupId>org.apache.maven</groupId> + <artifactId>maven-core</artifactId> + <scope>test</scope> + </dependency> + + <dependency> <groupId>jaxen</groupId> <artifactId>jaxen</artifactId> <scope>runtime</scope> diff --git a/doxia-module-jrst-legacy/src/main/java/org/nuiton/jrst/JrstParser.java b/doxia-module-jrst-legacy/src/main/java/org/nuiton/jrst/JrstParser.java index 03ea800..e4cef1d 100644 --- a/doxia-module-jrst-legacy/src/main/java/org/nuiton/jrst/JrstParser.java +++ b/doxia-module-jrst-legacy/src/main/java/org/nuiton/jrst/JrstParser.java @@ -2,7 +2,7 @@ * #%L * JRst :: Doxia module legacy * %% - * Copyright (C) 2009 - 2010 CodeLutin + * Copyright (C) 2009 - 2017 CodeLutin * %% * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as @@ -40,7 +40,7 @@ import org.codehaus.plexus.component.annotations.Requirement; " the specified doxia Sink.") public class JrstParser extends AbstractJrstParser { - @Requirement(optional = false, hint = "legacy") + @Requirement(hint = "legacy") protected JRSTToXmlStrategy jrstStrategy; @Override diff --git a/doxia-module-jrst-legacy/src/test/java/org/nuiton/jrst/JrstParserTest.java b/doxia-module-jrst-legacy/src/test/java/org/nuiton/jrst/JrstParserTest.java index 4f17643..bf2b6e1 100644 --- a/doxia-module-jrst-legacy/src/test/java/org/nuiton/jrst/JrstParserTest.java +++ b/doxia-module-jrst-legacy/src/test/java/org/nuiton/jrst/JrstParserTest.java @@ -2,7 +2,7 @@ * #%L * JRst :: Doxia module legacy * %% - * Copyright (C) 2009 - 2010 CodeLutin + * Copyright (C) 2009 - 2017 CodeLutin * %% * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as @@ -34,10 +34,7 @@ import org.junit.Ignore; /** * @author chatellier * @version $Revision : 1$ - * - * Test ignored due to bug : http://jira.codehaus.org/browse/MPLUGINTESTING-25 */ -@Ignore public class JrstParserTest extends AbstractModuleTest { protected JrstParser parser; @@ -46,7 +43,7 @@ public class JrstParserTest extends AbstractModuleTest { protected void setUp() throws Exception { super.setUp(); - parser = (JrstParser) lookup(Parser.ROLE, "jrst"); + parser = lookup(Parser.ROLE, "jrst"); } public void testParse() throws Exception { diff --git a/doxia-module-jrst/pom.xml b/doxia-module-jrst/pom.xml index 1b40e6a..3f4ac38 100644 --- a/doxia-module-jrst/pom.xml +++ b/doxia-module-jrst/pom.xml @@ -3,7 +3,7 @@ #%L JRst :: Doxia module %% - Copyright (C) 2012 CodeLutin, Chemit tony + Copyright (C) 2012 - 2017 CodeLutin, Chemit tony %% This program is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as @@ -94,6 +94,12 @@ </dependency> <dependency> + <groupId>org.apache.maven</groupId> + <artifactId>maven-core</artifactId> + <scope>test</scope> + </dependency> + + <dependency> <groupId>jaxen</groupId> <artifactId>jaxen</artifactId> <scope>runtime</scope> diff --git a/doxia-module-jrst/src/main/java/org/nuiton/jrst/JrstParser.java b/doxia-module-jrst/src/main/java/org/nuiton/jrst/JrstParser.java index 68ff6cf..5fd8aba 100644 --- a/doxia-module-jrst/src/main/java/org/nuiton/jrst/JrstParser.java +++ b/doxia-module-jrst/src/main/java/org/nuiton/jrst/JrstParser.java @@ -2,7 +2,7 @@ * #%L * JRst :: Doxia module * %% - * Copyright (C) 2009 - 2010 CodeLutin + * Copyright (C) 2009 - 2017 CodeLutin * %% * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as @@ -40,7 +40,7 @@ import org.codehaus.plexus.component.annotations.Requirement; "into the specified doxia Sink.") public class JrstParser extends AbstractJrstParser { - @Requirement(optional = false, hint = "docutils") + @Requirement(hint = "docutils") protected JRSTToXmlStrategy jrstStrategy; @Override diff --git a/doxia-module-jrst/src/test/java/org/nuiton/jrst/JrstParserTest.java b/doxia-module-jrst/src/test/java/org/nuiton/jrst/JrstParserTest.java index a1eb5f8..ac3666a 100644 --- a/doxia-module-jrst/src/test/java/org/nuiton/jrst/JrstParserTest.java +++ b/doxia-module-jrst/src/test/java/org/nuiton/jrst/JrstParserTest.java @@ -2,7 +2,7 @@ * #%L * JRst :: Doxia module * %% - * Copyright (C) 2009 - 2010 CodeLutin + * Copyright (C) 2009 - 2017 CodeLutin * %% * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as @@ -34,10 +34,7 @@ import java.io.StringWriter; /** * @author chatellier * @version $Revision : 1$ - * - * Test ignored due to bug : http://jira.codehaus.org/browse/MPLUGINTESTING-25 */ -@Ignore public class JrstParserTest extends AbstractModuleTest { protected JrstParser parser; @@ -46,7 +43,7 @@ public class JrstParserTest extends AbstractModuleTest { protected void setUp() throws Exception { super.setUp(); - parser = (JrstParser) lookup(Parser.ROLE, "jrst"); + parser = lookup(Parser.ROLE, "jrst"); } public void testParse() throws Exception { diff --git a/jrst-site-util/pom.xml b/jrst-site-util/pom.xml index 40afcef..0a82c15 100644 --- a/jrst-site-util/pom.xml +++ b/jrst-site-util/pom.xml @@ -3,7 +3,7 @@ #%L JRst :: Site util %% - Copyright (C) 2012 - 2016 CodeLutin, Chemit tony + Copyright (C) 2012 - 2017 CodeLutin, Chemit tony %% This program is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as @@ -143,7 +143,6 @@ <dependency> <groupId>dom4j</groupId> <artifactId>dom4j</artifactId> - <!--<scope>runtime</scope>--> </dependency> <dependency> diff --git a/jrst-site-util/src/main/java/org/nuiton/jrst/AbstractJrstParser.java b/jrst-site-util/src/main/java/org/nuiton/jrst/AbstractJrstParser.java index fa68a7e..5eeb67a 100644 --- a/jrst-site-util/src/main/java/org/nuiton/jrst/AbstractJrstParser.java +++ b/jrst-site-util/src/main/java/org/nuiton/jrst/AbstractJrstParser.java @@ -2,7 +2,7 @@ * #%L * JRst :: Site util * %% - * Copyright (C) 2012 - 2015 CodeLutin + * Copyright (C) 2012 - 2017 CodeLutin * %% * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as @@ -100,12 +100,11 @@ public abstract class AbstractJrstParser extends XdocParser { sourceFile = File.createTempFile("source", "rst"); } else { - File temporayDirectory = new File( + File tempDirectory = new File( mavenProject.getBasedir(), "target" + File.separator + "generated-jrst"); - sourceFile = new File(temporayDirectory, - renderingContext.getInputName()); + sourceFile = new File(tempDirectory, renderingContext.getInputName()); FileUtil.createDirectoryIfNecessary(sourceFile.getParentFile()); } diff --git a/pom.xml b/pom.xml index 1f91507..10130c3 100644 --- a/pom.xml +++ b/pom.xml @@ -113,7 +113,8 @@ <nuitonI18nVersion>3.6.3</nuitonI18nVersion> <xalanVersion>2.7.1</xalanVersion> <jaxxVersion>2.40</jaxxVersion> - <mavenVersion>3.3.9</mavenVersion> + <!-- tests fail with 3.3.x --> + <mavenVersion>3.2.5</mavenVersion> <!-- site configuration --> -- To stop receiving notification emails like this one, please contact nuiton.org SCM administrator <admin+scm@nuiton.org>.
This is an automated email from the git hooks/post-receive script. New commit to branch develop in repository jrst. See https://gitlab.nuiton.org/nuiton/jrst.git commit d44412e65ed2fdd70fbd2e30ccbe705883d1756d Author: Eric Chatellier <eric.chatellier@gmail.com> Date: Sun Feb 12 17:15:41 2017 +0100 Remove myself from copyright --- jrst/pom.xml | 2 +- jrst/src/main/assembly/jrst.sh | 2 +- jrst/src/main/java/org/nuiton/jrst/JRST.java | 2 +- jrst/src/main/java/org/nuiton/jrst/JRSTConfig.java | 2 +- jrst/src/main/java/org/nuiton/jrst/JRSTConfigAction.java | 2 +- jrst/src/main/java/org/nuiton/jrst/JRSTConfigOption.java | 2 +- jrst/src/main/java/org/nuiton/jrst/JRSTInterface.java | 2 +- jrst/src/main/java/org/nuiton/jrst/legacy/JRSTLexer.java | 2 +- jrst/src/main/resources/xsl/rst2xhtml.xsl | 2 +- jrst/src/test/java/org/nuiton/jrst/bugs/DirectiveTest.java | 2 +- jrst/src/test/java/org/nuiton/jrst/bugs/HtmlTest.java | 2 +- jrst/src/test/java/org/nuiton/jrst/bugs/TableTest.java | 2 +- jrst/src/test/java/org/nuiton/jrst/bugs/TextTest.java | 2 +- jrst/src/test/java/org/nuiton/jrst/bugs/TitlesTest.java | 2 +- 14 files changed, 14 insertions(+), 14 deletions(-) diff --git a/jrst/pom.xml b/jrst/pom.xml index 0b41f3b..d2075ce 100644 --- a/jrst/pom.xml +++ b/jrst/pom.xml @@ -3,7 +3,7 @@ #%L JRst :: Api %% - Copyright (C) 2004 - 2016 CodeLutin, Chatellier Eric, Chemit tony + Copyright (C) 2004 - 2017 CodeLutin, Chemit tony %% This program is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as diff --git a/jrst/src/main/assembly/jrst.sh b/jrst/src/main/assembly/jrst.sh index a842767..4c9865a 100755 --- a/jrst/src/main/assembly/jrst.sh +++ b/jrst/src/main/assembly/jrst.sh @@ -6,7 +6,7 @@ # $Id$ # $HeadURL$ # %% -# Copyright (C) 2004 - 2011 CodeLutin, Chatellier Eric +# Copyright (C) 2004 - 2017 CodeLutin # %% # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License as diff --git a/jrst/src/main/java/org/nuiton/jrst/JRST.java b/jrst/src/main/java/org/nuiton/jrst/JRST.java index 3bb605d..6091a3b 100644 --- a/jrst/src/main/java/org/nuiton/jrst/JRST.java +++ b/jrst/src/main/java/org/nuiton/jrst/JRST.java @@ -2,7 +2,7 @@ * #%L * JRst :: Api * %% - * Copyright (C) 2004 - 2015 CodeLutin, Chatellier Eric + * Copyright (C) 2004 - 2017 CodeLutin * %% * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as diff --git a/jrst/src/main/java/org/nuiton/jrst/JRSTConfig.java b/jrst/src/main/java/org/nuiton/jrst/JRSTConfig.java index fedde22..126e8c7 100644 --- a/jrst/src/main/java/org/nuiton/jrst/JRSTConfig.java +++ b/jrst/src/main/java/org/nuiton/jrst/JRSTConfig.java @@ -2,7 +2,7 @@ * #%L * JRst :: Api * %% - * Copyright (C) 2011 CodeLutin, Chatellier Eric + * Copyright (C) 2011 - 2017 CodeLutin * %% * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as diff --git a/jrst/src/main/java/org/nuiton/jrst/JRSTConfigAction.java b/jrst/src/main/java/org/nuiton/jrst/JRSTConfigAction.java index 67cc816..7839155 100644 --- a/jrst/src/main/java/org/nuiton/jrst/JRSTConfigAction.java +++ b/jrst/src/main/java/org/nuiton/jrst/JRSTConfigAction.java @@ -2,7 +2,7 @@ * #%L * JRst :: Api * %% - * Copyright (C) 2011 - 2014 CodeLutin, Chatellier Eric + * Copyright (C) 2011 - 2017 CodeLutin * %% * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as diff --git a/jrst/src/main/java/org/nuiton/jrst/JRSTConfigOption.java b/jrst/src/main/java/org/nuiton/jrst/JRSTConfigOption.java index 95b28c5..48c28f1 100644 --- a/jrst/src/main/java/org/nuiton/jrst/JRSTConfigOption.java +++ b/jrst/src/main/java/org/nuiton/jrst/JRSTConfigOption.java @@ -2,7 +2,7 @@ * #%L * JRst :: Api * %% - * Copyright (C) 2011 CodeLutin, Chatellier Eric + * Copyright (C) 2011 - 2017 CodeLutin * %% * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as diff --git a/jrst/src/main/java/org/nuiton/jrst/JRSTInterface.java b/jrst/src/main/java/org/nuiton/jrst/JRSTInterface.java index 92dac96..987cc92 100644 --- a/jrst/src/main/java/org/nuiton/jrst/JRSTInterface.java +++ b/jrst/src/main/java/org/nuiton/jrst/JRSTInterface.java @@ -2,7 +2,7 @@ * #%L * JRst :: Api * %% - * Copyright (C) 2004 - 2011 CodeLutin, Chatellier Eric + * Copyright (C) 2004 - 2017 CodeLutin * %% * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as diff --git a/jrst/src/main/java/org/nuiton/jrst/legacy/JRSTLexer.java b/jrst/src/main/java/org/nuiton/jrst/legacy/JRSTLexer.java index 0a13711..01f1278 100644 --- a/jrst/src/main/java/org/nuiton/jrst/legacy/JRSTLexer.java +++ b/jrst/src/main/java/org/nuiton/jrst/legacy/JRSTLexer.java @@ -2,7 +2,7 @@ * #%L * JRst :: Api * %% - * Copyright (C) 2004 - 2015 CodeLutin, Chatellier Eric + * Copyright (C) 2004 - 2017 CodeLutin * %% * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as diff --git a/jrst/src/main/resources/xsl/rst2xhtml.xsl b/jrst/src/main/resources/xsl/rst2xhtml.xsl index 525799b..ef1d00d 100644 --- a/jrst/src/main/resources/xsl/rst2xhtml.xsl +++ b/jrst/src/main/resources/xsl/rst2xhtml.xsl @@ -3,7 +3,7 @@ #%L JRst :: Api %% - Copyright (C) 2004 - 2015 CodeLutin, Chatellier Eric + Copyright (C) 2004 - 2017 CodeLutin %% This program is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as diff --git a/jrst/src/test/java/org/nuiton/jrst/bugs/DirectiveTest.java b/jrst/src/test/java/org/nuiton/jrst/bugs/DirectiveTest.java index 0d0b073..df4cd64 100644 --- a/jrst/src/test/java/org/nuiton/jrst/bugs/DirectiveTest.java +++ b/jrst/src/test/java/org/nuiton/jrst/bugs/DirectiveTest.java @@ -2,7 +2,7 @@ * #%L * JRst :: Api * %% - * Copyright (C) 2011 Codelutin, Chatellier Eric + * Copyright (C) 2011 - 2017 Codelutin * %% * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as diff --git a/jrst/src/test/java/org/nuiton/jrst/bugs/HtmlTest.java b/jrst/src/test/java/org/nuiton/jrst/bugs/HtmlTest.java index 80060bf..c382f1b 100644 --- a/jrst/src/test/java/org/nuiton/jrst/bugs/HtmlTest.java +++ b/jrst/src/test/java/org/nuiton/jrst/bugs/HtmlTest.java @@ -2,7 +2,7 @@ * #%L * JRst :: Api * %% - * Copyright (C) 2015 CodeLutin, Chatellier Eric + * Copyright (C) 2015 - 2017 CodeLutin * %% * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as diff --git a/jrst/src/test/java/org/nuiton/jrst/bugs/TableTest.java b/jrst/src/test/java/org/nuiton/jrst/bugs/TableTest.java index b999905..94b1e60 100644 --- a/jrst/src/test/java/org/nuiton/jrst/bugs/TableTest.java +++ b/jrst/src/test/java/org/nuiton/jrst/bugs/TableTest.java @@ -2,7 +2,7 @@ * #%L * JRst :: Api * %% - * Copyright (C) 2011 Codelutin, Chatellier Eric + * Copyright (C) 2011 - 2017 Codelutin * %% * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as diff --git a/jrst/src/test/java/org/nuiton/jrst/bugs/TextTest.java b/jrst/src/test/java/org/nuiton/jrst/bugs/TextTest.java index 1b323c7..3bd5079 100644 --- a/jrst/src/test/java/org/nuiton/jrst/bugs/TextTest.java +++ b/jrst/src/test/java/org/nuiton/jrst/bugs/TextTest.java @@ -2,7 +2,7 @@ * #%L * JRst :: Api * %% - * Copyright (C) 2011 Codelutin, Chatellier Eric + * Copyright (C) 2011 - 2017 Codelutin * %% * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as diff --git a/jrst/src/test/java/org/nuiton/jrst/bugs/TitlesTest.java b/jrst/src/test/java/org/nuiton/jrst/bugs/TitlesTest.java index cf5c3d9..33e2a00 100644 --- a/jrst/src/test/java/org/nuiton/jrst/bugs/TitlesTest.java +++ b/jrst/src/test/java/org/nuiton/jrst/bugs/TitlesTest.java @@ -2,7 +2,7 @@ * #%L * JRst :: Api * %% - * Copyright (C) 2011 Codelutin, Chatellier Eric + * Copyright (C) 2011 - 2017 Codelutin * %% * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as -- To stop receiving notification emails like this one, please contact nuiton.org SCM administrator <admin+scm@nuiton.org>.
participants (1)
-
nuiton.org scm