Customizing input and output

By default, frontmatter reads and writes YAML metadata. But maybe you don’t like YAML. Maybe enjoy writing metadata in JSON, or TOML, or some other exotic markup not yet invented. For this, there are handlers.

This module includes handlers for YAML, JSON and TOML, as well as a BaseHandler that outlines the basic API and can be subclassed to deal with new formats.

Handlers

Handlers do most of the underlying work parsing and exporting front matter. When you call frontmatter.loads, frontmatter first needs to figure out the best handler for the format you’re using (YAML, JSON, TOML, etc), then call methods to read or write metadata.

A handler needs to do four things:

  • detect whether it can parse the given piece of text
  • split front matter from content, returning both as a two-tuple
  • parse front matter into a Python dictionary
  • export a dictionary back into text

An example:

Calling frontmatter.load (or loads) with the handler argument tells frontmatter which handler to use. The handler instance gets saved as an attribute on the returned post object. By default, calling frontmatter.dumps on the post will use the attached handler.

>>> import frontmatter
>>> from frontmatter.default_handlers import YAMLHandler, TOMLHandler
>>> post = frontmatter.load('tests/hello-toml.markdown', handler=TOMLHandler())
>>> post.handler 
<frontmatter.default_handlers.TOMLHandler object at 0x...>

>>> print(frontmatter.dumps(post)) 
+++
test = "tester"
something = "else"
author = "bob"
+++

Title
=====

title2
------

Hello.

Just need three dashes
---

And this shouldn't break.

Passing a new handler to frontmatter.dumps (or dump) changes the export format:

>>> print(frontmatter.dumps(post, handler=YAMLHandler())) 
---
author: bob
something: else
test: tester
---

Title
=====

title2
------

Hello.

Just need three dashes
---

And this shouldn't break.

Changing the attached handler on a post has the same effect. Setting handler to None will default the post back to YAMLHandler. These three variations will produce the same export:

# set YAML format when dumping, but the old handler attached
>>> t1 = frontmatter.dumps(post, handler=YAMLHandler())

# set a new handler, changing all future exports
>>> post.handler = YAMLHandler()
>>> t2 = frontmatter.dumps(post)

# remove handler, defaulting back to YAML
>>> post.handler = None
>>> t3 = frontmatter.dumps(post)

>>> t1 == t2 == t3
True

All handlers use the interface defined on BaseHandler. Each handler needs to know how to:

  • split metadata and content, based on a boundary pattern (handler.split)
  • parse plain text metadata into a Python dictionary (handler.load)
  • export a dictionary back into plain text (handler.export)
class frontmatter.default_handlers.BaseHandler(fm_boundary=None, start_delimiter=None, end_delimiter=None)

BaseHandler lays out all the steps to detecting, splitting, parsing and exporting front matter metadata.

All default handlers are subclassed from BaseHandler.

detect(text)

Decide whether this handler can parse the given text, and return True or False.

Note that this is not called when passing a handler instance to frontmatter.load or loads.

export(metadata, **kwargs)

Turn metadata back into text

load(fm)

Parse frontmatter and return a dict

split(text)

Split text into frontmatter and content

class frontmatter.default_handlers.YAMLHandler(fm_boundary=None, start_delimiter=None, end_delimiter=None)

Load and export YAML metadata. By default, this handler uses YAML’s “safe” mode, though it’s possible to override that.

class frontmatter.default_handlers.JSONHandler(fm_boundary=None, start_delimiter=None, end_delimiter=None)

Load and export JSON metadata.

Note that changing START_DELIMITER or END_DELIMITER may break JSON parsing.

class frontmatter.default_handlers.TOMLHandler(fm_boundary=None, start_delimiter=None, end_delimiter=None)

Load and export TOML metadata.

By default, split based on +++.