MkDocs and MathJax - python

I'm new to MkDocs and am writing some technical documentation that requires latex. I've successfully built a small website with one of the MkDocs themes, however it won't properly display the latex equations. I followed the instructions at:
http://www.vlfeat.org/matconvnet/developers/
as well as the instructions following the python-markdown-mathjax link from that page. I have also tinkered with adding appropriate lines to my mkdocs.yaml file, similar to:
https://github.com/EdyJ/vehicle-physics-docs/blob/master/mkdocs.yml
However, issuing the command 'mkdocs build' still results in a site that doesn't render the equations. I've also tried adding a -x mathjax flag with the mkdocs build command.
I've scoured the web and have been tinkering for quite a bit of time now. Can anyone shed light on what I need to do to get these two playing together?

This is actually easier than I expected. First I installed the Python-Markdown-Math Extension:
pip install https://github.com/mitya57/python-markdown-math/archive/master.zip
Then I created a new MkDocs project:
mkdocs new test_math
Next I edited the test_math/docs/index.md file to be as follows (sample borrowed from the MathJax documentation):
# MathJax Test Page
When \(a \ne 0\), there are two solutions to \(ax^2 + bx + c = 0\) and they are
$$x = {-b \pm \sqrt{b^2-4ac} \over 2a}.$$
Finally, I edited the test_math/config.yaml file to be as follows:
site_name: Test Math
extra_javascript:
- https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.0/MathJax.js?config=TeX-AMS-MML_HTMLorMML
markdown_extensions:
- mdx_math
I was unsure if this would work, but I ran the test server to see:
mkdocs serve
I then opened my browser and loaded http://127.0.0.1:8000/. The page displayed with the sample equations properly formatted:
Then I remembered that the OP asked for this to work with ReadTheDocs, so I added the following line to the config:
theme: readthedocs
My browser reloaded and the following (properly formatted equations) displayed:
I should note that I'm getting some weird error about fontawesome not loading. With the MkdDocs' theme, the equations disappear after a minute (when the error appears in the browser's console). However, in the ReadTheDocs theme, the equations display properly, even with the error. Either way, I believe this error is related to some other issue on my local machine.
Finally, the Bounty is...
Looking for an answer drawing from credible and/or official sources
I don't normally advertise this, but since you asked, I am the lead developer of Python-Markdown, I work regularly with mitya57 (the creator of Python-Markdown-Math Extension) as he is one of two other developers with commit access to Python-Markdown, and I am a contributor to MkDocs (one of those contributions being support for Python-Markdown Extensions).

You will need to install the extension as indicated in the github README. It sounds as if you have already done that.
Then you need to tell Mkdocs that you are using this Python Markdown extension. You would do this by having a line such as this in your mkdocs.yaml:
markdown_extensions: [mathjax]
The YAML configuration documentation can be found at:
http://www.mkdocs.org/user-guide/configuration/#formatting-options

I am no expert on any of this but the below is what worked for me. One of my needs was to have the $...$ notation work for inline Latex, instead of \(..\) because the $ notation works directly in Jupyter notebooks and you can see what your text will look like without first running mkdocs.
For both $..$ and $$..$$ styles to work, first install pip install --upgrade python-markdown-math. Then do the following:
Put a text file called mathjaxhelper.js in the /docs folder, and it should contain only the following:
MathJax.Hub.Config({
config: ["MMLorHTML.js"],
jax: ["input/TeX", "output/HTML-CSS", "output/NativeMML"],
extensions: ["MathMenu.js", "MathZoom.js"]
});
The project.yml file should contain the following. (replace project.yml with your actual yml file)
markdown_extensions:
- extra
- tables
- mdx_math:
enable_dollar_delimiter: True
- fenced_code
theme: readthedocs
extra_javascript:
- https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.4/MathJax.js?config=TeX-AMS-MML_HTMLorMML
I will admit I am no expert and really only cared about what worked. It took me several hours to figure out what combination of things in the .yml and the mathjaxhelper.js file will get both $ and $$ to work. Hope this helps someone else.

It looks like be that this extension is not required:
docs/mathjaxhelper.js
MathJax.Hub.Config({
"tex2jax": { inlineMath: [ [ '$', '$' ] ] }
});
MathJax.Hub.Config({
config: ["MMLorHTML.js"],
jax: ["input/TeX", "output/HTML-CSS", "output/NativeMML"],
extensions: ["MathMenu.js", "MathZoom.js"]
});
mkdocs.yml
markdown_extensions:
- extra
- tables
- fenced_code
extra_javascript:
- https://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS_HTML
- mathjaxhelper.js
Seems to do the trick.

Here is a way to get LaTeX in MkDocs with the extension arithmatex.
I'm answering again because I want to document a solution that doesn't link to third party sites like Cloudflare and Google.
I'm going the way with the theme named mkdocs-material but you can replace theme: ...school with theme: readthedocs.
First install MkDocs and create a project:
https://www.mkdocs.org/#installation.
Then install mkdocs-material and MathJax as follows.
Say the project is called my-project.
Use downloads and not pip because you want to change the CDN to Cloudflare and the link to google.
cd my-project
git clone https://github.com/squidfunk/mkdocs-material.git
git clone https://github.com/mathjax/MathJax.git MathJax
Edit mkdocs.yml like described under "Usage", for example:
site_name: My Project
pages:
- Home: index.md
theme:
name: null
custom_dir: 'mkdocs-material/material'
palette:
primary: amber
accent: pink
language: de
feature:
tabs: true
font: false
logo:
icon: school
markdown_extensions:
- pymdownx.arithmatex
extra_javascript:
- ../MathJax/MathJax.js?config=TeX-AMS-MML_HTMLorMML
You can insert some TeX in index.md, build the site (mkdocs build) and open the index.html to check that MathJax works.
Because it doesn't work with mkdocs serve I uploaded the MathJax folder and linking to it instead of the link to the local path.
extra_javascript:
- https://mysite/MathJax/MathJax.js?config=TeX-AMS-MML_HTMLorMML
To activate TeX inline with $...$ you have to create an extra JS-file
cd docs
mkdir assets
touch extra.js
Insert the following text into extra.js:
window.MathJax = {
tex2jax: {
inlineMath: [ ["$","$"], ["\\(","\\)"] ],
displayMath: [ ["\\[","\\]"] ]
},
TeX: {
TagSide: "right",
TagIndent: ".8em",
MultLineWidth: "85%",
equationNumbers: {
autoNumber: "AMS",
},
unicode: {
fonts: "STIXGeneral,'Arial Unicode MS'"
}
},
displayAlign: "center",
showProcessingMessages: false,
messageStyle: "none"
};
and link to it in mkdocs.yml. Finaly the extra_javascript section can like this:
extra_javascript:
- https://mysite/MathJax/MathJax.js?config=TeX-AMS-MML_HTMLorMML
- assets/extra.js
Because we don't want to use CDN you can edit mkdocs-material/material/base.html and delete/uncomment the line with <link href="https://fonts.gstatic.com" rel="preconnect" crossorigin>.
Font-awesome and material-icons are already on board within mkdocs-material.

Related

Python library for dynamic documents

I want to write a script that generates reports for each team in my unit where each report uses the same template, but where the numbers specific to each team is used for each report. The report should be in a format like .pdf that non-programmers know how to open and read. This is in many ways similar to rmarkdown for R, but the reports I want to generate are based on data from code already written in python.
The solution I am looking for does not need to export directly to pdf. It can export to markdown and then I know how to convert. I do not need any fancier formatting than what markdown provides. It does not need to be markdown, but I know how to do everything else in markdown, if I only find a way to dynamically populate numbers and text in a markdown template from python code.
What I need is something that is similar to the code block below, but on a bigger scale and instead of printing output on screen this would saved to a file (.md or .pdf) that can then be shared with each team.
user = {'name':'John Doe', 'email':'jd#example.com'}
print('Name is {}, and email is {}'.format(user["name"], user["email"]))
So the desired functionality heavily influenced by my previous experience using rmarkdown would look something like the code block below, where the the template is a string or a file read as a string, with placeholders that will be populated from variables (or Dicts or objects) from the python code. Then the output can be saved and shared with the teams.
user = {'name':'John Doe', 'email':'jd#example.com'}
template = 'Name is `user["name"]`, and email is `user["email"]`'
output = render(template, user)
When trying to find a rmarkdown equivalent in python, I have found a lot of pointers to Jupyter Notebook which I am familiar with, and very much like, but it is not what I am looking for, as the point is not to share the code, only a rendered output.
Since this question was up-voted I want to answer my own question, as I found a solution that was perfect for me. In the end I shared these reports in a repo, so I write the reports in markdown and do not convert them to PDF. The reason I still think this is an answer to my original quesiton is that this works similar to creating markdown in Rmarkdown which was the core of my question, and markdown can easily be converted to PDF.
I solved this by using a library for backend generated HTML pages. I happened to use jinja2 but there are many other options.
First you need a template file in markdown. Let say this is template.md:
## Overview
**Name:** {{repo.name}}<br>
**URL:** {{repo.url}}
| Branch name | Days since last edit |
|---|---|
{% for branch in repo.branches %}
|{{branch[0]]}}|{{branch[1]}}|
{% endfor %}
And then you have use this in your python script:
from jinja2 import Template
import codecs
#create an dict will all data that will be populate the template
repo = {}
repo.name = 'training-kit'
repo.url = 'https://github.com/github/training-kit'
repo.branches = [
['master',15],
['dev',2]
]
#render the template
with open('template.md', 'r') as file:
template = Template(file.read(),trim_blocks=True)
rendered_file = template.render(repo=repo)
#output the file
output_file = codecs.open("report.md", "w", "utf-8")
output_file.write(rendered_file)
output_file.close()
If you are OK with your dynamic doc being in markdown you are done and the report is written to report.py. If you want PDF you can use pandoc to convert.
I would strongly recommend to install and use the pyFPDF Library, that enables you to write and export PDF files directly from python. The Library was ported from php and offers the same functionality as it's php-variant.
1.) Clone and install pyFPDF
Git-Bash:
git clone https://github.com/reingart/pyfpdf.git
cd pyfpdf
python setup.py install
2.) After successfull installation, you can use python code similar as if you'd work with fpdf in php like:
from fpdf import FPDF
pdf = FPDF()
pdf.add_page()
pdf.set_xy(0, 0)
pdf.set_font('arial', 'B', 13.0)
pdf.cell(ln=0, h=5.0, align='L', w=0, txt="Hello", border=0)
pdf.output('myTest.pdf', 'F')
For more Information, take a look at:
https://pypi.org/project/fpdf/
To work with pyFPDF clone repo from: https://github.com/reingart/pyfpdf
pyFPDF Documentation:
https://pyfpdf.readthedocs.io/en/latest/Tutorial/index.html

