Merge pull request #162 from barrysteyn/master
Logic for MathMl; Fixed Bug; Updated Readme
This commit is contained in:
@@ -1,10 +1,20 @@
|
|||||||
Latex Plugin For Pelican
|
Latex Plugin For Pelican
|
||||||
========================
|
========================
|
||||||
|
|
||||||
This plugin allows you to write mathematical equations in your articles using Latex.
|
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 that is embedded in
|
It uses the MathJax Latex JavaScript library to render *Latex* and *MathMl* that is embedded in
|
||||||
between `$..$` for inline math and `$$..$$` for displayed math. It also allows for
|
your site.
|
||||||
writing equations in by using `\begin{equation}`...`\end{equation}`.
|
|
||||||
|
### 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
|
Installation
|
||||||
------------
|
------------
|
||||||
@@ -13,7 +23,7 @@ Then use as follows by adding the following to your settings.py:
|
|||||||
|
|
||||||
PLUGINS = ["latex"]
|
PLUGINS = ["latex"]
|
||||||
|
|
||||||
Your site is now capable of rendering latex math using the mathjax JavaScript
|
Your site is now capable of rendering math math using the mathjax JavaScript
|
||||||
library. No alterations to the template file is needed.
|
library. No alterations to the template file is needed.
|
||||||
|
|
||||||
### Typogrify
|
### Typogrify
|
||||||
@@ -22,15 +32,24 @@ 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
|
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.
|
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
|
Usage
|
||||||
-----
|
-----
|
||||||
### Backward Compatibility
|
### Backward Compatibility
|
||||||
This plugin is backward compatible in the sense that it
|
This plugin is backward compatible in the sense that it
|
||||||
accompishes what previous versions did without needing any setup in the
|
will render previous setups correctly. This is because those
|
||||||
metadata or settings files.
|
settings and metadata information is ignored by this version. Therefore
|
||||||
|
you can remove them to neaten up your site
|
||||||
|
|
||||||
### Settings File
|
### Settings File
|
||||||
Extra options regarding how mathjax renders latex can be set in the settings
|
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
|
file. These options are in a dictionary variable called `LATEX` in the pelican
|
||||||
settings file.
|
settings file.
|
||||||
|
|
||||||
@@ -40,7 +59,8 @@ The dictionary can be set with the following keys:
|
|||||||
html. For example, setting `wrap` to `'mathjax'` would wrap all math inside
|
html. For example, setting `wrap` to `'mathjax'` would wrap all math inside
|
||||||
`<mathjax>...</mathjax>` tags. If typogrify is set to True, then math needs
|
`<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
|
to be wrapped in tags and `wrap` will therefore default to `mathjax` if not
|
||||||
set.
|
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
|
* `align`: controls how displayed math will be aligned. Can be set to either
|
||||||
`left`, `right` or `center` (default is `center`).
|
`left`, `right` or `center` (default is `center`).
|
||||||
* `indent`: if `align` not set to `center`, then this controls the indent
|
* `indent`: if `align` not set to `center`, then this controls the indent
|
||||||
@@ -51,7 +71,7 @@ level (default is `0em`).
|
|||||||
loading.
|
loading.
|
||||||
* `color`: controls the color of the mathjax rendered font.
|
* `color`: controls the color of the mathjax rendered font.
|
||||||
|
|
||||||
For example, in settings.py, the following would make latex render in blue and
|
For example, in settings.py, the following would make math render in blue and
|
||||||
displaymath align to the left:
|
displaymath align to the left:
|
||||||
|
|
||||||
LATEX = {'color':'blue','align':left}
|
LATEX = {'color':'blue','align':left}
|
||||||
|
|||||||
@@ -28,11 +28,12 @@ from pelican import contents
|
|||||||
import re
|
import re
|
||||||
|
|
||||||
# Global Variables
|
# 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)
|
_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\{(.+?)\}).*?\1|\\end\{\2\}', re.DOTALL | re.IGNORECASE) # used to detect latex
|
_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_SUMMARY_REGEX = None # used to match latex in summary
|
||||||
_LATEX_PARTIAL_REGEX = None # used to match latex that has been cut off in summary
|
_LATEX_PARTIAL_REGEX = None # used to match latex that has been cut off in summary
|
||||||
_MATHJAX_SETTINGS = {} # Settings that can be specified by the user, used to control mathjax script settings
|
_MATHJAX_SETTINGS = {} # settings that can be specified by the user, used to control mathjax script settings
|
||||||
_MATHJAX_SCRIPT="""
|
_MATHJAX_SCRIPT="""
|
||||||
<script type= "text/javascript">
|
<script type= "text/javascript">
|
||||||
if (!document.getElementById('mathjaxscript_pelican')) {{
|
if (!document.getElementById('mathjaxscript_pelican')) {{
|
||||||
@@ -124,7 +125,11 @@ def wrap_latex(content, ignore_within):
|
|||||||
# determine if the tags are within <pre> and <code> blocks
|
# 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) and binary_search(match.span(2), ignore_within)
|
||||||
|
|
||||||
if ignore:
|
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
|
||||||
|
|
||||||
return match.group(0)
|
return match.group(0)
|
||||||
else:
|
else:
|
||||||
wrap_latex.foundlatex = True
|
wrap_latex.foundlatex = True
|
||||||
@@ -142,7 +147,7 @@ def process_summary(instance, ignore_within):
|
|||||||
|
|
||||||
process_summary.altered_summary = False
|
process_summary.altered_summary = False
|
||||||
insert_mathjax_script = False
|
insert_mathjax_script = False
|
||||||
endtag = '</%s>' % _WRAP_TAG if _WRAP_TAG != None else ''
|
end_tag = '</%s>' % _WRAP_TAG if _WRAP_TAG != None else ''
|
||||||
|
|
||||||
# use content's _get_summary method to obtain summary
|
# use content's _get_summary method to obtain summary
|
||||||
summary = instance._get_summary()
|
summary = instance._get_summary()
|
||||||
@@ -158,23 +163,33 @@ def process_summary(instance, ignore_within):
|
|||||||
|
|
||||||
# Repair the latex if it was cut off mathitem will be the final latex
|
# Repair the latex if it was cut off mathitem will be the final latex
|
||||||
# code matched that is not within <pre> or <code> tags
|
# code matched that is not within <pre> or <code> tags
|
||||||
if mathitem and mathitem.group(4) == ' ...':
|
if mathitem and '...' in mathitem.group(6):
|
||||||
end = r'\end{%s}' % mathitem.group(3) if mathitem.group(3) is not None else mathitem.group(2)
|
if mathitem.group(3) is not None:
|
||||||
latex_match = re.search('%s.*?%s' % (re.escape(mathitem.group(1)), re.escape(end)), instance._content, re.DOTALL | re.IGNORECASE)
|
end = r'\end{%s}' % mathitem.group(3)
|
||||||
new_summary = summary.replace(mathitem.group(0), latex_match.group(0)+'%s ...' % endtag)
|
elif mathitem.group(4) is not None:
|
||||||
|
end = r'</math>'
|
||||||
|
elif mathitem.group(2) is not None:
|
||||||
|
end = mathitem.group(2)
|
||||||
|
|
||||||
if new_summary != summary:
|
search_regex = r'%s(%s.*?%s)' % (re.escape(instance._content[0:mathitem.start(1)]), re.escape(mathitem.group(1)), re.escape(end))
|
||||||
return new_summary+_MATHJAX_SCRIPT.format(**_MATHJAX_SETTINGS)
|
latex_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 new_summary != summary:
|
||||||
|
return new_summary+_MATHJAX_SCRIPT.format(**_MATHJAX_SETTINGS)
|
||||||
|
|
||||||
def partial_regex(match):
|
def partial_regex(match):
|
||||||
"""function for use in re.sub"""
|
"""function for use in re.sub"""
|
||||||
if binary_search(match.span(), ignore_within):
|
if binary_search(match.span(3), ignore_within):
|
||||||
return match.group(0)
|
return match.group(0)
|
||||||
|
|
||||||
process_summary.altered_summary = True
|
process_summary.altered_summary = True
|
||||||
return match.group(1) + match.group(4)
|
return match.group(1) + match.group(4)
|
||||||
|
|
||||||
# check for partial latex tags at end. These must be removed
|
# check for partial latex tags at end. These must be removed
|
||||||
|
|
||||||
summary = _LATEX_PARTIAL_REGEX.sub(partial_regex, summary)
|
summary = _LATEX_PARTIAL_REGEX.sub(partial_regex, summary)
|
||||||
|
|
||||||
if process_summary.altered_summary:
|
if process_summary.altered_summary:
|
||||||
@@ -252,9 +267,10 @@ def process_content(instance):
|
|||||||
# with latex, we set it to False. This means that the default reader will
|
# with latex, 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
|
# 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 latex if necessary
|
||||||
if process_content.typogrify:
|
if _TYPOGRIFY:
|
||||||
# Tell typogrify to ignore the tags that latex has been wrapped in
|
# Tell typogrify to ignore the tags that latex has been wrapped in
|
||||||
ignore_tags = [_WRAP_TAG] if _WRAP_TAG else None
|
# also, typogrify must always ignore mml (math) tags
|
||||||
|
ignore_tags = [_WRAP_TAG,'math'] if _WRAP_TAG else ['math']
|
||||||
|
|
||||||
# Exact copy of the logic as found in the default reader
|
# Exact copy of the logic as found in the default reader
|
||||||
from typogrify.filters import typogrify
|
from typogrify.filters import typogrify
|
||||||
@@ -278,6 +294,7 @@ def pelican_init(pelicanobj):
|
|||||||
False should it be set to True.
|
False should it be set to True.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
global _TYPOGRIFY
|
||||||
global _WRAP_TAG
|
global _WRAP_TAG
|
||||||
global _LATEX_SUMMARY_REGEX
|
global _LATEX_SUMMARY_REGEX
|
||||||
global _LATEX_PARTIAL_REGEX
|
global _LATEX_PARTIAL_REGEX
|
||||||
@@ -298,7 +315,7 @@ def pelican_init(pelicanobj):
|
|||||||
if pelicanobj.settings['TYPOGRIFY'] == True:
|
if pelicanobj.settings['TYPOGRIFY'] == True:
|
||||||
pelicanobj.settings['TYPOGRIFY'] = False
|
pelicanobj.settings['TYPOGRIFY'] = False
|
||||||
_WRAP_TAG = 'mathjax' # default to wrap mathjax content inside of
|
_WRAP_TAG = 'mathjax' # default to wrap mathjax content inside of
|
||||||
process_content.typogrify = True
|
_TYPOGRIFY = True
|
||||||
except KeyError:
|
except KeyError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@@ -311,10 +328,13 @@ def pelican_init(pelicanobj):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
# regular expressions that depend on _WRAP_TAG are set here
|
# regular expressions that depend on _WRAP_TAG are set here
|
||||||
tagstart = r'<%s>' % _WRAP_TAG if not _WRAP_TAG is None else ''
|
tag_start= r'<%s>' % _WRAP_TAG if not _WRAP_TAG is None else ''
|
||||||
tagend = 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\{(.+?)\}).+?)(\2|\\end\{\3\}|\s?\.\.\.)(%s)?' % tagend
|
latex_summary_regex = r'((\$\$|\$|\\begin\{(.+?)\}|<(math)(\s.*?)?>).+?)(\2|\\end\{\3\}|</\4>|\s?\.\.\.)(%s|</\4>)?' % tag_end
|
||||||
latex_partial_regex = r'(.*)(%s)(\\.*?|\$.*?)(\s?\.\.\.)(%s)' % (tagstart, tagend)
|
|
||||||
|
# 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)
|
||||||
|
|
||||||
_LATEX_SUMMARY_REGEX = re.compile(latex_summary_regex, re.DOTALL | re.IGNORECASE)
|
_LATEX_SUMMARY_REGEX = re.compile(latex_summary_regex, re.DOTALL | re.IGNORECASE)
|
||||||
_LATEX_PARTIAL_REGEX = re.compile(latex_partial_regex, re.DOTALL | re.IGNORECASE)
|
_LATEX_PARTIAL_REGEX = re.compile(latex_partial_regex, re.DOTALL | re.IGNORECASE)
|
||||||
|
|||||||
Reference in New Issue
Block a user