Markdown File Wrapper

pymdtools.mdfile provides MarkdownContent, a stateful wrapper for editable Markdown files. It combines the text-file behavior of pymdtools.filetools.FileContent with Markdown-specific helpers from pymdtools.instruction and pymdtools.normalize.

Common Usage

Edit variables and titles in a Markdown document:

from pymdtools.mdfile import MarkdownContent

md = MarkdownContent("README.md")
md["project"] = "pymdtools"
md.title = "Project README"
md.process_tags()
md.write()

Use process_tags when include files, include refs, and variables must be resolved back into the in-memory content before writing.

Public API

pymdtools.mdfile

High-level wrapper for editable Markdown files.

This module provides MarkdownContent, a convenience object that combines the generic text-file behavior from pymdtools.filetools.FileContent with Markdown-specific helpers from pymdtools.instruction and pymdtools.normalize.

The wrapper is intentionally stateful. Methods operate on the inherited in-memory content buffer, and FileContent.write() persists that buffer to disk. Any method that assigns to content also marks the object as needing a save through the inherited dirty-flag behavior.

Public API

MarkdownContent

File-backed Markdown buffer with helpers for variables, titles, table of contents, include-file directives, beautification, and include processing.

Supported Markdown helpers

Variables:

Mapping-style access to <!-- var(NAME)="value" --> declarations via md["NAME"], md["NAME"] = value, del md["NAME"], keys(), values() and items().

Title:

title reads, replaces, or inserts the first level-1 Markdown heading. Both ATX and Setext heading styles are handled by pymdtools.instruction.

Table of contents:

toc renders the current Markdown through Python-Markdown’s toc extension and returns the generated HTML fragment.

Include files:

set_include_file and del_include_file manage <!-- include-file(...) --> directives.

Processing:

process_tags resolves include files, include variables, and include refs back into the current buffer.

Design notes

  • Filesystem behavior, backups, text validation, and encoding detection are delegated to pymdtools.filetools.FileContent.

  • Markdown parsing and marker manipulation are delegated to pymdtools.instruction.

  • Formatting normalization is delegated to pymdtools.normalize.

  • content=None is treated as an empty Markdown document for convenience methods, while preserving the inherited unloaded-buffer representation.

Usage example

from pymdtools.mdfile import MarkdownContent

md = MarkdownContent("README.md")
md["author"] = "Ada"
md.title = "Project README"
md.process_tags()
md.write()
class pymdtools.mdfile.MarkdownContent(filename: str | PathLike[str] | Path | None = None, content: str | None = None, backup: bool = True, encoding: str | None = None, **kwargs: Any)

Bases: FileContent

Text-file wrapper specialized for Markdown content.

MarkdownContent inherits path, read, write, backup, and dirty-flag behavior from pymdtools.filetools.FileContent. It adds Markdown helpers while keeping all edits in the inherited content buffer.

Variables declared in the Markdown text can be accessed like a mapping:

md = MarkdownContent(content='<!-- var(author)="Ada" -->\n# Doc')
assert md["author"] == "Ada"
md["author"] = "Grace"

content=None is treated as an empty Markdown document by convenience methods. This makes MarkdownContent() usable as an initially empty buffer while still preserving the inherited FileContent representation of unloaded content.

Keyword arguments are stored and reused by process_tags(). They are primarily forwarded to pymdtools.instruction.include_files_to_md_text() and related include-file lookup helpers. Two options are interpreted by this class:

  • search_folders: optional iterable of folders scanned for refs in addition to refs found around full_filename;

  • refs_depth: recursion depth used when scanning search_folders.

Parameters:
  • filename – Optional file path. If it points to an existing file and content is None, the file is read immediately.

  • content – Optional Markdown text to use as the initial buffer. Passing a string marks the inherited object as needing a save.

  • backup – Whether inherited writes should create backups before overwriting existing files.

  • encoding – Encoding used when reading an existing file. None keeps the automatic detection behavior provided by FileContent.

  • **kwargs – Options reused by include processing, such as search_folders, relative_paths, include_cwd, nb_up_path, error_if_no_file, render_mode and refs_depth.

Raises:
  • OSError – Propagated from file reading when filename points to a file.

  • ValueError – Propagated from lower-level path or text validation helpers.

  • TypeError – If content is not str or None.

beautify() str

Normalize Markdown formatting in the current buffer.

The operation delegates to pymdtools.normalize.md_beautifier(), stores the normalized text back into content, and returns it.

Returns:

The normalized Markdown text.

del_include_file(filename: str) None

Remove include-file directives that reference filename.

Parameters:

filename – Referenced file name to remove.

Raises:
  • TypeError – If the current content or filename is invalid.

  • ValueError – If filename is empty.

has_key(k: str) bool

Return whether a Markdown variable exists.

This method is kept for backward compatibility with older callers. Prefer key in markdown_content in new code.

Parameters:

k – Variable name to test.

items() ItemsView[str, str]

Return a dynamic view of (name, value) variable pairs.

The variable cache is refreshed before the view is returned.

keys() KeysView[str]

Return a dynamic view of declared variable names.

The variable cache is refreshed before the view is returned.

process_tags() str

Resolve include-related directives in the current Markdown buffer.

Processing happens in this order:

  1. include-file directives are replaced by file content.

  2. begin-var/end-var blocks are filled from local variable declarations.

  3. begin-include/end-include blocks are filled from refs found around the current file and optional search_folders.

The resulting text is stored back into content and returned.

Returns:

The processed Markdown text.

Raises:
  • OSError – If an included file or scanned ref file cannot be read.

  • KeyError – If a variable or include ref is requested but missing and the corresponding lower-level helper is configured to fail.

  • ValueError – If include markers are malformed.

set_include_file(filename: str) None

Ensure an include-file directive exists in the Markdown text.

If the directive already exists, the content is left unchanged. If not, the directive is inserted according to pymdtools.instruction.ensure_include_file_in_md_text().

Parameters:

filename – Referenced file name as it should appear in <!-- include-file(filename) -->.

Raises:
  • TypeError – If the current content or filename is invalid.

  • ValueError – If filename is empty.

property title: str | None

Return the first level-1 Markdown title, or None when absent.

Both ATX (# Title) and Setext (Title followed by ===) styles are supported by the lower-level instruction helper.

property toc: str

Return an HTML table of contents generated from the current Markdown.

The property uses Python-Markdown with the toc extension and returns the extension-generated HTML fragment. Empty content returns an empty string.

values() ValuesView[str]

Return a dynamic view of declared variable values.

Values are interpreted strings; escape sequences in variable declarations have already been decoded by instruction.