FLM Definitions: flm.flmspecinfo

FLM specification info classes for defining macros, environments, and specials.

This module provides the base classes that specify how parsed LaTeX-like constructs (macros, environments, specials) are finalized after parsing and how they are rendered into output primitives understood by FragmentRenderer objects.

The main classes are:

This module also provides several built-in construct specifications such as FLMSpecInfoConstantValue (for literal character replacements), TextFormatMacro (for \\emph, \\textbf, etc.), and FLMSpecInfoParagraphBreak (for paragraph breaks).

Base FLMSpecInfo class

class flm.flmspecinfo.FLMSpecInfo(*, spec_node_parser_type, arguments_spec_list=None, **kwargs)

Class that specifies how to finalize a given parsed node and how to process it to render into primitives understood by FragmentRenderer objects

delayed_render: bool | Callable[[LatexNode, TypeRenderContext], bool] = False

Whether this node needs to be rendered at the delayed rendering stage, i.e., after a first pass through the document. This is the case, for instance, for \ref commands etc. for which the entire document needs to have been traversed at least once beforehand. See the delayed render mechanism in the documentation for the flmdocument.FLMDocument class.

Set to True or False to determine whether or not the node needs a delayed render. Set to a callable func(node, render_context) -> bool to compute at render time whether the node should be delayed or not.

is_block_level: bool | None = False

If this flag is set to True, then elements of this type are always parsed as separate block-level elements (e.g., a section heading, an enumeration list, etc.)

If this flag is None, then the spec does not commit as to whether the node produces a block-level or inline-level element. It is strongly recommended you then manually set the flm_is_block_level attribute on the node object to True or False, since the default implementation of finalize_node() won’t be able to do it.

is_block_heading: bool = False

If is_block_level=True and this flag is also set to True, then this element introduces a new paragraph. I.e., a block-level/paragraph break is introduced immediately before this item. The present item is itself included along with the non-block-level content that follows to form a new paragraph.

For example, use is_block_heading=True for the node created by a \paragraph{..} call that produces a run-in heading.

is_paragraph_break_marker: bool = False

True if this node’s sole purpose is to split paragraphs. Use this for \n\n breaks or maybe if the user would like to introduce support for \par macros. If is_paragraph_break_marker = True then you must also set is_block_level=True.

allowed_in_standalone_mode: bool = False

Whether or not this node is allowed in standalone mode, i.e., whether or not this node can be rendered independently of any document object.

body_contents_is_block_level: bool | None = None

Applicable only to environment specifications. Specifies whether or not the body contents of the body should be parsed as block-level code or not. By default, environment contents are parsed in the same mode as the surrounding content.

postprocess_parsed_node(node) None

Can be overridden to add additional information to node objects.

You shouldn’t change the standard node structure (arguments/body nodelist/etc), rather, you should add custom properties to store any additional information that is relevant to this node.

You don’t have to return the updated node. The default implementation does nothing.

prepare_delayed_render(node, render_context) None

Called during the first rendering pass for items with delayed_render set to True. This method is called instead of render() so that the node can register itself with document feature managers (e.g., to collect reference targets or footnote content) before the full document has been traversed.

Subclasses must override this method if they set delayed_render=True; the default implementation raises RuntimeError.

This method is never called if delayed_render=False.

Parameters:
render(node, render_context) Any

Produce a rendered representation of the node using the given render context.

Subclasses must override this method to return rendered output appropriate for the active FragmentRenderer. The default implementation raises RuntimeError.

Parameters:
  • node – The parsed LatexNode.

  • render_context – The FLMRenderContext carrying the current fragment renderer and document state.

Returns:

A rendered output value (typically a string in the format produced by the active fragment renderer).

finalize_node(node)

Override this method only if you know what you’re doing!

make_body_parsing_state_delta(token, nodeargd, arg_parsing_state_delta, latex_walker)

Compute the parsing state delta to apply when parsing the body of an environment.

If body_contents_is_block_level is not None, the returned delta chains the parent class’s delta with a FLMParsingStateDeltaSetBlockLevel to enforce the desired block-level mode inside the environment body.

