plasTeX 3.0 — A Python Framework forProcessing LaTeX Documents

Kevin D. Smith

January 1, 2023

SAS
Email: Kevin.Smith@sas.com

ii

CONTENTS

1

Introduction

1

2

plastex — The Command-Line Interface
2.1 Command-Line and Configuration Options . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

3
3

3

The plasTEX Document
3.1 Sections . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
3.2 Paragraphs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
3.3 Complex Structures . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

15
17
20
20

4

Understanding Macros and Packages
4.1 Defining Macros in LATEX . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
4.2 Defining Macros in Python . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
4.3 Packages . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

27
27
28
36

5

Renderers
5.1 Simple Renderer Example . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
5.2 Renderable Objects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
5.3 Page Template Renderer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
5.4 HTML5 Renderer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
5.5 XHTML Renderer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
5.6 Other builtin renderers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

39
40
43
46
51
53
54

6

plasTEX Frameworks and APIs
6.1 plasTeX — The Python Macro and Document Interfaces . . . . . . . . . . . . . . . . . . . . . . .
6.2 plasTeX.ConfigManager — plasTEX Configuration . . . . . . . . . . . . . . . . . . . . . . .
6.3 plasTeX.DOM — The plasTEX Document Object Model (DOM) . . . . . . . . . . . . . . . . . . .
6.4 plasTeX.TeX — The TEX Stream . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
6.5 plasTeX.Context — The TEX Context . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
6.6 plasTeX.Renderers — The plasTEX Rendering Framework . . . . . . . . . . . . . . . . . . .
6.7 plasTeX.Imagers — The plasTEX Imaging Framework . . . . . . . . . . . . . . . . . . . . . .
6.8 Plugins . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

55
55
60
64
69
71
74
77
80

A About This Document85

B Frequently Asked Questions
B.1 Parsing LATEX . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

87
87

C Debugging
C.1 Logging levels . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

89
89

i

C.2

Using the python debugger . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

89

D Zope Page Template Tutorial
D.1 Template Attribute Language Expression Syntax (TALES) . . . . . . . . . . . . . . . . . . . . . . .
D.2 Template Attribute Language (TAL) Attributes . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

91
91
93

Index

99

ii

CHAPTERONE

Introduction
plasTEXis a collection of Python frameworks that allow you to process LATEX documents. This processing includes, but
is not limited to, conversion of LATEX documents to various document formats. Of course, it is capable of converting toHTML or XML formats such as DocBook, but it is an open framework that allows you to drive any type of rendering.
This means that it could be used to drive a COM object that creates a MS Word Document.
The plasTEX framework allows you to control all of the processes including tokenizing, object creation, and rendering
through API calls. You also have access to all of the internals such as counters, the states of “if” commands, locallyand globally defined macros, labels and references, etc. In essence, it is a LATEX document processor that gives you theadvantages of an XML document in the context of a language as superb as Python.
Here are some of the main features and benefits of plasTEX.
Simple High-Level API The API for processing a LATEX document is simple enough that you can write a LATEX to
HTML converter in one line of code (not including the Python import lines). Just to prove it, here it is!
import sys
from plasTeX.TeX import TeXfrom plasTeX.Renderers.HTML5 import Renderer
Renderer().render(TeX(file=sys.argv[-1]).parse())

Full Configuration File and Command-Line Option Control The configuration object included with plasTEX canbe extended to include your own options.
Low-Level Tokenizing Control The tokenizer in plasTEX works very much like the tokenizer in TEX itself. In yourmacro classes, you can actually control the draining of tokens and even change category codes.
Document Object While most other LATEX converters translate from LATEX source another type of markup, plasTEX
actually converts the document into a document object very similar to the DOM used in XML. Of course, there
are many Python constructs built on top of this object to make it more Pythonic, so you don’t have to deal withthe objects using only DOM methods. What’s really nice about this is that you can actually manipulate thedocument object prior to rendering. While this may be an esoteric feature, not many other converters let you get
between the parser and the renderer.
Full Rendering Control In plasTEX you get full control over the renderer. The basic distribution includes a HTML5
renderer based on Jinja2 templates, as well as a legacy XHTML renderer based on Zope templates (ZPT), butthese are merely examples of what you can do. A renderer is simply a collection of functions1 . During therendering process, each node in the document object is passed to the function in the renderer that has the same
name as the node. What that function does is up to the renderer. In the case of the Jinja2-based renderer, thenode is simply applied to the template using the render() method. If you don’t like Jinja2 or ZPT, there
1 “functions” is being used loosely here. Actually, any callable Python object (i.e. function, method, or any object with the __call__ method
implemented) can be used.

1

is nothing preventing you from populating a renderer with functions that invoke other types of templates, orfunctions that simply generate markup with print statements. You could even drive a COM interface to create a
MS Word document.

2

Contents

CHAPTER

TWO

plastex — The Command-Line Interface
While plasTEX makes it possible to parse LATEX directly from Python code, most people will simply use the suppliedcommand-line interface, plastex. plastex will invoke the parsing processes and apply a specified renderer. By default,
plastex will convert to HTML, although this can be changed in the plastex configuration.
Invoking plastex is very simple. To convert a LATEX document to HTML using all of the defaults, simply type thefollowing at shell prompt.
plastex mylatex.tex

where ‘mylatex.tex’ is the name of your LATEX file. The LATEX source will be parsed, all packages will be loaded andmacros expanded, and converted to HTML. Hopefully, at this point you will have a lovely set of HTML files that
accurately reflect the LATEX source document. Unfortunately, converting LATEX to other formats can be tricky, and there
are many pitfalls. If you are getting warnings or errors while converting your document, you may want to check the
FAQ in the appendix to see if your problem is addressed.
Running plastex with the default options may not give you output exactly the way you had envisioned. Luckily,
there are many options that allow you to change the rendering behavior. These options are described in the following
section.

2.1

Command-Line and Configuration Options

There are many options to plastex that allow you to control things input and output file encodings, where files are
generated and what the filenames look like, rendering parameters, etc. While plastex is the interface where theoptions are specified, for the most part these options are simply passed to the parser and renderers for their use. It iseven possible to create your own options for use in your own Python-based macros and renderers (see in particular
Section 5.1.2). The following options are currently available on the plastex command. They are categorized forconvenience.
Note that some commands such as --link and --lang-terms take in a list of arguments. If this is the last option supplied,
you would have to separate the filename from the list of arguments, e.g.
plastex --lang-terms foo bar -- input.tex

The plasTeX command line and configuration supports interpolation. That is, in options whose value is a string (or alist of strings), we replace all instances of %(foo)s with the value of the option foo. The formatting is done withpythons %-formatting and all %-formatting features are supported. Note that we only specify the name of the option,and not the section it belongs to.

3

Interpolation is performed each time a configuration option is accessed.

2.1.1

General Options

Configuration files
Command-Line Options: --config=config-file or -c config-file
Config File: [ general ] config
specifies a configuration file to load. This should be the first option specified on the command-line. Below is asample configuration file:[general]renderer=HTML5
copy-theme-extras=yes[document]
lang-terms=lang.xml[files]split-level=1

KpsewhichCommand-Line Options: --kpsewhich=program
Config File: [ general ] kpsewhich
Default: kpsewhich
specifies the kpsewhich program to use to locate LATEX files and packages.
Plugins
Command-Line Options: --plugins=plugins
Config File: [ general ] plugins
Default: []specifies a list of plugins to be used. Each element should be package name that python can import. See
Section 6.8 for more details.
Load LATEXpackages
Command-Line Options: --load-tex-packages or --no-load-tex-packages
Config File: [ general ] load-tex-packages
Default: True
specifies whether to attempt loading LATEXimplementations of packages when no python implementation exists.
LATEXpackages white-list
Command-Line Options: --tex-packages=packages
Config File: [ general ] tex-packages
Default: []specifies a list of packages whose LATEXimplementation should be loaded if there is no python implementations,even if --no-load-tex-packages is set.
Renderer
Command-Line Options: --renderer=renderer-name
Config File: [ general ] renderer
Default: HTML5
specifies which renderer to use. This is either one of the built in renderers, a renderer defined by a plugin, or a4

Contents

path to the directory of a renderer. A plugin can provide a renderer my_renderer by having a Renderers
submodule containing a my_renderer submodule exporting a Renderer class.
Packages directories
Command-Line Options: --packages-dir=directories
Config File: [ general ] packages-dirsDefault: []specifies a list of directories where python implementations of packages should be searched.
ThemesCommand-Line Options: --theme=theme-name
Config File: [ general ] theme
Default: default
specifies which theme to use.
Extra theme files
Command-Line Options: --copy-theme-extras or --ignore-theme-extras
Config File: [ general ] copy-theme-extras
Default: yes
indicates whether or not extra files that belong to a theme (if there are any) should be copied to the output
directory.
Extra templates directories
Command-Line Options: --extra-templates=directories
Config File: [ general ] extra-templates
Default: []specifies a list of directories where extra templates should be searched. Paths are relative to the current directory.
Dump XML output
Command-Line Options: --xml
Config File: [ general ] xml
Default: False
dumps a XML representation of the document (for debugging).
Debug parsing
Command-Line Options: --debug
Config File: [ general ] debug
Default: False
parses the document and drops into a debugger.

2.1.2

Document Properties

Base URL
Command-Line Options: --base-url=url
Config File: [ document ] base-url
specifies a base URL to prepend to the path of all links.
Number of Columns in the Index
Command-Line Options: --index-columns=integer
Config File: [ document ] index-columns
specifies the number of columns to group the index into.

Contents5

Language terms
Command-Line Options: --lang-terms string1 string2 . . .
Config File: [ document ] lang-terms
specifies a list of files that contain language terms
Section number depth
Command-Line Options: --sec-num-depth=integer
Config File: [ document ] sec-num-depth
Default: 6specifies the section level depth that should appear in section numbers. This value overrides the value of the
secnumdepth counter in the document.
Title for the document
Command-Line Options: --title=string
Config File: [ document ] title
specifies a title to use for the document instead of the title given in the LATEX source document
Table of contents depth
Command-Line Options: --toc-depth=integer
Config File: [ document ] toc-depth
specifies the number of levels to include in each table of contents.
Display sections in the table of contents that do not create files
Command-Line Options: --toc-non-files
Config File: [ document ] toc-non-files
specifies that sections that do not create files should still appear in the table of contents. By default, only sections
that create files will show up in the table of contents.
Disable character substitutions
Command-Line Options: --disable-charsub
Config File: [ document ] disable-charsub
specifies a list of characters not to perform character substitutions on. Character substitutions replace certain
characters or groups of characters with typographically superior unicode versions, e.g. ‘ with ‘. This may be
unsuitable for certain use cases. For example, it may make search harder.

2.1.3

Counters

It is possible to set the initial value of a counter from the command-line using the --counter option or the “counters”
section in a configuration file. The configuration file format for setting counters is very simple. The option name inthe configuration file corresponds to the counter name, and the value is the value to set the counter to.
[counters]
chapter=4
part=2The sample configuration above sets the chapter counter to 4, and the part counter to 2.
The --counter can also set counters. It accepts multiple arguments which must be surrounded by square brackets ([ ]).
Each counter set in the --counter option requires two values: the name of the counter and the value to set the counterto. An example of --counter is shown below.

6

Contents

plastex --counter part 2 --counter chapter 4 file.tex

Just as in the configuration example, this command-line sets the part counter to 2, and the chapter counter to 4.
Note that our notion of “setting” a counter to ‘n‘ is equivalent to the LATEX command\setcounter{counter}{n - 1}. This is so that, for example, in the above configuration, when we
first encounter \section{Foo}, we get Section 2 instead of Section 3 (since \section first increments thecounter then uses the counter value).
Set initial counter values
Command-Line Options: --counter=counter-name initial-value
specifies the initial counter values.

2.1.4

Document Links

The links section of the configuration is a little different than the others. The options in the links section are notpreconfigured, they are all user-specified. The links section includes information to be included in the navigation
object available on all sections in a document. By default, the section’s navigation object includes things like theprevious and next objects in the document, the child nodes, the sibling nodes, etc. The table below lists all of thenavigation objects that are already defined. The names for these items came from the link types defined at http://fantasai.tripod.com/qref/Appendix/LinkTypes/ltdef.html. Of course, it is up to the renderer
to actually make use of them.
Name
home
start
begin
first
end
last
next
prev
previousup
top
originparentchild
siblings
document
part
chapter
sectionsubsection
navigator
toc
contents
breadcrumbs

Description
the first section in the document
same as homesame as homesame as homethe last section in the document
same as end
the next section in the document
the previous section in the document
same as prev
the parent section
the top section in the document
same as top
the parent section
a list of the subsections
a list of the sibling sections
the document object
the current part object
the current chapter object
the current section object
the current subsection object
the top node in the document object
the node containing the table of contents
same as toc
a list of the parent objects of the current nodeSince each of these items references an object that is expected to have a URL and a title, any user-defined fields should
contain these as well (although the URL is optional in some items). To create a user-defined field in this object, youContents

7

need to use two options: one for the title and one for the URL, if one exists. They are specified in the config file asfollows:[links]next-url=http://myhost.com/glossary
next-title=The Next Document
mylink-title=Another Title

While you can not override a field that is populated by the document, there are times when a field isn’t populated. Thisoccurs, for example, in the prev field at the beginning of the document, or the next field at the end of the document. If
you specify a prev or next field in your configuration, those fields will be used when no prev or next is available. This
allows you to link to external documents at those points.
Set document links
Command-Line Options: --link=key optional-url title
specifies links to be included in the navigation object.

2.1.5

Input and Output Files

If you have a renderer that only generates one file, specifying the output filename is simple: use the --filename option
to specify the name. However, if the renderer you are using generates multiple files, things get more complicated.
The --filename option is also capable of handling multiple names, as well as giving you a templating way to build
filenames.
Below is a list of all of the options that affect filename generation.
Characters that shouldn’t be used in a filename
Command-Line Options: --bad-filename-chars=string
Config File: [ files ] bad-chars
Default: : #$%^&*!~‘"’=?/[]()|<>;\,.
specifies all characters that should not be allowed in a filename. These characters will be replaced by the valuein --bad-filename-chars-sub.
String to use in place of invalid characters
Command-Line Options: --bad-filename-chars-sub=string
Config File: [ files ] bad-chars-sub
Default: specifies a string to use in place of invalid filename characters ( specified by the --bad-chars-sub option)
Output Directory
Command-Line Options: --dir=directory or -d directory
Config File: [ files ] directory
Default: $jobname
specifies a directory name to use as the output directory.
Escaping characters higher than 7-bit
Command-Line Options: --escape-high-chars
Config File: [ files ] escape-high-chars
Default: False
some output types allow you to represent characters that are greater than 7-bits with an alternate representation
to alleviate the issue of file encoding. This option indicates that these alternate representations should be used.

8

Contents

Note: The renderer is responsible for doing the translation into the alternate format. This might not be supportedby all output types.
Template to use for output filenames
Command-Line Options: --filename=string
Config File: [ files ] filename
specifies the templates to use for generating filenames. The filename template is a list of space separated names.
Each name in the list is returned once. An example is shown below.
index.html toc.html file1.html file2.html

If you don’t know how many files you are going to be reproducing, using static filenames like in the example
above is not practical. For this reason, these filenames can also contain variables as described in Python’s string
Templates (e.g. $title, $id). Note that, if this option is configured on command line rather than in a configuration
file, the dollar characters probably need to be protected. For instance bash would require single quote protection,
as in plastex --filename=’$id’. These variables come from the namespace created in the renderer andinclude:• $name, the name of the item (e.g. part, chapter or section),• $id, the ID (i.e. label) of the item,• $ref , the counter associated to the item (if it exists),• $title, the title of the item,• $jobname, the basename of the LATEX file being processed.
One special variable is $num. This value in generated dynamically whenever a filename with $num is requested.
Each time a filename with $num is successfully generated, the value of $num is incremented.
The values of variables can also be modified by a format specified in parentheses after the variable. The format
is simply an integer that specifies how wide of a field to create for integers (zero-padded), or, for strings, howmany space separated words to limit the name to. The example below shows $num being padded to four places
and $title being limited to five words.
sect$num(4) $title(5)The list can also contain a wildcard filename (which should be specified last). Once a wildcard name is reached,
it is used from that point on to generate the remaining filenames. The wildcard filename contains a list ofalternatives to use as part of the filename indicated by a comma separated list of alternatives surrounded by a setof square brackets ([ ]). Each of the alternatives specified is tried until a filename is successfully created (i.e. allvariables resolve). For example, the specification below creates three alternatives.
$jobname_[$id, $title, sect$num(4)]The code above is expanded to the following possibilities.
$jobname_$id$jobname_$title$jobname_sect$num(4)Each of the alternatives is attempted until one of them succeeds. In order for an alternative to succeed, all of
the variables referenced in the template must be populated. For example, the $id variable will not be populated
Contents

9

unless the node had a \$label macro pointing to it. The $title variable would not be populated unless the node
had a title associated with it (e.g. such as section, subsection, etc.). Generally, the last one should contain novariables except for $num as a fail-safe alternative.
The default value for this option is index [$id, sect$num(4)] which, assuming HTML output, will
first generate a file index.html. Then, for each node triggering a file creation, it will try to use the node label. If
no label exists, it will use sectN.html where N is the next available number (starting from one), padded to four
digits. Of course the prefix sect is chosen because the default value for split-level is 2, which means generatinga new file or each section.
As last example, one could use index $name-[$ref, sect$num(4)]. Assuming our document contains two chapterswhich each contain two sections (and using the LATEXdefault numbering scheme and default plasTEXsplit level),
we would get filenames index.html, chapter-1.html, section-1-1.html, section-1-2.html, chapter-2.html, section2-1.html, section-2-2.html.
Input Encoding
Command-Line Options: --input-encoding=string
Config File: [ files ] input-encoding
Default: utf-8
specifies which encoding the LATEX source file is in
Output Encoding
Command-Line Options: --output-encoding=string
Config File: [ files ] output-encoding
Default: utf-8
specifies which encoding the output files should use. Note: This depends on the output format as well. While
HTML and XML use encodings, a binary format like MS Word, would not.
Splitting document into multiple files
Command-Line Options: --split-level=integer
Config File: [ files ] split-level
Default: 2
specifies the highest section level that generates a new file. Each section in a LATEX document has a number
associated with its hierarchical level. These levels are -2 for the document, -1 for parts, 0 for chapters, 1 forsections, 2 for subsections, 3 for subsubsections, 4 for paragraphs, and 5 for subparagraphs. A new file will
be generated for every section in the hierarchy with a value less than or equal to the value of this option. Thismeans that for the value of 2, files will be generated for the document, parts, chapters, sections, and subsections.
Log messages to file
Command-Line Options: --log
Config File: [ files ] log
Default: False
specifies whether log messages should be put into a file instead of printed.

2.1.6

Image Options

Images are created by renderers when the output type in incapable of rendering the content in any other way. Thismethod was commonly used to display equations in XHTML output. Nowadays, MathJax arguably provides a bettermethod, see Section 2.1.7 below. But there are still pieces of mathematics they are not handled by MathJax, such ascommutative diagrams written using the tikz-cd package. The following options control how images are generated.
Base URL
Command-Line Options: --image-base-url=url
Config File: [ images ] base-url
specifies a base URL to prepend to the path of all images.
10

Contents

LATEX program to use to compile image document
Command-Line Options: --image-compiler=program
Config File: [ images ] compiler
Default: latex
specifies which program to use to compile the images LATEX document. If unspecified, the default is specified
by the imager. Note that not all imagers are compatible with all compilers. Specifically, some imagers needcompilers that produces pdf’s and others need dvi’s.
LATEX program to use to compile vector image document
Command-Line Options: --vector-image-compiler=program
Config File: [ images ] vector-compiler
Default: latex
specifies which program to use to compile the vector images LATEX document. If unspecified, this uses the valueof --image-compiler.
Enable or disable image generation
Command-Line Options: --enable-images or --disable-images
Config File: [ images ] enabled
Default: yes
indicates whether or not images should be generated.
Enable or disable the image cacheCommand-Line Options: --enable-image-cache or --disable-image-cache
Config File: [ images ] cache
Default: yes
indicates whether or not images should use a cache between runs.
Convert LATEX output to images
Command-Line Options: --imager=program
Config File: [ images ] imager
Default: gspdfpng pdftoppm dvipng dvi2bitmap gsdvipng OSXCoreGraphics
specifies which converter will be used to take the output from the LATEX compiler and convert it to images. You
can specify a space delimited list of names as well. If a list of names is specified, each one is verified in order tosee if it works on the current machine. The first one that succeeds is used.
You can use the value of “none” to turn the imager off.
Image filenames
Command-Line Options: --image-filenames=filename-template
Config File: [ images ] filenames
Default: images/img-$num(4).png
specifies the image naming template to use to generate filenames. This template is the same as the templates
used by the --filename option.
Convert LATEX output to vector images
Command-Line Options: --vector-imager=program
Config File: [ images ] vector-imager
Default: pdf2svg dvisvgm
specifies which converter will be used to take the output from the LATEX compiler and convert it to vector images.
You can specify a space delimited list of names as well. If a list of names is specified, each one is verified inorder to see if it works on the current machine. The first one that succeeds is used.
You can use the value of “none” to turn the vector imager off.

Contents

11

Note: When using the vector imager, a bitmap image is also created using the regular imager. This bitmap isused to determine the depth information about the vector image and can also be used as a backup if the vector
image is not supported by the viewer.
Save temporary files for debugging
Command-Line Options: --save-image-file or --delete-image-file
Config File: [ images ] save-file
Default: no
specifies whether the temporary images.tex file should be retained after compilation. It can be useful to retain
the images for debugging purposes.
Scale factor of image
Command-Line Options: --image-scale-factor
Config File: [ images ] scale-factor
Default: 1.0
the default scale factor to apply to images after compilation. Not all imagers respect this option.
Scale factor for given node typeCommand-Line Options: --scales=node-name scale_factor
specifies the image scale factor for the specified type of node. Not all imagers respect this option.

