Browse Source

moved latex to render_math; latex now symbolic link

Barry Steyn 10 years ago
parent
commit
5af9d08c06
7 changed files with 310 additions and 207 deletions
  1. 1 0
      latex
  2. 0 95
      latex/Readme.md
  3. 0 1
      latex/__init__.py
  4. 166 0
      render_math/Readme.md
  5. 1 0
      render_math/__init__.py
  6. 112 111
      latex/latex.py
  7. 30 0
      render_math/mathjax_script.txt

+ 1 - 0
latex

@@ -0,0 +1 @@
+render_math/

+ 0 - 95
latex/Readme.md

@@ -1,95 +0,0 @@
-Latex Plugin For Pelican
-========================
-
-This plugin allows you to write mathematical equations in your articles using Latex and MathMl.
-It uses the MathJax Latex JavaScript library to render *Latex* and *MathMl* that is embedded in
-your site.
-
-### Latex
-Anything between `$..$` (inline math) and `$$..$$` (displayed math) will be recognized as
-Latex. In addition, anything between between `\begin` and `\end` macros will also be 
-recognized as Latex. For example, `\begin{equation}`...`\end{equation}` would be used to 
-render math equations with numbering.
-
-Within recognized Latex as described above, Latex macros can be used.
-
-### MathMl
-Anything between `<math>` and `</math>` tags will be recognized as *MathMl*.
-
-Installation
-------------
-To enable, ensure that `latex.py` is put somewhere that is accessible.
-Then use as follows by adding the following to your settings.py:
-
-    PLUGINS = ["latex"]
-
-Your site is now capable of rendering math math using the mathjax JavaScript
-library. No alterations to the template file is needed.
-
-### Typogrify
-Typogrify will now play nicely with Latex (i.e. typogrify can be enabled
-and Latex will be rendered correctly). In order for this to happen,
-version 2.07 (or above) of typogrify is required. In fact, this plugin expects
-that at least version 2.07 is present and will fail without it.
-
-### Summaries
-Summaries that contain math are processed to ensure that math is not off. If
-math is cut off, it will add it back into the summary.
-
-### Templates
-No alteration is needed to a template for this plugin to work. Just install
-the plugin and start writing your Math.
-
-Usage
------
-### Backward Compatibility
-This plugin is backward compatible in the sense that it
-will render previous setups correctly. This is because those
-settings and metadata information is ignored by this version. Therefore
-you can remove them to neaten up your site
-
-### Settings File
-Extra options regarding how mathjax renders math can be set in the settings
-file. These options are in a dictionary variable called `LATEX` in the pelican
-settings file.
-
-The dictionary can be set with the following keys:
-
- * `wrap`: controls the tags that math is wrapped with inside the resulting
-html. For example, setting `wrap` to `'mathjax'` would wrap all math inside
-`<mathjax>...</mathjax>` tags. If typogrify is set to True, then math needs
-to be wrapped in tags and `wrap` will therefore default to `mathjax` if not
-set. `wrap` cannot be set to `'math'` because this tag is reserved for 
-mathml notation
- * `align`: controls how displayed math will be aligned. Can be set to either
-`left`, `right` or `center` (default is `center`).
- * `indent`: if `align` not set to `center`, then this controls the indent
-level (default is `0em`).
- * `show_menu`: controls whether the mathjax contextual menu is shown.
- * `process_escapes`: controls whether mathjax processes escape sequences.
- * `preview`: controls the preview message users are seen while mathjax is
-loading.
- * `color`: controls the color of the mathjax rendered font.
-
-For example, in settings.py, the following would make math render in blue and
-displaymath align to the left:
-
-    LATEX = {'color':'blue','align':left}
-
-Latex Examples
---------------
-###Inline
-Latex between `$`..`$`, for example, `$`x^2`$`, will be rendered inline
-with respect to the current html block.
-
-###Displayed Math
-Latex between `$$`..`$$`, for example, `$$`x^2`$$`, will be rendered centered in a
-new paragraph.
-
-###Equations
-Latex between `\begin` and `\end`, for example, `begin{equation}` x^2 `\end{equation}`,
-will be rendered centered in a new paragraph with a right justified equation number
-at the top of the paragraph. This equation number can be referenced in the document.
-To do this, use a `label` inside of the equation format and then refer to that label
-using `ref`. For example: `begin{equation}` `\label{eq}` X^2 `\end{equation}`. Now
-refer to that equation number by `$`\ref{eq}`$`.