Parameters:
  • token – The opening token of the environment.

  • nodeargd – The parsed arguments so far.

  • arg_parsing_state_delta – The parsing state delta from argument parsing.

  • latex_walker – The FLMLatexWalker instance.

Returns:

A ParsingStateDelta instance (possibly chained).

Convenience base classes

class flm.flmspecinfo.FLMMacroSpecBase(macroname: str, arguments_spec_list=None, **kwargs)

Bases: FLMSpecInfo

Convenience base class for a FLM LaTeX macro specification.

Subclass this to define a new macro. Override render() to produce output, and optionally postprocess_parsed_node() to attach extra information to the parsed node.

Parameters:
  • macroname – The macro name (without the leading backslash).

  • arguments_spec_list – List of argument specifications.

class flm.flmspecinfo.FLMEnvironmentSpecBase(environmentname: str, arguments_spec_list=None, **kwargs)

Bases: FLMSpecInfo

Convenience base class for a FLM LaTeX environment specification.

Subclass this to define a new environment (\begin{name}...\end{name}). Override render() to produce output.

Parameters:
  • environmentname – The environment name.

  • arguments_spec_list – List of argument specifications.

class flm.flmspecinfo.FLMSpecialsSpecBase(specials_chars: str, arguments_spec_list=None, **kwargs)

Bases: FLMSpecInfo

Convenience base class for a FLM LaTeX specials specification.

Specials are character sequences that have a special meaning in FLM, such as ~ (non-breaking space) or \\n\\n (paragraph break).

Parameters:
  • specials_chars – The special character(s) that trigger this specification.

  • arguments_spec_list – List of argument specifications.

Built-in construct specifications

Constant/Literals

class flm.flmspecinfo.FLMSpecInfoConstantValue(value, **kwargs)

Bases: FLMSpecInfo

Render a constant, literal character string.

allowed_in_standalone_mode: bool = True

Whether or not this node is allowed in standalone mode, i.e., whether or not this node can be rendered independently of any document object.

get_flm_doc()
render(node, render_context)
class flm.flmspecinfo.ConstantValueMacro(macroname, **kwargs)

Bases: FLMSpecInfoConstantValue

LaTeX macro specification for a constant/literal value.

class flm.flmspecinfo.ConstantValueSpecials(specials_chars, **kwargs)

Bases: FLMSpecInfoConstantValue

LaTeX speicals specification for the FLMSpecInfoConstantValue specinfo.

Paragraph breaks

class flm.flmspecinfo.FLMSpecInfoParagraphBreak(*, spec_node_parser_type, arguments_spec_list=None, **kwargs)

Bases: FLMSpecInfo

Specification for paragraph break markers (e.g., \n\n or \par). These nodes split content into separate paragraphs. Their render() method raises an error because paragraph breaks are handled structurally by the block decomposition, not by direct rendering.

is_block_level: bool | None = True

If this flag is set to True, then elements of this type are always parsed as separate block-level elements (e.g., a section heading, an enumeration list, etc.)

If this flag is None, then the spec does not commit as to whether the node produces a block-level or inline-level element. It is strongly recommended you then manually set the flm_is_block_level attribute on the node object to True or False, since the default implementation of finalize_node() won’t be able to do it.

is_paragraph_break_marker: bool = True

True if this node’s sole purpose is to split paragraphs. Use this for \n\n breaks or maybe if the user would like to introduce support for \par macros. If is_paragraph_break_marker = True then you must also set is_block_level=True.

allowed_in_standalone_mode: bool = True

Whether or not this node is allowed in standalone mode, i.e., whether or not this node can be rendered independently of any document object.

render(node, render_context)
get_flm_doc()
class flm.flmspecinfo.ParagraphBreakSpecials(specials_chars: str, **kwargs)

Bases: FLMSpecInfoParagraphBreak

class flm.flmspecinfo.ParagraphBreakMacro(macroname: str, **kwargs)

Bases: FLMSpecInfoParagraphBreak

Text formatting

class flm.flmspecinfo.TextFormatMacro(macroname: str, *, text_formats: Sequence[str])

Bases: FLMMacroSpecBase

The argument text_formats is a list of strings, each string is a format name to apply. Format names are inspired from the corresponding canonical LaTeX macros that apply them. They are:

  • textit

  • textbf

  • (possibly more in the future)

