From 409750078ec3ec0773ab764a98d47bf8e9f4801c Mon Sep 17 00:00:00 2001 From: Nicholas Jitkoff Date: Sat, 29 Jan 2022 21:55:46 -0800 Subject: [PATCH] adjust formatting --- docs/extractrecipe.js | 41 ++++++++++++++++-------- docs/render/recipe.css | 35 ++++++++++++-------- docs/render/recipe.js | 72 +++++++++++++++++++++++++++--------------- 3 files changed, 95 insertions(+), 53 deletions(-) diff --git a/docs/extractrecipe.js b/docs/extractrecipe.js index 8d32e50..9776dd6 100644 --- a/docs/extractrecipe.js +++ b/docs/extractrecipe.js @@ -1,18 +1,31 @@ javascript:((itty_bitty_recipes) => { -let l=document.querySelector('script[type="application/ld+json"]'); -if (!l) return alert("No Recipe element found in HTML") -let ldjson = l.innerText.trim(); -let json = JSON.parse(ldjson); -if (Array.isArray(json)) json = json.find((o)=>o['@type']=="Recipe") -console.log(json) -var blob = new Blob([JSON.stringify(json)],{type : 'application/ld+json;charset=utf-8'}); -var a = new FileReader(); -a.onload = function(e) { - let url = itty_bitty_recipes + '/#/' + e.target.result; - console.log("URL", url.length, url) - open(url); -}; -a.readAsDataURL(blob); + try { + + let l=document.querySelector('script[type="application/ld+json"]'); + + if (!l) throw ("No metadata found in HTML.") + let ldjson = l.innerText.trim(); + let json = JSON.parse(ldjson); + + console.log("Found metadata:", json) + if (json["@graph"]) json = json["@graph"]; + if (!Array.isArray(json)) json = [json]; + json = json.find((o)=>o['@type']=="Recipe") + + if (!json?.recipeInstructions?.length) throw ("Incomplete recipe information.") + + var blob = new Blob([JSON.stringify(json)],{type : 'application/ld+json;charset=utf-8'}); + var a = new FileReader(); + a.onload = function(e) { + let url = itty_bitty_recipes + '/#/' + e.target.result; + console.log("URL", url.length, url) + open(url); + }; + a.readAsDataURL(blob); + + } catch (e) { + alert("itty.bitty.recipes: Failed\n" + e) + } })('http://localhost') diff --git a/docs/render/recipe.css b/docs/render/recipe.css index dc89a1e..232efc8 100644 --- a/docs/render/recipe.css +++ b/docs/render/recipe.css @@ -26,7 +26,7 @@ img.publisher { .recipe { max-width: 40em; margin: auto; - line-height: 133%; + line-height: 125%; } .columns { @@ -57,7 +57,7 @@ h1 { flex-wrap: wrap; gap: 0 1em; margin-bottom: 1em; - line-height: 2em; + /* line-height: 2em; */ } .metadata div:after { @@ -65,22 +65,32 @@ h1 { margin-left: 1em; } +.time { + text-transform: uppercase; + /* margin-bottom: 1em; */ +} + .ingredients { font-weight: 600; font-size: 100%; - padding-top: 1em; + /* padding-top: 1em; */ flex: 0 1 35%; } .instructions { white-space: pre-wrap; - line-height: 125%; - font-size: 100%; + /* line-height: 125%; */ + /* font-size: 100%; */ flex: 0 1 65%; + margin-top: -1px; } +.substep { + margin-bottom: 1em; + /* display: inline; */ +} .ingredient { - padding: 0.625em 1em; + padding: 0.5em 1em; margin: 0 -1em; line-height: 1.25em; opacity: 0.75; @@ -89,10 +99,9 @@ h1 { } .ingredients .yield { - margin-bottom:2em; + margin-bottom: 1.5em; font-weight:bold; text-transform: uppercase; - margin-left:2em; } .ingredients .quantity { @@ -114,19 +123,19 @@ h1 { } .step { - padding-top: 2em; max-width: 40em; cursor: pointer; + /* border:1px solid red; */ + margin-bottom: 1em; } -.step:before { - content: ""; +.instructions hr { width: 100px; - float: left; - margin-top: -1em; height: 0.5px; background-color: currentColor; opacity: 0.54; + border:none; + margin: 0 0 1em 0; } hr { /* width: 100px; diff --git a/docs/render/recipe.js b/docs/render/recipe.js index 2ad02ec..5dbc0ac 100644 --- a/docs/render/recipe.js +++ b/docs/render/recipe.js @@ -1,7 +1,5 @@ let script = document.currentScript; -console.log("data!", data); - FRACTION_MAP = { '1/4': '\u00BC', @@ -86,8 +84,8 @@ function formatTime(time) { duration.minutes = duration.minutes % 60 } - if (duration.hours > 0) time.push(duration.hours + "h"); - if (duration.minutes > 0) time.push(duration.minutes + "m"); + if (duration.hours > 0) time.push(duration.hours + "hr"); + if (duration.minutes > 0) time.push(duration.minutes + "min"); time = time.join(" "); } return time; @@ -102,7 +100,7 @@ function highlightStep(e) { // e.target.parent.children.forEach((i,el) => { // el.classList.toggle("complete", ) // } - e.target.classList.toggle("complete") + e.target.closest(".step").classList.toggle("complete") } @@ -138,19 +136,36 @@ function render() { if (Array.isArray(image)) image = image.shift(); image = image?.url || image; instructions = json.recipeInstructions; - if (Array.isArray(instructions)) { - if (Array.isArray(instructions[0])) instructions = instructions.flat() - } else { - instructions = [{ text: instructions }]; + + + + function parseInstructions(instruction) { + + if (instruction.itemListElement) { + return m(".section", m("hr"), m("h3", instruction.name), parseInstructions(instruction.itemListElement)); + } + + if (Array.isArray(instruction)) { + if (Array.isArray(instruction[0])) instruction = instruction.flat(); + return instruction.map(i => parseInstructions(i)); + } + let text = (instruction.text || instruction); + // text = text.split(". ").map((t, i) => m("div.substep", t)) + console.log("text",text); + return m("div.step", { onclick: highlightStep }, m("hr"), text) } + + instructions = m(".instructions",parseInstructions(instructions)); + parent.postMessage({title:json.name, favicon:"🍳"}, "*"); -console.log("post message") - instructions = instructions.map(i => i.text || i); - let text = instructions.join(" "); - var terms = new Set(text.split(/\s/).filter(s => s.length > 2)); - instructions = instructions.map(i => m("div.step", { onclick: highlightStep }, i)) + + // let text = instructions.join(" "); + var terms = new Set(instructions.textContent.split(/\s/).filter(s => s.length > 2)); + console.log("instructions.innerText", terms) + + // instructions = instructions.map(i => m("div.step", { onclick: highlightStep }, i)) let rating = json.aggregateRating; @@ -163,6 +178,21 @@ console.log("post message") m("img.publisher", { src: json.publisher?.image ?.[0]?.url ?? json.publisher ?.logo ?.url }), m("h1", json.name), m(".metadata", + m(".time", + json.totalTime ? m("span", formatTime(json.totalTime)) : undefined, + json.prepTime ? m("span", " - ", formatTime(json.prepTime), " prep") : undefined, + json.cookTime ? m("span", " - ", formatTime(json.cookTime), " cook") : undefined, + ), + + (rating && rating.ratingCount != 0) ? [ + " • ", + "\u2606".repeat(rating.ratingValue), " ", + parseFloat(rating.ratingValue).toFixed(1), " ", + rating.ratingCount ? m("span.count", `(${rating.ratingCount.toString()})`) : null + ] : null, + " • ", m("a.action.noprint", { onclick: () => window.print() }, "print"), + " • ", m("a.action.noprint", { href: json.mainEntityOfPage || json.url, target:"_blank"}, "link"), + // json.nutrition?.calories ? m("div", (json.nutrition?.calories) + (parseFloat(json.nutrition?.calories) != NaN ? " calories" : "")) : null, // m(".rating", (json.aggregateRating?.ratingValue), (json.aggregateRating?.ratingCount)), @@ -174,15 +204,6 @@ console.log("post message") m("p"), - (rating && rating.ratingCount != 0) ? [ - " • ", - "\u2606".repeat(rating.ratingValue), " ", - parseFloat(rating.ratingValue).toFixed(1), " ", - rating.ratingCount ? m("span.count", `(${rating.ratingCount.toString()})`) : null - ] : null, - " • ", m("a.action.noprint", { onclick: () => window.print() }, "print"), - " • ", m("a.action.noprint", { href: json.mainEntityOfPage || json.url, target:"_blank"}, "link"), - ), ), @@ -190,10 +211,9 @@ console.log("post message") m(".ingredients", m("div.yield", ingredientEl(getStringProperty(json.recipeYield))), - json.recipeIngredient?.map(i => m("div.ingredient", { onclick: markIngredient }, ingredientEl(i, terms))) + json.recipeIngredient?.map(i => m("div.ingredient", { onclick: markIngredient }, ingredientEl(clean(i), terms))) ), - m(".instructions", - json.totalTime ? m("div", formatTime(json.totalTime)) : undefined, + m(".instructions", instructions ) ),