Skip to main content

Tools to generate documentation.

Project description

Documentation tools for enterprise-quality documentation from Markdown source. Dactyl has advanced features to enable single-sourcing and an extensible syntax for building well-organized, visually attractive docs. It generates output in HTML (natively), and can make PDFs if you have Prince installed.


Dactyl requires Python 3. Install with pip:

sudo pip3 install dactyl

Or a local install in a virtualenv:

# Create an activate a virtualenv so the package and dependencies are localized
virtualenv -p `which python3` venv_dactyl
source venv_dactyl/bin/activate

# Check out this repo
git clone

# Install
pip3 install dactyl/

# Where 'dactyl/' is the top level directory of the repo, containing
# And note the trailing '/' which tells pip to use a local directory to install it.


Simple (“Ad-Hoc”) usage:

$ dactyl_build --pages

By default, the resulting HTML pages are written to a folder called out/ in the current working directory. You can specify a different output path in the config file or by using the -o parameter.

Building PDF

Dactyl generates PDFs by making temporary HTML files and running Prince. Use the --pdf command to generate a PDF. Dactyl tries to come up with a sensible output filename by default, or you can provide one (which must end in .pdf):

$ dactyl_build --pages --pdf MyGuide.pdf

Advanced Usage

Dactyl is intended to be used with a config file containing a list of pages to parse. Pages are grouped into “targets” that represent a group of documents to be built together; a page can belong to multiple targets, and can even contain conditional syntax so that it builds slightly different depending on the target in question. Targets and pages can also use different templates from each other, and pages can inherit semi-arbitrary key/value pairs from the targets.

For more information on configuration, see the default-config.yml and the examples folder.

The input pages in the config file should be specified relative to the content_path, which is content/ by default. You can also specify a URL to pull in a markdown file from a remote source, but if you do, Dactyl won’t run any pre-processing on it.

For a full list of Dactyl options, use the -h parameter.

Specifying a Config File

By default, Dactyl looks for a config file named dactyl-config.yml in the current working directory. You can specify an alternate config file with the -c or --config parameter:

$ dactyl_build -c path/to/alt-config.yml

For more information on configuration, see the default-config.yml and the examples folder.

Specifying a Target

If your config file contains more than one target, Dactyl builds the first one by default. You can specify a different target by passing its name value with the -t parameter:

$ dactyl_build -t non-default-target

Copying Static Files

If your content or templates require certain static files (e.g. JavaScript, CSS, and images) to display properly, you can add the -s parameter to copy the files into the output directory. By default, Dactyl assumes that templates have static files in the assets/ folder and documents have static files in the content/static/ folder. Both of these paths are configurable. You can combine this flag with other flags, e.g.:

$ dactyl_build -st non-default-target
# Builds non-default target and copies static files to the output dir

Listing Available Targets

If you have a lot of targets, it can be hard to remember what the short names for each are. If you provide the -l flag, Dactyl will list available targets and then quit without doing anything:

$ dactyl_build -l
tests       Dactyl Test Suite
rc-install      Ripple Connect v2.6.3 Installation Guide
kc-rt-faq       Ripple Trade Migration FAQ

Githubify Mode

This mode runs the preprocessor only, so you can generate Markdown files that are more likely to display properly in conventional Markdown parsers (like the one built into GitHub). Use the -g flag followed by a doc page (relative to the configured content dir):

$ dactyl_build -g

Style Checking

The style checker is experimental. It reads lists of discouraged words and phrases from the word_substitutions_file and phrase_substitutions_file paths (respectively) in the config. For each such word or phrase that appears in the output HTML (excluding code, pre, and tt elements), it counts and prints a violation, suggesting a replacement based on the word/phrase file.

The style checker re-generates HTML in-memory (never writing it out). It uses the first target in the config file unless you specify another target with -t.

Example usage:

$ dactyl_style_checker -t rippledevportal
Style Checker - checking all pages in target rippledevportal
Found 6 issues:
Page: Gateway Guide
   Discouraged phrase: in order to (1 instances); suggest 'to' instead.
   Discouraged phrase: and/or (1 instances); suggest '__ or __ or both' instead.
   Discouraged word: feasible (1 instances); suggest 'can be done, workable' instead.
   Discouraged phrase: in an effort to (1 instances); suggest 'to' instead.
   Discouraged phrase: comply with (1 instances); suggest 'follow' instead.
Page: Amendments
   Discouraged phrase: limited number (1 instances); suggest 'limits' instead.

You can add an exemption to a specific style rule with an HTML comment. The exemption applies to the whole output (HTML) file in which it appears.

Maybe the word "will" is a discouraged word, but you really want to use it here without flagging it as a violation? Adding a comment like this <!-- STYLE_OVERRIDE: will --> makes it so.


Many parts of Dactyl are configurable. An advanced setup would probably have the following folders in your directory structure:

