# containers URL: /api/parsing/containers/ Section: parsing -------------------------------------------------------------------------------- containers - Patitas window.BENGAL_THEME_DEFAULTS = { appearance: 'light', palette: 'brown-bengal' }; window.Bengal = window.Bengal || {}; window.Bengal.enhanceBaseUrl = '/patitas/assets/js/enhancements'; window.Bengal.watchDom = true; window.Bengal.debug = false; window.Bengal.enhanceUrls = { 'toc': '/patitas/assets/js/enhancements/toc.632a9783.js', 'docs-nav': '/patitas/assets/js/enhancements/docs-nav.57e4b129.js', 'tabs': '/patitas/assets/js/enhancements/tabs.aac9e817.js', 'lightbox': '/patitas/assets/js/enhancements/lightbox.1ca22aa1.js', 'interactive': '/patitas/assets/js/enhancements/interactive.fc077855.js', 'mobile-nav': '/patitas/assets/js/enhancements/mobile-nav.d991657f.js', 'action-bar': '/patitas/assets/js/enhancements/action-bar.d62417f4.js', 'copy-link': '/patitas/assets/js/enhancements/copy-link.7d9a5c29.js', 'data-table': '/patitas/assets/js/enhancements/data-table.1f5bc1eb.js', 'lazy-loaders': '/patitas/assets/js/enhancements/lazy-loaders.a5c38245.js', 'holo': '/patitas/assets/js/enhancements/holo.ee13c841.js', 'link-previews': '/patitas/assets/js/enhancements/link-previews.8d906535.js' }; (function () { try { var defaults = window.BENGAL_THEME_DEFAULTS || { appearance: 'system', palette: '' }; var defaultAppearance = defaults.appearance; if (defaultAppearance === 'system') { defaultAppearance = (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) ? 'dark' : 'light'; } var storedTheme = localStorage.getItem('bengal-theme'); var storedPalette = localStorage.getItem('bengal-palette'); var theme = storedTheme ? (storedTheme === 'system' ? defaultAppearance : storedTheme) : defaultAppearance; var palette = storedPalette ?? defaults.palette; document.documentElement.setAttribute('data-theme', theme); if (palette) { document.documentElement.setAttribute('data-palette', palette); } } catch (e) { document.documentElement.setAttribute('data-theme', 'light'); } })(); { "prerender": [ { "where": { "and": [ { "href_matches": "/docs/*" }, { "not": { "selector_matches": "[data-external], [target=_blank], .external" } } ] }, "eagerness": "conservative" } ], "prefetch": [ { "where": { "and": [ { "href_matches": "/*" }, { "not": { "selector_matches": "[data-external], [target=_blank], .external" } } ] }, "eagerness": "conservative" } ] } Skip to main content Magnifying Glass ESC Recent Clear Magnifying Glass No results for "" Start typing to search... ↑↓ Navigate ↵ Open ESC Close Powered by Lunr ฅᨐฅ DocumentationArrow ClockwiseGet StartedCodeSyntaxDirectivesStarburstExtendingBookmarkReferenceInfoAboutTroubleshootingReleasesDevGitHubPatitas API Reference Magnifying Glass Search ⌘K Palette Appearance Chevron Down Mode Monitor System Sun Light Moon Dark Palette Snow Lynx Brown Bengal Silver Bengal Charcoal Bengal Blue Bengal List ฅᨐฅ Magnifying Glass Search X Close Documentation Caret Down Arrow Clockwise Get Started Code Syntax Directives Starburst Extending Bookmark Reference Info About Troubleshooting Releases Dev Caret Down GitHub Patitas API Reference Palette Appearance Chevron Down Mode Monitor System Sun Light Moon Dark Palette Snow Lynx Brown Bengal Silver Bengal Charcoal Bengal Blue Bengal Patitas API Reference Caret Right Directives Caret Right Builtins admonition container dropdown tabs contracts decorator options protocol registry Caret Right Lexer Caret Right Classifiers directive fence footnote heading html link_ref list quote thematic Caret Right Scanners block directive fence html core modes Caret Right Parsing Caret Right Blocks Caret Right List blank_line indent item_blocks marker mixin nested trace types core directive footnote table Caret Right Inline core emphasis links match_registry special tokens charsets containers token_nav Caret Right Plugins autolinks footnotes math strikethrough table task_lists Caret Right Renderers html Caret Right Roles Caret Right Builtins formatting icons math reference protocol registry Caret Right Utils hashing logger text errors highlighting icons location nodes parser patitas protocols stringbuilder tokens Patitas API ReferenceParsing ᗢ Caret Down Link Copy URL External Open LLM text Copy Copy LLM text Share with AI Ask Claude Ask ChatGPT Ask Gemini Ask Copilot Module parsing.containers Container Stack Architecture for CommonMark Parsing. This module implements a Container Stack for managing nested block-level containers during Markdown parsing. The stack provides: Explicit indent ownership - Each container "claims" an indent range Automatic state propagation - Looseness propagates upward on pop Centralized indent queries - find_owner() replaces scattered logic Usage: stack = ContainerStack() # Initializes with DOCUMENT frame # Push a list container stack.push(ContainerFrame( container_type=ContainerType.LIST, start_indent=0, content_indent=2, )) # Find owner for a given indent owner, depth = stack.find_owner(4) # Pop and propagate state frame = stack.pop() 3Classes Classes ContainerType 0 ▼ Types of block-level containers in CommonMark. Types of block-level containers in CommonMark. ContainerFrame 14 ▼ A frame on the container stack representing a parsing context. Each container "claims" an indent r… A frame on the container stack representing a parsing context. Each container "claims" an indent range. Tokens are routed to the deepest container that claims their indent. Attributes Name Type Description container_type ContainerType The type of container (LIST, LIST_ITEM, etc.) start_indent int Where this container started (marker position) content_indent int Minimum indent for content continuation marker_width int Width of the marker (e.g., 2 for "- ") max_sibling_indent int For lists, marker siblings can appear at start_indent to start_indent+3 is_loose bool Whether the container has blank lines between content saw_blank_line bool Whether a blank line was seen in this container ordered bool For lists, whether the list is ordered bullet_char str For unordered lists, the bullet character start_number int For ordered lists, the starting number Methods owns_content 1 bool ▼ Does this container own content at this indent level? def owns_content(self, indent: int) -> bool Parameters Name Type Description indent — The indent level to check Returns bool True if content at this indent belongs to this container owns_marker 1 bool ▼ Could a list marker at this indent be a sibling in this container? Only valid … def owns_marker(self, indent: int) -> bool Could a list marker at this indent be a sibling in this container? Only valid for LIST containers. Parameters Name Type Description indent — The indent level of the marker Returns bool True if a marker at this indent is a sibling item is_nested_marker 1 bool ▼ Would a marker at this indent start a nested list? def is_nested_marker(self, indent: int) -> bool Parameters Name Type Description indent — The indent level of the marker Returns bool True if a marker at this indent starts a nested list Internal Methods 1 ▼ __post_init__ 0 ▼ Set default max_sibling_indent if not provided. def __post_init__(self) -> None ContainerStack 13 ▼ Manages the stack of active containers during parsing. Invariant: stack[0] is always DOCUMENT, sta… Manages the stack of active containers during parsing. Invariant: stack[0] is always DOCUMENT, stack[-1] is innermost container. Usage: stack = ContainerStack() # Initializes with DOCUMENT frame stack.push(frame) # Push new container stack.pop() # Pop and propagate state stack.find_owner(indent) # Find container owning this indent Attributes Name Type Description _stack list[ContainerFrame] — Methods push 1 ▼ Push a new container onto the stack. def push(self, frame: ContainerFrame) -> None Parameters Name Type Description frame — The container frame to push pop 0 ContainerFrame ▼ Pop the innermost container. Propagates state (looseness, blank lines) to pare… def pop(self) -> ContainerFrame Pop the innermost container. Propagates state (looseness, blank lines) to parent if applicable. When popping a LIST_ITEM with blank lines, propagates to parent LIST Note: For blank lines BETWEEN items (sibling separation), use mark_parent_list_loose() directly instead of relying on propagation. This propagation handles blank lines WITHIN item content. Note: Nested LIST does NOT propagate to parent LIST_ITEM, as nested list looseness should not affect the outer list's tightness. Returns ContainerFrame The popped container frame current 0 ContainerFrame ▼ Get the innermost container. def current(self) -> ContainerFrame Returns ContainerFrame The current (innermost) container frame depth 0 int ▼ Current nesting depth (document = 0). def depth(self) -> int Returns int The number of containers above DOCUMENT find_owner 1 tuple[ContainerFrame, in… ▼ Find which container owns content at this indent. Walks from innermost to oute… def find_owner(self, indent: int) -> tuple[ContainerFrame, int] Find which container owns content at this indent. Walks from innermost to outermost, returns first container that claims the indent. Parameters Name Type Description indent — The indent level to check Returns tuple[ContainerFrame, int] (owner_frame, stack_index) - the frame and its position in stack find_sibling_list 1 tuple[ContainerFrame, in… ▼ Find a list container where a marker at this indent would be a sibling. def find_sibling_list(self, marker_indent: int) -> tuple[ContainerFrame, int] | None Parameters Name Type Description marker_indent — The indent level of the marker Returns tuple[ContainerFrame, int] | None (frame, index) if found, None if marker starts new list at document level pop_until 1 list[ContainerFrame] ▼ Pop containers until stack has target_index + 1 elements. def pop_until(self, target_index: int) -> list[ContainerFrame] Parameters Name Type Description target_index — The index to stop at (inclusive) Returns list[ContainerFrame] List of popped frames (innermost first) mark_loose 0 ▼ Mark current container as loose (saw blank line with content after). def mark_loose(self) -> None mark_blank_line 0 ▼ Mark that a blank line was seen in current container. def mark_blank_line(self) -> None mark_parent_list_loose 0 ▼ Mark the parent LIST container as loose. Called when a blank line between sibl… def mark_parent_list_loose(self) -> None Mark the parent LIST container as loose. Called when a blank line between sibling items is detected. The current frame is LIST_ITEM, and the parent should be LIST. update_content_indent 1 ▼ Update the current container's content_indent to the actual value. Called when… def update_content_indent(self, actual_content_indent: int) -> None Update the current container's content_indent to the actual value. Called when the first content line is parsed and we know the actual column position where content starts. This allows find_owner() to use the correct indent for subsequent content. Parameters Name Type Description actual_content_indent — The actual content indent from first line Internal Methods 1 ▼ __post_init__ 0 ▼ Initialize with DOCUMENT frame. def __post_init__(self) -> None ← Previous charsets Next → parsing List © 2026 Patitas built in ᓚᘏᗢ { "linkPreviews": { "enabled": true, "hoverDelay": 200, "hideDelay": 150, "showSection": true, "showReadingTime": true, "showWordCount": true, "showDate": true, "showTags": true, "maxTags": 3, "includeSelectors": [".prose"], "excludeSelectors": ["nav", ".toc", ".breadcrumb", ".pagination", ".card", "[class*='-card']", ".tab-nav", "[class*='-widget']", ".child-items", ".content-tiles"], "allowedHosts": [], "allowedSchemes": ["https"], "hostFailureThreshold": 3 } } window.BENGAL_LAZY_ASSETS = { tabulator: '/patitas/assets/js/tabulator.min.js', dataTable: '/patitas/assets/js/data-table.js', mermaidToolbar: '/patitas/assets/js/mermaid-toolbar.9de5abba.js', mermaidTheme: '/patitas/assets/js/mermaid-theme.344822c5.js', graphMinimap: '/patitas/assets/js/graph-minimap.ff04e939.js', graphContextual: '/patitas/assets/js/graph-contextual.355458ba.js' }; window.BENGAL_ICONS = { close: '/patitas/assets/icons/close.911d4fe1.svg', enlarge: '/patitas/assets/icons/enlarge.652035e5.svg', copy: '/patitas/assets/icons/copy.3d56e945.svg', 'download-svg': '/patitas/assets/icons/download.04f07e1b.svg', 'download-png': '/patitas/assets/icons/image.c34dfd40.svg', 'zoom-in': '/patitas/assets/icons/zoom-in.237b4a83.svg', 'zoom-out': '/patitas/assets/icons/zoom-out.38857c77.svg', reset: '/patitas/assets/icons/reset.d26dba29.svg' }; Arrow Up -------------------------------------------------------------------------------- Metadata: - Word Count: 1528 - Reading Time: 8 minutes