import json from anytree.importer import DictImporter from sys import argv class TableCell: def __init__(self, name, rowspan="", colspan="", description="", is_header=False): self.name = name self.rowspan = rowspan self.colspan = colspan self.description = description self.is_header = is_header def to_html(self): if self.is_header: html = f"{self.name}" elif not self.name: html = f'' else: html = f"{self.name}" return html class Recipe: def __init__(self, json_filename: str): with open(json_filename, 'r') as f: recipe_dict = json.loads(f.read()) self.name = recipe_dict.get("name") self.desc = recipe_dict.get("description") importer = DictImporter() self.sub_recipes = [importer.import_(data) for data in recipe_dict["sub_recipes"]] def generate_ingredient_list(self): ingredients = [] for sub_recipe in self.sub_recipes: for ingredient in sub_recipe.leaves: if ingredient.description: ingredients.append(f"{ingredient.name} -- {ingredient.description}") else: ingredients.append(ingredient.name) return ingredients def generate_task_list(self): tasks = [] for sub_recipe in self.sub_recipes: tasks.extend(self.generate_steps_depth_first(sub_recipe, steps=[])) return tasks def generate_steps_depth_first(self, node, steps=[]): for child in sorted(node.children, key=lambda x: x.height, reverse=True): steps = self.generate_steps_depth_first(child, steps) if not node.is_leaf: steps.append(node.description if node.description else node.name) return steps def generate_tables(self): tables = [] for sub_recipe in self.sub_recipes: tables.append(self.build_table_rows_depth_first(sub_recipe)) return tables def build_table_rows_depth_first(self, node, rows=None): if rows is None: rows = [] for child in sorted(node.children, key=lambda x: x.height, reverse=True): rows = self.build_table_rows_depth_first(child, rows) colspan = 0 if node.siblings: max_sibling_height = max([s.height for s in node.siblings]) if max_sibling_height > node.height: colspan = max_sibling_height - node.height + 1 if node.is_leaf: rows.append([TableCell(node.name, description=node.description, is_header=True)]) if colspan > 1: rows[-1].append(TableCell("", colspan=colspan-1)) else: child_leaves = len(node.leaves) cur_row = len(rows) - child_leaves rows[cur_row].append(TableCell(node.name, rowspan=child_leaves, colspan=colspan, description=node.description)) return rows def to_html(self): return f""" {self.name}

{self.name}

{self.desc}

Needs

Preparation

    {"\n".join([f"
  1. {task}
  2. " for task in self.generate_task_list()])}

Tabular Layout

{"\n".join( [f"\n{"".join( [f"\n{"".join( [f" {cell.to_html()}\n" for cell in row] )}\n" for row in table] )}
" for table in self.generate_tables()] )}
""" if __name__ == "__main__": if len(argv) < 2: print(f"usage: {argv[0]} ") exit(1) print(Recipe(argv[1]).to_html())