+ 0 - 1
latex/__init__.py

@@ -1 +0,0 @@
-from .latex import *

+ 166 - 0
render_math/Readme.md

@@ -0,0 +1,166 @@
+Math Render Plugin For Pelican
+==============================
+This plugin gives pelican the ability to render mathematics. It accomplishes
+this by using the [MathJax](http://www.mathjax.org/) javascript engine. Both
+[LaTex](http://en.wikipedia.org/wiki/LaTeX) and [MathML](http://en.wikipedia.org/wiki/MathML) 
+can be rendered within the content.
+
+The plugin also ensures that pelican and recognized math "play" nicely together, by
+ensuring [Typogrify](https://github.com/mintchaos/typogrify) does not alter math content
+and summaries that get cut off are repaired.
+
+Recognized math in the context of this plugin is either LaTex or MathML as described below.
+
+### LaTex
+Anything between `$`...`$` (inline math) and `$$`..`$$` (displayed math) will be recognized as
+LaTex. In addition, anything the `\begin` and `\end` LaTex macros will also be 
+recognized as LaTex. For example, `\begin{equation}`...`\end{equation}` would be used to 
+render math equations with numbering.
+
+Within recognized LaTex as described above, any supported LaTex macro can be used.
+
+### MathML
+Anything between `<math>` and `</math>` tags will be recognized as MathML
+
+Installation
+------------
+To enable, ensure that `render_math` plugin is accessible.
+Then add the following to settings.py:
+
+    PLUGINS = ["render_math"]
+
+Your site is now capable of rendering math math using the mathjax JavaScript
+engine. No alterations to the template is needed, just use and enjoy!
+
+### Typogrify
+In the past, using [Typgogrify](https://github.com/mintchaos/typogrify) would alter the math contents resulting
+in math that could not be rendered by MathJax. The only option was to ensure
+that Typogrify was disabled in the settings.
+
+The problem has been recitified in this plugin, but it requires [Typogrify version 2.04](https://pypi.python.org/pypi/typogrify)
+(or higher). In fact, this plugin will not work with lower versions of Typogrfrify.
+
+Usage
+-----
+### Backward Compatibility
+This plugin is backward compatible in the sense that it
+will render previous setups correctly. This is because those
+settings and metadata information is ignored by this version. Therefore
+you can remove them to neaten up your site
+
+### Templates
+No alteration is needed to a template for this plugin to work. Just install
+the plugin and start writing your Math. 
+
+If on the other hand, you are template designer and want total control
+over the MathJax JavaScript, you can set the `auto_insert` setting to 
+`False` which will cause no MathJax JavaScript to be added to the content.
+
+If you choose this option, you should really know what you are doing. Therefore
+only do this if you are designing your template. There is no real advantage to
+to letting template logic handle the insertion of the MathJax JavaScript other
+than it being slightly neater.
+
+By setting `auto_insert` to `False`, metadata with `key` value of `mathjax`
+will be present in all pages and articles where MathJax should be present.
+The template designer can detect this and then use the `MATHJAXSCRIPT` setting
+which will contain the user specified MathJax script to insert into the content.
+
+For example, this code could be used:
+```
+{% if not MATH['auto_insert'] %}
+    {% if page and page.mathjax or article and article.mathjax %}
+        {{ MATHJAXSCRIPT }}
+    {% endif %}
+{% endif %}
+```
+
+### Settings
+Certain MathJax rendering options can be set. These options 
+are in a dictionary variable called `MATH` in the pelican
+settings file.
+
+The dictionary can be set with the following keys:
+
+ * `auto_insert`: controls whether plugin should automatically insert
+MathJax JavaScript in content that has Math. It is only recommended
+to set this to False if you are a template designer and you want
+extra control over where the MathJax JavaScript is renderd. **Default Value**:
+True
+ * `wrap_latex`: controls the tags that LaTex math is wrapped with inside the resulting
+html. For example, setting `wrap_latex` to `mathjax` would wrap all LaTex math inside
+`<mathjax>...</mathjax>` tags. If typogrify is set to True, then math needs
+to be wrapped in tags and `wrap_latex` will therefore default to `mathjax` if not
+set. `wrap_latex` cannot be set to `'math'` because this tag is reserved for 
+mathml notation. **Default Value**: None unless Typogrify is enabled in which case, 
+it defaults to `mathjax`
+ * `align`: controls how displayed math will be aligned. Can be set to either
+`left`, `right` or `center`. **Default Value**: `center`.
+ * `indent`: if `align` not set to `center`, then this controls the indent
+level. **Default Value**: `0em`.
+ * `show_menu`: a boolean value that controls whether the mathjax contextual 
+menu is shown. **Default Value**: True
+ * `process_escapes`: a boolean value that controls whether mathjax processes escape 
+sequences. **Default Value**: True
+ * `latex_preview`: controls the preview message users are seen while mathjax is
+rendering LaTex. If set to `Tex`, then the TeX code is used as the preview 
+(which will be visible until it is processed by MathJax). **Default Value**: `Tex`
+ * `color`: controls the color of the mathjax rendered font. **Default Value**: `black`
+
+For example, in settings.py, the following would make math render in blue and
+displaymath align to the left:
+
+    MATH = {'color':'blue','align':left}
+
+LaTex Examples
+--------------
+###Inline
+LaTex between `$`..`$`, for example, `$`x^2`$`, will be rendered inline
+with respect to the current html block.
+
+###Displayed Math
+LaTex between `$$`..`$$`, for example, `$$`x^2`$$`, will be rendered centered in a
+new paragraph.
+
+###Equations
+LaTex between `\begin` and `\end`, for example, `begin{equation}` x^2 `\end{equation}`,
+will be rendered centered in a new paragraph with a right justified equation number
+at the top of the paragraph. This equation number can be referenced in the document.
+To do this, use a `label` inside of the equation format and then refer to that label
+using `ref`. For example: `begin{equation}` `\label{eq}` X^2 `\end{equation}`. Now
+refer to that equation number by `$`\ref{eq}`$`.
+
+MathML Examples
+---------------
+The following will render the Quadratic formula:
+```
+<math xmlns="http://www.w3.org/1998/Math/MathML" display="block"> 
+  <mrow>
+    <mi>x</mi>
+    <mo>=</mo>
+    <mfrac>
+      <mrow>
+        <mo>&#x2212;</mo>
+        <mi>b</mi>
+        <mo>&#xB1;</mo>
+        <msqrt>
+          <mrow>
+            <msup>
+              <mi>b</mi>
+              <mn>2</mn>
+            </msup>
+            <mo>&#x2212;</mo>
+            <mn>4</mn>
+            <mi>a</mi>
+            <mi>c</mi>
+          </mrow>
+        </msqrt>
+      </mrow>
+      <mrow>
+        <mn>2</mn>
+        <mi>a</mi>
+      </mrow>
+    </mfrac>
+  </mrow>
+</math>
+```

+ 1 - 0
render_math/__init__.py

@@ -0,0 +1 @@
+from .math import *

+ 112 - 111
latex/latex.py

@@ -1,19 +1,14 @@
 # -*- coding: utf-8 -*-
 """
-Latex Plugin For Pelican
-========================
-
-This plugin allows you to write mathematical equations in your articles using Latex.
-It uses the MathJax Latex JavaScript library to render latex that is embedded in
-between `$..$` for inline math and `$$..$$` for displayed math. It also allows for
-writing equations in by using `\begin{equation}`...`\end{equation}`. No
-alteration to a template is required for this plugin to work, just install and
-use.
+Math Render Plugin For Pelican
+==============================
+This plugin allows your site to render Math. It supports both LaTex and MathML
+using the MathJax JavaScript engine.
 
 Typogrify Compatibility
 -----------------------
 This plugin now plays nicely with typogrify, but it requires
-typogrify version 2.07 or above.
+typogrify version 2.04 or above.
 
 User Settings
 -------------
@@ -25,45 +20,17 @@ See README for more details.
 
 from pelican import signals
 from pelican import contents
-import re
+import re, os
 
 # Global Variables
 _TYPOGRIFY = False  # used to determine if we should process typogrify
-_WRAP_TAG = None  # the tag to wrap mathjax in (needed to play nicely with typogrify or for template designers)
-_LATEX_REGEX = re.compile(r'(\$\$|\$|\\begin\{(.+?)\}|<(math).*?>).*?(\1|\\end\{\2\}|</\3>)', re.DOTALL | re.IGNORECASE) #  used to detect latex
-_LATEX_SUMMARY_REGEX = None  # used to match latex in summary
-_LATEX_PARTIAL_REGEX = None  # used to match latex that has been cut off in summary
+_WRAP_LATEX = None  # the tag to wrap LaTex math in (needed to play nicely with typogrify or for template designers)
+_MATH_REGEX = re.compile(r'(\$\$|\$|\\begin\{(.+?)\}|<(math)(?:\s.*?)?>).*?(\1|\\end\{\2\}|</\3>)', re.DOTALL | re.IGNORECASE) #  used to detect math
+_MATH_SUMMARY_REGEX = None  # used to match math in summary
+_MATH_INCOMPLETE_TAG_REGEX = None  # used to match math that has been cut off in summary
 _MATHJAX_SETTINGS = {}  # settings that can be specified by the user, used to control mathjax script settings
-_MATHJAX_SCRIPT="""
-<script type= "text/javascript">
-    if (!document.getElementById('mathjaxscript_pelican')) {{
-        var s = document.createElement('script');
-        s.id = 'mathjaxscript_pelican';
-        s.type = 'text/javascript'; s.src = 'https:' == document.location.protocol ? 'https://c328740.ssl.cf1.rackcdn.com/mathjax/latest/MathJax.js' : 'http://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML';
-        s[(window.opera ? "innerHTML" : "text")] =
-            "MathJax.Hub.Config({{" +
-            "    config: ['MMLorHTML.js']," +
-            "    TeX: {{ extensions: ['AMSmath.js','AMSsymbols.js','noErrors.js','noUndefined.js'], equationNumbers: {{ autoNumber: 'AMS' }} }}," +
-            "    jax: ['input/TeX','input/MathML','output/HTML-CSS']," +
-            "    extensions: ['tex2jax.js','mml2jax.js','MathMenu.js','MathZoom.js']," +
-            "    displayAlign: '{align}'," +
-            "    displayIndent: '{indent}'," +
-            "    showMathMenu: {show_menu}," +
-            "    tex2jax: {{ " +
-            "        inlineMath: [ [\'$\',\'$\'] ], " +
-            "        displayMath: [ [\'$$\',\'$$\'] ]," +
-            "        processEscapes: {process_escapes}," +
-            "        preview: '{preview}'," +
-            "    }}, " +
-            "    'HTML-CSS': {{ " +
-            "        styles: {{ '.MathJax_Display, .MathJax .mo, .MathJax .mi, .MathJax .mn': {{color: '{color} ! important'}} }}" +
-            "    }} " +
-            "}}); ";
-        (document.body || document.getElementsByTagName('head')[0]).appendChild(s);
-    }}
-</script>
-"""
-
+with open (os.path.dirname(os.path.realpath(__file__))+'/mathjax_script.txt', 'r') as mathjax_script:  # Read the mathjax javascript from file
+    _MATHJAX_SCRIPT=mathjax_script.read()
 
 # Python standard library for binary search, namely bisect is cool but I need
 # specific business logic to evaluate my search predicate, so I am using my
@@ -103,7 +70,7 @@ def ignore_content(content):
 
     # used to detect all <pre> and <code> tags. NOTE: Alter this regex should
     # additional tags need to be ignored
-    ignore_regex = re.compile(r'<(pre|code).*?>.*?</(\1)>', re.DOTALL | re.IGNORECASE)
+    ignore_regex = re.compile(r'<(pre|code)(?:\s.*?)?>.*?</(\1)>', re.DOTALL | re.IGNORECASE)
 
     for match in ignore_regex.finditer(content):
         ignore_within.append(match.span())
@@ -111,31 +78,32 @@ def ignore_content(content):
     return ignore_within
 
 
-def wrap_latex(content, ignore_within):
-    """Wraps latex in user specified tags.
+def wrap_math(content, ignore_within):
+    """Wraps math in user specified tags.
 
-    This is needed for typogrify to play nicely with latex but it can also be
+    This is needed for typogrify to play nicely with math but it can also be
     styled by template providers
     """
-    wrap_latex.foundlatex = False
+
+    wrap_math.found_math = False
 
     def math_tag_wrap(match):
         """function for use in re.sub"""
 
         # determine if the tags are within <pre> and <code> blocks
-        ignore = binary_search(match.span(1), ignore_within) and binary_search(match.span(2), ignore_within)
+        ignore = binary_search(match.span(1), ignore_within) or binary_search(match.span(4), ignore_within)
 
         if ignore or match.group(3) == 'math':
             if match.group(3) == 'math':
                 # Will detect mml, but not wrap anything around it
-                wrap_latex.foundlatex = True
+                wrap_math.found_math = True
 
             return match.group(0)
         else:
-            wrap_latex.foundlatex = True
-            return '<%s>%s</%s>' % (_WRAP_TAG, match.group(0), _WRAP_TAG)
+            wrap_math.found_math = True
+            return '<%s>%s</%s>' % (_WRAP_LATEX, match.group(0), _WRAP_LATEX)
 
-    return (_LATEX_REGEX.sub(math_tag_wrap, content), wrap_latex.foundlatex)
+    return (_MATH_REGEX.sub(math_tag_wrap, content), wrap_math.found_math)
 
 
 def process_summary(instance, ignore_within):
@@ -146,41 +114,51 @@ def process_summary(instance, ignore_within):
     """
 
     process_summary.altered_summary = False
-    insert_mathjax_script = False
-    end_tag = '</%s>' % _WRAP_TAG if _WRAP_TAG != None else ''
+    insert_mathjax = False
+    end_tag = '</%s>' % _WRAP_LATEX if _WRAP_LATEX != None else ''
 
     # use content's _get_summary method to obtain summary
     summary = instance._get_summary()
 
     # Determine if there is any math in the summary which are not within the
     # ignore_within tags
-    mathitem = None
-    for mathitem in _LATEX_SUMMARY_REGEX.finditer(summary):
-        if binary_search(mathitem.span(), ignore_within):
-            mathitem = None # In <code> or <pre> tags, so ignore
+    math_item = None
+    for math_item in _MATH_SUMMARY_REGEX.finditer(summary):
+        ignore = binary_search(math_item.span(2), ignore_within)
+        if '...' not in math_item.group(5):
+            ignore = ignore or binary_search(math_item.span(5), ignore_within)
+        else:
+            ignore = ignore or binary_search(math_item.span(6), ignore_within)
+
+        if ignore:
+            math_item = None # In <code> or <pre> tags, so ignore
         else:
-            insert_mathjax_script = True
+            insert_mathjax = True
 
-    # Repair the latex if it was cut off mathitem will be the final latex
+    # Repair the math if it was cut off math_item will be the final math
     # code  matched that is not within <pre> or <code> tags
-    if mathitem and '...' in mathitem.group(6):
-        if mathitem.group(3) is not None:
-            end = r'\end{%s}' % mathitem.group(3)
-        elif mathitem.group(4) is not None:
+    if math_item and '...' in math_item.group(5):
+        if math_item.group(3) is not None:
+            end = r'\end{%s}' % math_item.group(3)
+        elif math_item.group(4) is not None:
             end = r'</math>'
-        elif mathitem.group(2) is not None:
-            end = mathitem.group(2)
+        elif math_item.group(2) is not None:
+            end = math_item.group(2)
 
-        search_regex = r'%s(%s.*?%s)' % (re.escape(instance._content[0:mathitem.start(1)]), re.escape(mathitem.group(1)), re.escape(end))
-        latex_match = re.search(search_regex, instance._content, re.DOTALL | re.IGNORECASE)
+        search_regex = r'%s(%s.*?%s)' % (re.escape(instance._content[0:math_item.start(1)]), re.escape(math_item.group(1)), re.escape(end))
+        math_match = re.search(search_regex, instance._content, re.DOTALL | re.IGNORECASE)
 
-        if latex_match:
-            new_summary = summary.replace(mathitem.group(0), latex_match.group(1)+'%s ...' % end_tag)
+        if math_match:
+            new_summary = summary.replace(math_item.group(0), math_match.group(1)+'%s ...' % end_tag)
 
             if new_summary != summary:
-                return new_summary+_MATHJAX_SCRIPT.format(**_MATHJAX_SETTINGS)
+                if _MATHJAX_SETTINGS['auto_insert']:
+                    return new_summary+_MATHJAX_SCRIPT.format(**_MATHJAX_SETTINGS)
+                else:
+                    instance.mathjax = True
+                    return new_summary
 
-    def partial_regex(match):
+    def incomplete_end_latex_tag(match):
         """function for use in re.sub"""
         if binary_search(match.span(3), ignore_within):
             return match.group(0)
@@ -188,15 +166,20 @@ def process_summary(instance, ignore_within):
         process_summary.altered_summary = True
         return match.group(1) + match.group(4)
 
-    # check for partial latex tags at end. These must be removed
+    # check for partial math tags at end. These must be removed
 
-    summary = _LATEX_PARTIAL_REGEX.sub(partial_regex, summary)
+    summary = _MATH_INCOMPLETE_TAG_REGEX.sub(incomplete_end_latex_tag, summary)
 
-    if process_summary.altered_summary:
-        return summary+_MATHJAX_SCRIPT.format(**_MATHJAX_SETTINGS) if insert_mathjax_script else summary
+    if process_summary.altered_summary or insert_mathjax:
+        if insert_mathjax:
+            if _MATHJAX_SETTINGS['auto_insert']:
+                summary+= _MATHJAX_SCRIPT.format(**_MATHJAX_SETTINGS)
+            else:
+                instance.mathjax = True
 
-    return summary+_MATHJAX_SCRIPT.format(**_MATHJAX_SETTINGS) if insert_mathjax_script else None
+        return summary
 
+    return None  # Making it explicit that summary was not altered
 
 def process_settings(settings):
     """Sets user specified MathJax settings (see README for more details)"""
@@ -213,9 +196,18 @@ def process_settings(settings):
     _MATHJAX_SETTINGS['indent'] = '0em'  # if above is not set to 'center', then this setting acts as an indent
     _MATHJAX_SETTINGS['show_menu'] = 'true'  # controls whether to attach mathjax contextual menu
     _MATHJAX_SETTINGS['process_escapes'] = 'true'  # controls whether escapes are processed
-    _MATHJAX_SETTINGS['preview'] = 'TeX'  # controls what user sees as preview
+    _MATHJAX_SETTINGS['latex_preview'] = 'TeX'  # controls what user sees while waiting for LaTex to render
     _MATHJAX_SETTINGS['color'] = 'black'  # controls color math is rendered in
 
+    # This next setting controls whether the mathjax script should be automatically
+    # inserted into the content. The mathjax script will not be inserted into
+    # the content if no math is detected. For summaries that are present in the
+    # index listings, mathjax script will also be automatically inserted.
+    # Setting this value to false means the template must be altered if this
+    # plugin is to work, and so it is only recommended for the template
+    # designer who wants maximum control.
+    _MATHJAX_SETTINGS['auto_insert'] = True # controls whether mathjax script is automatically inserted into the content
+
     if not isinstance(settings, dict):
         return
 
@@ -223,6 +215,9 @@ def process_settings(settings):
     # Iterate over dictionary in a way that is compatible with both version 2
     # and 3 of python
     for key, value in ((key, settings[key]) for key in settings):
+        if key == 'auto_insert' and isinstance(value, bool):
+            _MATHJAX_SETTINGS[key] = value
+
         if key == 'align' and isinstance(value, str):
             if value == 'left' or value == 'right' or value == 'center':
                 _MATHJAX_SETTINGS[key] = value
@@ -238,7 +233,7 @@ def process_settings(settings):
         if key == 'process_escapes' and isinstance(value, bool):
             _MATHJAX_SETTINGS[key] = 'true' if value else 'false'
 
-        if key == 'preview' and isinstance(value, str):
+        if key == 'latex_preview' and isinstance(value, str):
             _MATHJAX_SETTINGS[key] = value
 
         if key == 'color' and isinstance(value, str):
@@ -247,7 +242,7 @@ def process_settings(settings):
 
 def process_content(instance):
     """Processes content, with logic to ensure that typogrify does not clash
-    with latex.
+    with math.
 
     In addition, mathjax script is inserted at the end of the content thereby
     making it independent of the template
@@ -258,31 +253,36 @@ def process_content(instance):
 
     ignore_within = ignore_content(instance._content)
 
-    if _WRAP_TAG:
-        instance._content, latex = wrap_latex(instance._content, ignore_within)
+    if _WRAP_LATEX:
+        instance._content, math = wrap_math(instance._content, ignore_within)
     else:
-        latex = True if _LATEX_REGEX.search(instance._content) else False
+        math = True if _MATH_REGEX.search(instance._content) else False
 
     # The user initially set typogrify to be True, but since it would clash
-    # with latex, we set it to False. This means that the default reader will
+    # with math, we set it to False. This means that the default reader will
     # not call typogrify, so it is called here, where we are able to control
-    # logic for it ignore latex if necessary
+    # logic for it ignore math if necessary
     if _TYPOGRIFY:
-        # Tell typogrify to ignore the tags that latex has been wrapped in
+        # Tell typogrify to ignore the tags that math has been wrapped in
         # also, typogrify must always ignore mml (math) tags
-        ignore_tags = [_WRAP_TAG,'math'] if _WRAP_TAG else ['math']
+        ignore_tags = [_WRAP_LATEX,'math'] if _WRAP_LATEX else ['math']
 
         # Exact copy of the logic as found in the default reader
         from typogrify.filters import typogrify
         instance._content = typogrify(instance._content, ignore_tags)
         instance.metadata['title'] = typogrify(instance.metadata['title'], ignore_tags)
 
-    if latex:
-        # Mathjax script added to the end of article. Now it does not need to
-        # be explicitly added to the template
-        instance._content += _MATHJAX_SCRIPT.format(**_MATHJAX_SETTINGS)
+    if math:
+        if _MATHJAX_SETTINGS['auto_insert']:
+            # Mathjax script added to content automatically. Now it
+            # does not need to be explicitly added to the template
+            instance._content += _MATHJAX_SCRIPT.format(**_MATHJAX_SETTINGS)
+        else:
+            # Place the burden on ensuring mathjax script is available to
+            # browser on the template designer (see README for more details)
+            instance.mathjax = True
 
-        # The summary needs special care because latex math cannot just be cut
+        # The summary needs special care because math math cannot just be cut
         # off
         summary = process_summary(instance, ignore_within)
         if summary != None:
@@ -295,12 +295,12 @@ def pelican_init(pelicanobj):
     """
 
     global _TYPOGRIFY
-    global _WRAP_TAG
-    global _LATEX_SUMMARY_REGEX
-    global _LATEX_PARTIAL_REGEX
+    global _WRAP_LATEX
+    global _MATH_SUMMARY_REGEX
+    global _MATH_INCOMPLETE_TAG_REGEX
 
     try:
-        settings = pelicanobj.settings['LATEX']
+        settings = pelicanobj.settings['MATH']
     except:
         settings = None
 
@@ -314,30 +314,31 @@ def pelican_init(pelicanobj):
     try:
         if pelicanobj.settings['TYPOGRIFY'] == True:
             pelicanobj.settings['TYPOGRIFY'] = False
-            _WRAP_TAG = 'mathjax' # default to wrap mathjax content inside of
+            _WRAP_LATEX = 'mathjax' # default to wrap mathjax content inside of
             _TYPOGRIFY = True
     except KeyError:
         pass
 
-    # Set _WRAP_TAG to the settings tag if defined. The idea behind this is
+    # Set _WRAP_LATEX to the settings tag if defined. The idea behind this is
     # to give template designers control over how math would be rendered
     try:
-        if pelicanobj.settings['LATEX']['wrap']:
-            _WRAP_TAG = pelicanobj.settings['LATEX']['wrap']
+        if pelicanobj.settings['MATH']['wrap_latex']:
+            _WRAP_LATEX = pelicanobj.settings['MATH']['wrap_latex']
     except (KeyError, TypeError):
         pass
 
-    # regular expressions that depend on _WRAP_TAG are set here
-    tag_start= r'<%s>' % _WRAP_TAG if not _WRAP_TAG is None else ''
-    tag_end = r'</%s>' % _WRAP_TAG if not _WRAP_TAG is None else ''
-    latex_summary_regex = r'((\$\$|\$|\\begin\{(.+?)\}|<(math)(\s.*?)?>).+?)(\2|\\end\{\3\}|</\4>|\s?\.\.\.)(%s|</\4>)?' % tag_end
+    # regular expressions that depend on _WRAP_LATEX are set here
+    tag_start= r'<%s>' % _WRAP_LATEX if not _WRAP_LATEX is None else ''
+    tag_end = r'</%s>' % _WRAP_LATEX if not _WRAP_LATEX is None else ''
+    math_summary_regex = r'((\$\$|\$|\\begin\{(.+?)\}|<(math)(?:\s.*?)?>).+?)(\2|\\end\{\3\}|</\4>|\s?\.\.\.)(%s|</\4>)?' % tag_end
 
     # NOTE: The logic in _get_summary will handle <math> correctly because it
-    # is perceived as an html tag. Therefore we are only interested in handling non mml
-    latex_partial_regex = r'(.*)(%s)(\\\S*?|\$)\s*?(\s?\.\.\.)(%s)?$' % (tag_start, tag_end)
+    # is perceived as an html tag. Therefore we are only interested in handling
+    # non mml (i.e. LaTex)
+    incomplete_end_latex_tag = r'(.*)(%s)(\\\S*?|\$)\s*?(\s?\.\.\.)(%s)?$' % (tag_start, tag_end)
 
-    _LATEX_SUMMARY_REGEX = re.compile(latex_summary_regex, re.DOTALL | re.IGNORECASE)
-    _LATEX_PARTIAL_REGEX = re.compile(latex_partial_regex, re.DOTALL | re.IGNORECASE)
+    _MATH_SUMMARY_REGEX = re.compile(math_summary_regex, re.DOTALL | re.IGNORECASE)
+    _MATH_INCOMPLETE_TAG_REGEX = re.compile(incomplete_end_latex_tag, re.DOTALL | re.IGNORECASE)
 
 
 def register():

+ 30 - 0
render_math/mathjax_script.txt

@@ -0,0 +1,30 @@
+<script type= "text/javascript">
+    if (!document.getElementById('mathjaxscript_pelican_#%@#$@#')) {{
+        var mathjaxscript = document.createElement('script');
+        mathjaxscript.id = 'mathjaxscript_pelican_#%@#$@#';
+        mathjaxscript.type = 'text/javascript';
+        mathjaxscript.src = 'https:' == document.location.protocol
+		? 'https://c328740.ssl.cf1.rackcdn.com/mathjax/latest/MathJax.js'
+		: 'http://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML';
+        mathjaxscript[(window.opera ? "innerHTML" : "text")] =
+            "MathJax.Hub.Config({{" +
+            "    config: ['MMLorHTML.js']," +
+            "    TeX: {{ extensions: ['AMSmath.js','AMSsymbols.js','noErrors.js','noUndefined.js'], equationNumbers: {{ autoNumber: 'AMS' }} }}," +
+            "    jax: ['input/TeX','input/MathML','output/HTML-CSS']," +
+            "    extensions: ['tex2jax.js','mml2jax.js','MathMenu.js','MathZoom.js']," +
+            "    displayAlign: '{align}'," +
+            "    displayIndent: '{indent}'," +
+            "    showMathMenu: {show_menu}," +
+            "    tex2jax: {{ " +
+            "        inlineMath: [ ['$','$'] ], " +
+            "        displayMath: [ ['$$','$$'] ]," +
+            "        processEscapes: {process_escapes}," +
+            "        preview: '{latex_preview}'," +
+            "    }}, " +
+            "    'HTML-CSS': {{ " +
+            "        styles: {{ '.MathJax_Display, .MathJax .mo, .MathJax .mi, .MathJax .mn': {{color: '{color} ! important'}} }}" +
+            "    }} " +
+            "}}); ";
+        (document.body || document.getElementsByTagName('head')[0]).appendChild(mathjaxscript);
+    }}
+</script>