all2md.ast.visitors

Visitor pattern implementation for AST traversal.

This module provides the visitor pattern base classes for traversing and processing AST nodes. Visitors enable separation of algorithms (like rendering, validation, transformation) from the node structure itself.

The visitor pattern allows for: - Clean separation of concerns - Easy addition of new processing algorithms - Type-safe node processing - Flexible tree traversal strategies

class all2md.ast.visitors.NodeVisitor

Bases: ABC

Abstract base class for AST node visitors.

Subclasses should implement visit_* methods for each node type they want to process. The visitor pattern allows algorithms to be separated from the node structure.

All visit methods should accept a node and return Any (typically None for side-effect visitors, or accumulated results for transforming visitors).

Examples

Simple visitor that counts nodes:

>>> class NodeCounter(NodeVisitor):
...     def __init__(self):
...         self.count = 0
...
...     def generic_visit(self, node):
...         self.count += 1
...         # Visit children if they exist
...         if hasattr(node, 'children'):
...             for child in node.children:
...                 child.accept(self)
...
>>> counter = NodeCounter()
>>> document.accept(counter)
>>> print(counter.count)
abstractmethod visit_document(node: Document) Any

Visit a Document node.

Parameters:

node (Document) – The document node to visit

Returns:

Result of processing this node

Return type:

Any

abstractmethod visit_heading(node: Heading) Any

Visit a Heading node.

Parameters:

node (Heading) – The heading node to visit

Returns:

Result of processing this node

Return type:

Any

abstractmethod visit_paragraph(node: Paragraph) Any

Visit a Paragraph node.

Parameters:

node (Paragraph) – The paragraph node to visit

Returns:

Result of processing this node

Return type:

Any

abstractmethod visit_code_block(node: CodeBlock) Any

Visit a CodeBlock node.

Parameters:

node (CodeBlock) – The code block node to visit

Returns:

Result of processing this node

Return type:

Any

abstractmethod visit_block_quote(node: BlockQuote) Any

Visit a BlockQuote node.

Parameters:

node (BlockQuote) – The block quote node to visit

Returns:

Result of processing this node

Return type:

Any

abstractmethod visit_list(node: List) Any

Visit a List node.

Parameters:

node (List) – The list node to visit

Returns:

Result of processing this node

Return type:

Any

abstractmethod visit_list_item(node: ListItem) Any

Visit a ListItem node.

Parameters:

node (ListItem) – The list item node to visit

Returns:

Result of processing this node

Return type:

Any

abstractmethod visit_table(node: Table) Any

Visit a Table node.

Parameters:

node (Table) – The table node to visit

Returns:

Result of processing this node

Return type:

Any

abstractmethod visit_table_row(node: TableRow) Any

Visit a TableRow node.

Parameters:

node (TableRow) – The table row node to visit

Returns:

Result of processing this node

Return type:

Any

abstractmethod visit_table_cell(node: TableCell) Any

Visit a TableCell node.

Parameters:

node (TableCell) – The table cell node to visit

Returns:

Result of processing this node

Return type:

Any

abstractmethod visit_thematic_break(node: ThematicBreak) Any

Visit a ThematicBreak node.

Parameters:

node (ThematicBreak) – The thematic break node to visit

Returns:

Result of processing this node

Return type:

Any

abstractmethod visit_html_block(node: HTMLBlock) Any

Visit an HTMLBlock node.

Parameters:

node (HTMLBlock) – The HTML block node to visit

Returns:

Result of processing this node

Return type:

Any

abstractmethod visit_comment(node: Comment) Any

Visit a Comment node (block-level).

Parameters:

node (Comment) – The comment block node to visit

Returns:

Result of processing this node

Return type:

Any

abstractmethod visit_text(node: Text) Any

Visit a Text node.

Parameters:

node (Text) – The text node to visit

Returns:

Result of processing this node

Return type:

Any

abstractmethod visit_emphasis(node: Emphasis) Any

Visit an Emphasis node.

Parameters:

node (Emphasis) – The emphasis node to visit

Returns:

Result of processing this node

Return type:

Any

abstractmethod visit_strong(node: Strong) Any

Visit a Strong node.

Parameters:

node (Strong) – The strong node to visit

Returns:

Result of processing this node

Return type:

Any

abstractmethod visit_code(node: Code) Any

Visit a Code node.

Parameters:

node (Code) – The code node to visit

Returns:

Result of processing this node

Return type:

Any

Visit a Link node.

Parameters:

node (Link) – The link node to visit

Returns:

Result of processing this node

Return type:

Any

abstractmethod visit_image(node: Image) Any

Visit an Image node.

Parameters:

node (Image) – The image node to visit

Returns:

Result of processing this node

Return type:

Any

abstractmethod visit_line_break(node: LineBreak) Any

Visit a LineBreak node.

Parameters:

node (LineBreak) – The line break node to visit

Returns:

Result of processing this node

Return type:

Any

abstractmethod visit_strikethrough(node: Strikethrough) Any