2.1.7

HTML5 Renderer Options

Each renderer can define its own configuration options. This section describes options from the HTML5 renderer.
These options have no effect if another renderer is used. Also these options may have no effect if the default theme is
not used.
The first three options give control on navigation helpers (tables of contents and breadcrumbs links). Together withthe extra-css option, which allows to set css rules overriding the default ones, they allow radical changes to the output
style without modifying any template or python code. See Section 5.4 for more information on the HTML5 renderer
and how to customize its output.
Display table of contents on each page
Command-Line Options: --display-toc or --no-display-toc
Config File: [ html5 ] display-toc
Default: true
specifies whether to display the table of contents on each page.
Local table of contents level
Command-Line Options: --localtoc-level=level
Config File: [ html5 ] localtoc-level
Default: Node.DOCUMENT_LEVEL-1
specifies from which level one creates local table of contents. The default value implies local table of contents
are never created.
Create breadcrumbs from this level
Command-Line Options: --breadcrumbs-level=level
Config File: [ html5 ] breadcrumbs-level
Default: 10
specifies from which level one creates breadcrumbs navigation links. The default value means no breadcrumbat all.

12

Contents

Use theme CSS
Command-Line Options: --use-theme-css or --no-theme-css
Config File: [ html5 ] use-theme-css
Default: True
specifies whether to use CSS files from the theme.
Theme CSS file
Command-Line Options: --theme-css=theme
Config File: [ html5 ] theme-css
Default: white
specifies when CSS theme to use. Possible values are currently white, blue or green.
Extra CSS file
Command-Line Options: --extra-css filename1 filename2 ...
Config File: [ html5 ] extra-css
Default: []specifies a list of css files to use in addition the theme css. These files are copied to the output directory by
the renderer and loaded by the main layout template in the list order after the theme css files (if any) and the
packages css files (if any).
Use theme javascript
Command-Line Options: --use-theme-js or --no-theme-js
Config File: [ html5 ] use-theme-js
Default: True
specifies whether to use javascript files from the theme. The default theme javascript is used to hide or show
part of the table of contents and proofs.
Extra javascript
Command-Line Options: --extra-js filename1 filename2 ...
Config File: [ html5 ] extra-css
Default: []specifies a list of javascript files to use (in addition to those coming from the theme is the use-theme-js option is
set to true). These files are copied to the output directory by the renderer and loaded by the main layout templatein the list order after the theme javascript files (if any) and the packages javascript files (if any).
Use MathJax
Command-Line Options: --use-mathjax or --no-mathjax
Config File: [ html5 ] use-mathjaxDefault: True
specifies whether to use MathJax for mathematics rendering. Setting this to False only makes sense if the
document contains no mathematics or if some filter is expected to handle mathematics (see --filters option
below).
MathJax library url
Command-Line Options: --mathjax-url=url
Config File: [ html5 ] mathjax-url
Default: http://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS_CHTML
specifies where to find the MathJax javascript lib (including the config information as in the default value).
Use single dollars as math delimiter for MathJax
Command-Line Options: --dollars or --no-dollars
Config File: [ html5 ] mathjax-dollars
Contents

13

Default: False
specifies whether single dollars can be used as math delimiters instead of \( and \). This information is usedby MathJax.
MathJax macros
Command-Line Options: --mj-macros name value
Config File: [ mathjax-macros ] macros
Default: {}specifies a dictionary of macros for MathJax. This can be used for common macros that are not implemented
by MathJax, for instance \qedhere. On the command line, the option can be provided several times to define
several macros. But this option is much more convenient to specify in a config file in a mathjax-macros
section containing one line name=value per macro.
Filters applied on output
Command-Line Options: --filters filter1 filter2 . . .
Config File: [ html5 ] filters
Default: []specifies a list of commands to invoke on each output page. Each command should expect one file to convert on
stdin and output the converted file on stdout.

14

Contents

CHAPTER

THREE

The plasTEX Document
The plasTEX document is very similar to an XML DOM structure. In fact, you can use XML DOM methods tocreate and populate nodes, delete or move nodes, etc. The biggest difference between the plasTEX document and an
XML document is that in XML the attributes of an element are simply string values, whereas attributes in a plasTEX
document are generally document fragments that contain the arguments of a macro. Attributes can be configured tohold other Python objects like lists, dictionaries, and strings as well (see the section 4 for more information).
While XML document objects have a very strict syntax, LATEX documents are a little more free-form. Because of this,the plasTEX framework does a lot of normalizing of the LATEX document to make it conform to a set of rules. This setof rules means that you will always get a consistent output document which is necessary for easy manipulation andprogramability.
The overall document structure should not be surprising. There is a document element at the top level which corresponds to the XML Document node. The child nodes of the Document node begin with the preamble to the LATEX
document. This includes things like the \documentclass, \newcommands, \title, \author, counter settings,
etc. For the most part, these nodes can be ignored. While they are a useful part of the document, they are generally
only used by internal processes in plasTEX. What is important is the last node in the document which corresponds to
LATEX’s document environment.
The document environment has a very simple structure. It consists solely of paragraphs (actually \pars in TEX’s
terms) and sections1 . In fact, all sections have this same format including parts, chapters, sections, subsections, subsubsections, paragraphs, and subparagraphs. plasTEX can tell which pieces of a document correspond to a sectioning
element by looking at the level attribute of the Python class that corresponds to the given macro. The section levels
in plasTEX are the same as those used by LATEX: -1 for part, 0 for chapter, 1 for section, etc. You can create your own
sectioning commands simply by subclassing an existing macro class, or by setting the level attribute to a value that
corresponds to the level of section you want to mimic. All level values less than 100 are reserved for sectioning so you
aren’t limited to LATEX’s sectioning depth. Figure 3.1 below shows an example of the overall document structure.
This document is constructed during the parsing process by calling the digest method on each node. The digest
method is passed an iterator of document nodes that correspond to the nodes in the document that follow the current
node. It is the responsibility of the current node to only absorb the nodes that belong to it during the digest process.
Luckily, the default digest method will work in nearly all cases. See section 4 for more information on the digestion
process.
Part of this digestion process is grouping nodes into paragraphs. This is done using the paragraphs method available in all Macro based classes. This method uses the same technique as TEX to group paragraphs of content. Section
3.2 has more information about the details of paragraph grouping.
In addition to the level attribute of sections, there is also a mixin class that assists in generating the table of contents and navigation elements during rendering. If you create your own sectioning commands, you should include
plasTeX.Base.LaTeX.Sectioning.SectionUtils as a base class as well. All of the standard LATEX section commands already inherit from this class, so if you subclass one of those, you’ll get the helper methods for free.
For more information on these helper methods see section 3.1.
1 “sections” in this document is used loosely to mean any type of section: part, chapter, section, etc.

15

Figure 3.1: The overall plasTEX document structure
The structure of the rest of the document is also fairly simple and well-defined. LATEX commands are each converted
into a document node with it’s arguments getting placed into the attributes dictionary. LATEX environments also
create a single node in the document, where the child nodes of the environment include everything between the \begin
and \end commands. By default, the child nodes of an environment are simply inserted in the order that they appear
in the document. However, there are some environments that require further processing due to their more complex
structures. These structures include arrays and tabular environments, as well as itemized lists. For more informationon these structures see sections 3.3.3 and 3.3.1, respectively. Figures 3.2 and 3.3 shows a common LATEX document
fragment and the resulting plasTEX document node structure.
\begin{center}
Every \textbf{good} boy does \textit{fine}.
\end{center}

Figure 3.2: Sample LATEX document fragment code
You may have noticed that in the document structure in Figure 3.3 the text corresponding to the argument for \textbf
and \textit is actually a child node and not an attribute. This is actually a convenience feature in plasTEX. For
macros like this where there is only one argument and that argument corresponds to the content of the macro, it iscommon to put that content into the child nodes. This is done in the args attribute of the macro class by setting theargument’s name to “self”. This magical value will link the attribute called “self” to the child nodes array. For more
information on the args attribute and how it populates the attributes dictionary see section 4.
In the plasTEX framework, the input LATEX document is parsed and digested until the document is finished. At thispoint, you should have an output document that conforms to the rules described above. The document should havea regular enough structure that working with it programatically using DOM methods or Python practices should be
fairly straight-forward. The following sections give more detail on document structure elements that require extra
16

Contents

Figure 3.3: Resulting plasTEX document node structure
processing beyond the standard parse-digest process.

3.1

Sections“Sections” in plasTEX refer to any macro that creates a section-like construct in a document including the
document environment, \part, \chapter, \section, \subsection, \subsubsection, \paragraph, and\subparagraph. While these are the sectioning macros defined by LATEX, you are not limited to using just thosecommands to create sections in your own documents. There are two elements that must exist for a Python macro classto act like a section: 1) the level attribute must be set to a value less than 100, and 2) the class should inherit fromplasTeX.Base.LaTeX.Sectioning.SectionUtils.
The level attribute refers to the section level in the document. The values for this attribute are the same values thatLATEX uses for its section levels, namely:-1 or Node.PART_LEVEL corresponds to \part0 or Node.CHAPTER_LEVEL corresponds to \chapter
1 or Node.SECTION_LEVEL corresponds to \section
2 or Node.SUBSECTION_LEVEL corresponds to \subsection
3 or Node.SUBSUBSECTION_LEVEL corresponds to \subsubsection
4 or Node.PARAGRAPH_LEVEL corresponds to \paragraph
5 or Node.SUBPARAGRAPH_LEVEL corresponds to \subparagraphplasTEX adds the following section related levels:-sys.maxint or Node.DOCUMENT_LEVEL corresponds to the document environment and is always the toplevel section
Contents17

6 or Node.SUBSUBPARAGRAPH_LEVEL this level was added to correspond to the sixth level of headings definedin HTML
100 or Node.ENDSECTIONS_LEVEL flag that indicates the last possible section nesting level. This is mainly used
for internal purposes.
plasTEX uses the level attribute to build the appropriate document structure. If all you need is a proper document
structure, the level attribute is the only thing that needs to be set on a macro. However, there are many convenience
properties in the plasTeX.Base.LaTeX.Sectioning.SectionUtils class that are used in the rendering
process. If you plan on rendering your document, your section classes should inherit from this class. Below is a list of
the additional properties and their purpose.
Name
allSections
documentSections
links

siblings
subsections
tableofcontents

Purposecontains a sequential list of all of the sections within and including thecurrent section
contains a sequential list of all of the sections within the entire document
contains a dictionary contain various amounts of navigation information corresponding mostly to the link types describedathttp://fantasai.tripod.com/qref/Appendix/
LinkTypes/ltdef.html. This includes things like breadcrumb
trails, previous and next links, links to the overall table of contents, etc.
See section 3.1.1 for more information.
contains a list of all of the sibling sections
contains a list of all of the sections within the current section
contains an object that corresponds to the table of contents for the section. The table of contents is configurable as well. For more information
on how to configure the table of contents see section 3.1.2

Note: When first accessed, each of these properties actually navigates the document and builds the returned object.
Since these operations can be rather costly, the values are cached. Therefore, if you modify the document after
accessing one of these properties you will not see the change reflected.

3.1.1

Navigation and Links

The plasTeX.Base.LaTeX.Sectioning.SectionUtils class has a property named links that contains
a dictionary of many useful objects that assist in creating navigation bars and breadcrumb trails in the rendered output.
This dictionary was modeled after the links described at http://fantasai.tripod.com/qref/Appendix/
LinkTypes/ltdef.html. Some of the objects in this dictionary are created automatically, others are created withthe help of the linkType attribute on the document nodes, and yet others can be added manually from a configuration
file or command-line options. The automatically generated values are listed in the following table.

18

Contents

Name
begin
breadcrumbs
chapterchildcontents
document
end
first
home
home
last
navigator
next
originparentpart
prev
previous
sectionsibling
subsection
start
toc
top
up

Purposethe first section of the document
a list containing the entire parentage of the current section (including thecurrent section)
the current chapter nodea list of the subsections
the section that contains the top-level table of contents
the document level node
the last section of the document
the first section of the document
the first section of the document
the first section of the document
the last section of the document
the section that contains the top-level table of contents
the next section in the document
the section that contains the top-level table of contents
the parent node
the current part node
the previous section in the document
the previous section in the document
the current section
a list of the section siblings
the current subsection
the first section of the document
the section that contains the top-level table of contents
the first section of the document
the parent section

Note: The keys in every case are simply strings. Note: Each of the elements in the table above is either a section nodeor a list of section nodes. Of course, once you have a reference to a node you can acces the attributes and methods ofthat object for further introspection. An example of accessing these objects from a section instance is shown below.
previousnode = sectionnode.links[’prev’]
nextnode = sectionnode.links[’next’]

The next method of populating the links table is semi-automatic and uses the linkType attribute on the Python
macro class. There are certain parts of a document that only occur once such as an index, glossary, or bibliography.
You can set the linkType attribute on the Python macro class to a string that corresponds to that sections role in the
document (i.e. ‘index’ for the index, ‘glossary’ for the glossary, ‘bibliography’ for the bibliography). When a nodewith a special link type is created, it is inserted into the dictionary of links with the given name. This allows you
to have links to indexes, glossaries, etc. appear in the links object only when they are in the current document. The
example below shows the theindex environment being configured to show up under the ‘index’ key in the links
dictionary.
class theindex(Environment, SectionUtils):
nodeType = ’index’
level = Environment.SECTION_LEVEL

Note: These links are actually stored under the ‘links’ key of the owner document’s userdata dictionary (i.e.
self.ownerDocument.userdata[’links’]). Other objects can be added to this dictionary manually.
The final way of getting objects into the links dictionary is through a configuration file or command-line options. Thismethod is described fully in section 2.1.4.
Contents

19

3.1.2

Table of Contents

The table of contents object returned by the tableofcontents property of SectionUtils is not an actual nodeof the document, but it is a proxy object that limits the number of levels that you can traverse. The number of levels
that you are allowed to traverse is determined by document:toc-depth section of the configuration (see section
2.1.2). Other than the fact that you can only see a certain number of levels of subsections, the object otherwise actsjust like any other section node.
In addition to limiting the number of levels of a table of contents, you can also determine whether or not sections that do not generate new files while rendering should appear in the table of contents. By default, only sections that generate a new file while rendering will appear in the table of contents object. If you set the value of
document:toc-non-files in the configuration to True, then all sections will appear in the table of contents.

3.2

Paragraphs

Paragraphs in a plasTEX document are grouped in the same way that they are grouped in TEX: essentially anything
within a section that isn’t a section itself is put into a paragraph. This is different than the HTML model where tables
and lists are not grouped into paragraphs. Because of this, it is likely that HTML generated that keeps the same
paragraph model will not be 100% valid. However, it is highly unlikely that this variance from validity will cause any
real problems in the browser rendering the correct output.
Paragraphs are grouped using the paragraphs method available on all Python macro classes. When this method is
invoked on a node, all of the child nodes are grouped into paragraphs. If there are no paragraph objects in the list ofchild nodes already, one is created. This is done to make sure that the document is fully normalized and that paragraphs
occur everywhere that they can occur. This is most noteworthy in constructs like tables and lists where some table
cells or list items have multiple paragraphs and others do not. If a paragraph weren’t forced into these areas, you could
have inconsistently paragraph-ed content.
Some areas where paragraphs are allowed, but not necessarily needed might not want the forced paragraph to begenerated, such as within a grouping of curly braces ({ }). In these cases, you can use the force=False keyword
argument to paragraphs. This still does paragraph grouping, but only if there is a paragraph element already in thelist of child nodes.

3.3

Complex Structures

While much of a plasTEX document mirrors the structure of the source LATEX document, some constructs do require alittle more work to be useful in the more rigid structure. The most noteworthy of these constructs are lists, arrays (ortabular environments), and indexes. These objects are described in more detail in the following sections.

3.3.1

Lists

Lists are normalized slightly more than the rest of the document. They are treated almost like sections in that they are
only allowed to contain a minimal set of child node types. In fact, lists can only contain one type of child node: list
item. The consequence of this is that any content before the first item in a list will be thrown out. In turn, list items
will only contain paragraph nodes. The structure of all list structures will look like the structure in Figure 3.4.
This structure allows you to easily traverse a list with code like the following.

20

Contents

Figure 3.4: Normalized structure of all lists# Iterate through the items in the list node
for item in listnode:# Iterate through the paragraphs in each item
for par in item:# Print the text content of each paragraphprint par.textContent# Print a blank line to separate each item
print

3.3.2

Bibliography

The bibliography is really just another list structure with a few enhancements to allow referencing of the items throughout the document. Bibliography processing is left to the normal tools. plasTEX expects a properly ‘.bbl’ file for the
bibliography. The LATEX bibliography is the format used by default; however, the natbib package is also included with
plasTEX for more complex formatting of bibliographies.

3.3.3

Arrays and Tabular Environments

Arrays and tabular environments are the most complex structures in a plasTEX document. This because tables can
include spanning columns, spanning rows, and borders specified on the table, rows, and individual cells. In addition,
there are alignments associated with each column and alignments can be specified by any \multicolumn command.
It is also possible with some packages to create your own column declarations. Add to that the fact that the longtable
package allows you to specify multiple headers, footers, and coptions, and you can see why tabular environments canbe rather tricky to deal with.
As with all parts of the document, plasTEX tries to normalize all tables to have a consistent structure. The structure forContents

21

arrays and tables is shown in Figure 3.5.

Figure 3.5: Normalized structure of all tables and arrays
Luckily, the array macro class that comes with plasTEX was made to handle all of the work for you. In fact, it also
handles the work of some extra packages such as longtable to make processing them transparent. The details of thetabular environments are described in the following sections.
With this normalized structure, you can traverse all array and table structures with code like the following.

22

Contents

# Iterate through all rows in the table
for row in tablenode:# Iterate through all cells in the row
for cell in row:
# Iterate through all paragraphs in the cellfor par in cell:# Print the text content of each cell
print ’
’ + par.textContent# Print a blank line after each cellprint
# Print a blank line after each row
print

Borders
Borders in a tabular environment are generally handled by \hline, \vline, \cline, as well as the column specifications on the tabular environment and the \multicolumn command. plasTEX merges all of the border specifications
and puts them into CSS formatted values in the style attribute of each of the table cell nodes. To get the CSS
information formatted such that it can be used in an inline style, simply access the inline property of the styleobject.
Here is an example of a tabular environment.
\begin{tabular}{|l|l|}\hlinex & y \\
1 & 2 \\\hline\end{tabular}

The table node can be traversed as follows.
# Print the CSS for the borders of each cellfor rownum, row in enumerate(table):for cellnum, cell in enumerate(row):
print ’(%s,%s) %s -- %s’ % (rownum, cellnum,
cell.textContent.strip(), cell.style.inline)

The code above will print the following output (whitespace has been added to make the output easier to read).

Contents23

(0,0) x -- border-top-style:solid;
border-left:1px solid black;border-right:1px solid black;border-top-color:black;border-top-width:1px;
text-align:left(0,1) y -- border-top-style:solid;
text-align:left;border-top-color:black;border-top-width:1px;
border-right:1px solid black(1,0) 1 -- border-bottom-style:solid;
border-bottom-width:1px;
border-left:1px solid black;border-right:1px solid black;text-align:left;border-bottom-color:black(1,1) 2 -- border-bottom-color:black;border-bottom-width:1px;
text-align:left;border-bottom-style:solid;
border-right:1px solid black

Alignments
Alignments can be specified in the column specification of the tabular environment as well as in the column specification of \multicolumn commands. Just like the border information, the alignment information is also stored in CSS
formatted values in each cell’s style attribute.
Longtables
Longtables are treated just like regular tables. Only the first header and the last footer are supported in the resulting
table structure. To indicate that these are verifiable header or footer cells, the isHeader attribute of the corresponding
cells is set to True. This information can be used by the renderer to more accurately represent the table cells.

3.3.4

Indexes

All index building and sorting is done internally in plasTEX. It is done this way because the information that tools likemakeindex generate is only useful to LATEX itself since the refence to the place where the index tag was inserted issimply a page number. Since plasTEX wants to be able to reference the index tag node, it has to do all of the index
processing natively.
There are actually two index structures. The default structure is simply the index nodes sorted and grouped into theappropriate hierarchies. This structure looks like the structure pictured in Figure 3.6.
Each item, subitem, and subsubitem has an attribute called key that contains a document fragment of the key for thatindex item. The document nodes that this key corresponds to are held in a list in the pages attribute. These nodes
are the actual nodes corresponding to the index entry macros from the LATEX document. The content of the node isa number corresponding to the index entry that is formatted according to the formatting rules specified in the index
entry.
While the structure above works well for paged media, it is sometimes nice to have the index entries grouped by first
letter and possibly even arranged into multiple columns. This alternate representation can be accessed in the groups
24

Contents

Figure 3.6: Default index structure
property. The structure for this type of index is shown in Figure 3.7.
In this case, the item, subitem, and subsubitem nodes are the same as in the default scheme. The group has a title
attribute that contains the first letter of the entries in that group. Entries that start with something other than a letter oran underscore are put into a group called “Symbols”. The columns are approximately equally sized columns of index
entries. The number of columns is determined by the document:index-columns configuration item.

Contents25

Figure 3.7: Grouped index structure

26

Contents

CHAPTER

FOUR

Understanding Macros and Packages
Macros and packages in plasTEX live a dual life. On one hand, macros can be defined in LATEX files and expanded byplasTEX itself. On the other hand, macros can also be implemented as Python classes. Packages are the same way.
plasTEX can handle some LATEX packages natively. Others may have to be implemented in Python. In most cases, both
implementations work transparently together. If you don’t define that many macros, and the ones that you do define
are simple or even of intermediate complexity, it’s probably better to just let plasTEX handle them natively. However,there are some reasons that you may want to implement Python versions of your macros:• Python versions of macros are generally faster• You have more control over what gets inserted into the output document• You can store information in the document’s userdata dictionary for use later• You can prevent a macro from being expanded into primitive LATEX commands, so that a custom renderer can beused on that node
• Some macros just don’t make sense in a plasTEX document• Some macros are just too complicated for plasTEX
If any of these reasons appeal to you, read the following sections on how to implement macros and packages inplasTEX.

