Rakesh Vidyadharan Help

OpenAPI to LaTeX

I developed this as a testbed while familiarising myself with Julia. A couple of companies I assisted also had a need for attaching API specifications with their customer contracts. The result of these needs is this project.

Note: I have since enhanced and rewritten the process in C++. The old julia implementation is still available in the julia branch.

The primary rationale for this utility is to be able to generate a PDF document that can be distributed to interested parties, when the source specifications are protected by access control (and where the said parties do not need to be provided with the access credentials). I have used the tool to create specification documents that have been included in customer contracts for a few companies that I have worked with.

The workflow is to use this process to generate the target LaTeX file, and run xelatex a few times (usually two times to get cross-references resolved) for the output PDF document. Also run makeindex to generate the document index if desired.

<path to>/oa2tex -i <path to>/openapi.yaml \ -o <path to output directory> \ -s -c --use-cmark cd <path to output directory> xelatex -interaction=nonstopmode openapi makeindex openapi xelatex -interaction=nonstopmode openapi

Structure

The generated LaTeX file has the following structure (you can of course modify the output file as desired):

  • Preamble - Preamble for the document (<path to output>/preamble.tex). Sets up various packages that are used. Edit the file as desired, especially the main font for the document. The generator sets the main font to Helvetica Neue (\setmainfont[Ligatures=TeX,Numbers=OldStyle]{Helvetica Neue}). Change to any system supported font as desired (through the command line option or by editing file as desired after generating the latex sources).

    • Sans-serif fonts like Helvetica, Verdana, Calibri... are good for digital display of the PDF.

    • Use traditional print friendly serif fonts like the LaTeX default Computer Modern (comment out the \setmainfont directive), Times New Roman, Garamond ... if the primary purpose of the output PDF is print.

    • You can also use modern variants of serif fonts such as Merriweather, Sabon... which were designed for both print and digital display.

    • See examples of the Petstore document with different fonts.

  • Frontmatter - Titlepage and table of contents.

  • Mainmatter - Contains two or three parts.

    • Info - The info object is presented as the first chapter.

    • Examples - Any examples that are defined in the openapi.components.examples section.

    • Parameters - Any parameters that are referenced from the various API endpoints. Will only list referenced parameters, not those that are defined in-line.

    • Endpoints - Part with the path operations grouped by tags. Each tag is presented in a chapter.

    • Schemas - Part with the schemas declared and referenced in the specification. Each schema is presented in a chapter. Schemas are listed alphabetically by their filename and entity name.

    • Responses - Optional part with responses declared in the openapi.components structure. If none are defined no part is created.

    • Request Bodies - Part with request bodies that are referenced, not if they are defined inline with schema references.

    • Code Samples - If the x-codeSamples extension exists for operations, these are collected together into another part. Code samples are grouped together under each tag group, which is presented as a chapter.

  • Backmatter

    • List of tables.

    • Index - Operation ids and schema property names are added to index. Note than makeindex must be run to generate the index.

See openapi.pdf for the PDF generated from the official petstore specifications. Note that the petstore sample has a commonmark table in the information, which the embedded converter does not support. This sample was generated using the cmark option.

Usage

The generator is written in C++ and has a dependency on the Boost libraries.

Pre-built binaries for Mac OS and Windows are available on the releases page.

Note: The old Julia version of the utility is still available in the julia branch.

Build project

To build the project install Boost and then checkout and build the project.

Install Dependencies

Build boost from sources.

BOOST_VERSION=1.89.0 INSTALL_DIR=/usr/local/boost cd /tmp ver=`echo "${BOOST_VERSION}" | awk -F'.' '{printf("%d_%d_%d",$1,$2,$3)}'` curl -OL https://archives.boost.io/release/${BOOST_VERSION}/source/boost_${ver}.tar.bz2 tar xfj boost_${ver}.tar.bz2 sudo rm -rf $INSTALL_DIR cd boost_${ver} \ && ./bootstrap.sh \ && sudo ./b2 -j8 cxxflags=-std=c++20 install link=static threading=multi runtime-link=static --prefix=$INSTALL_DIR --without-python --without-mpi

Build boost from sources. Download and extract Boost 1.89 (or above) to a temporary location (eg. `\opt\src`). Launch the Visual Studio Command utility and cd to the temporary location.

cd \opt\src curl -OL https://archives.boost.io/release/1.89.0/source/boost_1_89_0.tar.gz tar -xf boost_1_89_0.tar.gz cd boost_1_89_0 .\bootstrap.bat .\b2 -j8 install threading=multi address-model=64 architecture=arm asynch-exceptions=on --prefix=\opt\local --without-python --without-mpi cd .. del /s /q boost_1_89_0 rmdir /s /q boost_1_89_0
git clone https://github.com/sptrakesh/openapi-latex.git cd openapi-latex cmake -DCMAKE_PREFIX_PATH=/usr/local/boost \ -DCMAKE_BUILD_TYPE=Release \ -DCMAKE_INSTALL_PREFIX=/usr/local/spt \ -S . -B build cmake --build build -j12 sudo cmake --install build

