123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189 |
- # -*- coding: utf-8 -*-
- """
- Math Render Plugin for Pelican
- ==============================
- This plugin allows your site to render Math. It uses
- the MathJax JavaScript engine.
- For markdown, the plugin works by creating a Markdown
- extension which is used during the markdown compilation stage.
- Math therefore gets treated like a "first class citizen" in Pelican
- For reStructuredText, the plugin instructs the rst engine
- to output Mathjax for for math.
- The mathjax script is automatically inserted into the HTML.
- Typogrify Compatibility
- -----------------------
- This plugin now plays nicely with Typogrify, but it requires
- Typogrify version 2.04 or above.
- User Settings
- -------------
- Users are also able to pass a dictionary of settings in the settings file which
- will control how the MathJax library renders things. This could be very useful
- for template builders that want to adjust the look and feel of the math.
- See README for more details.
- """
- import os
- import sys
- from pelican import signals
- from . pelican_mathjax_markdown_extension import PelicanMathJaxExtension
- def process_settings(pelicanobj):
- """Sets user specified MathJax settings (see README for more details)"""
- mathjax_settings = {}
- # NOTE TO FUTURE DEVELOPERS: Look at the README and what is happening in
- # this function if any additional changes to the mathjax settings need to
- # be incorporated. Also, please inline comment what the variables
- # will be used for
- # Default settings
- mathjax_settings['align'] = 'center' # controls alignment of of displayed equations (values can be: left, right, center)
- 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['latex_preview'] = 'TeX' # controls what user sees while waiting for LaTex to render
- mathjax_settings['color'] = 'black' # controls color math is rendered in
- # Source for MathJax: Works boths for http and https (see http://docs.mathjax.org/en/latest/start.html#secure-access-to-the-cdn)
- mathjax_settings['source'] = "'//cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML'"
- # Get the user specified settings
- try:
- settings = pelicanobj.settings['MATH_JAX']
- except:
- settings = None
- # If no settings have been specified, then return the defaults
- if not isinstance(settings, dict):
- return mathjax_settings
- # The following mathjax settings can be set via the settings dictionary
- for key, value in ((key, settings[key]) for key in settings):
- # Iterate over dictionary in a way that is compatible with both version 2
- # and 3 of python
- if key == 'align' and isinstance(value, basestring):
- if value == 'left' or value == 'right' or value == 'center':
- mathjax_settings[key] = value
- else:
- mathjax_settings[key] = 'center'
- if key == 'indent':
- mathjax_settings[key] = value
- if key == 'show_menu' and isinstance(value, bool):
- mathjax_settings[key] = 'true' if value else 'false'
- if key == 'process_escapes' and isinstance(value, bool):
- mathjax_settings[key] = 'true' if value else 'false'
- if key == 'latex_preview' and isinstance(value, basestring):
- mathjax_settings[key] = value
- if key == 'color' and isinstance(value, basestring):
- mathjax_settings[key] = value
- return mathjax_settings
- def configure_typogrify(pelicanobj, mathjax_settings):
- """Instructs Typogrify to ignore math tags - which allows Typogfrify
- to play nicely with math related content"""
- # If Typogrify is not being used, then just exit
- if not pelicanobj.settings.get('TYPOGRIFY', False):
- return
- try:
- import typogrify
- from distutils.version import LooseVersion
- if LooseVersion(typogrify.__version__) < LooseVersion('2.0.7'):
- raise TypeError('Incorrect version of Typogrify')
- from typogrify.filters import typogrify
- # At this point, we are happy to use Typogrify, meaning
- # it is installed and it is a recent enough version
- # that can be used to ignore all math
- # Instantiate markdown extension and append it to the current extensions
- pelicanobj.settings['TYPOGRIFY_IGNORE_TAGS'].extend(['.math', 'script']) # ignore math class and script
- except (ImportError, TypeError, KeyError) as e:
- pelicanobj.settings['TYPOGRIFY'] = False # disable Typogrify
- if isinstance(e, ImportError):
- print("\nTypogrify is not installed, so it is being ignored.\nIf you want to use it, please install via: pip install typogrify\n")
- if isinstance(e, TypeError):
- print("\nA more recent version of Typogrify is needed for the render_math module.\nPlease upgrade Typogrify to the latest version (anything equal or above version 2.0.7 is okay).\nTypogrify will be turned off due to this reason.\n")
- if isinstance(e, KeyError):
- print("\nA more recent version of Pelican is needed for Typogrify to work with render_math.\nPlease upgrade Pelican to the latest version or clone it directly from the master GitHub branch\nTypogrify will be turned off due to this reason\n")
- def process_mathjax_script(mathjax_settings):
- """Load the mathjax script template from file, and render with the settings"""
- # Read the mathjax javascript template from file
- with open (os.path.dirname(os.path.realpath(__file__))+'/mathjax_script_template', 'r') as mathjax_script_template:
- mathjax_template = mathjax_script_template.read()
- return mathjax_template.format(**mathjax_settings)
- def mathjax_for_markdown(pelicanobj, mathjax_settings):
- """Instantiates a customized markdown extension for handling mathjax
- related content"""
- # Create the configuration for the markdown template
- config = {}
- config['mathjax_script'] = process_mathjax_script(mathjax_settings)
- config['math_tag_class'] = 'math'
- # Instantiate markdown extension and append it to the current extensions
- try:
- pelicanobj.settings['MD_EXTENSIONS'].append(PelicanMathJaxExtension(config))
- except:
- sys.excepthook(*sys.exc_info())
- sys.stderr.write("\nError - the pelican mathjax markdown extension failed to configure. MathJax is non-functional.\n")
- sys.stderr.flush()
- def mathjax_for_rst(pelicanobj, mathjax_settings):
- pelicanobj.settings['DOCUTILS_SETTINGS'] = {'math_output': 'MathJax'}
- rst_add_mathjax.mathjax_script = process_mathjax_script(mathjax_settings)
- def pelican_init(pelicanobj):
- """Loads the mathjax script according to the settings. Instantiate the Python
- markdown extension, passing in the mathjax script as config parameter
- """
- # Process settings
- mathjax_settings = process_settings(pelicanobj)
- # Configure Typogrify
- configure_typogrify(pelicanobj, mathjax_settings)
- # Configure Mathjax For Markdown
- mathjax_for_markdown(pelicanobj, mathjax_settings)
- # Configure Mathjax For RST
- mathjax_for_rst(pelicanobj, mathjax_settings)
- def rst_add_mathjax(instance):
- _, ext = os.path.splitext(os.path.basename(instance.source_path))
- if ext != '.rst':
- return
- # If math class is present in text, add the javascript
- if 'class="math"' in instance._content:
- instance._content += "<script type='text/javascript'>%s</script>" % rst_add_mathjax.mathjax_script
- def register():
- """Plugin registration"""
- signals.initialized.connect(pelican_init)
- signals.content_object_init.connect(rst_add_mathjax)
|