./                      # Top-level dir; this is where you run dactyl_*
./dactyl-config.yml     # Default config file name
./content               # Dir containing your .md source files
---------/*/*.md        # You can sort .md files into subdirs if you like
---------/static/*      # Static images referencd in your .md files
./templates/template-*.html # Custom HTML Templates
./assets                # Directory for static files referenced by templates
./out                   # Directory where output gets generated. Can be deleted

(All of these paths can be configured.)


A target represents a group of pages, which can be built together or concatenated into a single PDF. You should have at least one target defined in the targets array of your Dactyl config file. A target definition should consist of a short name (used to specify the target in the commandline and elsewhere in the config file) and a human-readable display_name (used mostly by templates but also when listing targets on the commandline).

A simple target definition:

    -   name: kc-rt-faq
        display_name: Ripple Trade Migration FAQ

In addition to name and display_name, a target definition can contain the following fields:






Names of filters to apply to all pages in this target.



Mapping of image paths to replacement paths that should be used when building this target. (Use this, for example, to provide absolute paths to images uploaded to a CDN or CMS.)



Same as image_subs, but the keys are regular expressions and the patterns can contain backreferences to matched subgroups (e.g. \\1 for the first parenthetical group).


Arbitrary key-values to be inherited by all pages in this target. (You can use this for pre-processing or in templates.) The following field names cannot be used: name, display_name, image_subs, filters, and pages.


Each page represents one HTML file in your output. A page can belong to one or more targets. When building a target, all the pages belonging to that target are built in the order they appear in the pages array of your Dactyl config file.

Example of a pages definition with two files:

    -   name: RippleAPI
        category: References
        html: reference-rippleapi.html
            - remove_doctoc
            - add_version
            - local

    -   name: rippled
        category: References
        html: reference-rippled.html
            - local

Each individual page definition can have the following fields:






The filename where this file should be written in the output directory.



The short names of the targets that should include this page.



(Optional) Human-readable display name for this page. If omitted but md is provided, Dactyl tries to guess the right file name by looking at the first two lines of the md source file.



(Optional) The markdown filename to parse to generate this page, relative to the content_path in your config. If this is not provided, the source file is assumed to be empty. (You might do that if you use a nonstandard template for this page.)



(Optional) The name of a category to group this page into. This is used by Dactyl’s built-in templates to organize the table of contents.



(Optional) The filename of a custom Jinja HTML template to use when building this page for HTML, relative to the template_path in your config.



(Optional) The filename of a custom Jinja HTML template to use when building this page for PDF, relative to the template_path in your config.

(Short names of targets)


(Optional) If provided, use these values to replace links that would go to this file when building the specified targets. Use this if the page can’t be accessed via its normal .html filename in some situations.


Additional arbitrary key-value pairs as desired. These values can be used by templates or pre-processing.


Dactyl supports extended Markdown syntax with the Python-Markdown Extra module. This correctly parses most GitHub-Flavored Markdown syntax (such as tables and fenced code blocks) as well as a few other features.


Dactyl pre-processes Markdown files by treating them as Jinja Templates, so you can use Jinja’s templating syntax to do advanced stuff like include other files or pull in variables from the config or commandline. Dactyl passes the following fields to Markdown files when it pre-processes them:




The target definition of the current target.


The array of page definitions in the current target.


The definition of the page currently being rendered.

Adding Variables from the Commandline

You can pass in a JSON or YAML-formatted list of variables using --vars commandline switch. Any such variables get added as fields of target and inherited by currentpage in any case where currentpage does not already have the same variable name set. For example:

$ cat md/
Myvar is: '{{ target.myvar }}'

$ dactyl_build --vars '{"myvar":"foo"}'
rendering pages...
writing to file: out/index.html...
Preparing page
reading markdown from file:
... parsing markdown...
... modifying links for target: default
... re-rendering HTML from soup...
writing to file: out/test_vars.html...
done rendering
copying static pages...

$ cat out/test_vars.html | grep Myvar
<p>Myvar is: 'foo'</p></main>

If argument to --vars ends in .yaml or .json, Dactyl treats the argument as a filename and opens it as a YAML file. (YAML is a superset of JSON, so this works for JSON files.) Otherwise, Dactyl treats the argument as a YAML/JSON object directly. Be sure that the argument is quoted and escaped as necessary based on the commandline shell you use.

You cannot set the following reserved keys:

  • name

  • display_name (Instead, use the --title argument to set the display name of the target on the commandline.)

  • filters

  • image_subs

  • image_re_subs

  • pages


Furthermore, Dactyl supports additional custom post-processing through the use of filters. Filters can operate on the markdown (after it’s been pre-processed), on the raw HTML (after it’s been parsed), or on a BeautifulSoup object representing the output HTML. Dactyl comes with several filters, which you can enable in your config file. Support for user-defined filters is planned but not yet implemented.

See the examples for examples of how to do many of these things.


Dactyl provides the following information to templates, which you can access with Jinja’s templating syntax (e.g. {{ target.display_name }}):




The target definition of the current target.


The array of page definitions in the current target. Use this to generate navigation across pages. (The default templates don’t do this, but you should.)


The definition of the page currently being rendered.


An array of categories that are used by at least one page in this target.


The parsed HTML content of the page currently being rendered.


The current date as of rendering, in the format “Monthname Day, Year”


A table of contents generated from the current page’s headers. Wrap this in a <ul> element.

Project details

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

dactyl-0.3.0.tar.gz (35.1 kB view hashes)

Uploaded Source

Built Distribution

dactyl-0.3.0-py2.py3-none-any.whl (42.8 kB view hashes)

Uploaded Python 2 Python 3

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page