Command Line Options

The following options are supported by the main.cpp executable:

  • --input | -i - Required. The main OpenAPI specification file to parse.

  • --output | -o - Required. The output LaTeX file to generate. Best to place this at another location than the api specifications. Program will attempt to create the directory tree if it does not exist. Since a lot of files are generated by this process, and further when running LaTeX, it would be best to write the output to a dedicated temporary directory.

  • --author | -a - The author credit to show on the titlepage.

  • --footer | -f - The right side footer text to display for the document.

  • --operation-summary | -s - A flag to indicate that Operation summary should be used as section headings instead of operationId.

  • --use-cmark | -m - Use cmark to convert info.description to latex. Recommended option, since the description can be quite long and complicated, and cmark should have much more comprehensive support for converting commonmark to latex. Note the program uses the cmark utility via std::system, and not the library.

  • --log-level | -l - Set the logging level (critical|warn|info|debug). Default info.

  • --console | -c - Flag to indicate logs should also be echoed to stdout.

  • --log-dir | -z - The directory under which the process log output is written. The directory must exist. Default /tmp/ - note the mandatory trailing /.

Example

The following options were used to generate the sample petstore specifications document.

/usr/local/spt/bin/oa2tex \ -i /tmp/petstore-official.yaml \ -o /tmp/petstore \ -s -c --use-cmark

Docker

A docker image is available for those who do not wish to build/install the utility on their computer. Use docker mounts to hold the source specification files as well as the destination output files. Once the output LaTeX files are generated, run xelatex as appropriate.

Note: cmark is installed in the docker image.

A sample invocation is as follows:

docker run --rm -it \ -v $PWD/tmp/test:/tmp/test \ sptrakesh/openapi-latex \ -i /tmp/test/docs/openapi.yaml \ -o /tmp/test/specs \ -s -m -c

Note: The output openapi.tex includes several other .tex files generated by the process with an \input directive. All file paths are absolute paths, hence the docker mount will need to set up appropriately, or the output moved to an appropriate location for the paths to work on the host machine.

Wrap Image

If you do not wish to have texlive installed on your local machine, you can create a wrapper image which also provides xelatex and run the entire process in a container.

FROM sptrakesh/openapi-latex USER root RUN apk add --no-cache texlive-xetex USER spt ENTRYPOINT [ "/bin/sh" ]

Extensions

A few extensions to the specifications developed by Redocly are supported.

  • Source code samples are parsed from the x-codeSamples array attached to an operation. All code samples are attached to a separate part of the output document, and follow the same chapter organisation as the API tags.

  • Tag groups are parsed from the x-tagGroups array attached to the root of the specification document. If specified, an initial chapter Tag Groups is added, which lists the groupings with links to the Tag chapters.

  • An additional custom extension for documenting the version from which an API operation or schema or property has been added is supported in the form of x-since-version. The generated LaTeX files will include this information if so annotated in the API specifications. Example: x-since-version: 2.6.8

    • Document for Operations and Schemas. See sample screen captures of operation version and schema version as rendered in a PDF

Operation Version
Operation Version

Examples

Screen captures of a TOC page from the petstore specification document with different fonts.

Document generated using *Helvetica Neue* font.

Helvetica Neue

Document generated using *Calibri* font.

Calibri

Document generated using *Times New Roman* font.

Times New Roman

Document generated using the default *Computer Modern Roman* font.

Computer Modern Roman

Document generated using the classic *Merriweather* font.

Merriweather

Document generated using *Merriweather Light* font.

Merriweather Light

Document generated using classic *Sabon* font.

Sabon

Document generated using modern *Sabon eText* font.

Sabon eText

Limitations

Probably too many to list, but the following items should be kept in mind.

  • This utility is based on the way I write API specifications, and markup descriptions.

  • Schema objects are assumed to model closely their organisation in a source code implementation. This in turn implies that nested structures are represented as schema references, and not listed in-line in the schema. Deeply nested in-line schemas would be very hard to represent in a printed document in any case.

  • Mainly tested with specifications that are split into individual files - representing paths, schemas, parameters etc. Most testing has been against large handwritten specifications, which follows the principles laid out in split specifications. A few simple single file specifications have also been tested.

  • Mainly supports OpenAPI specification version 3.0.3, although some properties from 3.1.0 are also included.

  • Only supports loading local specification files in YAML format. JSON is not supported at present.

  • Not all properties/aspects of the specification are output in the generated LaTeX file. I selected what I felt are most relevant to be shared.

  • Markdown markup may not be fully translated to LaTeX. See convert.cpp for basic rules implemented.

    • Bold/italic blocks of text (spanning paragraphs) are not supported.

The output is a wrapping LaTeX file that includes several smaller included files, and hence can be easily modified as needed to further customise the final PDF document.

Dependencies

  • rapidyaml YAML parser library. Via cmake fetchcontent

  • Boost local installation required.

  • Clara - Command line options parser. Included in project.

  • Catch2 - Testing framework. Via cmake fetchcontent

  • NanoLog - Logging framework used for the project. Modified version included in project.

Last modified: 06 October 2025