Visit a Strikethrough node.

Parameters:

node (Strikethrough) – The strikethrough node to visit

Returns:

Result of processing this node

Return type:

Any

visit_mark(node: Mark) Any

Visit a Mark (highlight) node.

Unlike most visit methods this is concrete rather than abstract so that visitors predating the Mark node (e.g. format renderers that do not have a dedicated highlight syntax) degrade gracefully: the default simply visits the node’s children, emitting their content unwrapped rather than dropping it. Visitors that support highlighting should override this method.

Parameters:

node (Mark) – The mark node to visit

Returns:

Result of processing this node

Return type:

Any

abstractmethod visit_underline(node: Underline) Any

Visit an Underline node.

Parameters:

node (Underline) – The underline node to visit

Returns:

Result of processing this node

Return type:

Any

abstractmethod visit_superscript(node: Superscript) Any

Visit a Superscript node.

Parameters:

node (Superscript) – The superscript node to visit

Returns:

Result of processing this node

Return type:

Any

abstractmethod visit_subscript(node: Subscript) Any

Visit a Subscript node.

Parameters:

node (Subscript) – The subscript node to visit

Returns:

Result of processing this node

Return type:

Any

abstractmethod visit_html_inline(node: HTMLInline) Any

Visit an HTMLInline node.

Parameters:

node (HTMLInline) – The inline HTML node to visit

Returns:

Result of processing this node

Return type:

Any

abstractmethod visit_comment_inline(node: CommentInline) Any

Visit a CommentInline node (inline).

Parameters:

node (CommentInline) – The inline comment node to visit

Returns:

Result of processing this node

Return type:

Any

abstractmethod visit_footnote_reference(node: FootnoteReference) Any

Visit a FootnoteReference node.

Parameters:

node (FootnoteReference) – The footnote reference node to visit

Returns:

Result of processing this node

Return type:

Any

abstractmethod visit_math_inline(node: MathInline) Any

Visit a MathInline node.

Parameters:

node (MathInline) – The inline math node to visit

Returns:

Result of processing this node

Return type:

Any

abstractmethod visit_footnote_definition(node: FootnoteDefinition) Any

Visit a FootnoteDefinition node.

Parameters:

node (FootnoteDefinition) – The footnote definition node to visit

Returns:

Result of processing this node

Return type:

Any

abstractmethod visit_definition_list(node: DefinitionList) Any

Visit a DefinitionList node.

Parameters:

node (DefinitionList) – The definition list node to visit

Returns:

Result of processing this node

Return type:

Any

abstractmethod visit_definition_term(node: DefinitionTerm) Any

Visit a DefinitionTerm node.

Parameters:

node (DefinitionTerm) – The definition term node to visit

Returns:

Result of processing this node

Return type:

Any

abstractmethod visit_definition_description(node: DefinitionDescription) Any

Visit a DefinitionDescription node.

Parameters:

node (DefinitionDescription) – The definition description node to visit

Returns:

Result of processing this node

Return type:

Any

abstractmethod visit_math_block(node: MathBlock) Any

Visit a MathBlock node.

Parameters:

node (MathBlock) – The math block node to visit

Returns:

Result of processing this node

Return type:

Any

generic_visit(node: Node) Any

Fallback visitor for unhandled node types.

This method is called when no specific visit_* method exists. The default implementation does nothing but can be overridden.

Parameters:

node (Node) – The node to visit

Returns:

Result of processing (default: None)

Return type:

Any

class all2md.ast.visitors.ValidationVisitor

Bases: NodeVisitor

Visitor that validates AST structure.

This visitor checks for structural issues in the AST, such as: - Invalid nesting (e.g., block nodes inside inline nodes) - Missing required fields - Invalid field values - Presence of raw HTML content (when disallowed) - Block/inline containment rules (in strict mode) - URL scheme validation (in strict mode)

Parameters:
  • strict (bool, default = True) – Whether to raise errors on validation failures

  • allow_raw_html (bool, default = False) – Whether to allow HTMLBlock and HTMLInline nodes. By default (False), any raw HTML content will trigger a validation error for security. Set to True only when you trust the HTML source and need to preserve raw HTML content. This follows security best practices of default-deny for potentially unsafe content.

Notes

Security Considerations:

Raw HTML in documents can pose security risks (XSS attacks, code injection). This validator defaults to rejecting HTML to enforce security best practices. Only set allow_raw_html=True when: - You trust the document source - HTML will be sanitized before rendering - You’re working in a trusted/non-web context

Examples

Strict validation (rejects HTML by default):
>>> validator = ValidationVisitor(strict=True)
>>> doc.accept(validator)  # Raises ValueError if HTML present
Allow HTML from trusted sources:
>>> validator = ValidationVisitor(strict=True, allow_raw_html=True)
>>> doc.accept(validator)  # Permits HTMLBlock/HTMLInline nodes

Initialize the validator with strictness and HTML policy.