4.1

Defining Macros in LATEXDefining macros in LATEX using plasTEX is no different than the way you would normally define you macros; however,there is a trick that you can use to improve you macros for plasTEX, if needed. While plasTEX can handle fairly
complicated macros, some macros might do things that don’t make sense in the context of a plasTEX document, or theymight just be too complicated for the plasTEX engine to handle. In cases such as these, you can use the \ifplastex
construct. As you may know in TEX, you can define your own \if commands using the \newif primitive. There isan \if command called \ifplastex built into the plasTEX engine that is always set to true. In you document, you
can define this command and set it to false (as far as LATEX is concerned) as follows.
\newif\ifplastex\plastexfalse

Now you can surround the portions of your macros that plasTEX has trouble with, or even write alternative versions of
the macro for LATEX and plasTEX. Here is an example.

27

\newcommand{\foo}[1]{\ifplastex\else\vspace*{0.25in}\fi\textbf{\Large{#1}}\ifplastex\else\vspace*{1in}\fi}\ifplastex\newenvironment{coolbox}{}{}\else\newenvironment{coolbox}{fbox\bgroup\begin{minipage}{5in}}{\end{minipage}\egroup}
\fi

4.2

Defining Macros in Python

Defining macros using Python classes (or, at least through Python interfaces) is done in one of three ways: INI files,
Python classes, and the document context. These three methods are described in the following sections.

4.2.1

Python Classes

Both LATEX command and environments can be implemented in Python classes. plasTEX includes a base class for eachone: Command for commands and Environment for environments. For the most part, these two classes behavein the same way. They both are responsible for parsing their arguments, organizing their child nodes, incrementing counters, etc. much like their LATEX counterparts. There is also a variant of the Environment class called
NoCharSubEnvironment which temporarily turns off character substitutions described in Section 6.3.10. The
Python macro class feature set is based on common LATEX conventions. So if the LATEX macro you are implementing
in Python uses standard LATEX conventions, you job will be very easy. If you are doing unconventional operations, youwill probably still succeed, you just might have to do a little more work.
The three most important parts of the Python macro API are: 1) the args attribute, 2) the invoke method, and 3)
the digest method. When writing your own macros, these are used the most by far.
The args Attribute
The args attribute is a string attribute on the class that indicates what the arguments to the macro are. In addition
to simply indicating the number of arguments, whether they are mandatory or optional, and what characters surroundthe argument as in LATEX, the args string also gives names to each of the argument and can also indicate the content
of the argument (i.e. int, float, list, dictionary, string, etc.). The names given to each argument determine the key thatthe argument is stored under in the the attributes dictionary of the class instance. Below is a simple example ofa macro class.
from plasTeX import Command, Environment
class framebox(Command):""" \framebox[width][pos]{text} """args = ’[ width ] [ pos ] text’

In the args string of the \framebox macro, three arguments are defined. The first two are optional and the third one

28

Contents

is mandatory. Once each argument is parsed, in is put into the attributes dictionary under the name given in theargs string. For example, the attributes dictionary of an instance of \framebox will have the keys “width”,“pos”, and “text” once it is parsed and can be accessed in the usual Python way.
self.attributes[’width’]
self.attributes[’pos’]self.attributes[’text’]

In plasTEX, any argument that isn’t mandatory (i.e. no grouping characters in the args string) is optional1 . This
includes arguments surrounded by parentheses (( )), square brackets ([ ]), and angle brackets (< >). This also lets you
combine multiple versions of a command into one macro. For example, the \framebox command also has a form
that looks like: \framebox(x_dimen,y_dimen)[pos]{text}. This leads to the Python macro class in thefollowing code sample that encompasses both forms.
from plasTeX import Command, Environment
class framebox(Command):"""\framebox[width][pos]{text} or\framebox(x_dimen,ydimen)[pos]{text}"""
args = ’( dimens ) [ width ] [ pos ] text’

The only thing to keep in mind is that in the second form, the pos attribute is going to end up under the width key inthe attributes dictionary since it is the first argument in square brackets, but this can be fixed up in the invoke
method if needed. Also, if an optional argument is not present on the macro, the value of that argument in theattributes dictionary is set to None.
As mentioned earlier, it is also possible to convert arguments to data types other than the default (a document fragment).
A list of the available types is shown in the table below.
1 While this isn’t always true when LAT X expands the macros, it will not cause any problems when plasT X compiles the document because
E
E
plasTEX is less stringent.

Contents

29

Name
str
chr
char
cs
label

id
idref

ref
nox
list

dict

dimen
dimension
lengthnumber
count
int
float
doublePurposeexpands all macros then sets the value of the argument in theattributes dictionary to the string content of the argument
same as ‘str’
same as ‘str’
sets the attribute to an unexpanded control sequence
expands all macros, converts the result to a string, then sets the current label to the object that is in the currentlabel attribute of the document
context. Generally, an object is put into the currentlabel attribute
if it incremented a counter when it was invoked. The value stored in theattributes dictionary is the string value of the argument.
same as ‘label’
expands all macros, converts the result to a string, retrieves the object
that was labeled by that value, then adds the labeled object to the idref
dictionary under the name of the argument. This type of argument isused in commands like \ref that must reference other abjects. The nicething about ‘idref’ is that it gives you a reference to the object itself
which you can then use to retrieve any type of information from it suchas the reference value, title, etc. The value stored in the attributes
dictionary is the string value of the argument.
same as ‘idref’
just parses the argument, but doesn’t expand the macros
converts the argument to a Python list. By default, the list item separator
is a comma (,). You can change the item separator in the args string by appending a set of parentheses surrounding the separator character immediately after ‘list’. For example, to specify a semi-colon separated list for
an argument called “foo” you would use the args string: “foo:list(;)”. It
is also possible to cast the type of each item by appending another colonand the data type from this table that you want each item to be. However,
you are limited to one data type for every item in the list.
converts the argument to a Python dictionary. This is commonly used byarguments set up using LATEX’s ‘keyval’ package. By default, key/value
pairs are separated by commas, although this character can be changedin the same way as the delimiter in the ‘list’ type. You can also cast eachvalue of the dictionary using the same method as the ‘list’ type. In allcases, keys are converted to strings.
reads a dimension and returns an instance of dimensame as ‘dimen’same as ‘dimen’reads an integer and returns a Python integersame as ‘number’same as ‘number’reads a decimal value and returns a Python floatsame as ‘float’

There are also several argument types used for more low-level routines. These don’t parse the typical LATEX arguments,
they are used for the somewhat more free-form TEX arguments.

30

Contents

Name
Dimen
LengthDimension
MuDimen
MuLength
Glue
Skip
NumberInt
IntegerToken
Tok
XToken
XTok
Args

Purposereads a TEX dimension and returns an instance of dimensame as ‘Dimen’same as ‘Dimen’reads a TEX mu-dimension and returns an instance of mudimensame as ‘MuDimen’reads a TEX glue parameter and returns an instance of glue
same as ‘MuLength’
reads a TEX integer parameter and returns a Python integersame as ‘Number’same as ‘Number’reads an unexpanded token
same as ‘Token’reads an expanded token
same as ‘XToken’reads tokens up to the first begin group (i.e. {)To use one of the data types, simple append a colon (:) and the data type name to the attribute name in the args
string. Going back to the \framebox example, the argument in parentheses would be better represented as a list ofdimensions. The width parameter is also a dimension, and the pos parameter is a string.
from plasTeX import Command, Environment
class framebox(Command):"""\framebox[width][pos]{text} or\framebox(x_dimen,ydimen)[pos]{text}"""
args = ’( dimens:list:dimen ) [ width:dimen ] [ pos:chr ] text’

The invoke Method
The invoke method is responsible for creating a new document context, parsing the macro arguments, and incrementing counters. In most cases, the default implementation will work just fine, but you may want to do some extra
processing of the macro arguments or counters before letting the parsing of the document proceed. There are actually
several methods in the API that are called within the scope of the invoke method: preParse, preArgument,
postArgument, and postParse.
The order of execution is quite simple. Before any arguments have been parsed, the preParse method is called. The
preArgument and postArgument methods are called before and after each argument, respectively. Then, after
all arguments have been parsed, the postParse method is called. The default implementations of these methods
handle the stepping of counters and setting the current labeled item in the document. By default, macros that havebeen “starred” (i.e. have a ‘*’ before the arguments) do not increment the counter. You can override this behavior in
one of these methods if you prefer.
The most common reason for overriding the invoke method is to post-process the arguments in the attributes
dictionary, or add information to the instance. For example, the \color command in LATEX’s color package could
convert the LATEX color to the correct CSS format and add it to the CSS style object.

Contents

31

from plasTeX import Command, Environment
def latex2htmlcolor(arg):
if ’,’ in arg:
red, green, blue = [float(x) for x in arg.split(’,’)]
red = min(int(red * 255), 255)
green = min(int(green * 255), 255)
blue = min(int(blue * 255), 255)
else:
try:
red = green = blue = float(arg)except ValueError:
return arg.strip()
return ’#%.2X%.2X%.2X’ % (red, green, blue)class color(Environment):args = ’color:str’def invoke(self, tex):a = Environment.invoke(tex)self.style[’color’] = latex2htmlcolor(a[’color’])

While simple things like attribute post-processing is the most common use of the invoke method, you can do very
advanced things like changing category codes, and iterating over the tokens in the TEX processor directly like theverbatim environment does.
One other feature of the invoke method that may be of interest is the return value. Most invoke method implementations do not return anything (or return None). In this case, the macro instance itself is sent to the output stream.
However, you can also return a list of tokens. If a list of tokens is returned, instead of the macro instance, those tokens
are inserted into the output stream. This is useful if you don’t want the macro instance to be part of the output stream
or document. In this case, you can simply return an empty list.
The digest Method
The digest method is responsible for converting the output stream into the final document structure. For commands,
this generally doesn’t mean anything since they just consist of arguments which have already been parsed. Environments, on the other hand, have a beginning and an ending which surround tokens that belong to that environment. In
most cases, the tokens between the \begin and \end need to be absorbed into the childNodes list.
The default implementation of the digest method should work for most macros, but there are instances where you
may want to do some extra processing on the document structure. For example, the \caption command within
figures and tables uses the digest method to populate the enclosing figure/table’s caption attribute.

32

Contents

from plasTeX import Command, Environment
class Caption(Command):args = ’[ toc ] self’def digest(self, tokens):
res = Command.digest(self, tokens)# Look for the figure environment that we belong tonode = self.parentNode
while node is not None and not isinstance(node, figure):
node = node.parentNode# If the figure was found, populate the caption attribute
if isinstance(node, figure):
node.caption = self
return res
class figure(Environment):args = ’[ loc:str ]’caption = Noneclass caption_(Caption):
macroName = ’caption’counter = ’figure’

More advanced uses of the digest method might be to construct more complex document structures. For example,
tabular and array structures in a document get converted from a simple list of tokens to complex structures with lotsof style information added (see section 3.3.3). One simple example of a digest that does something extra is shown
below. It looks for the first node with the name “item” then bails out.
from plasTeX import Command, Environment
class toitem(Command):def digest(self, tokens):""" Throw away everything up to the first ’item’ token """for tok in tokens:
if tok.nodeName == ’item’:# Put the item back into the stream
tokens.push(tok)breakOne of the more advanced uses of the digest is on the sectioning commands: \section, \subsection, etc. The
digest method on sections absorb tokens based on the level attribute which indicates the hierarchical level of thenode. When digested, each section absorbs all tokens until it reaches a section that has a level that is equal to or higher
than its own level. This creates the overall document structure as discussed in section 3.
Other Nifty Methods and Attributes
There are many other attributes and methods on macros that can be used to affect their behavior. For a full listing,see the API documentation in section 6.1. Below are descriptions of some of the more commonly used attributes andmethods.

Contents

33

The level attribute The level attribute is an integer that indicates the hierarchical level of the node in the output
document structure. The values of this attribute are taken from LATEX: \part is -1, \chapter is 0, \section is 1,\subsection is 2, etc. To create your owne sectioning commands, you can either subclass one of the existing
sectioning macros, or simply set its level attribute to the appropriate number.
The macroName attribute The macroName attribute is used when you are creating a LATEX macro whose name is
not a legal Python class name. For example, the macro \@ifundefined has a ‘@’ in the name which isn’t legal ina Python class name. In this case, you could define the macro as shown below.
class ifundefined_(Command):macroName = ’@ifundefined’

The counter attribute The counter attribute associates a counter with the macro class. It is simply a string that
contains the name of the counter. Each time that an instance of the macro class is invoked, the counter is incremented(unless the macro has a ‘*’ argument).
The ref attribute The ref attribute contains the value normally returned by the \ref command.
The title attribute The title attribute retrieves the “title” attribute from the attributes dictionary. This
attribute is also overridable.
The fullTitle attribute The same as the title attribute, but also includes the counter value at the beginning.
The tocEntry attribute The tocEntry attribute retrieves the “toc” attribute from the attributes dictionary.
This attribute is also overridable.
The fullTocEntry attribute The same as the tocEntry attribute, but also includes the counter value at the
beginning.
The style attribute The style attribute is a CSS style object. Essentially, this is just a dictionary where the key
is the CSS property name and the value is the CSS property value. It has an attribute called inline which contains
an inline version of the CSS properties for use in the style= attribute of HTML elements.
The id attribute This attribute contains a unique ID for the object. If the object was labeled by a \label command,the ID for the object will be that label; otherwise, an ID is generated.
The source attribute The source attribute contains the LATEX source representation of the node and all of its
contents.
The currentSection attribute The currentSection attribute contains the section that the node belongs to.
The expand method The expand method is a thin wrapper around the invoke method. It simply invokes themacro and returns the result of expanding all of the tokens. Unlike invoke, you will always get the expanded node(or nodes); you will not get a None return value.
34

Contents

The paragraphs method The paragraphs method does the final processing of paragraphs in a node’s childnodes. It makes sure that all content is wrapped within paragraph nodes. This method is generally called from thedigest method.

4.2.2

INI Files

Using INI files is the simplest way of creating customized Python macro classes. It does require a little bit of knowledge of writing macros in Python classes (section 4.2.1), but not much. The only two pieces of information about
Python macro classes you need to know are 1) the args string format, and 2) the superclass name (in most cases, you
can simply use Command or Environment). The INI file features correspond to Python macros in the followingway.
INI File
section nameoption nameoption value

Python Macro Use
the Python class to inherit fromthe name of the macro to create
the args string for the macro

