You should not use this project. You should use
knitpy
.
Evaluate code in markdown.
Mostly because I was jealous of RMarkdown/knitr.
The Jupyter notebook teaches us that interleaving prose, code, and results
conveys meaning well. However when we author persistent content we often want a
simple static text-based format. Markdown is good here because it plays well
with other tools like vi/emacs
, pandoc
, and git
.
RMarkdown/knitr has demonstrated value in the R ecosystem, lets mimic that.
PyMarkdown leverages the doctest
module to parse code into prose and code
segments much like a docstring. It then executes each code segment
sequentially with Python's exec
, tracking state throughout the document,
emitting or correcting results from computation where appropriate. For some
outputs we use custom rendering, notably leveraging common protocols like
__repr_html__
and special casing plotting libraries.
In simple cases both input and output documents are valid markdown appropriate for publication on github, your favorite blogging software, or with pandoc. For complex rendering we've specialized on emitting HTML-enhanced Markdown, which looks great in a browser but limits cross-markup-language compatibility (sorry LaTeX users).
Our documents contain prose with *rich formatting*.
```Python
# And code blocks
>>> x = 1
>>> x + 1
>>> 2 + 2*x
with potentially missing or wrong results
```
We run pymarkdown and look at updated results:
$ pymarkdown text.md text.out.md
Our documents contain prose with rich formatting.
# And code blocks
>>> x = 1
>>> x + 1
2
>>> 2 + 2*x
4
### HTML
PyMarkdown leverages standard protocols like `to_html` or `__repr_html__`.
```python
>>> import pandas as pd
>>> df = pd.DataFrame({'name': ['Alice', 'Bob', 'Charlie'],
... 'balance': [100, 200, 300]})
>>> df
```
PyMarkdown leverages standard protocols like to_html
or __repr_html__
.
>>> import pandas as pd
>>> df = pd.DataFrame({'name': ['Alice', 'Bob', 'Charlie'],
... 'balance': [100, 200, 300]})
>>> df
balance | name | |
---|---|---|
0 | 100 | Alice |
1 | 200 | Bob |
2 | 300 | Charlie |
PyMarkdown supports figure objects from both
[Matplotlib](http://matplotlib.org/) and
[Bokeh](http://bokeh.pydata.org/).
Bokeh plots only work in browser but remain interactive. You must create a
standalone HTML file, possibly with [Pandoc](http://johnmacfarlane.net/pandoc/)
pymarkdown myfile.md myfile.out.md
pandoc myfile.out.md -o myfile.html --standalone
But that output doesn't look good in a README, so here we'll use matplotlib
```Python
>>> import matplotlib.pyplot as plt
>>> fig = plt.figure()
>>> plt.plot([1, 2, 3, 4, 5], [6, 7, 2, 4, 5])
>>> fig
```
PyMarkdown supports figure objects from both Matplotlib and Bokeh.
Bokeh plots only work in browser but remain interactive. You must create a standalone HTML file, possibly with Pandoc
pymarkdown myfile.md myfile.out.md
pandoc myfile.out.md -o myfile.html --standalone
But that output doesn't look good in a README, so here we'll use matplotlib
>>> import matplotlib.pyplot as plt
>>> fig = plt.figure()
>>> plt.plot([1, 2, 3, 4, 5], [6, 7, 2, 4, 5])
[<matplotlib.lines.Line2D object at 0x7f1b53169690>]
>>> fig
There is none! This is a single-weekend project. Use at your own risk. Please contribute and take this project over.
I've learned both that this isn't that hard and that it would be well appreciated by many people. If you have the attention span to read this far then I encourage you to extend or reinvent this project.
- Interact with Bokeh plots. These already implement
__repr_html__
so this probably just means linking to some static content somewhere. - Interact with matplotlib
- Better command line interface (should use something like
argparse
rather thansys.argv
) - Support inlining of values in prose blocks
- Support options like ignore, echo=False, etc..
- Handle exceptions
- Find a better name?
-
I specialized towards HTML because that's what I care about at the moment. This might not be a good approach long term though.
-
Do we want to integrate with pandoc? I tend to do something like the following
pymarkdown myfile.md myfile.out.md && \ pandoc myfile.out.md -o myfile.html --standalone
But it would be nice for this to be easier to write in one go
pymarkdown myfile.md -o myfile.html
Have other thoughts? Great! Please implement them :)