allowed_in_standalone_mode: bool = True

Whether or not this node is allowed in standalone mode, i.e., whether or not this node can be rendered independently of any document object.

get_flm_doc()
render(node, render_context)

Render the macro’s text argument with the configured text format(s).

Delegates to render_text_format() on the active fragment renderer.

Parameters:
  • node – The parsed macro node.

  • render_context – The current FLMRenderContext.

Returns:

The rendered output with the text formats applied.

class flm.flmspecinfo.SemanticBlockEnvironment(environmentname: str, *, role: str, annotations: Sequence[str] | None = None)

Bases: FLMEnvironmentSpecBase

The argument role and annotations are passed on to the fragment renderer.

allowed_in_standalone_mode: bool = True

Whether or not this node is allowed in standalone mode, i.e., whether or not this node can be rendered independently of any document object.

is_block_level: bool | None = True

If this flag is set to True, then elements of this type are always parsed as separate block-level elements (e.g., a section heading, an enumeration list, etc.)

If this flag is None, then the spec does not commit as to whether the node produces a block-level or inline-level element. It is strongly recommended you then manually set the flm_is_block_level attribute on the node object to True or False, since the default implementation of finalize_node() won’t be able to do it.

get_flm_doc()
render(node, render_context)

Render the environment body as a semantic block.

First renders the body node list, then wraps it via render_semantic_block() using the configured role and annotations.

Parameters:
  • node – The parsed environment node.

  • render_context – The current FLMRenderContext.

Returns:

The rendered semantic block output.

Error enforcing

class flm.flmspecinfo.FLMSpecInfoError(error_msg: None | str = None, **kwargs)

Bases: FLMSpecInfo

A specification that always raises an error when rendered. Used to explicitly forbid certain macros, environments, or specials in a given context while providing a helpful error message.

Parameters:

error_msg – Custom error message. If None, a default message is generated from the node’s source text.

allowed_in_standalone_mode: bool = True

Whether or not this node is allowed in standalone mode, i.e., whether or not this node can be rendered independently of any document object.

render(node, render_context)
class flm.flmspecinfo.FLMMacroSpecError(macroname: str, **kwargs)

Bases: FLMSpecInfoError

class flm.flmspecinfo.FLMEnvironmentSpecError(environmentname: str, **kwargs)

Bases: FLMSpecInfoError

class flm.flmspecinfo.FLMSpecialsSpecError(specials_chars: str, **kwargs)

Bases: FLMSpecInfoError

Helpers

flm.flmspecinfo.text_arg = LatexArgumentSpec(argname='text', parser='{', parsing_state_delta=FLMParsingStateDeltaSetBlockLevel(is_block_level=False))

A convenience FLMArgumentSpec instance to capture an argument to a macro that is meant to contain FLM text content. The argument itself is parsed as a single LaTeX expression, i.e., a standard mandatory argument given in curly braces or a single LaTeX token.

flm.flmspecinfo.label_arg = LatexArgumentSpec(argname='label', parser=<LatexTackOnInformationFieldMacrosParser>, parsing_state_delta=FLMParsingStateDeltaSetBlockLevel(is_block_level=False))

A convenience FLMArgumentSpec instance to capture any appended \label{} command(s). This can be used, e.g., as the last “argument” of a sectioning command (\section{}), so that the labels are part of the macro call. The argument parser is a pylatexenc.latexnodes.parsers.LatexTackOnInformationFieldMacrosParser instance.

flm.flmspecinfo.helper_collect_labels(node_arg_label, allowed_prefixes, allow_unknown_macros=False) None | Sequence[tuple[str, str]]

Helper function to collect all labels associated with an argument with specification label_arg.

Parses \label{prefix:name} macros from the argument and returns a list of (prefix, name) tuples. Returns None if no label argument was provided.

Parameters:
  • node_arg_label – The parsed argument info for the label argument.

  • allowed_prefixes – A collection of allowed label prefixes (e.g., ('sec', 'eq', 'figure')). A LatexWalkerParseError is raised if a label uses a prefix not in this set.

  • allow_unknown_macros – If True, silently skip non-\label information field macros instead of raising an error.

Returns:

A list of (ref_type, ref_label) tuples, or None if no label was provided.