Parameters:
  • strict (bool, default = True) – Whether to raise errors immediately on validation failures

  • allow_raw_html (bool, default = False) – Whether to allow raw HTML nodes (security: default deny)

INLINE_NODES = frozenset({<class 'all2md.ast.nodes.Code'>, <class 'all2md.ast.nodes.Emphasis'>, <class 'all2md.ast.nodes.FootnoteReference'>, <class 'all2md.ast.nodes.HTMLInline'>, <class 'all2md.ast.nodes.Image'>, <class 'all2md.ast.nodes.LineBreak'>, <class 'all2md.ast.nodes.Link'>, <class 'all2md.ast.nodes.Mark'>, <class 'all2md.ast.nodes.MathInline'>, <class 'all2md.ast.nodes.Strikethrough'>, <class 'all2md.ast.nodes.Strong'>, <class 'all2md.ast.nodes.Subscript'>, <class 'all2md.ast.nodes.Superscript'>, <class 'all2md.ast.nodes.Text'>, <class 'all2md.ast.nodes.Underline'>})
BLOCK_NODES = frozenset({<class 'all2md.ast.nodes.BlockQuote'>, <class 'all2md.ast.nodes.CodeBlock'>, <class 'all2md.ast.nodes.DefinitionDescription'>, <class 'all2md.ast.nodes.DefinitionList'>, <class 'all2md.ast.nodes.DefinitionTerm'>, <class 'all2md.ast.nodes.Document'>, <class 'all2md.ast.nodes.FootnoteDefinition'>, <class 'all2md.ast.nodes.HTMLBlock'>, <class 'all2md.ast.nodes.Heading'>, <class 'all2md.ast.nodes.List'>, <class 'all2md.ast.nodes.ListItem'>, <class 'all2md.ast.nodes.MathBlock'>, <class 'all2md.ast.nodes.Paragraph'>, <class 'all2md.ast.nodes.Table'>, <class 'all2md.ast.nodes.TableCell'>, <class 'all2md.ast.nodes.TableRow'>, <class 'all2md.ast.nodes.ThematicBreak'>})
__init__(strict: bool = True, allow_raw_html: bool = False)

Initialize the validator with strictness and HTML policy.

Parameters:
  • strict (bool, default = True) – Whether to raise errors immediately on validation failures

  • allow_raw_html (bool, default = False) – Whether to allow raw HTML nodes (security: default deny)

errors: list[str]
visit_document(node: Document) None

Validate a Document node.

visit_heading(node: Heading) None

Validate a Heading node.

visit_paragraph(node: Paragraph) None

Validate a Paragraph node.

visit_code_block(node: CodeBlock) None

Validate a CodeBlock node.

visit_block_quote(node: BlockQuote) None

Validate a BlockQuote node.

visit_list(node: List) None

Validate a List node.

visit_list_item(node: ListItem) None

Validate a ListItem node.

visit_table(node: Table) None

Validate a Table node.

visit_table_row(node: TableRow) None

Validate a TableRow node.

visit_table_cell(node: TableCell) None

Validate a TableCell node.

visit_thematic_break(node: ThematicBreak) None

Validate a ThematicBreak node.

visit_html_block(node: HTMLBlock) None

Validate an HTMLBlock node.

Checks if raw HTML is allowed based on the allow_raw_html setting.

visit_comment(node: Comment) None

Validate a Comment node (block-level).

Comments are informational and generally safe, but we validate that they have content.

visit_text(node: Text) None

Validate a Text node.

visit_emphasis(node: Emphasis) None

Validate an Emphasis node.

visit_strong(node: Strong) None

Validate a Strong node.

visit_code(node: Code) None

Validate a Code node.

Validate a Link node.

visit_image(node: Image) None

Validate an Image node.

visit_line_break(node: LineBreak) None

Validate a LineBreak node.

visit_strikethrough(node: Strikethrough) None

Validate a Strikethrough node.

visit_mark(node: Mark) None

Validate a Mark (highlight) node.

visit_underline(node: Underline) None

Validate an Underline node.

visit_superscript(node: Superscript) None

Validate a Superscript node.

visit_subscript(node: Subscript) None

Validate a Subscript node.

visit_html_inline(node: HTMLInline) None

Validate an HTMLInline node.

Checks if raw HTML is allowed based on the allow_raw_html setting.

visit_comment_inline(node: CommentInline) None

Validate a CommentInline node (inline).

Comments are informational and generally safe, but we validate that they have content.

visit_footnote_reference(node: FootnoteReference) None

Validate a FootnoteReference node.

visit_math_inline(node: MathInline) None

Validate a MathInline node.

visit_footnote_definition(node: FootnoteDefinition) None

Validate a FootnoteDefinition node.

visit_definition_list(node: DefinitionList) None

Validate a DefinitionList node.

visit_definition_term(node: DefinitionTerm) None

Validate a DefinitionTerm node.

visit_definition_description(node: DefinitionDescription) None

Validate a DefinitionDescription node.

visit_math_block(node: MathBlock) None

Validate a MathBlock node.