Jupyter nbconvert LaTex Export Theme

I am using Jupyter Notebook nbconvert (Save as menu) to export as pdf via Latex. However, the pdf file is not in a good shape. For example, some wide tables are shown well. I would prefer to have a box for tables to be resized to the width of the page. Is there any style, template that I can use to have nice reports and how I may ask nbconverter to use that style?
Here is the Latex output:
I would like something like this:
Looks like Pandas gained a ._repr_latex_() method in version 0.23. You'll need to set pd.options.display.latex.repr=True to activate it.
Without latex repr:
With latex repr:
Check out the options to get the formatting close to what you want. In order to match your desired output exactly, you'll need to use a custom latex template.
Edited to provide more information on templates:
Start here for general information about templates. You can create a .tplx file in the same path as your notebook and specify it as the template when running nbconvert from the command line: !jupyter nbconvert --to python 'example.ipynb' --stdout --template=my_custom_template.tplx. Alternatively, you can specify a default template to use when exporting as Latex via the menu by modifying the jupyter_notebook_config.py file in your ~.jupyter directory. If this file doesn't exist already, you can generate it by running the command jupyter notebook --generate-config from the command line. I have my template sitting in the ~/.jupyter directory as well, so I added the following to my jupyter_notebook_config.py:
# Insert this at the top of the file to allow you to reference
# a template in the ~.jupyter directory
import os.path
import sys
sys.path.insert(0, os.path.expanduser("~") + '/.jupyter')
# Insert this at the bottom of the file:
c.LatexExporter.template_file = 'my_template' # no .tplx extension here
c.LatexExporter.template_path = ['.', os.path.expanduser("~") + '/.jupyter'] # nbconvert will look in ~/.jupyter
To understand a bit about how the templates work, start by taking a look at null.tplx. The line ((*- for cell in nb.cells -*)) loops over all the cells in the notebook. The if statements that follow check the type of each cell and call the appropriate block.
The other templates extend null.tplx. Each template defines (or redefines) some of the blocks. The hierarchy is null->display_priority->document_contents->base->style_*->article.
Your custom template should probably extend article.tplx and add some Latex commands to the header that sets up the tables the way you want. Take a look at this blog post for an example of setting up a custom template.
Any setting that change the table size to fit it in the width of the page?
Latex code is something like this: \resizebox*{\textwidth}{!}{%

How to render HTML from markdown, which contains tables, using Sphinx

I have a *.md files which I am going to put into documentation with help of Sphinx. These files contains tables.
The documentation said to do the following:
pip install recommonmark
add:
source_parsers = {
'.md': 'recommonmark.parser.CommonMarkParser',
}
source_suffix = ['.rst', '.md']
to the conf.py
As a result the tables do not rendered normally. Rest of the md syntax rendered ok.
It looks like recommonmark does not support tables, as noted in issue #3 and PR #68.

How do you wrap lines in a Jupyter notebook?

I have a Jupyter notebook that I wish to convert to pdf for publication, however when I save the notebook as a pdf many of the cells go over the edge.
Is there are way to wrap lines (to the standard 80 characters) so that as I type the cells are never wider than a standard A4 page?
Alternatively, is there something I can do when I convert to pdf instead?
Thanks.
Here is a solution which will always wrap long lines (not just on export to psd):
https://stackoverflow.com/a/39398949/5411817
Essentially, there is a flag in Jupyter's config file which turns on line wrapping.
Simply add the following to your config:
{
"MarkdownCell": {
"cm_config": {
"lineWrapping": true
}
},
"CodeCell": {
"cm_config": {
"lineWrapping": true
}
}
}
You'll need to restart Jupyter to see the change.
You can find (or create) your config file in your user directory: ~/.ipython/profile_nbserver/ipython_notebook_config.py,
-
My Bad: I did not realize that line wrapping breaks on export to PDF !!
Comment under question by #Louie links to a discussion and sample code for writing a custom exporter. He also poses a workaround of manually wrapping long lines (in a pinch).
I'll leave my answer here, as it answers the question posted as the Title ("How do you wrap lines in a Jupiter Notebook?"), and highlights that the usual solution breaks on pdf export. Others looking for that answer can easily find it in this thread.
The problem has been solved in nbconvert 5.5 Just update and run
jupyter nbconvert --to pdf your-notebook.ipynb

IPython.display.Audio cannot correctly handle `.ogg` file type?

I was doing some audio analysis stuff with Jupyter and tried to play .ogg files with IPython.display.Audio. Since PyCharm often failed to open big .ipynb files, I mostly used web browser to view my Notebook files at localhost:8888.
This picture is what I get with Chrome. As you can see, FailToDisplay.ogg is taken from my work, the audio play bar is not activated. File-ACDC_-_Back_In_Black-sample.ogg and song sample.mp3 are all downloaded from Internet. The integrity of 3 files are all validated, i.e., they can all be played correctly with audio players.
I also tested it with Microsoft Edge and Firefox, and the results are mostly the same. 2 .ogg playbars are all inactive while .mp3 playbar is active and works perfectly. So I guess the problem is not web browser dependent.
I checked the html source code of these 3 audio playbars with Chrome Developer Tool, they are all like:
<audio controls="controls">
<source src="data:None;base64,VERYLONGTEXT" type="None">
Your browser does not support the audio element.
</audio>
The type for mp3 is audio/mpeg and type for ogg is None. After some google search, I guess this has something to do with MIME type. So I inspected 3 audio files with command mimetype:
$ mimetype ./*
./AudioDisplayErrorTest.ipynb: text/plain
./FailToDisplay.ogg: audio/x-vorbis+ogg
./File-ACDC_-_Back_In_Black-sample.ogg: video/x-theora+ogg
./song sample.mp3: audio/mpeg
Not very strange. Then I find this blog post How to set MIMETYPES on server : Forums : PythonAnywhere and tested my python MIME type settings:
>>> import mimetypes
>>> mimetypes.guess_type("foo.ogg")
(None, None)
Now I don't know what to do next with this kind of situation. Is this just a bug of Jupyter or IPython or system-wide? Where can I change this behavior?
My Python environment settings are
audioread==2.1.4
ipykernel==4.4.1
ipython==5.1.0
ipython-genutils==0.1.0
ipywidgets==4.1.1
jupyter==1.0.0
jupyter-client==4.3.0
jupyter-console==5.0.0
jupyter-core==4.1.1
librosa==0.4.3
nbconvert==4.2.0
nbformat==4.0.1
notebook==4.2.2
numpy==1.11.1
openpyxl==2.3.2
pydub==0.16.5
Since no one gives a hint, I guess I'll have to work alone...
First look into the source code of IPython.display.audio: ipython/display.py at 48b01aadcbb6a53d2c77fa250c8a4344931c357c · ipython/ipython
def _repr_html_(self):
src = """
<audio controls="controls" {autoplay}>
<source src="{src}" type="{type}" />
Your browser does not support the audio element.
</audio>
"""
return src.format(src=self.src_attr(),type=self.mimetype, autoplay=self.autoplay_attr())
This is the code that generates html source code of audio control block, type is assigned from self.mimetype. And self.mimetype is derived from reload():
if self.filename is not None:
self.mimetype = mimetypes.guess_type(self.filename)[0]
elif self.url is not None:
self.mimetype = mimetypes.guess_type(self.url)[0]
else:
self.mimetype = "audio/wav"
It's obvious if mimetypes.guess_type("filename.ogg")[0] gets None, then we have type == None, which results an inactive audio control block.
From 18.7. mimetypes — Map filenames to MIME types — Python 2.7.12 documentation I learned that MIME types can be loaded from file or dynamically added with mimetypes.add_type(). It also said by default mimetypes will load from Windows registry. I tried to modify system-wide MIME type settings of .ogg with one small utility FileTypesMan - Alternative to 'File Types' manager of Windows but it did not reflect on mimetypes, so I guess I'll have to let it go.
At last I realized that a monkey patch before IPython.display.Audio was used will possibly work and it really does:
It may not be perfect to solve the problem, but at least it works. So be it for now.

Categories

Resources