# protocol URL: /api/roles/protocol/ Section: roles -------------------------------------------------------------------------------- protocol - 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 ReferenceRoles ᗢ 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 roles.protocol RoleHandler protocol for extensible inline markup. Roles are inline directives using MyST syntax: content Implement the RoleHandler protocol to create custom roles. Thread Safety: Handlers must be stateless. All state should be in the AST node or passed as arguments. Multiple threads may call the same handler instance concurrently. Example: >>> class KbdRole: ... names = ("kbd",) ... ... def parse(self, name, content, location): ... return Role(location, name, content) ... ... def render(self, node, sb): ... sb.append(f'<kbd>{node.content}</kbd>') 3Classes Classes RoleHandler 5 ▼ Protocol for role implementations. Roles are inline directives like {ref}`target` or {kbd}`Ctrl+C`… Protocol for role implementations. Roles are inline directives like target or Ctrl+C. They produce inline AST nodes rather than block nodes. Thread Safety: Handlers must be stateless. All mutable state must be in the AST node or passed as arguments. Multiple threads may call the same handler instance concurrently. Attributes Name Type Description names ClassVar[tuple[str, ...]] Tuple of role names this handler responds to. token_type ClassVar[str] Token type identifier for the AST. Example — ("ref", "doc") for reference roles Methods parse 3 Role ▼ Build the role AST node. Called by the parser when a role is encountered in in… def parse(self, name: str, content: str, location: SourceLocation) -> Role Build the role AST node. Called by the parser when a role is encountered in inline content. Return a Role node to include in the AST. Thread Safety: This method is called from parser context. Must not modify any shared state. Parameters Name Type Description name — The role name used (e.g., "ref" or "kbd") content — The content between backticks location — Source location for error messages Returns Role A Role node for the AST render 2 ▼ Render the role to HTML. Called by the renderer when a Role node is encountere… def render(self, node: Role, sb: StringBuilder) -> None Render the role to HTML. Called by the renderer when a Role node is encountered. Append HTML output to the StringBuilder. Thread Safety: This method may be called concurrently from multiple threads. Must not modify any shared state. Parameters Name Type Description node — The Role AST node to render sb — StringBuilder to append output to RoleParseOnly 3 ▼ Protocol for roles that only need custom parsing. Use this when default rendering is acceptable bu… Protocol for roles that only need custom parsing. Use this when default rendering is acceptable but you need custom AST construction. Attributes Name Type Description names ClassVar[tuple[str, ...]] — token_type ClassVar[str] — Methods parse 3 Role ▼ Build the role AST node. def parse(self, name: str, content: str, location: SourceLocation) -> Role Parameters Name Type Description name — content — location — Returns Role RoleRenderOnly 3 ▼ Protocol for roles that only need custom rendering. Use this when default parsing is acceptable bu… Protocol for roles that only need custom rendering. Use this when default parsing is acceptable but you need custom HTML output. Attributes Name Type Description names ClassVar[tuple[str, ...]] — token_type ClassVar[str] — Methods render 2 ▼ Render the role to HTML. def render(self, node: Role, sb: StringBuilder) -> None Parameters Name Type Description node — sb — Next → registry 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: 1059 - Reading Time: 5 minutes