def set_heading_attributes(self, root_node, max_depth): """Iterate over root node, create heading tokens to generate toc, replace heading nodes in tree with html. """ headings_list = [] for node, entering, node_type in ast_tools.walk(root_node): if not entering and node_type == _cmark.NODE_HEADING: level = ast_tools.get_heading_level(node) line_number = ast_tools.get_start_line(node) text = '' if not level > max_depth: for cur, entering, node_type in ast_tools.walk(node): if entering and node_type == _cmark.NODE_TEXT: text = ast_tools.get_literal(cur) data = { 'level': level, 'text': text, 'line_number': line_number } headings_list.append(data) # replace headings in AST with raw html for working toc links if self.inject: template = '<h{level} id="{_id}">{text}</h{level}>' _id = '{}-{}'.format(line_number, self.slugify(text)) heading = template.format(level=level, _id =_id, text=text) new_node =ast_tools.make_html_node(content=heading) ast_tools.replace_node(node, new_node) return headings_list
def get_headings(self, document): """Find all the headings in *document* and capture data from them. Contains an inner function that iterates over any found heading node to extract any text content. Args: document (cmark_node): the root node to iterate over Returns: list: a list of dictionaries containing info about the headings """ def get_heading_info(node): level = ast_tools.get_heading_level(node) line_no = ast_tools.get_start_line(node) # Get the heading level and line number # Find any text node to get the heading text for cur, entering, node_type in ast_tools.walk(node): if entering and node_type == _cmark.NODE_TEXT: text = ast_tools.get_literal(cur) data = { 'level': level, 'text': ast_tools.from_c_string(text), 'line_number': line_no } return(data) heads = [] for node, entering, node_type in ast_tools.walk(document): if not entering and node_type == _cmark.NODE_HEADING: info = get_heading_info(node) heads.append(info) return heads
def get_heading_info(node): level = ast_tools.get_heading_level(node) line_no = ast_tools.get_start_line(node) # Get the heading level and line number # Find any text node to get the heading text for cur, entering, node_type in ast_tools.walk(node): if entering and node_type == _cmark.NODE_TEXT: text = ast_tools.get_literal(cur) data = { 'level': level, 'text': ast_tools.from_c_string(text), 'line_number': line_no } return(data)
def enforce_max_heading_level(self, root_node, max_level=6): """Walks the document and checks the heading levels. If level is higher than *max_level* heading level is set to *max_level* Args: root_node (cmark_node): The document node to iterate over max_level (int, optional): The desired maximum heading level. Defaults to 6. Raises: ValueError: If the max_level is set to something higher than 6 or lower than 1 """ for node, entering, node_type in ast_tools.walk(root_node): if entering and node_type == _cmark.NODE_HEADING: level = ast_tools.get_heading_level(node) if max_level > 6 or max_level < 0: raise ValueError('max_level must be between 1 and 6') if level > max_level: ast_tools.set_heading_level(node, max_level)