def add(self, component: Component): if not self.attributes_buffer.empty(): component.apply_attributes(self.attributes_buffer) unknown_attr_keys = self.attributes_buffer.unknown_keys() if len(unknown_attr_keys) > 0: # TODO improve error message raise StxError(f'Unknown attributes: {unknown_attr_keys} ' f'for {type(component)}.') self.attributes_buffer.clear() if len(self.pre_captions) > 0: if isinstance(component, Table): component.caption = self.pre_captions.pop() self.components.append(component) else: figure = Figure(component.location, component, self.pre_captions.pop()) self.components.append(figure) else: self.components.append(component)
def append_component_tag(parent: Tag, component: Component, tag_name: str) -> Tag: for other_id in reversed(component.get_other_refs()): parent.append_tag('a', {'id': other_id}, text='') tag = parent.append_tag(tag_name) tag_id = component.get_main_ref() if tag_id is not None: tag['id'] = tag_id return tag
def collect_references(root: Component, refs: Set[str]): for component in root.walk(): for ref in component.get_refs(): if ref in refs: raise component.error(f'Reference already taken: {ref}') else: refs.add(ref)
def extend_base(component: Component, type_id: str, inherited: dict): return { 'type': type_id, 'refs': component.get_refs(), 'location': location_to_json(component.location), **inherited, }
def register_missing_references(root: Component, refs: Set[str]): for component in root.walk(): if isinstance(component, Section): register_section_reference(component, refs) elif isinstance(component, Table): register_table_reference(component, refs) elif isinstance(component, Figure): register_figure_reference(component, refs)
def resolve_component(document: Document, component: Component) -> int: count = 0 children = component.get_children() # Resolve children first for child in children: count += resolve_component(document, child) # Resolve function then if isinstance(component, FunctionCall): count += resolve_function_call(document, component) return count
def link_figure_and_table_numbers(root: Component): figure_count = 1 table_count = 1 for component in root.walk(): if isinstance(component, Table): component.number = f'{table_count}.' table_count += 1 elif isinstance(component, Figure): component.number = f'{figure_count}.' figure_count += 1
def generate_component_ref(component: Component, refs: Set[str]) -> str: count = 0 plain_text = component.get_text() while True: ref = make_ref(plain_text, REF_LENGTH_HINT, count) if ref not in refs: break count += 1 return ref
def collect_section_toc(component: Component, elements: List[ElementReference]): if isinstance(component, Section): element = ElementReference( title=component.heading.get_text().strip(), reference=component.get_main_ref(), number=component.number, ) elements.append(element) collect_section_toc(component.content, element.elements) elif isinstance(component, Composite): for child in component.components: collect_section_toc(child, elements)
def normalize_and_report_invalid_links(root: Component, refs: Set[str]): for component in root.walk(): if isinstance(component, LinkText): if component.reference is None: # Generate reference from the text component.reference = make_ref(component.get_text()) elif component.is_internal(): # Normalize wild reference component.reference = make_ref(component.reference) else: # Do not validate this link continue if component.reference not in refs: component.invalid = True logger.warning( f'Invalid link: {see(component.reference, None)}', component.location)
def link_section_numbers(root: Component, parent_number: str, current_level: int): if isinstance(root, Composite): count = 1 for child in root.components: if isinstance(child, Section): child.number = parent_number + f'{count}.' if child.level != current_level: logger.warning( f'Expected section level {current_level}' f' instead of {child.level}.', child.location) link_section_numbers(child.content, child.number, current_level + 1) count += 1 else: link_section_numbers(child, parent_number, current_level) elif isinstance(root, Section): root.number = parent_number + '1.' link_section_numbers(root.content, root.number, current_level + 1)
def normalize_references(root: Component): for component in root.walk(): wild_refs = component.get_refs() if len(wild_refs) > 0: component.ref = [make_ref(wild_ref) for wild_ref in wild_refs]
def make_plain_text(component: Component) -> str: if component.is_rich(): logger.warning('Rich component was converted to plain text.', component.location) return component.get_text()