Update recipe converter into an object.
This commit is contained in:
parent
fbd2222e1a
commit
b3be5fa90d
202
recipe.py
202
recipe.py
@ -4,13 +4,78 @@ from anytree.importer import DictImporter
|
|||||||
from sys import argv
|
from sys import argv
|
||||||
|
|
||||||
|
|
||||||
def build_table_depth_first(node, rows=None):
|
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:
|
if rows is None:
|
||||||
rows = []
|
rows = []
|
||||||
|
|
||||||
for child in sorted(node.children, key=lambda x: x.height, reverse=True):
|
for child in sorted(node.children, key=lambda x: x.height, reverse=True):
|
||||||
rows = build_table_depth_first(child, rows)
|
rows = self.build_table_rows_depth_first(child, rows)
|
||||||
|
|
||||||
colspan = 0
|
colspan = 0
|
||||||
if node.siblings:
|
if node.siblings:
|
||||||
@ -20,106 +85,69 @@ def build_table_depth_first(node, rows=None):
|
|||||||
colspan = max_sibling_height - node.height + 1
|
colspan = max_sibling_height - node.height + 1
|
||||||
|
|
||||||
if node.is_leaf:
|
if node.is_leaf:
|
||||||
rows.append([f'<th>{node.name}</th>'])
|
rows.append([TableCell(node.name, description=node.description, is_header=True)])
|
||||||
|
|
||||||
if colspan > 1:
|
if colspan > 1:
|
||||||
rows[-1].append(f'<td colspan="{colspan-1}" class="filler"></td>')
|
rows[-1].append(TableCell("", colspan=colspan-1))
|
||||||
|
|
||||||
else:
|
else:
|
||||||
child_leaves = len(node.leaves)
|
child_leaves = len(node.leaves)
|
||||||
cur_row = len(rows) - child_leaves
|
cur_row = len(rows) - child_leaves
|
||||||
rows[cur_row].append(f"<td rowspan='{child_leaves}' colspan='{colspan}' title='{node.description}'>{node.name}</td>")
|
rows[cur_row].append(TableCell(node.name, rowspan=child_leaves, colspan=colspan, description=node.description))
|
||||||
|
|
||||||
return rows
|
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>
|
||||||
|
|
||||||
def generate_steps_depth_first(node, steps=[]):
|
<header>
|
||||||
for child in sorted(node.children, key=lambda x: x.height, reverse=True):
|
<nav><a href='./'>Recipe Index</a></nav>
|
||||||
steps = generate_steps_depth_first(child, steps)
|
<h1>{self.name}</h1>
|
||||||
|
<p>{self.desc}</p>
|
||||||
|
</header>
|
||||||
|
|
||||||
if not node.is_leaf:
|
<main>
|
||||||
steps.append(node.description if node.description else node.name)
|
<div id='needs'>
|
||||||
|
<h2>Needs</h2>
|
||||||
|
<ul>
|
||||||
|
{"\n".join([f" <li>{ingredient}</li>" for ingredient in self.generate_ingredient_list()])}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
return steps
|
<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:
|
if len(argv) < 2:
|
||||||
print(f"usage: {argv[0]} <json file>")
|
print(f"usage: {argv[0]} <json file>")
|
||||||
exit()
|
exit(1)
|
||||||
|
|
||||||
with open(argv[1], 'r') as f:
|
print(Recipe(argv[1]).to_html())
|
||||||
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