quizcomp.parser.renderer.base
1import typing 2 3import markdown_it.renderer 4import markdown_it.token 5import markdown_it.utils 6 7import quizcomp.parser.ast 8import quizcomp.parser.common 9import quizcomp.parser.style 10 11class QuizComposerRendererBase(markdown_it.renderer.RendererProtocol): 12 """ The base class for renderers (objects that take tokens and output strings in a specific format. """ 13 14 def render(self, 15 tokens: typing.Sequence[markdown_it.token.Token], 16 options: markdown_it.utils.OptionsDict, 17 env: typing.MutableMapping[str, typing.Any], 18 ) -> str: 19 """ Render tokens to text. """ 20 21 context = typing.cast(quizcomp.parser.common.RenderContext, env[quizcomp.parser.common.ENV_KEY_CONTEXT]) 22 23 # Work with an AST instead of tokens. 24 ast = quizcomp.parser.ast.build(tokens) 25 26 return self._render_node(ast, context) 27 28 def clean_final(self, text: str, context: quizcomp.parser.common.RenderContext) -> str: 29 """ 30 Last chance for cleaning before leaving the renderer. 31 """ 32 33 return text.strip() 34 35 def _render_node(self, node: quizcomp.parser.ast.ASTNode, context: quizcomp.parser.common.RenderContext) -> str: 36 """ 37 Route rendering to the method '_render_<type>(self, node, context)', e.g.: '_image'. 38 """ 39 40 method_name = '_' + node.type 41 method = getattr(self, method_name, None) 42 if (method is None): 43 raise TypeError(f"Could not find TeX render method: '{method_name}'.") 44 45 return str(method(node, context)) 46 47 def _root(self, node: quizcomp.parser.ast.ASTNode, context: quizcomp.parser.common.RenderContext) -> str: 48 """ Render the 'root' token. """ 49 50 content = "\n\n".join([self._render_node(child, context) for child in node.children]) 51 content = self.clean_final(content, context) 52 return content 53 54 def _container_block(self, node: quizcomp.parser.ast.ASTNode, context: quizcomp.parser.common.RenderContext) -> str: 55 """ Render the 'container_block' token. """ 56 57 # Pull any style attatched to this block and put it in a copy of the context. 58 context, _ = quizcomp.parser.common.handle_block_style(node.attributes, context) 59 return "\n\n".join([self._render_node(child, context) for child in node.children]) 60 61 def _paragraph(self, node: quizcomp.parser.ast.ASTNode, context: quizcomp.parser.common.RenderContext) -> str: 62 """ Render the 'paragraph' token. """ 63 64 return "\n".join([self._render_node(child, context) for child in node.children]) 65 66 def _inline(self, node: quizcomp.parser.ast.ASTNode, context: quizcomp.parser.common.RenderContext) -> str: 67 """ Render the 'inline' token. """ 68 69 return ''.join([self._render_node(child, context) for child in node.children]) 70 71 def _text(self, node: quizcomp.parser.ast.ASTNode, context: quizcomp.parser.common.RenderContext) -> str: 72 """ Render the 'text' token. """ 73 74 raise NotImplementedError() 75 76 def _softbreak(self, node: quizcomp.parser.ast.ASTNode, context: quizcomp.parser.common.RenderContext) -> str: 77 """ Render the 'softbreak' token. """ 78 79 raise NotImplementedError() 80 81 def _hardbreak(self, node: quizcomp.parser.ast.ASTNode, context: quizcomp.parser.common.RenderContext) -> str: 82 """ Render the 'hardbreak' token. """ 83 84 raise NotImplementedError() 85 86 def _em(self, node: quizcomp.parser.ast.ASTNode, context: quizcomp.parser.common.RenderContext) -> str: 87 """ Render the 'em' token. """ 88 89 raise NotImplementedError() 90 91 def _strong(self, node: quizcomp.parser.ast.ASTNode, context: quizcomp.parser.common.RenderContext) -> str: 92 """ Render the 'strong' token. """ 93 94 raise NotImplementedError() 95 96 def _fence(self, node: quizcomp.parser.ast.ASTNode, context: quizcomp.parser.common.RenderContext) -> str: 97 """ Render the 'fence' token. """ 98 99 raise NotImplementedError() 100 101 def _code_block(self, node: quizcomp.parser.ast.ASTNode, context: quizcomp.parser.common.RenderContext) -> str: 102 """ 103 Render the 'code_block' token. 104 105 This token is poorly named, it is actually an indented code block. 106 Treat it like a fence with no info string. 107 """ 108 109 raise NotImplementedError() 110 111 def _code_inline(self, node: quizcomp.parser.ast.ASTNode, context: quizcomp.parser.common.RenderContext) -> str: 112 """ Render the 'code_inline' token. """ 113 114 raise NotImplementedError() 115 116 def _math_block(self, node: quizcomp.parser.ast.ASTNode, context: quizcomp.parser.common.RenderContext) -> str: 117 """ Render the 'math_block' token. """ 118 119 raise NotImplementedError() 120 121 def _math_inline(self, node: quizcomp.parser.ast.ASTNode, context: quizcomp.parser.common.RenderContext) -> str: 122 """ Render the 'math_inline' token. """ 123 124 raise NotImplementedError() 125 126 def _image(self, node: quizcomp.parser.ast.ASTNode, context: quizcomp.parser.common.RenderContext) -> str: 127 """ Render the 'image' token. """ 128 129 raise NotImplementedError() 130 131 def _link(self, node: quizcomp.parser.ast.ASTNode, context: quizcomp.parser.common.RenderContext) -> str: 132 """ Render the 'link' token. """ 133 134 raise NotImplementedError() 135 136 def _placeholder(self, node: quizcomp.parser.ast.ASTNode, context: quizcomp.parser.common.RenderContext) -> str: 137 """ Render the 'placeholder' token. """ 138 139 raise NotImplementedError() 140 141 def _table(self, node: quizcomp.parser.ast.ASTNode, context: quizcomp.parser.common.RenderContext) -> str: 142 """ Render the 'table' token. """ 143 144 raise NotImplementedError() 145 146 def _thead(self, node: quizcomp.parser.ast.ASTNode, context: quizcomp.parser.common.RenderContext) -> str: 147 """ Render the 'thead' token. """ 148 149 raise NotImplementedError() 150 151 def _tbody(self, node: quizcomp.parser.ast.ASTNode, context: quizcomp.parser.common.RenderContext) -> str: 152 """ Render the 'tbody' token. """ 153 154 raise NotImplementedError() 155 156 def _tr(self, node: quizcomp.parser.ast.ASTNode, context: quizcomp.parser.common.RenderContext) -> str: 157 """ Render the 'tr' token. """ 158 159 raise NotImplementedError() 160 161 def _th(self, node: quizcomp.parser.ast.ASTNode, context: quizcomp.parser.common.RenderContext) -> str: 162 """ Render the 'th' token. """ 163 164 raise NotImplementedError() 165 166 def _td(self, node: quizcomp.parser.ast.ASTNode, context: quizcomp.parser.common.RenderContext) -> str: 167 """ Render the 'td' token. """ 168 169 raise NotImplementedError() 170 171 def _bullet_list(self, node: quizcomp.parser.ast.ASTNode, context: quizcomp.parser.common.RenderContext) -> str: 172 """ Render the 'bullet_list' token. """ 173 174 raise NotImplementedError() 175 176 def _ordered_list(self, node: quizcomp.parser.ast.ASTNode, context: quizcomp.parser.common.RenderContext) -> str: 177 """ Render the 'ordered_list' token. """ 178 179 raise NotImplementedError() 180 181 def _list_item(self, node: quizcomp.parser.ast.ASTNode, context: quizcomp.parser.common.RenderContext) -> str: 182 """ Render the 'list_item' token. """ 183 184 raise NotImplementedError() 185 186 def _hr(self, node: quizcomp.parser.ast.ASTNode, context: quizcomp.parser.common.RenderContext) -> str: 187 """ Render the 'hr' token. """ 188 189 raise NotImplementedError() 190 191 def _heading(self, node: quizcomp.parser.ast.ASTNode, context: quizcomp.parser.common.RenderContext) -> str: 192 """ Render the 'heading' token. """ 193 194 raise NotImplementedError() 195 196 def _blockquote(self, node: quizcomp.parser.ast.ASTNode, context: quizcomp.parser.common.RenderContext) -> str: 197 """ Render the 'blockquote' token. """ 198 199 raise NotImplementedError() 200 201 def parse_heading_level(self, node: quizcomp.parser.ast.ASTNode) -> int: 202 """ Parse the level out of the HTML tag. """ 203 204 tag = node.get('tag', None) 205 if (tag is None): 206 raise ValueError("Failed to find a heading's level.") 207 208 try: 209 level = int(tag[1]) 210 except Exception as ex: 211 raise ValueError(f"Failed to parse heading level from '{tag}'.") from ex 212 213 return level
class
QuizComposerRendererBase(markdown_it.renderer.RendererProtocol):
12class QuizComposerRendererBase(markdown_it.renderer.RendererProtocol): 13 """ The base class for renderers (objects that take tokens and output strings in a specific format. """ 14 15 def render(self, 16 tokens: typing.Sequence[markdown_it.token.Token], 17 options: markdown_it.utils.OptionsDict, 18 env: typing.MutableMapping[str, typing.Any], 19 ) -> str: 20 """ Render tokens to text. """ 21 22 context = typing.cast(quizcomp.parser.common.RenderContext, env[quizcomp.parser.common.ENV_KEY_CONTEXT]) 23 24 # Work with an AST instead of tokens. 25 ast = quizcomp.parser.ast.build(tokens) 26 27 return self._render_node(ast, context) 28 29 def clean_final(self, text: str, context: quizcomp.parser.common.RenderContext) -> str: 30 """ 31 Last chance for cleaning before leaving the renderer. 32 """ 33 34 return text.strip() 35 36 def _render_node(self, node: quizcomp.parser.ast.ASTNode, context: quizcomp.parser.common.RenderContext) -> str: 37 """ 38 Route rendering to the method '_render_<type>(self, node, context)', e.g.: '_image'. 39 """ 40 41 method_name = '_' + node.type 42 method = getattr(self, method_name, None) 43 if (method is None): 44 raise TypeError(f"Could not find TeX render method: '{method_name}'.") 45 46 return str(method(node, context)) 47 48 def _root(self, node: quizcomp.parser.ast.ASTNode, context: quizcomp.parser.common.RenderContext) -> str: 49 """ Render the 'root' token. """ 50 51 content = "\n\n".join([self._render_node(child, context) for child in node.children]) 52 content = self.clean_final(content, context) 53 return content 54 55 def _container_block(self, node: quizcomp.parser.ast.ASTNode, context: quizcomp.parser.common.RenderContext) -> str: 56 """ Render the 'container_block' token. """ 57 58 # Pull any style attatched to this block and put it in a copy of the context. 59 context, _ = quizcomp.parser.common.handle_block_style(node.attributes, context) 60 return "\n\n".join([self._render_node(child, context) for child in node.children]) 61 62 def _paragraph(self, node: quizcomp.parser.ast.ASTNode, context: quizcomp.parser.common.RenderContext) -> str: 63 """ Render the 'paragraph' token. """ 64 65 return "\n".join([self._render_node(child, context) for child in node.children]) 66 67 def _inline(self, node: quizcomp.parser.ast.ASTNode, context: quizcomp.parser.common.RenderContext) -> str: 68 """ Render the 'inline' token. """ 69 70 return ''.join([self._render_node(child, context) for child in node.children]) 71 72 def _text(self, node: quizcomp.parser.ast.ASTNode, context: quizcomp.parser.common.RenderContext) -> str: 73 """ Render the 'text' token. """ 74 75 raise NotImplementedError() 76 77 def _softbreak(self, node: quizcomp.parser.ast.ASTNode, context: quizcomp.parser.common.RenderContext) -> str: 78 """ Render the 'softbreak' token. """ 79 80 raise NotImplementedError() 81 82 def _hardbreak(self, node: quizcomp.parser.ast.ASTNode, context: quizcomp.parser.common.RenderContext) -> str: 83 """ Render the 'hardbreak' token. """ 84 85 raise NotImplementedError() 86 87 def _em(self, node: quizcomp.parser.ast.ASTNode, context: quizcomp.parser.common.RenderContext) -> str: 88 """ Render the 'em' token. """ 89 90 raise NotImplementedError() 91 92 def _strong(self, node: quizcomp.parser.ast.ASTNode, context: quizcomp.parser.common.RenderContext) -> str: 93 """ Render the 'strong' token. """ 94 95 raise NotImplementedError() 96 97 def _fence(self, node: quizcomp.parser.ast.ASTNode, context: quizcomp.parser.common.RenderContext) -> str: 98 """ Render the 'fence' token. """ 99 100 raise NotImplementedError() 101 102 def _code_block(self, node: quizcomp.parser.ast.ASTNode, context: quizcomp.parser.common.RenderContext) -> str: 103 """ 104 Render the 'code_block' token. 105 106 This token is poorly named, it is actually an indented code block. 107 Treat it like a fence with no info string. 108 """ 109 110 raise NotImplementedError() 111 112 def _code_inline(self, node: quizcomp.parser.ast.ASTNode, context: quizcomp.parser.common.RenderContext) -> str: 113 """ Render the 'code_inline' token. """ 114 115 raise NotImplementedError() 116 117 def _math_block(self, node: quizcomp.parser.ast.ASTNode, context: quizcomp.parser.common.RenderContext) -> str: 118 """ Render the 'math_block' token. """ 119 120 raise NotImplementedError() 121 122 def _math_inline(self, node: quizcomp.parser.ast.ASTNode, context: quizcomp.parser.common.RenderContext) -> str: 123 """ Render the 'math_inline' token. """ 124 125 raise NotImplementedError() 126 127 def _image(self, node: quizcomp.parser.ast.ASTNode, context: quizcomp.parser.common.RenderContext) -> str: 128 """ Render the 'image' token. """ 129 130 raise NotImplementedError() 131 132 def _link(self, node: quizcomp.parser.ast.ASTNode, context: quizcomp.parser.common.RenderContext) -> str: 133 """ Render the 'link' token. """ 134 135 raise NotImplementedError() 136 137 def _placeholder(self, node: quizcomp.parser.ast.ASTNode, context: quizcomp.parser.common.RenderContext) -> str: 138 """ Render the 'placeholder' token. """ 139 140 raise NotImplementedError() 141 142 def _table(self, node: quizcomp.parser.ast.ASTNode, context: quizcomp.parser.common.RenderContext) -> str: 143 """ Render the 'table' token. """ 144 145 raise NotImplementedError() 146 147 def _thead(self, node: quizcomp.parser.ast.ASTNode, context: quizcomp.parser.common.RenderContext) -> str: 148 """ Render the 'thead' token. """ 149 150 raise NotImplementedError() 151 152 def _tbody(self, node: quizcomp.parser.ast.ASTNode, context: quizcomp.parser.common.RenderContext) -> str: 153 """ Render the 'tbody' token. """ 154 155 raise NotImplementedError() 156 157 def _tr(self, node: quizcomp.parser.ast.ASTNode, context: quizcomp.parser.common.RenderContext) -> str: 158 """ Render the 'tr' token. """ 159 160 raise NotImplementedError() 161 162 def _th(self, node: quizcomp.parser.ast.ASTNode, context: quizcomp.parser.common.RenderContext) -> str: 163 """ Render the 'th' token. """ 164 165 raise NotImplementedError() 166 167 def _td(self, node: quizcomp.parser.ast.ASTNode, context: quizcomp.parser.common.RenderContext) -> str: 168 """ Render the 'td' token. """ 169 170 raise NotImplementedError() 171 172 def _bullet_list(self, node: quizcomp.parser.ast.ASTNode, context: quizcomp.parser.common.RenderContext) -> str: 173 """ Render the 'bullet_list' token. """ 174 175 raise NotImplementedError() 176 177 def _ordered_list(self, node: quizcomp.parser.ast.ASTNode, context: quizcomp.parser.common.RenderContext) -> str: 178 """ Render the 'ordered_list' token. """ 179 180 raise NotImplementedError() 181 182 def _list_item(self, node: quizcomp.parser.ast.ASTNode, context: quizcomp.parser.common.RenderContext) -> str: 183 """ Render the 'list_item' token. """ 184 185 raise NotImplementedError() 186 187 def _hr(self, node: quizcomp.parser.ast.ASTNode, context: quizcomp.parser.common.RenderContext) -> str: 188 """ Render the 'hr' token. """ 189 190 raise NotImplementedError() 191 192 def _heading(self, node: quizcomp.parser.ast.ASTNode, context: quizcomp.parser.common.RenderContext) -> str: 193 """ Render the 'heading' token. """ 194 195 raise NotImplementedError() 196 197 def _blockquote(self, node: quizcomp.parser.ast.ASTNode, context: quizcomp.parser.common.RenderContext) -> str: 198 """ Render the 'blockquote' token. """ 199 200 raise NotImplementedError() 201 202 def parse_heading_level(self, node: quizcomp.parser.ast.ASTNode) -> int: 203 """ Parse the level out of the HTML tag. """ 204 205 tag = node.get('tag', None) 206 if (tag is None): 207 raise ValueError("Failed to find a heading's level.") 208 209 try: 210 level = int(tag[1]) 211 except Exception as ex: 212 raise ValueError(f"Failed to parse heading level from '{tag}'.") from ex 213 214 return level
The base class for renderers (objects that take tokens and output strings in a specific format.
def
render( self, tokens: Sequence[markdown_it.token.Token], options: markdown_it.utils.OptionsDict, env: MutableMapping[str, Any]) -> str:
15 def render(self, 16 tokens: typing.Sequence[markdown_it.token.Token], 17 options: markdown_it.utils.OptionsDict, 18 env: typing.MutableMapping[str, typing.Any], 19 ) -> str: 20 """ Render tokens to text. """ 21 22 context = typing.cast(quizcomp.parser.common.RenderContext, env[quizcomp.parser.common.ENV_KEY_CONTEXT]) 23 24 # Work with an AST instead of tokens. 25 ast = quizcomp.parser.ast.build(tokens) 26 27 return self._render_node(ast, context)
Render tokens to text.
29 def clean_final(self, text: str, context: quizcomp.parser.common.RenderContext) -> str: 30 """ 31 Last chance for cleaning before leaving the renderer. 32 """ 33 34 return text.strip()
Last chance for cleaning before leaving the renderer.
202 def parse_heading_level(self, node: quizcomp.parser.ast.ASTNode) -> int: 203 """ Parse the level out of the HTML tag. """ 204 205 tag = node.get('tag', None) 206 if (tag is None): 207 raise ValueError("Failed to find a heading's level.") 208 209 try: 210 level = int(tag[1]) 211 except Exception as ex: 212 raise ValueError(f"Failed to parse heading level from '{tag}'.") from ex 213 214 return level
Parse the level out of the HTML tag.