Configuration¶
FLM has a flexible configuration system. Configuration controls parser settings, renderer options, feature selection and options, and workflow behavior. Configuration can come from multiple sources that are merged together in a well-defined order.
Configuration Hierarchy¶
Configuration is merged from several sources. When the same setting appears in multiple sources, the highest priority source wins. From highest to lowest priority:
CLI flags (
-f,-w, etc.) and--inline-configYAML front matter in the input file
Configuration file (
flmconfig.yamlor specified with-C)Inline default config (
--inline-default-config)Built-in defaults
Configuration File Discovery¶
When no explicit configuration file is given with -C, FLM looks for
configuration files in the current directory. It tries the following name
patterns, and all matching files are loaded and merged together (more
specific patterns take higher priority):
flmconfig+WORKFLOW.FORMAT.yaml(or.yml)flmconfig+WORKFLOW.yaml(or.yml)flmconfig.FORMAT.yaml(or.yml)flmconfig.yaml(or.yml)
Here, WORKFLOW and FORMAT are replaced by the selected workflow and
output format names. For each pattern, if a .yaml file exists it is used;
otherwise a .yml file is tried.
This allows you to maintain a base flmconfig.yaml with shared settings and
override specific options in format- or workflow-specific files (e.g.,
flmconfig.html.yaml).
Configuration Structure¶
The top-level structure of an FLM configuration file is:
flm:
parsing:
# Parser settings
...
features:
# Feature selection and per-feature configuration
...
renderer:
# Per-format renderer options
...
workflow:
# Workflow-specific configuration
...
# additional configuration possible: default format, default workflow,
# template settings... (cf. below)
You can also include top-level metadata such as a document title:
title: 'My Document Title'
flm:
...
Schema Validation¶
A JSON schema for FLM configuration files is available at:
You can use this schema to get autocompletion and validation in your editor.
VS Code: Install the Red Hat YAML
extension and add the following comment as the first line of your
flmconfig.yaml:
# yaml-language-server: $schema=https://flm-core.readthedocs.io/en/latest/flm-config-json-schema.json
flm:
parsing:
dollar_inline_math_mode: true
features:
headings: {}
...
You can also validate your configuration from the command line with
--validate-config-only:
flm myfile.flm --validate-config-only
Or print the full JSON schema with --print-config-json-schema:
flm myfile.flm --print-config-json-schema
YAML Front Matter¶
FLM documents can include YAML front matter at the top of the file, delimited
by --- lines. The front matter is merged into the configuration with higher
priority than the flmconfig.yaml file:
---
title: 'My FLM Document'
author: 'John Doe'
date: 'May 1, 2026'
flm:
parsing:
dollar_inline_math_mode: true
features:
endnotes:
categories:
- category_name: footnote
counter_formatter: unicodesuperscript
heading_title: 'Footnotes'
endnote_command: 'footnote'
---
\section{Greeting}
Hello, \emph{world}. Inline math can now also be typeset
as $a$ and $b$.
The $import Directive¶
Use the $import directive to import configuration from external files, URLs,
or Python extension packages:
$import:
- my-flm-config.yaml
flm:
...
The $import target can be:
A relative or absolute file path:
my-flm-config.yamlor/path/to/my/flm-config.yamlA URL:
https://example.com/my/flm-config.yamlA Python package prefixed with
pkg::pkg:flm_citations
When a package name is specified, the package is loaded and its default FLM
configuration is extracted from its flm_default_import_config attribute (a
dictionary or a callable that returns a dictionary).
You can optionally follow the package name with a path to specify
submodules/attributes to read instead of flm_default_import_config. For
example, pkg:mypackage/foo/bar will import the module mypackage and read
the configuration dictionary stored in mypackage.foo.bar.
Multiple imports are specified as a list; they are processed in order. Configuration specified alongside the import is merged on top.
Parser Configuration¶
flm:
parsing:
# Enable/disable comments as in LaTeX, led by '%%'
enable_comments: true
# This string initiates a comment up to the end of
# the line, if comments are enabled. By default we
# require TWO '%' signs to avoid accidental comments
# (e.g., "... is up 10% from ...")
comment_start: '%%'
# Enable/disable math mode with $ signs as in LaTeX
# in addition to \( ...\)
dollar_inline_math_mode: false
# Force parsing of the content in block-level mode
# (paragraphs). Here 'null' means to auto-detect
force_block_level: null
Renderer Configuration¶
Renderer options are specified under the format name within the renderer
key. Only the options for the selected output format are used.
HTML renderer¶
flm:
renderer:
html:
use_link_target_blank: false
html_blocks_joiner: ''
# use 'heading_tags_by_level: null' for defaults
heading_tags_by_level:
1: h1
2: h2
3: h3
4: span
5: span
6: span
inline_heading_add_space: true
Text renderer¶
flm:
renderer:
text:
display_href_urls: true
LaTeX renderer¶
flm:
renderer:
latex:
heading_commands_by_level:
1: "section"
2: "subsection"
3: "subsubsection"
4: "paragraph"
5: "subparagraph"
6: null
Markdown renderer¶
flm:
renderer:
markdown:
use_target_ids: 'github' # or 'anchor' or 'pandoc' or null
Feature Configuration¶
Features are selected and configured under the features key. Each feature
is identified by its name.
Enable a feature with default options (use an empty dict):
flm:
features:
headings: {}
refs: {}
Disable a feature:
flm:
features:
theorems: false
Configure a feature by providing a dict of options:
flm:
features:
endnotes:
categories:
- category_name: footnote
counter_formatter: alph
heading_title: 'Footnotes'
endnote_command: 'footnote'
render_options:
include_headings_at_level: 1
set_headings_target_ids: true
endnotes_heading_title: null
endnotes_heading_level: 1
Here is a more comprehensive example showing several features with their configuration:
flm:
features:
enumeration:
enumeration_environments:
enumerate:
counter_formatter: null # use defaults
itemize:
counter_formatter:
- "\u2022"
- '-'
- "\u25B8"
refs: {}
endnotes:
categories:
- category_name: footnote
counter_formatter: alph
endnote_command: footnote
heading_title: Footnotes
render_options:
include_headings_at_level: 1
set_headings_target_ids: true
floats:
float_types:
- counter_formatter: Roman
float_caption_name: Fig.
float_type: figure
content_handlers: ['includegraphics']
- counter_formatter: Roman
float_caption_name: Tab.
float_type: table
content_handlers: ['cells', 'includegraphics']
defterm: {}
graphics: {}
You can also load features from external packages by using their fully qualified Python module path as the feature name:
flm:
features:
'flm.main.feature_graphics_collection': {}
Some additional configuration options¶
Some additional keys inside the flm: block can help you set a default format, workflow, and template so you don’t have to specify them on the command line. You can also set configuration variables for the templates.
flm:
# ...
default_workflow: 'templatebasedworkflow'
default_format: 'html'
template:
# template to use when rendering html
html: 'simple'
# template to use when rendering latex
latex: 'revtex'
template_config:
html:
simple:
render_header: true
display_toc: true
font:
family: 'Source Serif Pro'
size: '16px'
layout:
content_width: '640px'
style:
extra_css: |
body { background-color: #e7e7f7; }
latex:
simple:
documentclass:
fontsize: '12pt'
preamble:
fonts: |
\usepackage{newtxtext}
\usepackage{newtxmath}
render_toc: true
Per-Format Configuration¶
The built-in defaults include per-format overrides for renderer options and
feature settings. For example, when rendering to text output, the endnotes
counter formatter is automatically set to unicodesuperscript instead of
alph.
You do not usually need to worry about per-format configuration, as the
defaults handle common cases. If you need to customize per-format behavior, you
can use format-specific config files (e.g., flmconfig.html.yaml) or specify
settings in the renderer section for each format.
Extension Packages¶
FLM can be extended with external Python packages that provide additional features, templates, and workflows.
flm-citations¶
Automatically fetch citations from arXiv, DOI cross-references, or bibliography files. Install and import:
pip install flm-citations
$import:
- pkg:flm_citations
bibliography:
- mybibliography.yaml
- anotherbib.json
Citations are organized by prefix:
arxiv:<arXiv ID>— retrieved from the arXiv APIdoi:<DOI>— retrieved from doi.orgmanual:{Manual citation}— uses the text directlybib:key— looks up a key in the specified bibliography files (CSL-JSON or CSL-YAML format)
flm-templates¶
Additional HTML templates and template engines. Install and use:
pip install flm-templates flm-htmlplus
flm mydocument.flm -o output.html -w flm_htmlplus \
-P 'pkg:flm_templates' -t sunset
Try also the template -t oldtextbook.
Writing your own extension packages¶
Extension packages are Python packages that can expose:
A
flm_default_import_configattribute (or callable) for use with the$import: pkg:...directiveA
get_template_path()function for template discoveryCustom feature classes for use in the
featuresconfiguration
See the flm-citations source for an example of how to structure an extension package.
Advanced: Config Merger Directives¶
The configuration merger supports several special directives for advanced use cases:
$importImport configuration from a file, URL, or package. See The $import Directive.
$defaultsPull in default values from lower-priority configuration sources. This is used internally by the default configuration to ensure that user configuration is merged with sensible defaults.
$merge-configMerge configuration into a named item within a list. Useful for modifying a specific item (identified by its
namefield) without replacing the entire list:- $merge-config: name: footnote config: counter_formatter: roman
$remove-itemRemove a named item from a list:
- $remove-item: footnote
$no-mergeMark a dictionary as non-mergeable. When this directive is present, the dictionary replaces any lower-priority value entirely instead of being recursively merged:
heading_tags_by_level: $no-merge: true 1: h2 2: h3