author Angelo Gladding
name Recipes
published 2026-10-21T21:50:34.046357-07:00
type entry
updated 2026-11-04T12:28:11.735711-08:00
url /recipes, /2026/10/22/xx
visibility public
Content
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 | $code: route = "/recipes" session = web.tx.user.session token = session.get("token") endpoint = str(session.get("endpoint") or "") if endpoint and "://" not in endpoint: endpoint = "https://" + endpoint fields = ( ("name", "Name", 1), ("summary", "Summary", 3), ("ingredient", "Ingredients (one per line)", 12), ("yield", "Yield", 1), ("duration", "Duration", 1), ("instructions", "Instructions (HTML)", 16), ("content", "Additional content (HTML)", 8), ) values = {key: "" for key, label, rows in fields} original = {} url = "" error = "" saved = False destination = "" method = web.tx.request.method def display_value(properties, key): items = properties.get(key, []) if key == "ingredient": return "\n".join(items) if not items: return "" value = items[0] if isinstance(value, dict): return value.get("html", value.get("value", "")) return str(value) if method == "GET": url = web.tx.request.uri.query.get("url", [""])[0].strip() elif method == "POST": form = web.form() # "url", # "name", # "summary", # "ingredient", # "yield", # "duration", # "instructions", # "content", #) if "url" in form: url = form["url"].strip() values = {key: form[key] for key, label, rows in fields} if not token or not endpoint: error = "Sign in with a Micropub account first." if not error: headers = { "Authorization": f"Bearer {token}", "Accept": "application/json", } if url and not url.startswith("https://"): error = "Enter the recipe's full HTTPS URL." if url and not error: source_response = web.get( endpoint, headers=headers, params={"q": "source", "url": url}, allow_redirects=False, ) if source_response.status != 200: error = f"Could not load recipe (HTTP {source_response.status})." else: source = source_response.json if not isinstance(source, dict): error = "The source response must be a JSON object." elif "recipe" not in source.get("type", []): error = "The source response does not identify this as an h-recipe." else: original = source # ["properties"] if method == "GET": values = { key: display_value(original, key) for key, label, rows in fields } # XXX elif not isinstance(source.get("properties"), dict): # XXX error = "The source response is missing its properties object." if method == "POST" and not error: if not values["name"].strip(): error = "Enter a recipe name." else: properties = {} deleted = [] for key, label, rows in fields: value = values[key] # Leave unchanged properties exactly as they were. if url and value == display_value(original, key): continue if not value.strip(): if key in original: deleted.append(key) continue if key == "ingredient": properties[key] = [ line.strip() for line in value.splitlines() if line.strip() ] elif key in ("instructions", "content"): properties[key] = [{"html": value}] else: properties[key] = [value.strip()] if url: payload = {"action": "update", "url": url} if properties: payload["replace"] = properties if deleted: payload["delete"] = deleted else: payload = { "type": ["h-recipe"], "properties": properties, } if url and not properties and not deleted: saved = True destination = url else: micropub_response = web.post( endpoint, headers=headers, json=payload, allow_redirects=False, ) expected = (200, 201, 204) if url else (201, 202) if micropub_response.status in expected: saved = True destination = micropub_response.headers.get( "Location", url ) else: error = ( "Could not save recipe " f"(HTTP {micropub_response.status})." ) <h1>$("Edit recipe" if url else "New recipe")</h1> $if saved: <p>Recipe saved.</p> $if destination: <p><a href="$destination">View recipe</a></p> <p><a href="$route">Create another recipe</a></p> $else: $if error: <p role="alert"><strong>$error</strong></p> $if token and endpoint: <form method="get" action="$route"> <p> <label> Existing recipe URL:<br> <input type="url" name="url" value="$url" placeholder="https://ragt.ag/recipes/beef-burgandy" style="width:100%;box-sizing:border-box"> </label> </p> <button type="submit">Load for editing</button> <a href="$route">New recipe</a> </form> <hr> $if method == "POST" or not error: <form method="post" action="$route"> <input type="hidden" name="url" value="$url"> $if url: <p>Editing <a href="$url">$url</a></p> $for key, label, rows in fields: <p> <label> $label:<br> $if rows == 1: <input name="$key" value="$values[key]" style="width:100%;box-sizing:border-box" $("required" if key == "name" else "")> $else: <textarea name="$key" rows="$rows" style="width:100%;box-sizing:border-box">$values[key]</textarea> </label> </p> <button type="submit"> $("Save changes" if url else "Publish recipe") </button> </form> |