Last active
March 26, 2025 01:47
-
-
Save alexkrolick/11beb8d72c6584c6ba6ea8a1866aa53d to your computer and use it in GitHub Desktop.
Recipe Parser
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env node | |
// Requires Node 14+ | |
const fs = require('fs/promises'); | |
const yaml = require('yaml'); | |
const markdown = require('micromark'); | |
async function main () { | |
const recipeFiles = await fs.readdir('./recipes'); | |
let recipesByCategory = {}; | |
for (const filepath of recipeFiles) { | |
if (filepath.endsWith('.yml')) { | |
const recipeStr = await fs.readFile('./recipes/' + filepath, 'utf8'); | |
let recipeObj = yaml.parse(recipeStr); | |
recipeObj.html = await recipe2html(recipeObj); | |
// console.log(recipeObj.html) | |
const category = recipeObj.category || 'Other'; | |
recipesByCategory[category] = (recipesByCategory[category] || []) | |
.concat(recipeObj); | |
} | |
} | |
const byPublishedDate = (i, j) => { | |
return (i.published_at > j.published_at) ? -1 | |
: (i.published_at < j.published_at) ? 1 | |
: 0; | |
} | |
const contentsHtml = ` | |
<ul id="recipe-list" class="note"> | |
${Object.entries(recipesByCategory).map(([category, recipes]) => { | |
return `\ | |
<li>${category} | |
<ul> | |
${recipes.sort(byPublishedDate).map(recipe => { | |
return `\ | |
<li><a href="#${recipe.id}">${recipe.title}</a></li>`; | |
}).join('\n')} | |
</ul> | |
</li>`; | |
}).join('\n')} | |
</ul> | |
`; | |
const recipesHtml = ` | |
<div id="recipes"> | |
${Object.entries(recipesByCategory).map(([category, recipes]) => { | |
return `\ | |
<h2>${category}</h2> | |
${recipes.sort(byPublishedDate).map(recipe => recipe.html).join('\n')} | |
` | |
}).join('\n')} | |
</div> | |
`; | |
await fs.writeFile('../_contents.html', contentsHtml); | |
await fs.writeFile('../_recipes.html', recipesHtml); | |
} | |
async function recipe2html(r) { | |
// console.log(JSON.stringify(r, null, 2)) | |
const html = ` | |
<article itemscope itemtype="http://schema.org/Recipe" id="${r.id}"> | |
<h3 itemprop="name">${r.title}</h3> | |
<p class="author"> | |
By <span itemprop="author">${r.author}</span> | |
</p> | |
<p> | |
<meta itemprop="datePublished" content="${r.published_at}" /> | |
<strong>${new Date(r.published_at).toLocaleDateString()}</strong> | |
<em>${r.category}</em> | |
</p> | |
<div itemprop="description"> | |
${markdown(r.description)} | |
</div> | |
<section> | |
<h4>Prep Time</h4> | |
<ul class="prep"> | |
<li> | |
Prep Time: <meta itemprop="prepTime" content="PT${r.prep_time}" /> | |
${r.prep_time} | |
</li> | |
<li> | |
Cook time: <meta itemprop="cookTime" content="PT${r.cook_time}" /> | |
${r.cook_time} | |
</li> | |
<li> | |
Yield: <span itemprop="recipeYield">${r.yield}</span> | |
</li> | |
</ul> | |
</section> | |
<section> | |
<h4>Ingredients</h4> | |
<ul class="ingredients"> | |
${r.ingredients.map(i => { | |
// TODO: parse quantities to allow scaling recipe | |
return `\ | |
<li itemprop="recipeIngredient"> | |
${i} | |
</li>`; | |
}).join('\n')} | |
</ul> | |
</section> | |
<section> | |
<h4>Instructions</h4> | |
<ul itemprop="recipeInstructions"> | |
${r.steps.map(step => { | |
return `\ | |
<li itemprop="step"> | |
${markdown(step)} | |
</li>`; | |
}).join('\n')} | |
</ul> | |
</section> | |
</article> | |
`; | |
return html; | |
} | |
main(); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
id: banana-bread | |
title: Banana Bread w/Sweet Potato and Pecans | |
author: Alex Krolick | |
published_at: 2020-06-10 | |
category: Bakery | |
prep_time: 20M | |
cook_time: 1H | |
yield: 8 servings | |
description: | | |
Based on this recipe: [Best Banana Bread](https://cookpad.com/us/recipes/4042250-best-banana-bread) | |
Substitute 1 banana (use 3 instead of 4) with about 1/3 cup cooked + | |
mashed sweet potato insides. Add some chopped roasted pecans to the mix, | |
and sprinkle some more on top. | |
I baked it more than an hour (1H15M) since it was in one big loaf pan instead of | |
the standard banana bread size (small) tins. | |
ingredients: | |
- 1 1/2 cup all-purpose flour | |
- 3 soft bananas with lots of brown spots | |
- 1/3 cup sweet potato, cooked and mashed | |
- 1/4 cup roast pecans, chopped | |
- 1/3 cup butter | |
- 2/3 cups white sugar | |
- 2 tbsp turbinado or brown sugar | |
- 1 egg | |
- 1 teaspoon vanilla extract | |
- 1 tsp baking soda | |
- 1 pinch salt | |
- 1/4 teaspoon ground cinnamon | |
- 1 pinch ground nutmeg | |
steps: | |
- Preheat oven to 350F. | |
- Melt butter in a pan. When it starts to turn brown, remove from heat and | |
let cool while you do the next steps. | |
- > | |
Mash together 3 bananas and 1/3 cup sweet potato in a mixing bowl. I used | |
about half of a baked sweet potato: bake at 400F for 1 hour with slashes | |
cut across the top, then scoop out insides. | |
- Add butter, 1 egg, spices, and 1 tsp baking soda to the bowl | |
- Mix in 2/3 cup sugar, then 1 1/2 cup flour to the bowl | |
- Mix in 1/3 cup chopped pecans | |
- Lightly grease 2 small baking pans, or 1 larger one | |
- Pour in banana bread mix. | |
- Sprinkle 2 tbsp brown sugar and more chopped pecans on top. | |
- Bake for 1 hour if using small pans or about 1:15 if using a single pan. | |
A toothpick poked into the loaf should come out clean. | |
- Remove from oven and let cool in the pan for about 15 min before dumping | |
it out onto a rack. Let it cool before serving. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"dependencies": { | |
"yaml": "*", | |
"micromark": "*", | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
id: | |
title: | |
author: | |
published_at: | |
category: | |
prep_time: | |
cook_time: | |
yield: | |
description: | | |
ingredients: | |
- | |
steps: | |
- |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment