milde  committed 9de5459

New default for `math-output` setting: "HTML math.css".

  • Participants
  • Parent commits 3618c41

Comments (0)

Files changed (7)

File docutils/HISTORY.txt

   - New setting `stylesheet_dirs`: Comma-separated list of directories
     where stylesheets are found. Used by `stylesheet_path` when expanding
     relative path arguments.
+  - New default for math-output_: ``HTML math.css``.
+.. _math-output: docs/user/config.html#math-output
 * docutils/writers/latex2e/

File docutils/RELEASE-NOTES.txt

 * docutils/writers/html4css1/
   - New setting `stylesheet_dirs` (see above).
     Now, it is easy to add a custom stylesheet to Docutils' default
     stylesheet with, e.g., ``--stylesheet_path='html4css1.css, mystyle.css'``
-    Changed behaviour of the default settings: 
+    Changed behaviour of the default settings:
       if there is a file ``html4css1.css`` in the working directory of the
       process at launch, it is used instead of the one provided by Docutils
       in the writer source directory.
+  - New default for `math-output` setting: "HTML math.css".
+    Secure and self-contained alternative to the old default
+    ("MathJax" requiring JavaScript from the MathJax server network).
 Release 0.10 (2012-12-16)
-.. Note:: 
+.. Note::
    Docutils 0.9.x is the last version supporting Python 2.3.
    Docutils 0.10 is compatible with Python versions from 2.4 to 3.2
    (cf. `Python 3 compatibility`_).
   - ``docutils/math``, ``docutils/``, and
     ``docutils/`` moved to the utils package.
     Code importing these modules needs to adapt, e.g.::
           import docutils.math as math
       except ImportError:
 * docutils/
-  - FileInput/FileOutput: no system-exit on IOError. 
+  - FileInput/FileOutput: no system-exit on IOError.
     The `handle_io_errors` option is ignored.
 .. _Python 3 compatibility: README.html#python-3-compatibility

File docutils/docs/user/config.txt

 The format of mathematical content (`math directive`_ and role) in
 the output document. Supported values are (case insensitive):
+  Format math in standard HTML enhanced by CSS rules.
+  Requires the ``math.css`` stylesheet (in the system
+  `stylesheet directory <stylesheet_dirs [html4css1 writer]_>`_
+  A `stylesheet_path <stylesheet_path [html4css1 writer]_>`_
+  can be appended after whitespace, the specified
+  stylesheet(s) will only be referenced or embedded, if required
+  (i.e. if there is mathematical content in the document).
   Format math for display with MathJax_, a JavaScript-based math
   rendering engine that uses HTML/CSS, JavaScript, and unicode
-  Format math in standard HTML enhanced by CSS rules
-  Requires the ``math.css`` stylesheet (in the system
-  `stylesheet directory <stylesheet_dirs [html4css1 writer]_>`_
   Embed math content as presentational MathML_.
   The failsave fallback.
-Default: MathJax.  Option: ``--math-output``.
+Default: "HTML math.css".  Option: ``--math-output``.
 New in Docutils 0.8.
 matching file is found in the stylesheet_dirs__.
 If embed_stylesheet__ is False, paths are rewritten relative to the
 output file path. Run ``latex`` from the directory containing
-the output file. 
+the output file.
 The stylesheet__  option is preferred for files in the `TeX input path`_.

File docutils/docutils/writers/html4css1/

           {'default': ''}),
          ('Math output format, one of "MathML", "HTML", "MathJax" '
-          'or "LaTeX". Default: "MathJax"',
+          'or "LaTeX". Default: "HTML math.css"',
-          {'default': 'MathJax'}),
+          {'default': 'HTML math.css'}),
          ('Omit the XML declaration.  Use with caution.',
           {'dest': 'xml_declaration', 'default': 1, 'action': 'store_false',
         self.in_document_title = 0   # len(self.body) or 0
         self.in_mailto = False
         self.author_in_authors = False
-        self.math_header = ''
+        self.math_header = []
     def astext(self):
         return ''.join(self.head_prefix + self.head
         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:
-            self.head.append(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.body_prefix.append(self.starttag(node, 'div', CLASS='document'))
         # settings and conversion
         if self.math_output in ('latex', 'mathjax'):
             math_code = self.encode(math_code)
-        if self.math_output == 'mathjax':
+        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
+            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 != '')
+            math2html.DocumentParameters.displaymode = (math_env != '')
             math_code = math2html.math2html(math_code)
         elif self.math_output == 'mathml':
             self.doctype = self.doctype_mathml

File docutils/test/functional/expected/standalone_rst_html4css1.html

 <meta name="copyright" content="This document has been placed in the public domain. You may do with it as you wish. You may copy, modify, redistribute, reattribute, sell, buy, rent, lease, destroy, or improve it, quote it at length, excerpt, incorporate, collate, fold, staple, or mutilate it, or do anything else to it that your or anyone else's heart desires." />
 <meta content="reStructuredText, test, parser" name="keywords" />
 <meta content="A test document, containing at least one example of each reStructuredText construct." lang="en" name="description" />
-<script type="text/javascript" src=""></script>
 <link rel="stylesheet" href="../input/data/html4css1.css" type="text/css" />
+<link rel="stylesheet" href="../input/data/math.css" type="text/css" />
 <div class="header">
 or as base for special code roles, e.g. the LaTeX code in the next
 <p>Docutils uses LaTeX syntax for math directives and roles:
-<code class="tex">\alpha = f(x)</code> prints <span class="math">\(\alpha = f(x)\)</span>
+<code class="tex">\alpha = f(x)</code> prints <span class="formula"><i>α</i> = <i>f</i>(<i>x</i>)</span>
 <p>The <tt class="docutils literal">:code:</tt> option of the <cite>include</cite> directive sets the included content
 as a code block, here the rst file <tt class="docutils literal">header_footer.txt</tt> with line numbers:</p>

File docutils/test/functional/tests/

 writer_name = "html4css1"
 # Settings:
-# local copy of default stylesheet:
+# local copy of stylesheets:
 # (Test runs in ``docutils/test/``, we need relative path from there.)
-settings_overrides['stylesheet_path'] = ( 
-    'functional/input/data/html4css1.css')
+settings_overrides['stylesheet_dirs'] = ('.', 'functional/input/data')

File docutils/test/test_writers/

     data = ':math:`42`'
     def test_math_output_default(self):
-        # Currently MathJax with default URL. Likely to change to HTML!
+        # HTML with math.css stylesheet (since 0.11)
         mysettings = {'_disable_config': True,}
-        head = core.publish_parts(, writer_name='html4css1',
-                                  settings_overrides=mysettings)['head']
-        self.assertIn(self.mathjax_script % self.default_mathjax_url, head)
+        styles = core.publish_parts(, writer_name='html4css1',
+                                  settings_overrides=mysettings)['stylesheet']
+        self.assertIn('convert LaTeX equations to HTML output.', styles)
     def test_math_output_mathjax(self):
         # Explicitly specifying math_output=MathJax, case insensitively
         self.assertIn(self.mathjax_script % self.custom_mathjax_url, head)
     def test_math_output_html(self):
-        # There should be no MathJax script when math_output is not MathJax
         mysettings = {'_disable_config': True,
                       'math_output': 'HTML'}
         head = core.publish_parts(, writer_name='html4css1',
+        # There should be no MathJax script when math_output is not MathJax
         self.assertNotIn('MathJax.js', head)
+    def test_math_output_html_stylesheet(self):
+        mysettings = {'_disable_config': True,
+                      'math_output': 'HTML math.css,custom/style.css',
+                      'stylesheet_dirs': ('.', 'functional/input/data'),
+                      'embed_stylesheet': False}
+        styles = core.publish_parts(, writer_name='html4css1',
+            settings_overrides=mysettings)['stylesheet']
+        self.assertEqual(u"""\
+<link rel="stylesheet" href="functional/input/data/html4css1.css" type="text/css" />
+<link rel="stylesheet" href="functional/input/data/math.css" type="text/css" />
+<link rel="stylesheet" href="custom/style.css" type="text/css" />
+""", styles)
     def test_math_output_mathjax_no_math(self):
         mysettings = {'_disable_config': True,
                       'math_output': 'MathJax'}