Compare commits
	
		
			No commits in common. "b3be5fa90d9d9f5057a5257d9607377d9ebed0b1" and "7514e6bb228e58c1e60eaaeb71261b8f1b19e428" have entirely different histories.
		
	
	
		
			b3be5fa90d
			...
			7514e6bb22
		
	
		
							
								
								
									
										153
									
								
								recipe.py
									
									
									
									
									
								
							
							
						
						
									
										153
									
								
								recipe.py
									
									
									
									
									
								
							@ -1,153 +0,0 @@
 | 
				
			|||||||
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"<th title={self.description}>{self.name}</th>"
 | 
					 | 
				
			||||||
        elif not self.name:
 | 
					 | 
				
			||||||
            html = f'<td colspan="{self.colspan}" class="filler"></td>'
 | 
					 | 
				
			||||||
        else:
 | 
					 | 
				
			||||||
            html = f"<td rowspan='{self.rowspan}' colspan='{self.colspan}' title='{self.description}'>{self.name}</td>"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        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"""<!DOCTYPE html>
 | 
					 | 
				
			||||||
<html lang='en'>
 | 
					 | 
				
			||||||
<head><title>{self.name}</title>
 | 
					 | 
				
			||||||
<link rel='stylesheet' type='text/css' href='style.css'>
 | 
					 | 
				
			||||||
<meta name='viewport' content='width=device-width, initial-scale=1, maximum-scale=1'>
 | 
					 | 
				
			||||||
</head>
 | 
					 | 
				
			||||||
<body>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<header>
 | 
					 | 
				
			||||||
<nav><a href='./'>Recipe Index</a></nav>
 | 
					 | 
				
			||||||
<h1>{self.name}</h1>
 | 
					 | 
				
			||||||
<p>{self.desc}</p>
 | 
					 | 
				
			||||||
</header>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<main>
 | 
					 | 
				
			||||||
<div id='needs'>
 | 
					 | 
				
			||||||
<h2>Needs</h2>
 | 
					 | 
				
			||||||
<ul>
 | 
					 | 
				
			||||||
{"\n".join([f"  <li>{ingredient}</li>" for ingredient in self.generate_ingredient_list()])}
 | 
					 | 
				
			||||||
</ul>
 | 
					 | 
				
			||||||
</div>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<div id='preparation'>
 | 
					 | 
				
			||||||
<h2>Preparation</h2>
 | 
					 | 
				
			||||||
<ol>
 | 
					 | 
				
			||||||
{"\n".join([f"  <li>{task}</li>" for task in self.generate_task_list()])}
 | 
					 | 
				
			||||||
</ol>
 | 
					 | 
				
			||||||
</div>
 | 
					 | 
				
			||||||
</main>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<summary>
 | 
					 | 
				
			||||||
<h2>Tabular Layout</h2>
 | 
					 | 
				
			||||||
{"\n".join(
 | 
					 | 
				
			||||||
    [f"<table cellspacing=0 border=true>\n{"".join(
 | 
					 | 
				
			||||||
        [f"<tr>\n{"".join(
 | 
					 | 
				
			||||||
            [f"  {cell.to_html()}\n" for cell in row]
 | 
					 | 
				
			||||||
        )}</tr>\n" for row in table]
 | 
					 | 
				
			||||||
    )}</table>" for table in self.generate_tables()]
 | 
					 | 
				
			||||||
)}
 | 
					 | 
				
			||||||
</summary>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
</body>
 | 
					 | 
				
			||||||
</html>
 | 
					 | 
				
			||||||
"""
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
if __name__ == "__main__":
 | 
					 | 
				
			||||||
    if len(argv) < 2:
 | 
					 | 
				
			||||||
        print(f"usage: {argv[0]} <json file>")
 | 
					 | 
				
			||||||
        exit(1)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    print(Recipe(argv[1]).to_html())
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
							
								
								
									
										125
									
								
								recipe_json_to_html.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										125
									
								
								recipe_json_to_html.py
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,125 @@
 | 
				
			|||||||
 | 
					import json
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from anytree.importer import DictImporter
 | 
				
			||||||
 | 
					from sys import argv
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def build_table_depth_first(node, rows=None):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if rows is None:
 | 
				
			||||||
 | 
					        rows = []
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    for child in sorted(node.children, key=lambda x: x.height, reverse=True):
 | 
				
			||||||
 | 
					        rows = build_table_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([f'<th>{node.name}</th>'])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if colspan > 1:
 | 
				
			||||||
 | 
					            rows[-1].append(f'<td colspan="{colspan-1}" class="filler"></td>')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    else:
 | 
				
			||||||
 | 
					        child_leaves = len(node.leaves)
 | 
				
			||||||
 | 
					        cur_row = len(rows) - child_leaves
 | 
				
			||||||
 | 
					        rows[cur_row].append(f"<td rowspan='{child_leaves}' colspan='{colspan}' title='{node.description}'>{node.name}</td>")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return rows
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def generate_steps_depth_first(node, steps=[]):
 | 
				
			||||||
 | 
					    for child in sorted(node.children, key=lambda x: x.height, reverse=True):
 | 
				
			||||||
 | 
					        steps = generate_steps_depth_first(child, steps)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if not node.is_leaf:
 | 
				
			||||||
 | 
					        steps.append(node.description if node.description else node.name)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return steps
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if len(argv) < 2:
 | 
				
			||||||
 | 
					    print(f"usage: {argv[0]} <json file>")
 | 
				
			||||||
 | 
					    exit()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					with open(argv[1], 'r') as f:
 | 
				
			||||||
 | 
					    recipe = json.loads(f.read())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					recipe_name = recipe.get("name")
 | 
				
			||||||
 | 
					recipe_desc = recipe.get("description")
 | 
				
			||||||
 | 
					importer = DictImporter()
 | 
				
			||||||
 | 
					sub_recipes = [importer.import_(data) for data in recipe["sub_recipes"]]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					print("<!DOCTYPE html>")
 | 
				
			||||||
 | 
					print("<html lang='en'>")
 | 
				
			||||||
 | 
					print(f"<head><title>{recipe_name}</title>")
 | 
				
			||||||
 | 
					print("<link rel='stylesheet' type='text/css' href='style.css'>")
 | 
				
			||||||
 | 
					print("<meta name='viewport' content='width=device-width, initial-scale=1, maximum-scale=1'>")
 | 
				
			||||||
 | 
					print("</head>")
 | 
				
			||||||
 | 
					print("<body>")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					print("<header>")
 | 
				
			||||||
 | 
					print("<div id='title'>")
 | 
				
			||||||
 | 
					print(f"<h1>{recipe_name}</h1>")
 | 
				
			||||||
 | 
					print("</div>")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					print("<div id='description'>")
 | 
				
			||||||
 | 
					print(f"<p>{recipe_desc}</p>")
 | 
				
			||||||
 | 
					print("</div>")
 | 
				
			||||||
 | 
					print("</header>")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					print("<main>")
 | 
				
			||||||
 | 
					print("<div id='needs'>")
 | 
				
			||||||
 | 
					print("<h2>Needs</h2>")
 | 
				
			||||||
 | 
					print("<ul>")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					for sub_recipe in sub_recipes:
 | 
				
			||||||
 | 
					    for ingredient in sub_recipe.leaves:
 | 
				
			||||||
 | 
					        if ingredient.description:
 | 
				
			||||||
 | 
					            print(f"  <li>{ingredient.name} -- {ingredient.description}</li>")
 | 
				
			||||||
 | 
					        else:
 | 
				
			||||||
 | 
					            print(f"  <li>{ingredient.name}</li>")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					print("</ul>")
 | 
				
			||||||
 | 
					print("</div>")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					print("<div id='preparation'>")
 | 
				
			||||||
 | 
					print("<h2>Preparation</h2>")
 | 
				
			||||||
 | 
					print("<ol>")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					for sub_recipe in sub_recipes:
 | 
				
			||||||
 | 
					    tasks = generate_steps_depth_first(sub_recipe, steps=[])
 | 
				
			||||||
 | 
					    for task in tasks:
 | 
				
			||||||
 | 
					        print(f"  <li>{task}</li>")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					print("</ol>")
 | 
				
			||||||
 | 
					print("</div>")
 | 
				
			||||||
 | 
					print("</main>")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					print("<summary>")
 | 
				
			||||||
 | 
					print("<h2>Tabular Layout</h2>")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					for sub_recipe in sub_recipes:
 | 
				
			||||||
 | 
					    print("<p>")
 | 
				
			||||||
 | 
					    print("<table cellspacing='0' border=true>")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    output_rows = build_table_depth_first(sub_recipe)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    for row in output_rows:
 | 
				
			||||||
 | 
					        print("<tr>")
 | 
				
			||||||
 | 
					        for cell in row:
 | 
				
			||||||
 | 
					            print(f"  {cell}")
 | 
				
			||||||
 | 
					        print("</tr>")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    print("</table>")
 | 
				
			||||||
 | 
					    print("</p>")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					print("</summary>")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					print("</body>")
 | 
				
			||||||
 | 
					print("</html>")
 | 
				
			||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user