Here is an example of an INI file that defines several macros.
[Command]; \program{ self }program=self; \programopt{ self }programopt=self[Environment]; \begin{methoddesc}[ classname ]{ namemethoddesc=[ classname ] name args
; \begin{memberdesc}[ classname ]{ namememberdesc=[ classname ] name args

{ args } ... \end{methoddesc}{ args } ... \end{memberdesc}[section]; \headi( options:dict )[ toc ]{ title }headi=( options:dict ) [ toc ] title[subsection]; \headii( options:dict )[ toc ]{ title }headii=( options:dict ) [ toc ] title

In the INI file above, six macro are being defined. \program and \programopt both inherit from Command,
the generic LATEX macro superclass. They also both take a single mandatory argument called “self.” There are twoenvironments defined also: methoddesc and memberdesc. Each of these has three arguments where the firstargument is optional. The last two macros actually inherit from standard LATEX sectioning commands. They add an
option, surrounded by parentheses, to the options that \section and \subsection already had defined.
INI versions of plasTEX packages are loaded much in the same way as Python plasTEX packages. For details on how
packages are loaded, see section 4.3.

4.2.3

The Document Context

It is possible to define commands using the same interface that is used by the plasTEX engine itself. This interface
belongs to the Context object (usually accessed through the document object’s context attribute). Defining

Contents

35

commands using the context object is generally done in the ProcessOptions function of a package. The following
methods of the context object create new commands.
Methodnewcounter

newcount
newdimennewskip
newmuskip
newif
newcommand
newenvironment
newdefchardef

Purposecreates a new counter, and also creates a command called \thecounter
which generates the formatted version of the counter. This macro corresponds to the \newcounter macro in LATEX.
corresponds to TEX’s \newcount command.
corresponds to TEX’s \newdimen command.
corresponds to TEX’s \newskip command.
corresponds to TEX’s \newmuskip command.
corresponds to TEX’s \newif command. This command also generates
macros for \ifcommandtrue and \ifcommandfalse.
corresponds to LATEX’s \newcommand macro.
corresponds to LATEX’s \newenvironment macro.
corresponds to TEX’s \def command.
corresponds to TEX’s \chardef command.

Note: Since many of these methods accept strings containing LATEX markup, you need to remember that the category
codes of some characters can be changed during processing. If you are defining macros using these methods in theProcessOptions function in a package, you should be safe since this function is executed in the preamble of the
document where category codes are not changed frequently. However, if you define a macro with this interface in acontext where the category codes are not set to the default values, you will have to adjust the markup in your macrosaccordingly.
Below is an example of using this interface within the context of a package to define some commands. For the fullusage of these methods see the API documentation of the Context object in section 6.5.
def ProcessOptions(options, document):
context = document.context# Create some counters
context.newcounter(’secnumdepth’, initial=3)
context.newcounter(’tocdepth’, initial=2)# \newcommand{\config}[2][general]{\textbf{#2:#1}
context.newcommand(’config’, 2, r’\textbf{#2:#1}’, opt=’general’)# \newenvironment{note}{\textbf{Note:}}{}
context.newenvironment(’note’, 0, (r’\textbf{Note:}’, r’’))4.3

Packages

Packages in plasTEX are loaded in one of three ways: standard LATEX package, Python package, and INI file. LATEX
packages are loaded in much the same way that LATEX itself loads packages. The kpsewhich program is used to locate
the requested file which can be either in the search path of your LATEX distribution or in one of the directories specified
in the TEXINPUTS environment variable. plasTEX read the file and expand the macros therein just as LATEX would do.
This happens only if the --load-tex-packages option is set (which is the default value), or the package is white-listed
in the --tex-packages option (see Section2.1.1). It will work as expected only for simple packages.
Python packages are located by successively trying three strategies. First plasTEX looks into the directories listed in
the --packages-dirs option (see Section2.1.1), in the order they are listed. If this fail then plasTEX looks into theplugins listed in the --plugins option (see Sections 2.1.1 and 6.8), in the reversed order they are listed (the general
36

Contents

idea here is that later plugins are allowed to overrule earlier ones). If this also fails then plasTEX looks into the builtin
packages folder that comes with every installation of plasTEX. After a package is loaded, it is checked to see if there
is a function called ProcessOptions in its namespace. If there is, that function is called with two arguments: 1)
the dictionary of options that were specified when loading the package, and 2) the document object that is currently
being processed. This function allows you to make adjustments to the loaded macros based on the options specified,and define new commands in the document’s context (see section 4.2.3 for more information). Of course, you can also
define Python based macros (section 4.2.1) in the Python package as well.
The last type of packages is based on the INI file format. This format is discussed in more detail in section 4.2.2.
INI formatted packages are loaded in conjunction with a LATEX or Python package. When a package is loaded, an
INI file with the same basename is searched for in the same director as the package. If it exists, it is loaded as well.
For example, if you had a package called ‘python.sty’ and a file called ‘python.ini’ in the same package directory,‘python.sty’ would be loaded first, then ‘python.ini’ would be loaded. The same operation applies for Python based
packages.

Contents37

38

CHAPTER

FIVE

Renderers
Renderers allow you to convert a plasTEX document object into viewable output such as HTML, RTF, or PDF, or
simply a data structure format such as DocBook or tBook. Since the plasTEX document object gives you everythingthat you could possibly want to know about the LATEX document, it should, in theory, be possible to generate any typeof output from the plasTEX document object while preserving as much information as the output format is capable of.
In addition, since the document object is not affected by the rendering process, you can apply multiple renderers insequence so that the LATEX document only needs to be parsed one time for all output types.
While it is possible to write a completely custom renderer, a couple of renderer implementations are included withthe plasTEX framework. While the rendering process in this implementation is fairly simple, it is also very powerful.
Some of the main features are listed below.
• ability to generate multiple output files• automatic splitting of files is configurable by section level, or can be invoked using ad-hoc methods in thefilenameoverride property• powerful output filename generation utility• image generation for portions of the document that cannot be easily rendered in a particular output formate (e.g.
TikZ pictures in HTML)• theming support• hooks for post-processing of output files• configurable output encodings
The API of the renderer itself is very small. In fact, there are only a couple of methods that are of real interest to an end
user: render and cleanup. The render method is the method that starts the rendering process. Its only argument
is a plasTEX document object. The cleanup method is called at the end of the rendering process. It is passed the
document object and a list of all of the files that were generated. This method allows you to do post-processing on the
output files. In general, this method will probably only be of interest to someone writing a subclass of the Renderer
class, so most users of plasTEX will only use the render method. The real work of the rendering process is handled
in the Renderable class which is discussed later in this chapter.
The Renderer class is a subclass of the Python dictionary. Each key in the renderer corresponds to the name of anode in the document object. The value stored under each key is a function. As each node in the document object istraversed, the renderer is queried to see if there is a key that matches the name of the node. If a key is found, the value
at that key (which must be a function) is called with the node as its only argument. The return value from this callmust be a string object that contains the rendered output. Based on the configuration, the renderer will handle all of
the file generation and encoding issues.
If a node is traversed that doesn’t correspond to a key in the renderer dictionary, the default rendering method is called.
The default rendering method is stored in the default attribute. One exception to this rule is for text nodes. The
39

default rendering method for text nodes is actually stored in textDefault. Again, these attributes simply need toreference any Python function that returns a string object of the rendered output. The default method in both of these
attributes is the str built-in function.
As mention previously, most of the work of the renderer is actually done by the Renderable class. This is a mixinclass1 that is mixed into the Node class in the render method. It is unmixed at the end of the render method. The
details of the Renderable class are discussed in section 5.2.

5.1

Simple Renderer Example

It is possible to write a renderer with just a couple of methods: default and textDefault. The code below
demonstrates how one might create a generic XML renderer that simply uses the node names as XML tag names. The
text node renderer escapes the <, >, and & characters.
import stringfrom plasTeX.Renderers import Renderer as _Renderer
class Renderer(_Renderer):def default(self, node):""" Rendering method for all non-text nodes """s = []# Handle characters like \&, \$, \%, etc.
if len(node.nodeName) == 1 and node.nodeName not in string.ascii_letters:
return self.textDefault(node.nodeName)# Start tags.append(’<%s>’ % node.nodeName)# See if we have any attributes to render
if node.hasAttributes():s.append(’<attributes>’)for key, value in node.attributes.items():# If the key is ’self’, don’t render it# these nodes are the same as the child nodes
if key == ’self’:continues.append(’<%s>%s</%s>’ % (key, str(value), key))s.append(’</attributes>’)# Invoke rendering on child nodess.append(str(node))# End tags.append(’</%s>’ % node.nodeName)
return ’\n’.join(s)def textDefault(self, node):""" Rendering method for all text nodes """return node.replace(’&’,’&amp;’).replace(’<’,’&lt;’).replace(’>’,’&gt;’)

1 A mixin class is simply a class that is merely a collection of methods that are intended to be included in the namespace of another class.

40

Contents

To use the renderer, simply parse a LATEX document and apply the renderer using the render method.
# Import renderer from previous code sample
from MyRenderer import Rendererfrom plasTeX.TeX import TeX# Instantiate a TeX processor and parse the input text
tex = TeX()
tex.ownerDocument.config[’files’][’split-level’] = -100
tex.ownerDocument.config[’files’][’filename’] = ’test.xml’
tex.input(r’’’\documentclass{book}\begin{document}
Previous paragraph.
\section{My Section}\begin{center}
Centered text with <, >, and \& charaters.
\end{center}
Next paragraph.
\end{document}’’’)
document = tex.parse()# Render the document
renderer = Renderer()
renderer.render(document)

The output from the renderer, located in ‘test.xml’, looks like the following.
<document><par>Previous paragraph.
</par><section><attributes><toc>None</toc><*modifier*>None</*modifier*><title>My Section</title></attributes><par><center>
Centered text with &lt;, &gt;, and &amp; charaters.
</center></par><par>Next paragraph.
</par></section></document>

Contents

41

5.1.1

Extending the Simple RendererNow that we have a simple renderer working, it is very simple to extend it to do more specific operations. Let’s saythat the default renderer is fine for most nodes, but for the \section node we want to do something special. For thesection node, we want the title argument to correspond to the title attribute in the output XML2 . To do this we need amethod like the following.
def handle_section(node):
return ’\n\n<%s title="%s">\n%s\n</%s>\n’ % \(node.nodeName, str(node.attributes[’title’]),str(node), node.nodeName)

Now we simply insert the rendering method into the renderer under the appropriate key. Remember that the key in therenderer should match the name of the node you want to render. Since the above rendering method will work for all
section types, we’ll insert it into the renderer for each LATEX sectioning command.
renderer = Renderer()
renderer[’section’] = handle_section
renderer[’subsection’] = handle_section
renderer[’subsubsection’] = handle_section
renderer[’paragraph’] = handle_section
renderer[’subparagraph’] = handle_section
renderer.render(document)

Running the same LATEX document as in the previous example, we now get this output.
<document><par>Previous paragraph.
</par><section title="My Section"><par><center>
Centered text with &lt;, &gt;, and &amp; charaters.
</center></par><par>Next paragraph.
</par></section></document>

Of course, you aren’t limited to using just Python methods. Any function that accepts a node as an argument canbe used. The Page Template renderer included with plasTEX is an example of how to write a renderer that uses atemplating language to render the nodes (see section 5.3).
2 This will only work properly in XML if the content of the title is plain text since other nodes will generate markup.

42

Contents

5.1.2Using a Renderer from the plastex Script

In the preceding sections, the simple renderer example was called from a custom python script. In order
to use it through the main plastex script (described in Chapter 2), it needs to be located in some directoryplasTeX/Renderers/SimpleRenderer, where plasTeX is the directory containing the plastex script. This
directory must contain a __init__.py file defining the Renderer class (with this name). This directory can also
contain a Themes directory in order to use the theme option described in Section 2.1.1. Each subdirectory in the
Themes directory is considered as a theme.
Each renderer can define its own configuration options which are loaded by the plastex script. This is done in a file
named Config.py in the renderer directory. This file must define a variable named config which is a ConfigManager
instance, as described in Section 6.2. Inspiration can be drawn from the file defining the global configuration which isplasTeX/Config.py.
For instance, one could add a file plasTeX/Renderers/SimpleRenderer/Config.py containing:from plasTeX.ConfigManager import *config = ConfigManager()section = config.add_section(’simplerenderer’)config.add_category(’simplerenderer’, ’Simple Renderer Options’)
section[’my-option’] = StringOption(""" My option """,
options=’--my-option’,category=’simplerenderer’,default=’’,)Options values are attached to the document currently rendered. For instance, in the default method implemented in Section 5.1, which takes a node argument, one could access the value of the option defined above as
node.ownerDocument.config[’simplerenderer’][’my-option’].

5.2

Renderable Objects

The Renderable class is the real workhorse of the rendering process. It traverses the document object, looks up
the appropriate rendering methods in the renderer, and generates the output files. It also invokes the image generatingprocess when needed for parts of a document that cannot be rendered in the given output format.
Most of the work of the Renderable class is done in the __str__ method. This is rather convenient since eachof the rendering methods in the renderer are required to return a string object. When the str function is called witha renderable object as its argument, the document traversal begins for that node. This traversal includes iterating
through each of the node’s child nodes, and looking up and calling the appropriate rendering method in the renderer.
If the child node is configured to generate a new output file, the file is created and the rendered output is written to it;
otherwise, the rendered output is appended to the rendered output of previous nodes. Once all of the child nodes havebeen rendered, the string object containing that output is returned. This recursive process continues until the entire
document has been rendered.
There are a few useful things to know about renderable objects such as how they determine which rendering method
to use, when to generate new files, what the filenames will be, and how to generate images. These things are discussed
below.

Contents

43

5.2.1

Determining the Correct Rendering Method

Looking up the correct rendering method is quite straight-forward. If the node is a text node, the textDefault
attribute on the renderer is used. If it is not a text node, then the node’s name determines the key name in the renderer.
In most cases, the node’s name is the same name as the LATEX macro that created it. If the macro used some type ofmodifier argument (i.e. *, +, -), a name with that modifier applied to it is also searched for first. For example, if you
used the tablular* environment in your LATEX document, the renderer will look for “tabular*” first, then “tabular”.
This allows you to use different rendering methods for modified and unmodified macros. If no rendering method isfound, the method in the renderer’s default attribute is used.

5.2.2

Generating Files

Any node in a document has the ability to generate a new file. During document traversal, each node is queried for afile name. If a non-None is returned, a new file is created for the content of that node using the given file name. The
querying for the file name is simply done by accessing the filename property of the node. This property is added to
the node’s namespace during the mixin process. The default behavior for this property is to only return file names for
sections with a level less than the split-level given in the configuration (see section 2.1.5). The file names generated
by this routine are very flexible. They can be statically given names, or names based on the ID and/or title, or simply
generically numbered. For more information on configuring file names see section 2.1.5.
While the file naming mechanism is very powerful, you may want to name your files based on some other information.
This is possible through the filenameoverride attribute. If the filenameoverride is set, the name returnedby that attribute is used as the filename. The string in filenameoverride is still processed in the same way as thefilename specifier in the configuration so that you can use things like the ID or title of the section in the overridden
filename.
The string used to specify filenames can also contain directory paths. This is not terribly useful at the moment since
there is no way to get the relative URLs between two nodes for linking purposes.
If you want to use a filename override, but want to do it conditionally you can use a Python property to do this.
Just calculate the filename however you wish, if you decide that you don’t want to use that filename then raise an
AttributeError exception. An example of this is shown below.
class mymacro{Command):args = ’[ filename:str ] self’@property
def filenameoverride(self):# See if the attributes dictionary has a filename
if self.attributes[’filename’] is not None:
return self.attributes[’filename’]raise AttributeError, ’filenameoverride’

Note: The filename in the filenameoverride attribute must contain any directory paths as well as a file extension.

5.2.3

Generating Images

Not all output types that you might render are going to support everything that LATEX is capable of. For example,
HTML has no way of representing TikZ pictures directly, and most output types won’t be capable of rendering LATEX’s
picture environment. In cases like these, you can let plasTEX generate images of the document node. Generating
images is done with a subclass of plasTeX.Imagers.Imager. The imager is responsible for creating a LATEX
document from the requested document fragments, compiling the document and converting each page of the output
document into individual images. See section 2.1.6 on how to select an imager. The next section will explain how to
generate vector images such as SVG images, which are often a better solution because they scale much better.

44

Contents

To generate an image of a document node, simply access the image property during the rendering process. This
property will return an plasTeX.Imagers.Image instance. In most cases, the image file will not be available
until the rendering process is finished since most renderers will need the generated LATEX document to be complete
before compiling it and generating the final images.
The example below demonstrates how to generate an image for the tikzcd environment (this is for illustration
purposes only, plasTEXactually comes with a better handling of this package).
# Import renderer from first renderer example
from MyRenderer import Rendererfrom plasTeX.TeX import TeX
def handle_tikzcd(node):
return ’<div><img src="%s"/></div>’ % node.image.url# Instantiate a TeX processor and parse the input text
tex = TeX()
tex.input(r’’’\documentclass{book}\begin{document}
Previous paragraph.
\begin{tikzcd}
A \dar \rar & B \dar \\C \rar & D\end{tikzcd}
Next paragraph.
\end{document}’’’)
document = tex.parse()# Instantiate the rendererrenderer = Renderer()# Insert the rendering method into all of the environment that might need it
renderer[’tikzcd’] = handle_tikzcd# Render the document
renderer.render(document)

The rendered output looks like the following, and the image is generated is located in ‘images/img-0001.png’.
<document><par>Previous paragraph.
</par><par><div><img src="images/img-0001.png"/></div></par><par>Next paragraph.
</par></document>

Contents

45

The names of the image files are determined by the document’s configuration. The filename generator is very powerful, and is in fact, the same filename generator used to create the other output filenames. For more information on
customizing the image filenames see section 2.1.6.
In addition, the image types are customizable as well. plasTEX uses the Python Imaging Library (PIL) to do the final
cropping and saving of the image files, so any image format that PIL supports can be used. The format that PIL saves
the images in is determined by the file extension in the generated filenames, so you must use a file extension that PIL
recognizes.
It is possible to write your own Imager subclass if necessary. See the Imager API documentation for more information (see 6.7).

5.2.4

Generating Vector Images

If you have a vector imager configured (such as pdf2svg), you can generate a vector version of the requested image.
The nice thing about vector versions of images is that they can scale infinitely and not loose resolution.
Generating a vector image is just as easy as generating a bitmap image, you simply access the vectorImage propertyof the node that you want an image of. This will return an plasTeX.Imagers.Image instance that corresponds
to the vector image.
Everything that was described about generating images in the previous section is also true of vector images with the
exception of cropping. plasTEX does not attempt to crop vector images. The program that converts the LATEX output toa vector image is expected to crop the image down to the image content. Depending on the renderer configuration, abitmap may be generated to determine the proper height, width and depth of the vector image.

5.2.5

Static Images

There are some images in a document that don’t need to be generated, they simply need to be copied to the output directory and possibly converted to an appropriate formate. This is accomplished with the imageoverride attribute.
When the image property is accessed, the imageoverride attribute is checked to see if an image is already available for that node. If there is, the image is copied to the image output directory using a name generated using the same
method as described in the previous section. The image is copied to that new filename and converted to the appropriate
image format if needed. While it would be possible to simply copy the image over using the same filename, this may
cause filename collisions depending on the directory structure that the original images were store in.
Below is an example of using imageoverride for copying stock icons that are used throughout the document.
from plasTeX import Commandclass dangericon(Command):imageoverride = ’danger.gif’
class warningicon(Command):imageoverride = ’warning.gif’

It is also possible to make imageoverride a property so that the image override can done conditionally. In the casewhere no override is desired in a property implementation, simply raise an AttributeError exception.

5.3

Page Template Renderer

The Page Template (PT) renderer is a renderer for plasTEX document objects that supports various page templateengines such as Zope Page Templates (ZPT), Jinja2 templates, Cheetah templates, Kid templates, Genshi templates,
46

Contents

Python string templates, as well as plain old Python string formatting. It is also possible to add support for othertemplate engines. Note that all template engines except ZPT, Python formats, and Python string templates must be
installed in your Python installation. They are not included. In particular the Jinja2 template engine must be installed
in order to use the HTML5 renderer (this is already taken care of if you installed plasTEX in the recommended way).
The Jinja2 engine is used for all of the plasTEX delivered templates in the HTML5 renderer; however, the other templates work in a very similar way. The actual ZPT implementation used is SimpleTAL (http://www.owlfish.
com/software/simpleTAL/). This implementation implements almost all of the ZPT API and is very stable.
However, some changes were made to this package to make it more convenient to use within plasTEX. These changes
are discussed in detail in the ZPT Tutorial (see Appendix D).
Since the above template engines can be used to generate any form of XML or HTML, the PT renderer is in particulara general solution for rendering XML or HTML from a plasTEX document object. When switching from one DTD toanother,you simply need to use a different set of templates.
As in all Renderer-based renderers, each key in the PT renderer returns a function. These functions are actually
generated when the template files are parsed by the PT renderer. As is the case with all rendering methods, the only
argument is the node to be rendered, and the output is a string object containing the rendered output. In addition to therendering methods, the textDefault method escapes all characters that are special in XML and HTML (i.e. <, >,and &).
The following sections describe how templates are loaded into the renderer, how to extend the set of templates withyour own, as well as a theming mechanism that allows you to apply different looks to output types that are visual (e.g.
HTML).

5.3.1

Defining and Using Templates

By default, templates are loaded from the directory where the renderer module was imported from. In addition, thetemplates from each of the parent renderer class modules are also loaded. This makes it very easy to extend a renderer
and add just a few new templates to support the additions that were made.
The template files in the module directories can either contain a single template, corresponding to a single type ofnode, or several templates. In the first case, the basename of the template file is used as the key to store the templatein the renderer, and the extension specifies the template engine to use. Keep in mind that the names of the keys in
the renderer correspond to the node names in the document object. The extensions used for all templating engines areshown in the table below.
EngineJinja2
ZPT
Python string formatting
Python string templates
Kid
Cheetah
Genshi

Extension.jinja2.html, .htm, .zpt
.xhtml, .xhtm, .xml
.pyt
.st
.kid
.che
.gen

Output Type
Any
HTML
XML/XHTML
Any
Any
XML/XHTML
XML/XHTMLHTMLThe file listing below is an example of a directory of template files. In this case the templates correspond to nodes inthe document created by the description environment, the tabular environment, \textbf, and \textit.
description.xml
tabular.xml
textbf.html
textit.html

Contents

47

Since there are a lot of templates that are merely one line, it would be inconvenient to have to create a new file foreach template. In cases like this, you can use the ‘.zpts’ extension for collections of ZPT templates, or the ‘.jinja2s’
extension for collections of Jinja2 templates, or more generally ‘.pts’ for collections of various template types. Fileswith this extension have multiple templates in them. Each template is separated from the next by the template metadata
which includes things like the name of the template, the type (xml, html, or text), and can also alias template names toanother template in the renderer. The following metadata names are currently supported.
Nameengine

name

type

alias

Purposethe name of the templating engine to use. At the time of this writing, the value could be jinja2, zpt, tal (same as zpt), html (ZPT HTML
template), xml (ZPT XML template), jinja2, python (Python formatted
string), string (Python string template), kid, cheetah, or genshi.
the name or names of the template that is to follow. This name is used as
the key in the renderer, and also corresponds to the node name that will
be rendered by the template. If more than one name is desired, they aresimply separated by spaces.
the type of the template: xml, html, or text. XML templates must containa well-formed XML fragment. HTML templates are more forgiving, but
do not support all features of ZPT (see the SimpleTAL documentation).
specifies the name of another template that the given names should bealiased to. This allows you to simply reference another template to use
rather than redefining one. For example, you might create a new section
heading called \introduction that should render the same way as\section. In this case, you would set the name to “introduction” andthe alias to “section”.

There are also some defaults that you can set at the top of the file that get applied to the entire file unles overridden by
the meta-data on a particular template.
Namedefault-engine
default-type

Purposethe name of the engine to use for all templates in the file.
the default template type for all templates in the file.

The code sample below shows the basic format of a jinja2s file.
name: textbf bfseries<b>{{ obj }}</b>name: textit<i>{{ obj }}</i>name: introduction introduction*
alias: section
name: description<dl>{% for item in obj %}<dt>{{ item.attributes.term }}</dt><dd>{{ item }}</dd>{% endfor %}</dl>

The code above is a jinja2s file that contains four templates. Each template begins when a line starts with “name:”.
Other directives have the same format (i.e. the name of the directive followed by a colon) and must immediately follow
48

Contents

the name directive. The first template definition actually applies to two types of nodes textbf and bfseries. You canspecify ony number of names on the name line. The third template isn’t a template at all; it is an alias. When an alias
is specified, the name (or names) given use the same template as the one specified in the alias directive. Notice alsothat starred versions of a macro can be specified separately. This means that they can use a different template than the
un-starred versions of the command. The last template shows a loop example.
Here is an example of using various templates engines in a single file.
name: equationengine: jinja2<div class="equation" id="{{ obj.id }}">
<span class="equation_label">{{ obj.ref }}</span>{{ obj }}</div>
name: textbf
engine: python<b>%(self)s</b>name: textit
engine: string<i>${self}</i>name: textsc
engine: cheetah<span class="textsc">${here}</span>
name: textrm
engine: kid<span class="textrm" py:content="XML(str(here))">normal text</span>
name: textup
engine: genshi<span class="textup" py:content="markup(here)">upcase text</span>

There are several variables inserted into the template namespace. Here is a list of the variables and the templates that
support them.
Objectdocument node
parent node
document config
template instancerenderer instance

ZPT/Python Formats/String Templateself or here
container
configtemplate
templates

Jinja2obj or here
container
configCheetahhere
container
configKid/Genshi
herecontainer
configtemplates

templates

templates

You’ll notice that Kid and Genshi templates require some extra processing of the variables in order to get the proper
markup. By default, these templates escape characters like <, >, and &. In order to get HTML/XML markup from thevariables you must wrap them in the code shown in the example above. Hopefully, this limitation will be removed in
the future.
When using Jinja2 templates, the default configuration trims white spaces before and after template tags (seetrim_blocks and lstrip_blocks in Jinja2’s documentation). Also, when developing Jinja2 templates, inserting{{ debug() }} will launch a python debugger session to allow inspection of the context variable during rendering.

Contents49Template Overrides
It is possible to override the templates located in a renderer’s directory with templates defined elsewhere. This canbe done using the --extra-templates option or using the *TEMPLATES environment variable. The “*” in thename *TEMPLATES is a wildcard and must be replaced by the name of the renderer. For example, if you are using
the HTML5 renderer, the environment variable would be HTML5TEMPLATES. For the PageTemplate renderer, theenvironment variable would be PAGETEMPLATETEMPLATES.
The format of this variable is the same as that of the PATH environment variable which means that you can put multiple
directory names in this variable. In addition, the environment variables for each of the parent renderers is also used,
so that you can use multiple layers of template directories.
You can actually create an entire renderer just using overrides and the PT renderer. Since the PT renderer doesn’t
actually define any templates, it is just a framework for defining other XML/HTML renderers, you can simply load the
PT renderer and set the PAGETEMPLATETEMPLATES environment variable to the locations of your templates. Thismethod of creating renderers will work for any XML/HTML that doesn’t require any special post-processing.

5.3.2

Defining and Using Themes

In addition to the templates that define how each node should be rendered, there are also templates that define pagelayouts. Page layouts are used whenever a node in the document generates a new file. Page layouts generally include
all of the markup required to make a complete document of the desired DTD, and may include things like navigation
buttons, tables of contents, breadcrumb trails, etc. to link the current file to other files in the document.
When rendering files, the content of the node is generated first, then that content is wrapped in a page layout. The pagelayouts are defined the same way as regular templates; however, they all include “-layout” at the end of the template
name. For example the sectioning commands in LATEX would use the layout templates “section-layout”, “subsectionlayout”, “subsubsection-layout”, etc. Again, these templates can exist in files by themselves or multiply specified in a
zpts file. If no layout template exists for a particular node, the template name “default-layout” is used.
Since there can be several themes defined within a renderer, theme files are stored in a subdirectory of a renderer
directory. This directory is named ‘Themes’. The ‘Themes’ directory itself only contains directories that correspond to
the themes themselves where the name of the directory corresponds to the name of the theme. These theme directories
generally only consist of the layout files described above, but can override other templates as well. Below is a filelisting demonstrating the structure of a renderer with multiple themese.
# Renderer directory: contains template files
HTML5/# Theme directory: contains theme directories
HTML5/Themes/# Theme directories: contain page layout templates
HTML5/Themes/default/
HTML5/Themes/minimal/
HTML5/Themes/fragment/

Note: If no theme is specified in the document configuration, a theme with the name “default” is used.
Since all template directories are created equally, you can also define themes in template directories specified by environment variables as described in section 5.3.1. Also, theme files are searched in the same way as regular templates,
so any theme defined in a renderer superclass’ directory is valid as well.

50

Contents

5.4

HTML5 Renderer

5.4.1

Basic use and configuration

The HTML5 Renderer is a subclass of the Page Template Renderer (Section 5.3). Therefore most of the work is donein its collection of templates, all written using the Jinja2 template engine.
In addition, this renderer allows packages to override certain templates, add css or javascript files, and push output
files through various filters, see Section 5.4.2.
Options described in Section 2.1.7 provide easy ways to customize output. In particular the --extra-css option allows
to override CSS styles. Since the generated HTML contains no inline style (except for some size specification forimages and tables), these CSS overrides allow to completely change the output style.
For large scale CSS changes, one can create a new CSS theme, either from scratch or by customizing an existing theme.
Existing themes are generated using the CSS extension language SASS (see http://sass-lang.com/). Theirsources are located in ‘plasTeX/Renderers/HTML5/sources/sass/’. One way to use customize them is to do the following (assuming SASS is available on your system). Copy the above directory somewhere else, say in ‘mysass’, copy
‘theme-blue.scss’ to ‘theme-custom.scss’ and replace “blue” in the first line by “custom”, copy ‘_variables_blue.scss’
to ‘_variables_custom.scss’, modify a number of values in this file and compile usingsass --update --sourcemap=none mysass:build

This will create ‘build/theme-custom.css’ which can be copied to your project and used by plasTeX using
plastex ---no-theme-css --extra-css=theme-custom.css mytexfile.tex

Of course one can also change other ‘scss’ files for larger changes.
Note that distributed theme css
also went through autoprefixer (https://autoprefixer.github.io/) to ensure cross browser compatibility and cssnano (http://cssnano.co/) to reduce their size (all those steps are performed by‘plasTeX/Renderers/HTML5/sources/build-css.sh’). If CSS modifications are not enough, one can override templates
as discussed in Section 5.3.1.
The normal way to handle mathematics in this renderer is to use MathJax (see https://www.mathjax.org) torender mathematics on client side. This is controlled by the --use-mathjax option which is set to true by default.
Option --mathjax-url indicates where to find the MathJax library. By default it uses a CDN which ensures using thelatest version but prevents offline use. Instead of client-side rendering, one can use filters to handle mathematics on
the author side. For instance one can use mathjax-node (https://github.com/mathjax/MathJax-node) or
KaTeX (https://khan.github.io/KaTeX/). In this case, one can disable inclusion of MathJax using option--no-mathjax and use option --filters to call the author-side mathematics renderer.

5.4.2

Interactions with packages

This section is useful for packages authors. The HTML5 Renderer allows packages to interact with the rendering
process in several ways through packages resources. Each such resource is wrapped in an object whose class inherits
from PackageResource located in the module plasTeX.PackageResource. Those objects are typicallyattached to the document during package loading using the document addPackageResource method inside theProcessOptions function.

Contents

51

Extra input files
The following example shows how a package can register templates overriding regular renderer templates, as well
as extra CSS and javascript files. The following function should be part of a python package, say ‘mypkg.py’ which
imports Path from pathlib. Next to this file, there should be a folder ‘mypkg’ containing files ‘test.css’ and‘test.js’, and a ‘templates’ subfolder.
def ProcessOptions(options, document):
css = PackageCss(
renderers=’html5’,
path=Path(__file__).parent/’mypkg’/’test.css’)
js = PackageJs(
renderers=’html5’,
path=Path(__file__).parent/’mypkg’/’test.js’)
tpl = PackageTemplateDir(renderers=’html5’,
path=Path(__file__).parent/’mypkg’/’templates’)
document.addPackageResource([css, js, tpl])

When rendering any document containing \usepackage{mypkg}, the HTML5 renderer will
• copy ‘mypkg/test.css’ to the ‘styles’ subdirectory of the output directory and call it from the default html layout• copy ‘mypkg/test.js’ to the ‘js’ subdirectory of the output directory and call it from the default html layout• load any template contained in ‘mypkg/templates’, overiding the renderer default templates if needed.
If you want to copy a CSS or Javascript file to the output directory but without linking to it from the default html layout,
you can use the keyword argument copy_only=True. The renderer argument can also be a list of renderers,
and its default value is html5.
Extra output files and filters
The HTML5 Renderer allows packages to produce extra output files and define filters that are applied to any output
file.
In order to create new output files, any package can register a callback function taking a document as input a returninga list of created file names. As an example, let us write a package which adds some document statistics to an extra
output file ‘stats.html’ (we will not try to produce valid html below, only illustrate our point). The package module
only needs to contain the following.

52

Contents

import os
def ProcessOptions(options, document):
def makeStats(document):
nbChap = len(document.getElementsByTagName(’chapter’))nbSec = len(document.getElementsByTagName(’section’))with open(’stats.html’, ’w’) as outfile:outfile.write("%d chapters and %d sections" % (nbChap, nbSec))
return [’stats.html’]
cb = PackagePreCleanupCB(
renderers=’html5’,
data=makeStats)document.addPackageResource(cb)As suggested by the key name, those pre-cleanup callbacks are called before the renderer cleanup method.
Packages can also register filters to be applied during the cleanup process. Those filters are functions that take a
document and a string to filter and return the filtered string (using the document object to provide context if needed).
They will be called on the content of each rendered file, after all files have been rendered. Registration is analogous topre-cleanup callbacks but replacing PackagePreCleanupCB by PackageProcessFileContent.

5.4.3

Themes

The theming support in the HTML5 renderer is a superset of that of the Page Template Renderer. Any template
directory can have a subdirectory called ‘Themes’ which contains theme directories with sets of templates in them.
The names of the directories in the ‘Themes’ directory corresponds to the name of the theme. Each of these directories
can contain folders named ‘css’ and ‘js’, and containing CSS and javascript files respectively. Those files are copied
while rendering, unless option --copy-theme-extras is unset.
There are currently three themes included with plasTEX: default, minimal and fragment. The first two themes produce
standalone HTML files, including a head section. The fragment theme produces output that is meant to be inserted
in a HTML document already containg a head section. The default theme include some javascript and CSS file. One
can choose between three variations on CSS using option --theme-css which can be white, blue or green. The default
value is white which uses a sober black on white color scheme with no gradient background of shadow. The green
CSS theme uses the historical plasTEX green and yellow color scheme, with gradients and shadows. The blue one uses
a blue and gray color scheme, with gradients and shadows.
When displaying the table of contents navigation panel, the default theme adds at the end the elements of the list
document.rendererdata[’html5’][’extra_toc_items’]. Each element should be a dictionary withkeys text and url.

5.5

XHTML Renderer

The XHTML renderer used to be the default renderer of plasTeX but is now deprecated in favor of the HTML5
renderer, and kept only for backward compatibility purposes. The XHTML renderer is a subclass of the Page Template
Renderer (section 5.3). Since the Page Template Renderer can render any variant of XML or HTML, the XHTML
renderer has very little to do in the Python code. Almost all of the additional processing in the XHTML renderer
has to do with generated images. Since MathJax (or KaTeX) didn’t exist at the time when XHTML was used, all
LATEXequations are converted to images by this renderer. In order for inline equations to line up correctly with the text
around them, CSS attributes are used to adjust the vertical alignment. Since the images aren’t generated until after allof the document has been rendered, this CSS information is added in post-processing (i.e. the cleanup method).
In addition to the processing of images, all characters with a ordinal greater than 127 are converted into numericalContents

53

entities. This should prevent any rendering problems due to unknown encodings.
Most of the work in this renderer was in creating the templates for every LATEX construct. Since this renderer was
intended to be the basis of all HTML-based renderers, it must be capable of rendering all LATEX constructs; therefore,
there are ZPT templates for every LATEX command, and the commands in some common LATEX packages.

5.5.1

Themes

The theming support in the XHTML renderer is the same as that of the Page Template Renderer. Any template
directory can have a subdirectory called ‘Themes’ which contains theme directories with sets of templates in them.
The names of the directories in the ‘Themes’ directory corresponds to the name of the theme. There are currently twothemes included with plasTEX: default and plain. The default theme is a minor variation of the one used in the Python
1.6 documentation. The plain theme is a theme with no extra navigation bars.

5.6

Other builtin renderers

In addition to the renderers covered in previous sections, plasTEX comes with a couple of smaller renderers that areless tested but can still be useful, at least as technological examples.
The simplest output format is given by the Text renderer that will output a simple unicode text file. It is not based ona templating engine, it is therefore a good example for people who want to write a renderer from scratch.
The ManPage renderer outputs files ready for consumption by groff (directly of through man). Like the Text renderer,
it is written from scratch, without any template engine.
The DocBook renderer is based on the Page Template Renderer. It supports two themes: book and article having
different root elements. The templates for this renderer using the Cheetah engine which is not installed by default
when installing plasTEX. Be careful to install the Cheetah3 fork which is compatible with python 3.
There is also a EPUB renderer based on the XHTML renderer.

54

Contents

CHAPTERSIXPLASTEX Frameworks and APIs
6.1 plasTeX — The Python Macro and Document Interfaces
While plasTEX does a respectable job expanding LATEX macros, some macros may be too complicated for it to handle.
These macros may have to be re-coded as Python objects. Another reason you may want to use Python-based macros
is for performance reasons. In most cases, macros coded using Python will be faster than those expanded as true LATEX
macros.
The API for Python macros is much higher-level than that of LATEX macros. This has good and bad ramifications. The
good is that most common forms of LATEX macros can be parsed and processed very easily using Python code whichis easier to read than LATEX code. The bad news is that if you are doing something that isn’t common, you will havemore work to do. Below is a basic example.
from plasTeX import Commandclass mycommand(Command):""" \mycommand[name]{title} """args = ’[ name ] title’The code above demonstrates how to create a Python-based macro corresponding to LATEX macro with the form
\mycommand[name]{title} where ‘name’ is an optional argument and ‘title’ is a mandatory argument. In the
Python version of the macro, you simply declare the arguments in the args attribute as they would be used in the
LATEX macro, while leaving the braces off of the mandatory arguments. When parsed in a LATEX document, an instanceof the class mycommand in created and the arguments corresponding to ‘name’ and ‘title’ are set in the attributes
dictionary for that instance. This is very similar to the way an XML DOM works, and there are more DOM similarities
yet to come. In addition, there are ways to handle casting of the arguments to various data types in Python. The API
documentation below goes into more detail on these and many more aspects of the Python macro API.

6.1.1

Macro Objects

class Macro()
The Macro class is the base class for all Python based macros although you will generally want to subclassfrom Command or Environment in real-world use. There are various attributes and methods that affect how
Python macros are parsed, constructed and inserted into the resulting DOM. These are described below.
args
specifies the arguments to the LATEX macro and their data types. The args attribute gives you a very simple,
yet extremely powerful way of parsing LATEX macro arguments and converting them into Python objects. Once
parsed, each LATEX macro argument is set in the attributes dictionary of the Python instance using the namegiven in the args string. For example, the following args string will direct plasTEX to parse two mandatory55

arguments, ‘id’ and ‘title’, and put them into the attributes dictonary.
args = ’id title’

You can also parse optional arguments, usually surrounded by square brackets ([ ]). However, in plasTEX, anyarguments specified in the args string that aren’t mandatory (i.e. no braces surrounding it) are automaticallyconsidered optional. This may not truly be the case, but it doesn’t make much difference. If they truly aremandatory, then your LATEX source file will always have them and plasTEX will simply always find them eventhough it considers them to be optional.
Optional arguments in the args string are surround by matching square brackets ([ ]), angle brackets (< >), or
parentheses (( )). The name for the attribute is placed between the matching symbols as follows:args = ’[ toc ] title’args = ’( position ) object’args = ’< markup > ref’You can have as many optional arguments as you wish. It is also possible to have optional arguments using
braces ({ }), but this requires you to change TEX’s category codes and is not common.
Modifiers such as asterisks (*) are also allowed in the args string. You can also use the plus (+) and minus (-)
signs as modifiers although these are not common. Using modifiers can affect the incrementing of counters (seethe parse() method for more information).
In addition to specifying which arguments to parse, you can also specify what the data type should be. Bydefault, all arguments are processed and stored as document fragments. However, some arguments may be
simpler than that. They may contain an integer, a string, an ID, etc. Others may be collections like a list or
dictionary. There are even more esoteric types for mostly internal use that allow you to get unexpanded tokens,
TEX dimensions, and the like. Regardless, all of these directives are specified in the same way, using the typecast
operator: ‘:’. To cast an argument, simply place a colon (:) and the name of the argument type immediately after
the name of the argument. The following example casts the ‘filename’ argument to a string.
args = ’filename:str’Parsing compound arguments such as lists and dictionaries is very similar.
args = ’filenames:list’

By default, compound arguments are assumed to be comma separated. If you are using a different separator, it
is specified in parentheses after the type.
args = ’filenames:list(;)’

Again, each element element in the list, by default, is a document fragment. However, you can also give the data
type of the elements with another typecast.
args = ’filenames:list(;):str’Parsing dictionaries is a bit more restrictive. plasTEX assumes that dictionary arguments are always key-value
pairs, that the key is always a string and the separator between the key and value is an equals sign (=). Other
than that, they operate in the same manner.
A full list of the supported data types as well as more examples are discussed in section 4.
argSource
the source for the LATEX arguments to this macro. This is a read-only attribute.

56

Contents

arguments
gives the arguments in the args attribute in object form (i.e. Argument objects). Note: This is a read-only
attribute. Note: This is generally an internal-use-only attribute.
blockTypeindicates whether the macro node should be considered a block-level element. If true, this node will be put into
its own paragraph node (which also has the blockType set to True) to make it easier to generate output that
requires block-level to exist outside of paragraphs.
counter
specifies the name of the counter to associate with this macro. Each time an instance of this macro is created,
this counter is incremented. The incrementing of this counter, of course, resets any “child” counters just like in
LATEX. By default and LATEX convention, if the macro’s first argument is an asterisk (i.e. *), the counter is notincremented.
id
specifies a unique ID for the object. If the object has an associated label (i.e. \label), that is its ID. You canalso set the ID manually. Otherwise, an ID will be generated based on the result of Python’s id() function.
idref
a dictionary containing all of the objects referenced by “idref” type arguments. Each idref attribute is stored
under the name of the argument in the idref dictionary.
level
specifies the hierarchical level of the node in the DOM. For most macros, this will be set toNode.COMMAND_LEVEL or Node.ENVIRONMENT_LEVEL by the Command and Environment macros,respectively. However, there are other levels that invoke special processing. In particular, sectioning commands such as \section and \subsection have levels set to Node.SECTION_LEVEL and
Node.SUBSECTION_LEVEL. These levels assist in the building of an appropriate DOM. Unless you arecreating a sectioning command or a command that should act like a paragraph, you should leave the value of
this attribute alone. See section 6.3 for more information.
macroName
specifies the name of the LATEX macro that this class corresponds to. By default, the Python class name is thename that is used, but there are some legal LATEX macro names that are not legal Python class names. In thosecases, you would use macroName to specify the correct name. Below is an example.
class _illegalname(Command):macroName = ’@illegalname’

Note: This is a class attribute, not an instance attribute.
macroMode
specifies what the current parsing mode is for this macro. Macro classes are instantiated for every invocation including each \begin and \end. This attribute is set to Macro.MODE_NONE for normal commands,
Macro.MODE_BEGIN for the beginning of an environment, and Macro.MODE_END for the end of an environment.
These attributes are used in the invoke() method to determine the scope of macros used within the environment. They are also used in printing the source of the macro in the source attribute. Unless you really knowwhat you are doing, this should be treated as a read-only attribute.
mathModeboolean that indicates that the macro is in TEX’s “math mode.” This is a read-only attribute.
nodeNamethe name of the node in the DOM. This will either be the name given in macroName, if defined, or the nameof the class itself. Note: This is a read-only attribute.
refContents

57

specifies the value to return when this macro is referenced (i.e. \ref). This is set automatically when the counter
associated with the macro is incremented.
sourcespecifies the LATEX source that was parsed to create the object. This is most useful in the renderer if you needto generate an image of a document node. You can simply retrieve the LATEX source from this attribute, create a
LATEX document including the source, then convert the DVI file to the appropriate image type.
style
specifies style overrides, in CSS format, that should be applied to the output. This object is a dictionary, so styleproperty names are given as the key and property values are given as the values.
inst.style[’color’] = ’red’
inst.style[’background-color’] = ’blue’

Note: Not all renderers are going to support CSS styles.
tagNamesame as nodeName
title
specifies the title of the current object. If the attributes dictionary contains a title, that object is returned. An
AttributeError is thrown if there is no ‘title’ key in that dictionary. A title can also be set manually by
setting this attribute.
digest(tokens)
absorb the tokens from the given output stream that belong to the current object. In most commands, this doesnothing. However, LATEX environments have a \begin and an \end that surround content that belong to them.
In this case, these environments need to absorb those tokens and construct them into the appropriate document
object model (see the Environment class for more information).
digestUntil(tokens, endclass)utility method to help macros like lists and tables digest their contents. In lists and tables, the items, rows, andcells are delimited by \begin and \end tokens. They are simply delimited by the occurrence of another item,
row, or cell. This method allows you to absorb tokens until a particular class is reached.
expand()the expand method is a thin wrapper around the invoke method. The expand method makes sure that all
tokens are expanded and will not return a None value like invoke.
invoke()invokes the macro. Invoking the macro, in the general case, includes creating a new context, parsing the optionsof the macro, and removing the context. LATEX environments are slightly different. If macroMode is set to
Macro.MODE_BEGIN, the new context is kept on the stack. If macroMode is set to Macro.MODE_END,
no arguments are parsed, the context is simply popped. For most macros, the default implementation will workfine.
The return value for this method is generally None (an empty return statement or simply no return statement).
In this case, the current object is simply put into the resultant output stream. However, you can also return a listof tokens. In this case, the returned tokens will be put into the output stream in place of the current object. You
can even return an empty list to indicate that you don’t want anything to be inserted into the output stream.
locals()retrieves all of the LATEX macros that belong to the scope of the current Python based macro.
paragraphs(force=True)
group content into paragraphs. Paragraphs are grouped once all other content has been digested. The paragraph grouping routine works like TEX’s, in that environments are included inside paragraphs. This is unlikeHTML’s model, where lists and tables are not included inside paragraphs. The force argument allows you to decide whether or not paragraphs should be forced. By default, all content of the node is grouped into paragraphs

58

Contents

whether or not the content originally contained a paragraph node. However, with force set to False, a node will
only be grouped into paragraphs if the original content contained at least one paragraph node.
Even though the paragraph method follow’s TEX’s model, it is still possible to generate valid HTML content.
Any node with the blockType attribute set to True is considered to be a block-level node. This means that it will
be contained in its own paragraph node. This paragraph node will also have the blockType attribute set to Trueso that in the renderer the paragraph can be inserted or ignored based on this attribute.
parse(tex)parses the arguments defined in the args attribute from the given token stream. This method also calls several
hooks as described in the table below.
Description
Method Name
preParse()
called at the beginning of the argument parsing process
called before parsing each argument
preArgument()
postArgument() called after parsing each argument
called at the end of the argument parsing process
postParse()
The methods are called to assist in labeling and counting. For example, by default, the counter associated with amacro is automatically incremented when the macro is parsed. However, if the first argument is a modifier (i.e.
*, +, -), the counter will not be incremented. This is handled in the preArgument() and postArgument()
methods.
Each time an argument is parsed, the result is put into the attributes dictionary. The key in the dictionaryis, of course, the name given to that argument in the args string. Modifiers such as *, +, and - are stored under
the special key ‘*modifier*’.
The return value for this method is simply a reference to the attributes dictionary.
Note: If parse() is called on an instance with macroMode set to Macro.MODE_END, no parsing takes
place.
postArgument(arg, tex)
called after parsing each argument. This is generally where label and counter mechanisms are handled.
arg is the Argument instance that holds all argument meta-data including the argument’s name, source, andoptions.
tex is the TeX instance containing the current context
postParse(tex)do any operations required immediately after parsing the arguments. This generally includes setting up the valuethat will be returned when referencing the object.
preArgument(arg, tex)
called before parsing each argument. This is generally where label and counter mechanisms are handled.
arg is the Argument instance that holds all argument meta-data including the argument’s name, source, andoptions.
tex is the TeX instance containing the current context
preParse(tex)do any operations required immediately before parsing the arguments.
refstepcounter(tex)set the object as the current labellable object and increment its counter. When an object is set as the current
labellable object, the next \label command will point to that object.
stepcounter(tex)step the counter associated with the macro

Contents596.2 plasTeX.ConfigManager — plasTEX Configuration
A ConfigManager manages the configuration options for plastex. From the end user’s point of view, this behaves
like a 2-layered nested dict, so that configuration options can be retrieved as config["general"]["theme"],for example. However, ConfigManager is much more powerful than a nested dict. It supports reading in configuration options from .ini files and command line arguments.
The former is performed via the read function, and the latter is via the registerArgparse andupdateFromDict functions. The first function adds the options to an ArgumentParser from argparse,
and the latter reads in the values obtained from argparse. The interaction looks as follows:

config = ConfigManager()# Set up the config manager here
# Construct an ArgumentParser
parser = ArgumentParser("plasTeX")# This function adds a command line option to ‘parser‘ for each# configuration item in ‘config‘
config.registerArgparse(parser)# We now let the parser parse the arguments in ‘sys.argv‘
data = vars(parser.parse_args())# Finally, we let ‘config‘ read the values back in
config.updateFromDict(data)

The following sample code shows how one would set up a ‘ConfigManager‘ object:from plasTeX.ConfigManager import *c = ConfigManager()# Create a new section in the config file.
# [ sectionname ] sections in an INI file.
# a reference to the new sectiond = c.add_section(’debugging’)

This corresponds to the
The returned value is# Add an option to the ’debugging’ section called ’verbose’.
# This corresponds to the config file setting:## [debugging]# verbose = no#d[’verbose’] = BooleanOption(""" Increase level of debugging information """,
options = ’-v --verbose !-q !--quiet’,
default = False,)# Read config files
c.loadFromFiles([’/etc/myconfig.ini’, ’~/myconfig.ini’)

60

Contents

The configuration system supports interpolation. That is, in options whose value is a string (or a list of strings), we
replace all instances of %(foo)s with the value of the option foo. The formatting is done with pythons %-formatting
and all %-formatting features are supported. Note that we only specify the name of the option, and not the section it
belongs to. For example,
plastex --renderer=HTML5 --theme=%(renderer)stheme

sets the theme to HTML5theme.
Interpolation is performed when you access the value of an option, not when the value is set. For example, if we modify
the renderer variable in runtime and then access theme, it changes accordingly. Specifically, this is performed in
ConfigSection.__getitem__.

6.2.1

ConfigManager Objects

class ConfigManager()
A configuration manager.
addSection(name, description=None)
Creates a section with the given name and description and adds it to the ConfigManager.
name is the key for accessing the section, which is also the section header used in the INI file.
description is the header of the section for the cli ‘–help‘ function. Defaults to ‘name.capitalize() + " Options"‘
Returns the new ConfigSection object produced.
read(filenames)
loads config from the INI files in filenames. The function ignores files that do not exist. The argument may also
be a single filename.
registerArgparse(parser)
adds command line options to parser for each configuration item. This function merely delegates the job to theidentically-named function of each of the sections.
updateFromDict(data)reads in configuration options from the dict returned by ‘vars(ArgumentParser.parse_args)‘. This function
merely delegates the job to the identically-named function of each of the sections.

6.2.2

ConfigSection Objects

class ConfigSection(name, parent)
For the most part, a ConfigSection is a dict of ConfigOptions. However, when we accesssection["key"], it doesn’t return the ConfigOption itself, but the value of the option.
The rationale for this setup is that we want to think of a ConfigOption as the value of the option together
with some metadata. When trying to read or write the config option, what we want to do is the read or write to
the value and ignoring the metadata.
The only exception is when we want to add a new config option to the section, where we would write
section["new_key"] = ConfigOption(...)

name is the name of the section.
parent is the ConfigManager that contains this section.
data
dictionary that contains the option instances. This is only accessed if you want to retrieve the real option
Contents

61

instances. Normally, you would use standard dictionary key access syntax on the section itself to retrieve theoption values.
namethe name given to the section.
get(option)
retrieve the value of option, returning None if option doesn’t exist.
__getitem__(key)retrieve the value of an option, raising a KeyError if the option does not exist. This method allows you to use
Python’s dictionary syntax on a section as shown below.
# Print the value of the ’optionname’ option
print(mysection[’optionname’])parenta reference to the parent ConfigManager object.
__setitem__(key, value)
create a new option or set an existing option with the name key and the value of value. This method allows you
to use Python’s dictionary syntax to set options as shown below.
# Create a new option called ’optionname’
mysection[’optionname’] = IntegerOption("Test", --option="--test", default=0)
mysection[’optionname’] = 10

6.2.3

Configuration Option Types

class ConfigOption[T](description, options, default)This class represents an option whose value has a “simple” type. Specifically, we require T(s) to correctly
converts a string s to an object of type T. The type is determined at runtime based on the type of the default
value. More complex options should inherit this class.
From the point of view of the external API, every option item is expected to inherit ConfigOption, andis expected to implement the methods described below correctly. Moreover, the instance attribute value is
expected to hold the value of the option.
On the other hand, custom __init__ implementations are not required to set the other instance attributes (i.e.
description, options and name) described below.
description
description of this option to be used in the plastex --help output.
options
space separated list of command line argument that correspond to this option. The behaviour of this variable
may be customized by implementations of ConfigOption.
namethe key used by argparse to store the value read from the command line. Note that argparse does not group theargument values by section, so one has to be careful to avoid collision.
This is set to the first entry in self.option with leading -s stripped.
value
the actual value of the option
registerArgparse(group)
this function should add the command line arguments for this configuration to the argparse._ArgumentGroupobject group.
62

Contents

updateFromDict(data)
sets the value of the option based on the data in data. The format of data is defined to be what is returned byvars(parser.parse_args()), where parser is populated by registerArgparse. This is intended
to be used in conjuction with registerArgparse.
class BooleanConfigOption([ConfigOption arguments ])Boolean options are simply options that allow you to specify an ‘on’ or ‘off’ state. In a config file, the value
is converted to a boolean via the builtin bool function. Boolean options on the command-line do not take anargument; simply specifying the option sets the state to true.
One interesting feature of boolean options is in specifying the command-line options. Since you cannot specify
a value on the command-line (the existence of the option indicates the state), there must be a way to set the state
to false. This is done using the ‘not’ operator (!). When specifying the options argument of the constructor, if
you prefix an command-line option with an exclamation point, the existence of that option indicates a false staterather than a true state. Below is an example of an options value that has a way to turn debugging informationon (--debug) or off (--no-debug).
BooleanOption("", options = ’--debug !--no-debug’, default=True)class FloatOption([ConfigOption arguments ])A FloatOption is an option that accepts a floating point number.
class IntegerOption([ConfigOption arguments ])An IntegerOption is an option that accepts an integer value.
class StringOption([ConfigOption arguments ])A StringOption is an option that accepts an arbitrary string.
class MultiStringOption([ConfigOption arguments ])A MultiStringOption is an option that is intended to be used multiple times on the command-line,
or take a list of values. Other options when specified more than once simply overwrite the previous value.
MultiStringOptions will append the new values to a list.
In the configuration file, this is a space separated list, interpreted in the same ways as shell arguments (with thesame escaping/quoting rules for strings that contains whitespaces). In fact, it is processed by shlex.split.
The individual values of MultiStringOption are strings. This can, of course, be made generic, but such a
use case has not arisen.
class DictOption[T]([ConfigOption arguments ])This is an abstract base class for options whose value is a Dict[str, T]. This receives special treatment by
ConfigManager.read — in a config file, any line whose key is unrecognized (i.e. not the key of an existing
option) is added to the first DictOption in the section. Usually, such sections only contain a single option
which is a DictOption.
The value can also be set directly, in the form
data=a=b,c=d,e=f

There is no implementor in ConfigManager.py, but is used by CountersOption, LinksOption, ImageScaleOption and LogOption in Config.py.
Note that all implementors of DictOption must also implement registerArgparse (and can optionallyimplement other methods of ConfigOption).
entryFromString(entry)
a class method to convert a string to the desired value entry. This is used by the in the default implementationof set.
set(key, value)
sets the value of the dict. The value is assumed to be a string.
Contents63

6.3 plasTeX.DOM — The plasTEX Document Object Model (DOM)
While most LATEX processors use a stream model where the input is directly connected to the output, plasTEX actuallyworks in two phases. The first phase reads in the LATEX document, expands macros, and constructs an object similar
to an XML DOM. This object is then passed to the renderer which translates it into the appropriate output format.
The benefit to doing it this way is that you are not limited to a single output format. In addition, you can actually
apply multiple renderers with only one parse step. This section describes the DOM used by plasTEX, its API, and thesimilarities and differences between the plasTEX DOM and the XML DOM.

6.3.1

plasTEX vs. XML

The plasTEX DOM and XML DOM have more similarities than differences. This similarity is purely intentional toreduce the learning curve and to prevent reinventing the wheel. However, the XML DOM can be a bit cumbersome
especially when you’re used to much simpler and more elegant Python code. Because of this, some Python behaviors
were adopted into the plasTEX DOM. The good news is that these extensions do not break compatibility with the XML
DOM. There are, however, some differences due to conventions used LATEX.
The only significant difference between the plasTEX DOM and the XML DOM is that plasTEX nodes do not have true
attributes like in XML. Attributes in XML are more like arguments in LATEX, because they are similar the plasTEX
DOM actually puts the LATEX macro arguments into the attributes dictionary. This does create an incompatibility
though since XML DOM attributes can only be strings whereas LATEX arguments can contain lots of markup. In
addition, plasTEX allows you to convert these arguments into Python strings, lists, dictionaries, etc., so essentially any
type of object can occur in the attributes dictionary.
Other than paying attention to the the attributes dictionary difference, you can use most other XML DOM methods on
plasTEX document objects to create nodes, delete nodes, etc. The full API is described below.
In most cases, you will not need to be concerned with instantiating nodes. The plasTEX framework does this. However,the API can be helpful if you want to modify the document object that plasTEX creates.

6.3.2

Node Objects

class Node()
The Node class is the base class for all nodes in the plasTEX DOM inluding elements, text, etc.
attributes
a dictionary containing the attributes, in the case of plasTEX the LATEX macro arguments
childNodes
a list of the nodes that are contained by this one. In plasTEX, this generally contains the contents of a LATEX
environment.
isElementContentWhitespaceboolean indicating whether or not the node only contains whitespace.
lastChildthe last node in the childNodes list. If there are no child nodes, the value is None.
nodeNamethe name of the node. This is either the special node name as specified in the XML DOM (e.g. #documentfragment, #text, etc.), or, if the node corresponds to an element, it is the name of the element.
nodeType
integer indicating the type of the node. The node types are defined as:•Node.ELEMENT_NODE•Node.ATTRIBUTE_NODE
64

Contents

•Node.TEXT_NODE•Node.CDATA_SECTION_NODE•Node.ENTITY_REFERENCE_NODE•Node.ENTITY_NODE•Node.PROCESSING_INSTRUCTION_NODE•Node.COMMENT_NODE•Node.DOCUMENT_NODE•Node.DOCUMENT_TYPE_NODE•Node.DOCUMENT_FRAGMENT_NODE•Node.NOTATION_NODE
Note: These are defined by the XML DOM, not all of them are used by plasTEX.
parentNoderefers to the node that contains this nodepreviousSibling
the node in the document that is adjacent to and immediately before this node. If one does not exist, the value is
None.
nextSibling
the node in the document that is adjacent to and immediately after this node. If one does not exist, the value isNone.
ownerDocument
the node that owner of, and ultimate parent of, all nodes in the document
textContent
contains just the text content of this nodestr
specifies a string that could be used in place of the node. This string will be converted into tokens in the plasTEX
output stream.
userdata
dictionary used for holding user-defined data__add__(other)create a new node that is the sum of self and other. This allows you to use nodes in Python statements like:node + other.
append(newChild)adds a new child to the end of the child nodes
appendChild(newChild)same as append
cloneNode(deep=False)
create a clone of the current node. If deep is true, then the attributes and child nodes are cloned as well.
Otherwise, all references to attributes and child nodes will be shared between the nodes.
__cmp__(other)same as isEqualNode, but allows you to compare nodes using the Python statement: node == other.
extend(other)appends other to list of children then returns self__getitem__(i)returns the child node at the index given by i. This allows you to use Python’s slicing syntax to retrieve childnodes: node[i].
Contents65

getUserData(key)retrieves the data in the userdata dictionary under the name key
hasAttributes()
returns a boolean indicating whether or not this node has attributes defined
hasChildNodes()returns a boolean indicating whether or not the node has child nodes__iadd__(other)same as extend. This allows you to use nodes in Python statements like: node += other.
insert(i, newChild)inserts node newChild into position i in the child nodes list
insertBefore(newChild, refChild)inserts newChild before refChild in this node. If refChild is not found, a NotFoundErr exception is raised.
isEqualNode(other)indicates whether the given node is equivalent to this one
isSameNode(other)indicates whether the given node is the same node as this one__iter__()returns an iterator that iterates over the child nodes. This allows you to use Python’s iter() function on nodes.
__len__()
returns the number of child nodes. This allows you to use Python’s len() function on nodes.
normalize()
combine consecutive text nodes and remove comments in this nodepop(index=-1)
removes child node and the index given by index. If no index is specified, the last child is removed.
__radd__(other)create a new node that is the sum of other and self . This allows you to use nodes in Python statements like:other + node.
replaceChild(newChild, oldChild)replaces oldChild with newChild in this node. If oldChild is not found, a NotFoundErr exception is raised.
removeChild(oldChild)removes oldChild from this node. If oldChild is not found, a NotFoundErr exception is raised.
__setitem__(i, node)sets the item at index i to node. This allows you to use Python’s slicing syntax to insert child nodes; see theexample below.
mynode[5] = othernode
mynode[6:10] = [node1, node2]

setUserData(key, data)
put data specified in data into the userdata dictionary under the name given by key
toXML()
return an XML representation of the node66

Contents

6.3.3DocumentFragment Objects

class DocumentFragment()
A collection of nodes that make up only part of a document. This is mainly used to hold the content of a LATEX
macro argument.

6.3.4

Element Objects

class Element()
The base class for all element-type nodes in a document. Elements generally refer to nodes created by LATEX
commands and environments.
getAttribute(name)returns the attribute specified by namegetElementById(elementId)
retrieve the element with the given ID
getElementsByTagName(tagName)retrieve all nodes with the given name in the node
hasAttribute(name)returns a boolean indicating whether or not the specified attribute exists
removeAttribute(name)removes the attribute name from the attributes dictionary
setAttribute(name, value)
sets the attribute value in the attributes dictionary using the key name

6.3.5

Text Objects

class Text()
This is the node type used for all text data in a document object. Unlike XML DOM text nodes, text nodes inplasTEX are not mutable. This is because they are a subclass of str. This means that they will respond to all of
the standard Python string methods in addition to the Node methods and the methods described below.
data
the text content of the nodelengththe length of the text content
nodeValue
the text content of the node
wholeText
returns the text content from the current text node as well as its siblings

6.3.6

Document Objects

class Document()
The top-level node of a document that contains all other nodes.
createDocumentFragment()
instantiate a new document fragment
createElement(tagName)
instantiate a new element with the given nameContents

67

createTextNode(data)
instantiate a new text node initialized with data
importNode(importedNode, deep=False)
import a node from another document. If deep is true, all nodes within importedNode are cloned.
normalizeDocument()
concatenate all consecutive text nodes and remove comments

6.3.7

Command Objects

class Command()The Command class is a subclass of Macro. This is the class that should be subclassed when creating Python
based macros that correspond to LATEX commands.
For more information on the Command class’ API, see the Macro class.

6.3.8

Environment Objects

class Environment()
The Environment class is a subclass of Macro. This is the class that should be subclassed when creating
Python based macros that correspond to LATEX environments. The main difference between the processing ofCommands and Environments is that the invoke() method does special handling of the LATEX document
context, and the digest() method absorbs the output stream tokens that are encapsulated by the \begin and\end tokens.
For more information on the Environment class’ API, see the Macro class.

6.3.9

TeXFragment Objects

class TeXFragment()
A fragment of a document. This class is used mainly to store the contents of LATEX macro arguments.
sourcethe LATEX source representation of the document fragment

6.3.10

TeXDocument Objects

class TeXDocument()
A complete LATEX document.
charsubs
a list of two element tuples containing character substitutions for all text nodes in a document. This is used toconvert character strings like “---” into “—”. The first element in each tuple in the string to replace, the second
element is the character or sequence to replace the original string with.
preamblereturns the LATEX source representation of the document preamble (i.e.
\begin{document})

everything before thesourcethe LATEX source representation of the document

68

Contents

6.4 plasTeX.TeX — The TEX Stream
The TEX stream is the piece of plasTEX where the parsing of the LATEX document takes place. While the TeX class isfairly large, there are only a few methods and attributes designated in the public API.
The TEX stream is based on a Python generator. When you feed it a LATEX source file, it processes the file much like
TEX itself. However, on the output end, rather than a PDF or DVI file, you get a plasTEX document object. The basic
usage is shown in the code below.
from plasTeX.TeX import TeX
doc = TeX(file=’myfile.tex’).parse()

6.4.1

TeX Objects

class TeX([ownerDocument, file ])The TeX class is the central TEX engine that does all of the parsing, invoking of macros, and other documentbuilding tasks. You can pass in an owner document if you have a customized document node, or if it contains acustomized configuration; otherwise, the default TeXDocument class is instantiated. The file argument is thename of a LATEX file. This file will be searched for using the standard LATEX technique and will be read using thedefault input encoding in the document’s configuration.
disableLogging()
disables logging. This is useful if you are using the TeX object within another library and do not want all of thestatus information to be printed to the screen.
Note: This is a class method.
filenamethe current filename being processedjobnamethe name of the basename at the top of the input stack
lineNumber
the line number of the current file being processed
expandTokens(tokens, normalize=False)
expand a list of unexpanded tokens. This method can be used to expand tokens without having them sent to the
output stream. The returned value is a TeXFragment populated with the expanded tokens.
input(source)
add a new input source to the input stack. source should be a Python file object. This can be used to add
additional input sources to the stream after the TeX object has been instantiated.
__iter__()return a generator that iterates through the tokens in the source. This method allows you to treat the TeX stream
as an iterable and use it in looping constructs. While the looping is generally handled in the parse() method,
you can manually expand the tokens in the source by looping over the TeX object as well.
for tok in TeX(open(’myfile.tex’)):print tokitertokens()
return an iterator that iterates over the unexpanded tokens in the input document.
kpsewhich(name)locate the given file in a kpsewhich-like manner. The full path to the file is returned if it is found; otherwise,Contents

69

None is returned. Note: Currently, only the directories listed in the environment variable TEXINPUTS are
searched.
normalize(tokens)
joins consecutive text tokens into a string. If the list of tokens contain tokens that are not text tokens, the originallist of tokens is returned.
parse(output=None)parse the sources currently in the input stack until they are empty. The output argument is an optional
Document node to put the resulting nodes into. If none is supplied, a TeXDocument instance will be created.
The return value is the document from the output argument or the instantiated TeXDocument object.
pushToken(token)
pushes a token back into the input stream to be re-read.
pushTokens(tokens)pushes a list of tokens back into the input stream to be re-read.
readArgument(*args, **kwargs)
parse a macro argument without the LATEX source that created it. This method is just a thin wrapper around
readArgumentAndSource. See that method for more information.
readArgumentAndSource(spec=None, subtype=None, delim=’,’, expanded=False, default=None, parentNode=None, name=None)parse a macro argument. Return the argument and the LATEX source that created it. The arguments are described
below.
Description
Optionspec
string containing information about the type of argument to get. If it
is ’None’, the next token is returned. If it is a two-character string, agrouping delimited by those two characters is returned (i.e. ’[]’). If it is asingle-character string, the stream is checked to see if the next characteris the one specified. In all cases, if the specified argument is not found,’None’ is returned.
type
data type to cast the argument to. New types can be added to theself.argtypes dictionary. The key should match this ’type’ argument andthe value should be a callable object that takes a list of tokens as the firstargument and a list of unspecified keyword arguments (i.e. **kwargs)
for type specific information such as list delimiters.
subtypedata type to use for elements of a list or dictionary
delim
item delimiter for list and dictionary types
boolean indicating whether the argument content should be expanded or
expandedjust returned as an unexpanded text string
default
value to return if the argument doesn’t exist
parentNode the node that the argument belongs to
namethe name of the argument being parsed
The return value is always a two-element tuple. The second value is always a string. However, the first value
can take the following values.
Value
None
object of requested type
list of tokens

Condition
the requested argument wasn’t found
if type was specified
all other arguments

source(tokens)
return the LATEX representation of the tokens in tokens
textTokens(text)
convert a string of text into a series of tokens

70

Contents

6.5 plasTeX.Context — The TEX Context
The Context class stores all of the information associated with the currently running document. This includes things
like macros, counters, labels, references, etc. The context also makes sure that localized macros get popped off whenprocessing leaves a macro or environment. The context of a document also has the power to create new counters,
dimens, if commands, macros, as well as change token category codes.
Each time a TeX object is instantiated, it will create its own context. This context will load all of the base macros andinitialize all of the context information described above.

6.5.1

Context Objects

class Context([load ])Instantiate a new context.
If the load argument is set to true, the context will load all of the base macros defined in plasTEX. This includes
all of the macros used in the standard TEX and LATEX distributions.
contexts
stack of all macro and category code collections currently in the document being processed. The item at index
0 include the global macro set and default category codes.
counters
a dictionary of counters.
currentlabel
the object that is given the label when a \label macro is invoked.
isMathModeboolean that specifies if we are currently in TEX’s math mode or not.
labelsa dictionary of labels and the objects that they refer to.
addGlobal(key, value)
add a macro value with name key to the global namespace.
addLocal(key, value)
add a macro value with name key to the current namespace.
append([context ])same as push()
catcode(char, code)
set the category code for a character in the current scope. char is the character that will have its category codechanged. code is the TEX category code (0-15) to change it to.
chardef(name, num)
create a new TEX chardef like \chardef.
name is the name of the command to create.
num is the character number to use.
__getitem__(key)look through the stack of macros and return the one with the name key. The return value is an instance of therequested macro, not a reference to the macro class. This method allows you to use Python’s dictionary syntax
to retrieve the item from the context as shown below.
tex.context[’section’]Contents71

importMacros(context)
import macros from another context into the global namespace. The argument, context, must be a dictionary ofmacros.
label(label)
set the given label to the currently labelable object. An object can only have one label associated with it.
let(dest, source)
create a new TEX let like \let.
dest is the command sequence to create.
source is the token to set the command sequence equivalent to.
Examplec.let(’bgroup’, BeginGroup(’{’))

loadBaseMacros()imports all of the base macros defined by plasTEX. This includes all of the macros specified by the TEX andLATEX systems.
loadLanguage(language, document)loads a language package to configure names such as \figurename, \tablename, etc. See Section 6.5.2 formore information.
language is a string containing the name of the language file to load.
document is the document object being processed.
loadINIPackage(inifile)load an INI formatted package file (see section 4.3 for more information).
loadPackage(tex, file, [options ])loads a LATEX package.
tex is the TEX processor to use in parsing the package content
file is the name of the package to load
options is a dictionary containing the options to pass to the package. This generally comes from the optional
argument on a \usepackage or \documentclass macro.
The package being loaded by this method can be one of three type: 1) a native LATEX package, 2) a Python
package, or 3) an INI formatted file. The Python version of the package is searched for first. If it is found, it isloaded and an INI version of the package is also loaded if it exists. If there is no Python version, the true LATEX
version of the package is loaded. If there is an INI version of the package in the same directory as the LATEX
version, that file is loaded also.
newcommand(name[, nargs[, definition[, opt ]]])
create a new LATEX command like \newcommand.
name is the name of the macro to create.
nargs is the number of arguments including optional arguments.
definition is a string containing the macro definition.
opt is a string containing the default optional value.
Examplesc.newcommand(’bold’, 1, r’\\textbf{#1}’)
c.newcommand(’foo’, 2, r’{\\bf #1#2}’, opt=’myprefix’)72

Contents

newcount(name[, initial ])create a new count like \newcount.
newcounter(name, [resetby, initial, format ])create a new counter like \newcounter.
name is the name of the counter to create.
resetby is the counter that, when incremented, will reset the new counter.
initial is the initial value for the counter.
format is the printed format of the counter.
In addition to creating a new counter macro, another macro corresponding to the \thename is created which
prints the value of the counter just like in LATEX.
newdef(name[, args[, definition[, local ]]])
create a new TEX definition like \def.
name is the name of the definition to create.
args is a string containing the TEX argument profile.
definition is a string containing the macro code to expand when the definition is invoked.
local is a boolean that specifies that the definition should only exist in the local scope. The default value is true.
Examplesc.newdef(’bold’, ’#1’, ’{\\bf #1}’)
c.newdef(’put’, ’(#1,#2)#3’, ’\\dostuff{#1}{#2}{#3}’)

newdimen(name[, initial ])create a new dimen like \newdimen.
newenvironment(name[, nargs[, definition[, opt ]]])
create a new LATEX environment like \newenvironment. This works exactly like the newcommand()method, except that the definition argument is a two element tuple where the first element is a string containing
the macro content to expand at the \begin, and the second element is the macro content to expand at the \end.
Examplec.newenvironment(’mylist’, 0, (r’\\begin{itemize}’, r’\\end{itemize}’))newif(name[, initial ])create a new if like \newif. This also creates macros corresponding to \nametrue and \namefalse.
newmuskip(name[, initial ])create a new muskip like \newmuskip.
newskip(name[, initial ])create a new skip like \newskip.
packagesa dictionary of LATEX packages. The keys are the names of the packages. The values are dictionaries containing
the options that were specified when the package was loaded.
pop([obj ])pop the top scope off of the stack. If obj is specified, continue to pop scopes off of the context stack until thescope that was originally added by obj is found.
push([context ])add a new scope to the stack. If a macro instance context is specified, the new scope’s namespace is given bythat object.
Contents73ref(obj, label)
set up a reference for resolution.
obj is the macro object that is doing the referencing.
label is the label of the node that obj is looking for.
If the item that obj is looking for has already been labeled, the idref attribute of obj is set to the abject.
Otherwise, the reference is stored away to be resolved later.
setVerbatimCatcodes()set the current set of category codes to the set used for the verbatim environment.
whichCode(char)
return the character code that char belongs to. The category codes are the same codes used by TEX and aredefined in the Token class.

6.5.2

Context language

Contexts objects hold language information for the currently running document. The current language is stored inContext.currentLanguage. It can be changed from the TEX source using the babel package which invokes the Context.loadLanguage method. New terms can be added in a user defined language file using the lang-terms options (seeSection 2.1.2). Languages files are xml files. The following example should be self-explanatory.
<languages><terms lang="fr" babel="french"><term name="proof">Démonstration</term></terms></languages>

This allows to add new terms which are then available to renderers in the dictionary Context.terms. It also allows
to override default translations. For instance the above language file overwrites the default translation of “proof” as“Preuve” in French.

6.6 plasTeX.Renderers — The plasTEX Rendering Framework
The renderer is responsible for taking the information in a plasTEX document object and creating a another (usuallyvisual) representation of it. This representation may be HTML, XML, RTF, etc. While this could be implemented invarious ways. One rendering framework is included with plasTEX.
The renderer is essentially just a dictionary of functions1 . The keys in this dictionary correspond to names of the nodes
in the document object. The values are the functions that are called when a node in the document object needs to berendered. The only argument to the function is the node itself. What this function does in the rendering process iscompletely up to it; however, it should refrain from changing the document object itself as other renderers may beusing that same object.
There are some responsibilities that all renderers share. Renderers are responsible for checking options in the configuration object. For instance, renderers are responsible for generating filenames, creating directories, writing files
in the proper encoding, generating images, splitting the document into multiple output files, etc. Of course, how it
accomplishes this is really renderer dependent. An example of a renderer based on Zope Page Templates (ZPT) is
included with plasTEX. This renderer is capable of generating XML and HTML output.
1 “functions” is being used loosely here. Actually, any Python callable object (i.e. function, method, or any object with the __call__ method
implemented) can be used

74

Contents

6.6.1

Renderer Objects

class Renderer()
Base class for all renderers. Renderer is a dictionary and contains functions that are called for each node in
the plasTEX document object. The keys in the dictionary correspond to the names of the nodes.
This renderer implementation uses a mixin called Renderable that is mixed into the Node class prior to rendering.
Renderable adds various methods to the Node namespace to assist in the rendering process. The primary inclusion
is the __str__() method. This method returns a string representation of the current node and all of its child nodes.
For more information, see the Renderable class documentation.
default
the default renderer value. If a node is being rendered and no key in the renderer matches the name of the node
being rendered, this function is used instead.
fileExtension
contains the file extension to use for generated files. This extension is only used if the filename generator does
not supply a file extension.
files
a list of files created during rendering.
imageAttrs
contains a string template that renders the placeholder for the image attributes: width, height, and depth. This
placeholder is inserted into the document where the width, height, and depth of an image is needed. The
placeholder is needed because images are not generated until after the document is rendered. See the Imager
API (section 6.7) for more information.
imageUnits
contains a string template that renders the placeholder for the image attribute units. This placeholder is inserted
in the document any time an attribute of a particular unit is requested. This placeholder will always occur
immediately after the string generated by imageAttrs. The placeholder is needed because images are notgenerated until after the document is rendered. See the Imager API (section 6.7) for more information.
imagera reference to an Imager implementation. Imagers are responsible for generating images from LATEX code. Thisis needed for output types which aren’t capable of displaying equations, LATEX pictures, etc. such as HTML.
vectorBitmap
a boolean indicating whether bitmap versions should be generated for vector images. The bitmap version is used
to read off the height, width and depth of the image. If such information is not used by the renderer, we can skip
producing the bitmap, which may take a long time.
This defaults to True.
imageTypes
contains a list of file extensions of valid image types for the renderer. The first element in the list is the default
image format. This format is used when generating images (if the image type isn’t specified by the filename
generater). When static images are simply copied from the document, their format is checked against the list of
supported image types. If the static image is not in the correct format it is converted to the default image format.
Below is an example of a list of image types used in the HTML renderer. These image types are valid because
web browsers all support these formats.
imageTypes = [’.png’,’.gif’,’.jpg’,’.jpeg’]

vectorImageTypes
contains a list of file extensions of valid vector image types for the renderer. The first element in the list is thedefault vector image format. This format is used when generating images. Static images are simply copied into
the output document directory. Below is an example of a list of image types used in the HTML renderer. These

Contents

75

image types are valid because there are plug-ins available for these formats.
vectorImageTypes = [’.svg’]

newFilename
filename generator. This method generates a basename based on the options in the configuration.
The generator has an attribute called namespace which contains the namespace used to resolve the variablesin the filename string. This namespace should be populated prior to invoking the generator. After a successful
filename is generated, the namespace is automatically cleared (with the exception of the variables sent in thenamespace when the generator was instantiated).
Note: This generator can be accessed in the usual generator fashion, or called like a function.
outputTypea function that converts the content returned from each rendered node to the appropriate value.
textDefault
the default renderer to use for text nodes.
cleanup(document, files[, postProcess ])this method is called once the entire rendering process is finished. Subclasses can use this method to run any
post-rendering cleanup tasks. The first argument, document, is the document instance that is being rendered.
The second argument, files, is a list of all of the filenames that were created.
This method opens each file, reads the content, and calls processFileContent on the file content. It issuggested that renderers override that method instead of cleanup.
In addition to overriding processFileContent, you can post-process file content without having to subclass a renderer by using the postProcess argument. See the render method for more information.
find(keys[, default ])locate a rendering method from a list of possibilities.
keys is a list of strings containing the requested name of a rendering method. This list is traversed in order. The
first renderer that is found is returned.
default is a default rendering method to return if none of the keys exists in the renderer.
initialize()
this routine is called after the renderer is instantiated. It can be used by subclasses to do any initialization
routines before the rendering process.
processFileContent(document, content)
post-processing routine that allows renders to modify the output documents one last time before the rendering
process is finished. document is the input document instance. content is the content of the file in a string object.
The value returned from this method will be written to the output file in the appropriate encoding.
render(document[, postProcess ])invokes the rendering process on document. You can post-process each file after it is rendered by passing afunction into the postProcess argument. This function must take two arguments: 1) the document object and 2)
the content of a file as a string object. It should do whatever processing it needs to the file content and return astring object.

6.6.2

Renderable MixInclass Renderable()
The Renderable mixin is mixed into the Node namespace prior to the rendering process. The methods mixed
in assist in the rendering process.

76

Contents

filenamethe filename that this object will create. Objects that don’t create new files should simply return None. The
configuration determines which nodes should create new files.
image
generate an image of the object and return the image filename. See the Imager documentation in section 6.7
for more information.
vectorImage
generate a vector image of the object and return the image filename. See the Imager documentation in section
6.7 for more information.
url
return the relative URL of the object.
If the object actually creates a file, just the filename will be returned (e.g. ‘foo.html’). If the object is within afile, both the filename and the anchor will be returned (e.g. ‘foo.html#bar’).
__str__()
invoke the rendering process on all of the child nodes. The rendering process includes walking through the childnodes, looking up the appropriate rendering method from the renderer, and calling the method with the childnode as its argument.
In addition to the actual rendering process, this method also prints out some status information about the rendering process. For example, if the node being rendered has a non-empty filename attribute, that meansthat the node is generating a new file. This filename information is printed to the log. One problem with thismethodology is that the filename is not actually created at this time. It is assumed that the rendering method will
check for the filename attribute and actually create the file.

6.7 plasTeX.Imagers — The plasTEX Imaging Framework
The imager framework is used when an output format is incapable of representing part of a LATEX document natively.
One example of this TikZ pictures in HTML. In cases like this you can use an Imager to generate images of thecommands and environments that cannot be rendered in any other way.
Currently, plasTEX comes with several imager implementations based on dvi2bitmap (http://dvi2bitmap.
sourceforge.net/), dvipng (http://savannah.nongnu.org/projects/dvipng/), and ghostscriptwith the PNG driver (http://www.cs.wisc.edu/~ghost/doc/GPL/index.htm) called gspdfpng andgspspng, as well as one that uses OS X’s CoreGraphics library. Creating imagers based on other programs is quite
simple.
In addition to imagers that generate bitmap images, it is also possible to generate vector images using programs likedvisvg (http://dvisvg.sourceforge.net/) or dvisvgm (http://dvisvgm.sourceforge.net/).
The Imager framework does all of its work in temporary directories the one requirement that it has is that Imager
subclasses need to generate images with the basenames ‘img%d’ where ‘%d’ is the number of the image.
The only requirement by the plasTEX framework is that the imager class within the imager module is called “Imager”
and should be installed in the plasTeX.Imagers package. The basename of the imager module is the name used
when plasTEX looks for a specified imager.

6.7.1

Imager Objects

class Imager(document)
Instantiate the imager class.
document the document object that is being rendered.

Contents

77

The Imager class is responsible for creating a LATEX document of requested images, compiling it, and generating images from each page in the document.
commandspecifies the converter that translates the output from the LATEX document compiler (e.g. PDF, DVI, PS) into
images (e.g. PNG, JPEG, GIF). The only requirement is that the basename of each image is of the form ‘img%d’
where ‘%d’ is the number of the image.
Note: This is a class attribute.
Writing a renderer requires you to at least override the command that creates images. It can be as simple as theexample below.
import plasTeX.Imagers
class DVIPNG(plasTeX.Imagers.Imager):""" Imager that uses dvipng """command = ’dvipng -o img%d.png -D 110’compiler
specifies the LATEX document compiler (i.e. latex, pdflatex) command.
Note: This is a class attribute.
configcontains the “images” section of the document configuration.
fileExtension
contains the file extension to use if no extension is supplied by the filename generator.
imageAttrs
contains a string template that will be used as a placeholder in the output document for the image height, width,and depth. These attributes cannot be determined in real-time because images are not generated until after the
document has been fully rendered. This template generates a string that is put into the output document so thatthe image attributes can be post-processed in. For example, the default template (which is rather XML/HTMLbiased) is:&${filename}-${attr};

The two variables available are filename, the filename of the image, and attr, the name of the attr (i.e. width,height, or depth).
imageUnits
contains a string template that will be used as a placeholder in the output document for the image units. This
template generates a string that is put into the output document so that the image attribute units can be postprocessed in. For example, the default template (which is rather XML/HTML biased) is:&${units);

The only variable available is units and contains the CSS unit that was requested. The generate string will always
occur immediately after the string generated by imageAttrs.
imagesdictionary that contains the Image objects corresponding to the requested images. The keys are the image
filenames.
newFilename
callable iterator that generates filenames according to the filename template in the configuration.
sourcefile object where the image LATEX document is written to.

78

Contents

verifications
a list of commands that verifies the existence of the image converter on the current machine. If
verifications is not specified, the executable specified in command is executed with the --help. If the
return code of all commands are zero, the imager is considered valid. Otherwise, the imager is not consideredvalid.
close()
closes the generated LATEX document and starts the image generation routine.
compileLatex(source)
the method responsible for compiling the LATEX source. The source file is ‘images.tex‘ in the current working
directory (which is a temporary directory, not the directory from which the command is run). The result should
be saved in the same directory, to be used by ‘executeConverter‘.
executeConverter(output)
executes the command that converts the output from the LATEX compiler into image files. In the default implementation, it tries to convert from ‘./images.dvi‘, ‘./images.pdf‘ or ‘./images.ps‘, in that order.
getImage(node)
get an image for node in any way possible. The node is first checked to see if the imageoverride attribute isset. If it is, that image is copied to the image directory. If imageoverride is not set, or there was a problem
in saving the image in the correct format, an image is generated using the source of node.
newImage(text, [context, filename ])invokes the creation of an image using the LATEX content in text.
context is the LATEX code that sets up the context of the document. This generally includes the setting of counters
so that counters used within the image code are correct.
filename is an optional filename for the output image. Generally, image filenames are generated automatically,
but they can be overridden with this argument.
verify()verifies that the command in command is valid for the current machine. The verify method returns True if
the command will work, or False if it will not.
writeImage(filename, code, context)
writes the LATEX code to the generated document that creates the image content.
filename is the final filename of the image. This is not actually used in the document, but can be handy fordebugging.
code is the LATEX code that an image is needed of.
context is the LATEX code that sets up the context of the document. This generally includes the setting of counters
so that counters used within the image code are correct.
writePreamble(document)
this method is called when the imager is instantiated and is used to write any extra information to the preamble.
If overridden, the subclass needs to make sure that document.preamble.source is the first thing written to thepreamble.

6.7.2

Image Objects

class Image(filename, config, [width, height, alt, depth, longdesc ])Instantiate an Image object.
Image objects contain information about the generated images. This information includes things such as width,height, filename, absolute path, etc. Images objects also have the ability to crop the image that they reference andreturn information about the baseline of the image that can be used to properly align the image with surrounding
text.

Contents79

filename is the input filename of the image.
config is the “images” section of the document configuration.
width is the width of the image. This is usually extracted from the image file automatically.
height is the height of the image. This is usually extracted from the image file automatically.
alt is a text alternative of the image to be use by renderers such as HTML.
depth is the depth of the image below the baseline of the surrounding text. This is generally calculated automatically when the image is cropped.
longdesc is a long description used to describe the content of the image for renderers such as HTML.
alta text alternative of the image to be use by renderers such as HTML.
configthe “images” section of the document’s configuration.
depth
the depth of the image below the baseline of the surrounding text. This is generally calculated automaticallywhen the image is cropped.
filenamethe filename of the image.
heightthe heigt of the image in pixels.
longdesca long description used to describe the content of the image for renderers such as HTML.
path
the absolute path of the image file.
url
the URL of the image. This may be used during rendering.
width
the width of the image in pixels.
crop()
crops the image so that the image edges are flush with the image content. It also sets the depth attribute of theimage to the number of pixels that the image extends below the baseline of the surrounding text.

6.8

Plugins

As explained in Chapter 2, one can use command line options of configuration files to use extra packages or templates
or even a full custom renderer. However this is not convenient if you want use the same extras in several projects, orwant to distribute them. In order to do that, you can create a plasTEX plugin. Such a plugin is simply a python packagethat contains one or several subpackages named ‘templates’, ‘Packages’ or ‘Renderers’.
In this section, we describe some minimalistic plugins demonstrating the possibilities offered. For clarity we willseparate the three kinds of plugin content into three plugins but of course a sophisticated plugin can combine several
kinds.
Any kind of python packaging can be used as long as it allows to put the plugin code into the Python search path and canbundle Python code with some other files, typically template files. In this documentation we will use setuptools
and put all configuration into a ‘pyproject.toml’ file which is essentially the same for all three examples, differing onlyin the name and description metadata.

80

Contents

[ project ]name = " m y _ w o n d e r f u l _ p l a s t e x _ p l u g i n "version = "1.0.0"
d e s c r i p t i o n = "A n i c e p l a s T e X p l u g i n . "r e q u i r e s −python = " >=3.7"
dependencies = [" plastex >=3.0"][ t o o l . s e t u p t o o l s . package − d a t a ]plastex_markdown_renderer = [ " * * / * . j i n j a 2 " , "**/*. j i n j a 2 s "][ build −system ]requires = [" setuptools "]build −backend = " s e t u p t o o l s . build_meta "Note in particular the line about packaging Jinja files together with python files. Of course you can add CSS file ofjavascript files or any other kind of required file. Note also that you will need a bit more metadata if you want to
upload your plugin to pypi for instance.
You can then install this python package by running pip install . from the folder containing that‘pyproject.toml’. Then you can compile a file ‘text.tex’ using your plugin by running
plastex --plugins my_wonderful_plastex_plugin -- test.tex

In the above command, the double-dash before the file name is needed because the --plugins options takes a list of
space separated plugins.

6.8.1

Templates plugin

The simplest kind of plugin is useful when you need to reuse custom templates. Say you do not like the HTML5
template for quotes and often want to use the same custom template. You can create a folder with the following
structure.
my_templates_plugin
pyproject.toml
src
plastex_div_quote__init__.py
templates
Quote.jinja2The ‘pyproject.toml’ was already explained and the ‘__init__.py’ can be empty in this case. In this case the plugin nameis plastex_div_quote. The content of ‘Quote.jinja2’ could be:name : q u o t e< d i v c l a s s = " q u o t e " >{{ o b j }} < / d i v >Contents

81

6.8.2

Package plugin

For a slighly more complicated example, assume that you have implemented a python version of some package that is
not natively supported by plasTEX, or you don’t like the available implementation and, for some reason, contributing
your implementation to plasTEXis not possible. You can use the --packages-dir option to use your implementation,
but this is not convenient if you want to distribute it. So you can create a folder with the following structure
my_package_plugin
pyproject.toml
src
plastex_foo_package__init__.py
Packagesfoo.pytemplates
Foo.jinja2The ‘pyproject.toml’ was already explained and the ‘__init__.py’ can be empty in this case. In this case the plugin nameis plastex_foo_package. The content of ‘foo.py’ could be:from p l a s T e X import Commandc l a s s f o o ( Command ) :pass
and the content of ‘Foo.jinja2’ could be:name : f o oFoo !
When compiling a file using this plugin, you can put \usepackage{foo} in the preamble and then use the \foocommand that will be rendered as “Foo!” with any template based renderer (for instance the default HTML5 renderer).

6.8.3

Renderer plugin

For our final example, we build a plugin which brings a new renderer. We will use as an example a renderer targetting
Markdown. This is slightly silly since markdown itself is a source code format, and much cruder that LATEX, but thisis only an example.

82

Contentsmy_renderer_plugin
pyproject.toml
src
plastex_markdown_renderer__init__.py
Renderers
Markdown__init__.py
Math.jinja2s
Sectioning.jinja2s
Text.jinja2s
Themesdefault
default-layout.jinja2The ‘__init__.py’ in ‘plastex_markdown_renderer’ is empty but the one in ‘Markdown’ contains
from p l a s T e X . R e n d e r e r s . P a g e T e m p l a t e import R e n d e r e r a s P T R e n d e r e rc l a s s Renderer ( PTRenderer ) :" " " R e n d e r e r t a r g e t t i n g Markdown u s i n g t e m p l a t e s . " " "f i l e E x t e n s i o n = ’ . md ’which simply declares a page template based renderer which will produce files with extension ‘.md’. The various files
with ‘.jinja2s’ extension contain the following code split into three files for convenience:name : math d i s p l a y m a t h{{ o b j . m a t h j a x _ s o u r c e }}name : document{{ o b j }}name : s e c t i o n# {{ o b j . f u l l T i t l e }}{{ o b j }}name : s u b s e c t i o n## {{ o b j . f u l l T i t l e }}{{ o b j }}name : p a r{{ o b j }}name : emph em* {{ o b j }} *name : i t s h a p e t e x t i t* {{ o b j }} *Contents83name : b f s e r i e s t e x t b f** {{ o b j }} **name : t t f a m i l y‘{{ obj }} ‘

textttand the file ‘default-layout.jinja2’ simply contains one line saying {{ obj }}. This will allow to run
plastex --plugins

plastex_markdown_renderer --renderer Markdown test.tex

to render a tiny subset of LATEX to markdown.

84

Contents

APPENDIXA

About This Document
This document was writted using LaTeX (http://www.latex-project.org/). The documents use macros
written for documenting the Python (http://www.python.org) language and Python packages. Generating the
PDF version of the document is simply a matter of using the pdflatex command. Generating the HTML version of the
document, of course, uses plasTeX.
The wonderful thing about the HTML version is that it was generated from the LaTeX source and Python style
files without customization1 ! In fact, in its current state, plasTeX can generate the HTML versions of the Python
documentation found on their website, http://www.python.org/doc/. Without customization of plasTeX,
the only remaining issues are that the module index is missing and there are some formatting differences. Not bad,considering plasTeX is doing actually expanding the LaTeX document natively.

1 Ok, there was one customization to \var for a whitespace issue, but the change works both in the PDF and HTML version

85

86

APPENDIXB

Frequently Asked Questions
B.1

Parsing LATEX

B.1.1

How can I make plasTEX work with my complicated macros?

While plasTEX makes a valiant effort to expand all LATEX macros, it isn’t TEX and may have problems if your macros
are complicated. There are things that you can do to remedy the situation. If you are getting failures or warnings, you
can do one of two things: 1) you can create a simplified version of the macro that plasTEX uses for its work, while
LATEX uses the more complicated one, or 2) you can implement the macro as a Python class.
In the first solution, you can use the \ifplastex construct to wrap your plasTEX and LATEX versions of the macros.
You can even just remove parts of the macros. See the example below.
% Print a double line, then bold the text.
% In plasTeX, leave the lines out.
\newcommand{\mymacro}[1]{\ifplastex\else\vspace*{1in}\fi\textbf{#1}}

Depending on how complicated you macro is, you may want to implement it as a Python class instead of a LATEX
macro. Using a Python class gives you full access to all of the plasTEX internal mechanisms to do whatever you needto do in your macro. To read more about writing Python class macros, see the section 4.

B.1.2

How can I get plasTEX to find my LATEX packages?

There are two types of packages that can be loaded by plasTEX: 1) native LATEX packages, and 2) packages written
entirely in Python. plasTEX first looks for packages written in Python. Packages such as this are written specifically for
plasTEX and will yield better parsing performance as well as better looking output. If you have a true LATEX package,plasTEX will try to locate it using the kpsewhich program just like LATEX does. For more information about packages,
see the section 4.3.

87

88

APPENDIXC

Debugging
C.1

Logging levels

plasTEXuses standard python logging to document what it is doing. The loggers that are defined by default are context, context.macros, context.stack, imager, parse, parse.commands,
parse.definitions,parse.digest,parse.environments,
parse.mathshift,parse.persistent,parse.sections,parse.tokens,
render,render.images,
render.images.depth, simpleTAL, simpleTALES, status, tex, tex.kpsewhich.
When using the main plastex script, you can change the corresponding levels to values CRITICAL, ERROR,WARNING, INFO, or DEBUG by using a configuration file with a [logging] section such as:[logging]
parse.environments=DEBUG

if you want more information about environment parsing.
If the renderer you use does not call LATEX for creating images, you can also achieve thesame result from your LATEX document by writing \usepackage{debugplastex} and then\setloglevel{parse.environments}{DEBUG}.
When using plasTEX from python, you can use the function plasTeX.Logging.updateLogLevels to update
logging levels. It takes a dictionary whose keys are logger names and values are levels (both are strings). Non-existentloggers are created, loggers whose names are not keys of the input dictionary are unaffected.

C.2

Using the python debugger

For more drastic debugging, the debugplastex package also provides the command settrace to drop into thepython debugger while parsing. You can also use \usepackage[post_parse_trace]{debugplastex} toask plasTEXto drop into the python debugger after parsing the full LaTeX input. You can also use the --debug
command line option for a similar result without changing the source file.
When using Jinja2 templates with a renderer extending PageTemplate, you can also use {{ debug() }} in atemplate in order to drop into the python debugger while rendering the template. In particular this allows to inspect
obj which contains the node being rendered and config which contains the current plasTeX configuration.

89

90

APPENDIX

D

Zope Page Template Tutorial
The Zope Page Template (ZPT) language is actually just a set of XML attributes that can be applied to markup of
an DTD. These attributes tell the ZPT interpreter how to process the element. There are seven different attributes
that you can use to direct the processing of an XML or HTML file (in order of evaluation): define, condition, repeat,
content, replace, attributes, and omit-tag. These attributes are described in section D.2. For a more complete description, see the official ZPT documentation at http://www.zope.org/Documentation/Books/ZopeBook/
2_6Edition/ZPT.stx.

D.1

Template Attribute Language Expression Syntax (TALES)The Template Attribute Language Expression Syntax (TALES) is used by the attribute language described in the next
section. The TALES syntax is used to evaluate expressions based on objects in the template namespace. The resultsof these expressions can be used to define variables, produce output, or be used as booleans. There are also several
operators used to modify the behavior or interpretation of an expression. The expressions and their modifiers aredescribed below.
path: operator A “path” is the most basic form on an expression in ZPT. The basic form is shown below.
[path:]string [ | TALES expression ]The path: operator is actually optional on all paths. Leaving it off makes no difference. The “string” in the above
syntax is a ’/’ delimited string of names. Each name refers to a property of the previous name in the string. Properties
can include attributes, methods, or keys in a dictionary. These properties can in turn have properties of their own.
Some examples of paths are shown below.
# Access the parentNode attribute of chapter, then get its title
chapter/parentNode/title# Get the key named ’foo’ from the dictionary bar
bar/foo# Call the title method on the string in the variable booktitle
booktitle/title

It is possible to specify multiple paths separated by a pipe (|). These paths are evaluated from left to right. The first
one to return a non-None value is used.

91

# Look for the title on the current chapter node as well as its parents
chapter/title | chapter/parentNode/title | chapter/parentNode/parentNode/title# Look for the value of the option otherwise get its default value
myoptions/encoding | myoptions/defaultencoding

There are a few keywords that can be used in place of a path in a TALES expression as well.
Namenothing
default
options
repeatattrs
CONTEXTS

Purposesame as None in Python
keeps whatever the existing value of the element or attribute isdictionary of values passed in to the template when instatiatedthe repeat variable (see D.2)
dictonary of the original attributes of the element
dictionary containing all of the above

exists: operator This operator returns true if the path exists. If the path does not exist, the operator returns false.
The syntax is as follows.
exists:path

The “path” in the code above is a path as described in section D.1. This operator is commonly combined with the not:operator.
nocall: operator By default, if a property that is retrieved is callable, it will be called automatically. Using thenocall: operator, prevents this execution from happening. The syntax is shown below.
nocall:path

not: operator The not: operator simply negates the boolean result of the path. If the path is a boolean true, the not:operator will return false, and vice versa. The syntax is shown below.
not:path

string: operator The string: operator allows you to combine literal strings and paths into one string. Paths areinserted into the literal string using a syntax much like that of Python Templates: $path or ${path}. The general syntax
is:string:text

Here are some examples of using the string: operator.

92

Contents

string:Next - ${section/links/next}
string:($pagenumber)string:[${figure/number}] ${figure/caption}

python: operator The python: operator allows you to evaluate a Python expression. The syntax is as follows.
python:python-code

The “python-code” in the expression above can include any of the Python built-in functions and operators as well asfour new functions that correspond to the TALES operators: path, string, exists, and nocall. Each of these functions
takes a string containing the path to be evaluated (e.g. path(’foo/bar’), exists(’chapter/title’), etc.).
When using Python operators, you must escape any characters that would not be legal in an XML/HTML document(i.e. <>&). For example, to write an expression to test if a number was less than or greater than two numbers, you
would need to do something like the following example.
# See if the figure number is less than 2 or greater than 4python: path(’figure/number’) &lt; 2 or path(’figure/number’) &gt; 4stripped: operator The stripped: operator only exists in the SimpleTAL distribution provided by plasTEX. It evaluates the given path and removes any markup from that path. Essentially, it is a way to get a plain text representationof the path. The syntax is as follows.
stripped:path

D.2

Template Attribute Language (TAL) Attributes

tal:define The tal:define attribute allows you to define a variable for use later in the template. Variables can be
specifies as local (only for use in the scope of the current element) or global (for use anywhere in the template). The
syntax of the define attribute is shown below.
tal:define="[ local | global ] name expression [; define-expression ]"The define attributes sets the value of “name” to “expression.” By default, the scope of the variable is local, but canbe specified as global by including the “global” keyword before the name of the variable. As shown in the grammar
above, you can specify multiple variables in one tal:define attribute by separating the define expressions bysemi-colons.
Examples of using the tal:define attribute are shown belaw.

Contents93<p tal:define="global title document/title;
next self/links/next;
previous self/links/previous;
length python:len(self);
up string:Up - ${self/links/up}">
...
</p>

tal:condition The tal:condition attribute allows you to conditionally include an element. The syntax is shown
below.
tal:condition="expression"

The tal:condition attribute is very simple. If the expression evaluates to true, the element and its children will
be evaluated and included in the output. If the expression evaluates to false, the element and its children will not be
evaluated or included in the output. Valid expressions for the tal:condition attribute are the same as those forthe expressions in the tal:define attribute.
<p tal:condition="python:len(self)"><b tal:condition="self/caption">Caption for paragraph</b>
...
</p>

tal:repeat The tal:repeat attribute allows you to repeat an element multiple times; the syntax is shown below.
tal:repeat="name expression"

When the tal:repeat attribute is used on an element, the result of“expression” is iterated over, and a new element isgenerated for each item in the iteration. The value of the current item is set to “name” much like in the tal:define
attribute.
Within the scope of the repeated element, another variable is available: repeat. This variable contains several properties
related to the loop.

94

Contents

Name
index
number
even
odd
start
end
lengthletterLetterroman
Roman

Purposenumber of the current iteration starting from zero
number of the current iteration starting from one
is true if the iteration number is evenis true if the iteration number is odd
is true if this is the first iterationis true if this is the last iteration; This is never true if the repeat expression
returns an iterator
the length of the sequence being iterated over; This is set to sys.maxint
for iterators.
lower case letter corresponding to the current iteration number startingwith ’a’
upper case letter corresponding to the current iteration number startingwith ’A’
lower case Roman numeral corresponding to the current iteration number
starting with ’i’upper case Roman numeral corresponding to the current iteration number
starting with ’I’

To access the properties listed above, you must use the property of the repeat variable that corresponds to the repeat
variable name. For example, if your repeat variable name is “item”, you would access the above variables using theexpressions repeat/item/index, repeat/item/number, repeat/item/even, etc.
A simple example of the tal:repeat attribute is shown below.
<ol><li tal:repeat="option options" tal:content="option/name">option name</li></ol>

One commonly used feature of rendering tables is alternating row colors. This is a little bit tricky with ZPT since thetal:condition attribute is evaluated before the tal:repeat directive. You can get around this by using themetal: namespace. This is the namespace used by ZPT’s macro language1 You can create another element aroundthe element you want to be conditional. This wrapper element is simply there to do the iterating, but is not included in
the output. The example below shows how to do alternating row colors in an HTML table.
<table><metal:block tal:repeat="employee employees"><!-- even rows --><tr tal:condition="repeat/employee/even" style="background-color: white"><td tal:content="employee/name"></td><td tal:content="employee/title"></td></tr><!-- odd rows --><tr tal:condition="repeat/employee/odd" style="background-color: gray"><td tal:content="employee/name"></td><td tal:content="employee/title"></td></tr></metal:block></table>1 The macro language isn’t discussed here. See the official ZPT documentation for more information.

Contents

95

tal:content The tal:content attribute evaluates an expression and replaces the content of the element with theresult of the expression. The syntax is shown below.
tal:content="[ text | structure ] expression"

The text and structure options in the tal:content attribute indicate whether or not the content returned by theexpression should be escaped (i.e. "&<> replaced by &quot;, &amp;, &lt;, and &gt;, respectively). When the text
option is used, these special characters are escaped; this is the default behavior. When the structure option is specified,
the result of the expression is assumed to be valid markup and is not escaped.
In SimpleTAL, the default behavior is the same as using the text option. However, in plasTEX, 99.9% of the time thecontent returned by the expression is valid markup, so the default was changed to structure in the SimpleTAL package
distributed with plasTEX.
tal:replace The tal:replace attribute is much like the tal:content attribute. They both evaluate an expression and include the content of that expression in the output, and they both have a text and structure option to indicate
escaping of special characters. The difference is that when the tal:replace attribute is used, the element with thetal:replace attribute on it is not included in the output. Only the content of the evaluated expression is returned.
The syntax of the tal:replace attribute is shown below.
tal:replace="[ text | structure ] expression"

tal:attributes The tal:attributes attribute allows you to programatically create attributes on the element. The
syntax is shown below.
tal:attributes="name expression [; attribute-expression ]"The syntax of the tal:attributes attribute is very similar to that of the tal:define attribute. However, in thecase of the tal:attributes attribute, the name is the name of the attribute to be created on the element and theexpression is evaluated to get the value of the attribute. If an error occurs or None is returned by the expression, thenthe attribute is removed from the element.
Just as in the case of the tal:define attribute, you can specify multiple attributes separated by semi-colons (;). If
a semi-colon character is needed in the expression, then it must be represented by a double semi-colon (;;).
An example of using the tal:attributes is shown below.
<a tal:attributes="href self/links/next/url;
title self/links/next/title">link text</a>tal:omit-tag The tal:omit-tag attribute allows you to conditionally omit an element. The syntax is shown
below.
tal:omit-tag="expression"

If the value of “expression” evaluates to true (or is empty), the element is omitted; however, the content of the element

96

Contents

is still sent to the output. If the expression evaluates to false, the element is included in the output.

Contents

97

98

INDEX__add__() (Node method), 65__cmp__() (Node method), 65__getitem__() (ConfigSection method), 62__getitem__() (Context method), 71__getitem__() (Node method), 65__iadd__() (Node method), 66__iter__() (Node method), 66__iter__() (TeX method), 69__len__() (Node method), 66__radd__() (Node method), 66__setitem__() (ConfigSection method), 62__setitem__() (Node method), 66__str__() (Renderable method), 77

config (Imager attribute), 78
ConfigManager (class in plasTeX.ConfigManager),61
ConfigOption[T](classinplasTeX.ConfigManager), 62
ConfigSection (class in plasTeX.ConfigManager),
61
Context (class in plasTeX.Context), 71
contexts (Context attribute), 71
counter (Macro attribute), 57
counters (Context attribute), 71
createDocumentFragment() (Document method),67
createElement() (Document method), 67
createTextNode() (Document method), 68
crop() (Image method), 80
currentlabel (Context attribute), 71

addGlobal() (Context method), 71
addLocal() (Context method), 71
addSection() (ConfigManager method), 61
alt (Image attribute), 80
append() (Context method), 71
append() (Node method), 65
appendChild() (Node method), 65
args (Macro attribute), 55
argSource (Macro attribute), 56
arguments (Macro attribute), 57
attributes (Node attribute), 64
blockType (Macro attribute), 57
BooleanConfigOption(classTeX.ConfigManager), 63
catcode() (Context method), 71
chardef() (Context method), 71
charsubs (TeXDocument attribute), 68
childNodes (Node attribute), 64
cleanup() (Renderer method), 76
cloneNode() (Node method), 65
close() (Imager method), 79
Command (class in plasTeX.DOM), 68
command (Imager attribute), 78
compileLatex() (Imager method), 79
compiler (Imager attribute), 78
config (Image attribute), 80

in

plas-

data (ConfigSection attribute), 61
data (Text attribute), 67
default (Renderer attribute), 75
depth (Image attribute), 80
description (ConfigOption attribute), 62
DictOption[T] (class in plasTeX.ConfigManager),63
digest() (Macro method), 58
digestUntil() (Macro method), 58
disableLogging() (TeX method), 69
Document (class in plasTeX.DOM), 67
DocumentFragment (class in plasTeX.DOM), 67
Element (class in plasTeX.DOM), 67
entryFromString() (DictOption method), 63
Environment (class in plasTeX.DOM), 68
environment variables
TEXINPUTS, 70
executeConverter() (Imager method), 79
expand() (Macro method), 58
expandTokens() (TeX method), 69
extend() (Node method), 65
fileExtension (Imager attribute), 78

99

fileExtension (Renderer attribute), 75
filename (Image attribute), 80
filename (Renderable attribute), 77
filename (TeX attribute), 69
files (Renderer attribute), 75
find() (Renderer method), 76
FloatOption (class in plasTeX.ConfigManager), 63
get() (ConfigManager method), 62
getAttribute() (Element method), 67
getElementById() (Element method), 67
getElementsByTagName() (Element method), 67
getImage() (Imager method), 79
getUserData() (Node method), 66
hasAttribute() (Element method), 67
hasAttributes() (Node method), 66
hasChildNodes() (Node method), 66
height (Image attribute), 80

length (Text attribute), 67
let() (Context method), 72
level (Macro attribute), 57
lineNumber (TeX attribute), 69
loadBaseMacros() (Context method), 72
loadINIPackage() (Context method), 72
loadLanguage() (Context method), 72
loadPackage() (Context method), 72
locals() (Macro method), 58
longdesc (Image attribute), 80
Macro (class in ), 55
macroMode (Macro attribute), 57
macroName (Macro attribute), 57
mathMode (Macro attribute), 57
MultiStringOption(classTeX.ConfigManager), 63

in

plas-

name (ConfigOption attribute), 62
name (ConfigSection attribute), 62
id (Macro attribute), 57
newcommand() (Context method), 72
idref (Macro attribute), 57
newcount() (Context method), 73
Image (class in plasTeX.Imagers), 79
newcounter() (Context method), 73
image (Renderable attribute), 77
newdef() (Context method), 73
imageAttrs (Imager attribute), 78
newdimen() (Context method), 73
imageAttrs (Renderer attribute), 75
newenvironment() (Context method), 73
Imager (class in plasTeX.Imagers), 77
newFilename (Imager attribute), 78
imager (Renderer attribute), 75
newFilename (Renderer attribute), 76
images (Imager attribute), 78
newif() (Context method), 73
imageTypes (Renderer attribute), 75
newImage() (Imager method), 79
imageUnits (Imager attribute), 78
newmuskip() (Context method), 73
imageUnits (Renderer attribute), 75
newskip() (Context method), 73
importMacros() (Context method), 72
nextSibling (Node attribute), 65
importNode() (Document method), 68
Node (class in plasTeX.DOM), 64
initialize() (Renderer method), 76
nodeName (Macro attribute), 57
input() (TeX method), 69
nodeName (Node attribute), 64
insert() (Node method), 66
nodeType (Node attribute), 64
insertBefore() (Node method), 66
nodeValue (Text attribute), 67
IntegerOption (class in plasTeX.ConfigManager), normalize() (Node method), 66
63
normalize() (TeX method), 70
invoke() (Macro method), 58
normalizeDocument() (Document method), 68
isElementContentWhitespace (Node attribute),
64
options (ConfigOption attribute), 62
isEqualNode() (Node method), 66
outputType (Renderer attribute), 76
isMathMode (Context attribute), 71
ownerDocument (Node attribute), 65
isSameNode() (Node method), 66
packages (Context attribute), 73
itertokens() (TeX method), 69
paragraphs() (Macro method), 58
jobname (TeX attribute), 69
parent (ConfigSection attribute), 62
parentNode (Node attribute), 65
kpsewhich() (TeX method), 69
parse() (Macro method), 59
parse() (TeX method), 70
label() (Context method), 72
path (Image attribute), 80
labels (Context attribute), 71
plasTeX.ConfigManager (standard module), 60
lastChild (Node attribute), 64
plasTeX.Context (standard module), 71
100

Index

plasTeX.DOM (standard module), 64
plasTeX.Imagers (standard module), 77
plasTeX.Renderers (standard module), 74
plasTeX.TeX (standard module), 69
pop() (Context method), 73
pop() (Node method), 66
postArgument() (Macro method), 59
postParse() (Macro method), 59
preamble (TeXDocument attribute), 68
preArgument() (Macro method), 59
preParse() (Macro method), 59
previousSibling (Node attribute), 65
processFileContent() (Renderer method), 76
push() (Context method), 73
pushToken() (TeX method), 70
pushTokens() (TeX method), 70
read() (ConfigManager method), 61
readArgument() (TeX method), 70
readArgumentAndSource() (TeX method), 70
ref() (Context method), 74
ref (Macro attribute), 57
refstepcounter() (Macro method), 59
registerArgparse() (ConfigManager method), 61
registerArgparse() (ConfigOption method), 62
removeAttribute() (Element method), 67
removeChild() (Node method), 66
render() (Renderer method), 76
Renderable (class in plasTeX.Renderers), 76
Renderer (class in plasTeX.Renderers), 75
replaceChild() (Node method), 66

title (Macro attribute), 58
toXML() (Node method), 66
updateFromDict() (ConfigManager method), 61
updateFromDict() (ConfigOption method), 63
url (Image attribute), 80
url (Renderable attribute), 77
userdata (Node attribute), 65
value (ConfigOption attribute), 62
vectorBitmap (Renderer attribute), 75
vectorImage (Renderable attribute), 77
vectorImageTypes (Renderer attribute), 75
verifications (Imager attribute), 79
verify() (Imager method), 79
whichCode() (Context method), 74
wholeText (Text attribute), 67
width (Image attribute), 80
writeImage() (Imager method), 79
writePreamble() (Imager method), 79

set() (DictOption method), 63
setAttribute() (Element method), 67
setUserData() (Node method), 66
setVerbatimCatcodes() (Context method), 74
source() (TeX method), 70
source (Imager attribute), 78
source (Macro attribute), 58
source (TeXDocument attribute), 68
source (TeXFragment attribute), 68
stepcounter() (Macro method), 59
str (Node attribute), 65
StringOption (class in plasTeX.ConfigManager), 63
style (Macro attribute), 58
tagName (Macro attribute), 58
TeX (class in plasTeX.TeX), 69
TeXDocument (class in plasTeX.DOM), 68
TeXFragment (class in plasTeX.DOM), 68
TEXINPUTS, 70
Text (class in plasTeX.DOM), 67
textContent (Node attribute), 65
textDefault (Renderer attribute), 76
textTokens() (TeX method), 70
Index101