mirror of
https://github.com/arfct/itty-bitty.git
synced 2026-03-11 08:54:33 +00:00
Add extractor
This commit is contained in:
parent
6fb057cec6
commit
82ad60c7bb
6 changed files with 275 additions and 128 deletions
29
docs/extractrecipe.js
Normal file
29
docs/extractrecipe.js
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
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);
|
||||
})('http://localhost')
|
||||
|
||||
|
||||
/*
|
||||
javascript:(function(){
|
||||
let id="ittybitty";
|
||||
if (document.getElementById(id)) return;
|
||||
var l = document.createElement('script');
|
||||
l.setAttribute('type','text/javascript');
|
||||
l.setAttribute('src','http://localhost/extractrecipe.js');
|
||||
l.id=id;
|
||||
document.head.appendChild(l);
|
||||
})();
|
||||
*/
|
||||
|
|
@ -5,6 +5,8 @@
|
|||
|
||||
<link id="favicon" rel=icon href=''>
|
||||
<script src="/js/lzma/lzma-d-min.js"></script>
|
||||
<script src="js/lzma/lzma_worker-min.js"></script>
|
||||
|
||||
<script src="/data.js"></script>
|
||||
<script src="/index.js"></script>
|
||||
|
||||
|
|
|
|||
217
docs/index.js
217
docs/index.js
|
|
@ -1,109 +1,133 @@
|
|||
var HEAD_TAGS = "PGJhc2UgdGFyZ2V0PSJfdG9wIj4K";
|
||||
var HEAD_TAGS_EXTENDED =
|
||||
"PG1ldGEgY2hhcnNldD0idXRmLTgiPjxtZXRhIG5hbWU9InZpZXdwb3J0IiBjb250ZW50PSJ3aWR0aD1kZXZpY2Utd2lkdGgiPjxiYXNlIHRhcmdldD0iX3RvcCI+PHN0eWxlIHR5cGU9InRleHQvY3NzIj5ib2R5e21hcmdpbjowIGF1dG87cGFkZGluZzoxMnZtaW4gMTB2bWluO21heC13aWR0aDozNWVtO2xpbmUtaGVpZ2h0OjEuNWVtO2ZvbnQtZmFtaWx5OiAtYXBwbGUtc3lzdGVtLEJsaW5rTWFjU3lzdGVtRm9udCxzYW5zLXNlcmlmO3dvcmQtd3JhcDogYnJlYWstd29yZDt9PC9zdHlsZT4g";
|
||||
(function () {
|
||||
|
||||
let dataRE = /^data:(?<type>[^;,]+)?(?<attrs>(?:;[^;,]+=[^;,]+)*)?(?:;(?<encoding>\w+64))?,(?<data>.*)$/
|
||||
const HEAD_TAGS = "PGJhc2UgdGFyZ2V0PSJfdG9wIj4K";
|
||||
const HEAD_TAGS_EXTENDED = "PG1ldGEgY2hhcnNldD0idXRmLTgiPjxtZXRhIG5hbWU9InZpZXdwb3J0IiBjb250ZW50PSJ3aWR0aD1kZXZpY2Utd2lkdGgiPjxiYXNlIHRhcmdldD0iX3RvcCI+PHN0eWxlIHR5cGU9InRleHQvY3NzIj5ib2R5e21hcmdpbjowIGF1dG87cGFkZGluZzoxMnZtaW4gMTB2bWluO21heC13aWR0aDozNWVtO2xpbmUtaGVpZ2h0OjEuNWVtO2ZvbnQtZmFtaWx5OiAtYXBwbGUtc3lzdGVtLEJsaW5rTWFjU3lzdGVtRm9udCxzYW5zLXNlcmlmO3dvcmQtd3JhcDogYnJlYWstd29yZDt9PC9zdHlsZT4g";
|
||||
|
||||
function dismiss() {
|
||||
if (document.getElementById("never").checked) window.localStorage.setItem('toasted', true);
|
||||
document.body.classList.remove("toasting")
|
||||
}
|
||||
let dataUrlRE = /^data:(?<type>[^;,]+)?(?<attrs>(?:;[^;,]+=[^;,]+)*)?(?:;(?<encoding>\w+64))?,(?<data>.*)$/
|
||||
|
||||
function setFavicon(favicon) {
|
||||
document.getElementById("favicon").href = 'data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em"><text y=".9em">'+ favicon + '</text></svg>'
|
||||
}
|
||||
|
||||
var validTypes = ["image/svg+xml", "application/ld+json"]
|
||||
window.addEventListener("message", (e) => {
|
||||
if (e.origin == 'null') {
|
||||
if (e.data.title) document.title = e.data.title;
|
||||
if (e.data.favicon) setFavicon(e.data.favicon);
|
||||
}
|
||||
}, false);
|
||||
|
||||
window.onhashchange = window.onload = function() {
|
||||
var hash = window.location.hash.substring(1);
|
||||
if (window.location.search) {
|
||||
console.log("window.location.search.substring(1)", window.location.search.substring(1))
|
||||
window.history.replaceState(null, null, window.location.search.substring(1) + "#" + hash)
|
||||
function dismiss() {
|
||||
if (document.getElementById("never").checked) window.localStorage.setItem('toasted', true);
|
||||
document.body.classList.remove("toasting")
|
||||
}
|
||||
|
||||
if (hash.length < 3) {
|
||||
location.href = "/edit";
|
||||
} else {
|
||||
// if (!window.localStorage.getItem('toasted')) document.body.classList.add("toasting");
|
||||
function setFavicon(favicon) {
|
||||
document.getElementById("favicon").href = 'data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em"><text y=".9em">'+ favicon + '</text></svg>'
|
||||
}
|
||||
|
||||
var iframe = document.getElementById("iframe");
|
||||
var link = document.getElementById("edit");
|
||||
var preamble = undefined;
|
||||
var renderMode = "data";
|
||||
const renderers = {"application/ld+json": "recipe"}
|
||||
|
||||
var slashIndex = hash.indexOf("/");
|
||||
var title = hash.substring(0, slashIndex);
|
||||
document.title = title.length
|
||||
? decodeURIComponent(title.replace(/_/g, " "))
|
||||
: location.hostname;
|
||||
window.addEventListener("message", function(e) {
|
||||
console.log("Message:", e.origin, e.data)
|
||||
// if (e.origin == 'null' || e.origin = ) {
|
||||
if (e.data.title) document.title = e.data.title;
|
||||
if (e.data.favicon) setFavicon(e.data.favicon);
|
||||
if (e.data.setStorage) document.localStorage.setItem(contentHash, e.data.set);
|
||||
if (e.data.getStorage) document.getElementById("iframe").postMessage(document.localStorage.getItem(contentHash), e.origin)
|
||||
// }
|
||||
}, false);
|
||||
|
||||
hash = hash.substring(slashIndex + 1);
|
||||
var editable = hash.charAt(0) == "?";
|
||||
if (editable) {
|
||||
hash = hash.substring(1);
|
||||
// window.onhashchange =
|
||||
window.onload = function() {
|
||||
if (window.location.search) { // Redirect search to path (coming out of server opengraph forwarding)
|
||||
console.log("window.location.search.substring(1)", window.location.search.substring(1))
|
||||
window.history.replaceState(null, null, window.location.search.substring(1) + "#" + fragment)
|
||||
}
|
||||
if (hash.indexOf("data:") != 0) {
|
||||
var colon = hash.indexOf(":");
|
||||
if ( colon > 0 && colon < 15) {
|
||||
document.body.classList.remove("toasting");
|
||||
return window.location.replace(hash);
|
||||
}
|
||||
var compressed = true;
|
||||
preamble = HEAD_TAGS_EXTENDED;
|
||||
hash =
|
||||
"data:text/html;charset=utf-8;" +
|
||||
(compressed ? "bxze64," : "base64,") +
|
||||
hash;
|
||||
} else if (hash.indexOf("data:text/html;") == 0) {
|
||||
preamble = HEAD_TAGS;
|
||||
} else if (hash.indexOf("data:text/plain;") == 0) {
|
||||
preamble = HEAD_TAGS_EXTENDED;
|
||||
} else if (hash.indexOf("data:text/") == 0) {
|
||||
} else if (hash.indexOf("data:image/") == 0) {
|
||||
} else {
|
||||
let match = hash.match(dataRE);
|
||||
let type = match?.groups.type;
|
||||
if (type == "application/ld+json") {
|
||||
let script = '<script src="' + location.origin + '/render/recipe.js"></script>'
|
||||
script = script + " ".repeat(3 - (script.length % 3))
|
||||
preamble = btoa(script);
|
||||
renderMode = "frame";
|
||||
} else if (!validTypes.includes(type)) {
|
||||
console.log("unknown type, rendering as download")
|
||||
let extension = title.split(".")
|
||||
document.querySelector("#dl-name").innerText = title;
|
||||
if (extension.length > 1) document.querySelector("#dl-image").innerText = extension.pop();
|
||||
renderMode = "download";
|
||||
}
|
||||
}
|
||||
link.onclick = function() {
|
||||
location.href = "/edit" + location.hash;
|
||||
};
|
||||
|
||||
var isIE = navigator.userAgent.match(/rv:11/);
|
||||
var isEdge = navigator.userAgent.match(/Edge\//);
|
||||
var isWatch = (window.outerWidth < 200);
|
||||
|
||||
var fragment = window.location.hash.substring(1);
|
||||
if (fragment.length < 3) {
|
||||
return location.href = "/edit";
|
||||
}
|
||||
|
||||
// if (!window.localStorage.getItem('toasted')) document.body.classList.add("toasting");
|
||||
|
||||
var iframe = document.getElementById("iframe");
|
||||
var link = document.getElementById("edit");
|
||||
var dataPrefix = undefined;
|
||||
var renderMode = "data";
|
||||
|
||||
var slashIndex = fragment.indexOf("/");
|
||||
var title = fragment.substring(0, slashIndex);
|
||||
document.title = title.length
|
||||
? decodeURIComponent(title.replace(/_/g, " "))
|
||||
: location.hostname;
|
||||
|
||||
fragment = fragment.substring(slashIndex + 1);
|
||||
var editable = fragment.charAt(0) == "?";
|
||||
if (editable) {
|
||||
fragment = fragment.substring(1);
|
||||
}
|
||||
if (fragment.startsWith("data:")) {
|
||||
let match = fragment.match(dataUrlRE);
|
||||
let attrs = new URLSearchParams(match.groups.attrs?.substring(1).replace(/;/g, "&"));
|
||||
|
||||
if (fragment.indexOf("data:text/html;") == 0) {
|
||||
dataPrefix = HEAD_TAGS;
|
||||
} else if (fragment.indexOf("data:text/plain;") == 0) {
|
||||
dataPrefix = HEAD_TAGS_EXTENDED;
|
||||
renderMode = "frame";
|
||||
} else if (fragment.indexOf("data:text/") == 0) {
|
||||
} else if (fragment.indexOf("data:image/") == 0) {
|
||||
} else {
|
||||
let type = match?.groups.type;
|
||||
const renderer = attrs.get("render") || renderers[type];
|
||||
if (renderer) {
|
||||
var script = renderer;
|
||||
if (script.indexOf("/") == -1) script = location.origin + '/render/' + script + '.js'
|
||||
renderMode = "script";
|
||||
} else {
|
||||
console.log("unknown type, rendering as download")
|
||||
let extension = title.split(".")
|
||||
document.querySelector("#dl-name").innerText = title;
|
||||
if (extension.length > 1) document.querySelector("#dl-image").innerText = extension.pop();
|
||||
renderMode = "download";
|
||||
}
|
||||
}
|
||||
|
||||
if (match?.groups.encoding == "base64") {
|
||||
compressDataURI(fragment, function(compressedFragment) {
|
||||
console.log("Compressing long url", fragment.length, compressedFragment.length)
|
||||
window.location.hash = window.location.hash.replace(fragment, compressedFragment);
|
||||
})
|
||||
|
||||
}
|
||||
} else {
|
||||
var colon = fragment.indexOf(":");
|
||||
if ( colon > 0 && colon < 15) {
|
||||
document.body.classList.remove("toasting");
|
||||
return window.location.replace(fragment);
|
||||
}
|
||||
var compressed = true;
|
||||
dataPrefix = HEAD_TAGS_EXTENDED;
|
||||
fragment =
|
||||
"data:text/html;charset=utf-8;" +
|
||||
(compressed ? "bxze64," : "base64,") +
|
||||
fragment;
|
||||
}
|
||||
|
||||
link.onclick = function() {
|
||||
location.href = "/edit" + location.hash;
|
||||
};
|
||||
|
||||
if ((isEdge || isIE) && location.href.length == 2083) {
|
||||
document.getElementById("warning").innerHTML =
|
||||
'Edge only supports shorter URLs (maximum 2083 bytes).<br>Larger sites may require a different browser.<br><a href="http://reference.bitty.site">Learn more</a>';
|
||||
}
|
||||
decompressDataURI(hash, preamble, function(dataURL) {
|
||||
decompressDataURI(fragment, dataPrefix, function(dataURL, dataContent) {
|
||||
if (!dataURL) return;
|
||||
iframe.sandbox = "allow-downloads allow-scripts allow-forms allow-top-navigation allow-popups allow-modals allow-popups-to-escape-sandbox";
|
||||
|
||||
if (renderMode == "script")
|
||||
if (isIE && renderMode == "data") renderMode = "frame";
|
||||
let contentTarget = iframe.contentWindow.document;
|
||||
if (isWatch) {
|
||||
renderMode = "rewrite";
|
||||
contentTarget = document;
|
||||
}
|
||||
console.log("Rendering via", renderMode)
|
||||
dataURL = dataURL.replace("application/ld+json", "text/plain");
|
||||
// dataURL = dataURL.replace("application/ld+json", "text/plain");
|
||||
if (renderMode == "download") {
|
||||
try {
|
||||
let dl = document.querySelector("#download");
|
||||
|
|
@ -116,25 +140,26 @@ window.onhashchange = window.onload = function() {
|
|||
}
|
||||
} else if (renderMode == "data") {
|
||||
iframe.src = dataURL;
|
||||
} else if (renderMode == "url") {
|
||||
location.href = dataURL;
|
||||
} else if (renderMode == "frame") {
|
||||
} else {
|
||||
dataToString(dataURL, function(content) {
|
||||
var doc = iframe.contentWindow.document;
|
||||
doc.open();
|
||||
doc.write(content);
|
||||
doc.close();
|
||||
});
|
||||
} else if (renderMode == "rewrite") {
|
||||
dataToString(dataURL, function(content) {
|
||||
document.open();
|
||||
document.write(content);
|
||||
document.close();
|
||||
if (renderMode == "frame") {
|
||||
writeDocContent(contentTarget, content)
|
||||
} else if (renderMode == "script") {
|
||||
writeDocContent(contentTarget, `<script>var data = ${content}</script><script src="${script}"></script>`)
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
var link = document.getElementById("edit");
|
||||
link.href = "/edit" + location.hash;
|
||||
link.style.display = editable ? "block" : "none";
|
||||
|
||||
};
|
||||
|
||||
function writeDocContent(doc, content) {
|
||||
doc.open();
|
||||
doc.write(content);
|
||||
doc.close();
|
||||
}
|
||||
};
|
||||
|
||||
})()
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
* {
|
||||
font-family: -apple-system, BlinkMacSystemFont, sans-serif;
|
||||
font-family: -apple-system, BlinkMacSystemFont, sans-serif;
|
||||
}
|
||||
|
||||
body {
|
||||
|
|
@ -12,12 +12,15 @@ body {
|
|||
background-color: gray;
|
||||
background-size: cover;
|
||||
background-position: center;
|
||||
margin-bottom:2em;
|
||||
}
|
||||
|
||||
img.publisher {
|
||||
max-width: 12em;
|
||||
float: right;
|
||||
margin-top: -0.5em;
|
||||
max-width: 5em;
|
||||
/* margin-top: -0.5em; */
|
||||
/* transform:scale(0.7); */
|
||||
|
||||
float:right;
|
||||
}
|
||||
|
||||
.recipe {
|
||||
|
|
@ -37,10 +40,15 @@ img.publisher {
|
|||
header {
|
||||
gap: 2em;
|
||||
margin-bottom: 2em;
|
||||
/*
|
||||
padding-left:15em; */
|
||||
}
|
||||
|
||||
h1 {
|
||||
margin-top: 2em;
|
||||
margin-top: 0.3em;
|
||||
margin-bottom:0.3em;
|
||||
line-height:125%;
|
||||
font-weight:500;
|
||||
}
|
||||
|
||||
.metadata {
|
||||
|
|
@ -77,6 +85,21 @@ h1 {
|
|||
line-height: 1.25em;
|
||||
opacity: 0.75;
|
||||
cursor: pointer;
|
||||
padding-left:3em;
|
||||
}
|
||||
|
||||
.ingredients .yield {
|
||||
margin-bottom:2em;
|
||||
font-weight:bold;
|
||||
text-transform: uppercase;
|
||||
|
||||
margin-left:2em;
|
||||
}
|
||||
.ingredients .quantity {
|
||||
float:left;
|
||||
margin-left:-2.5em;
|
||||
width:2em;
|
||||
text-align:center;
|
||||
}
|
||||
|
||||
.ingredient.complete,
|
||||
|
|
@ -105,6 +128,13 @@ h1 {
|
|||
background-color: currentColor;
|
||||
opacity: 0.54;
|
||||
}
|
||||
hr {
|
||||
/* width: 100px;
|
||||
float: left;
|
||||
height: 0.5px;
|
||||
background-color: currentColor;
|
||||
opacity: 0.54; */
|
||||
}
|
||||
|
||||
a.action {
|
||||
border: none;
|
||||
|
|
@ -112,14 +142,14 @@ a.action {
|
|||
text-transform: uppercase;
|
||||
text-decoration: none;
|
||||
color: currentColor;
|
||||
opacity:0.4;
|
||||
cursor: pointer;
|
||||
border-radius: 1em;
|
||||
line-height: 2em;
|
||||
padding: 0 1em;
|
||||
}
|
||||
|
||||
a.action:hover {
|
||||
background-color: rgba(128, 128, 128, 0.1)
|
||||
opacity:1.0;
|
||||
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 480px) {
|
||||
|
|
@ -134,6 +164,11 @@ a.action:hover {
|
|||
}
|
||||
.ingredient {
|
||||
margin: 0;
|
||||
margin-left:2em;
|
||||
margin-bottom:0.67em;
|
||||
}
|
||||
.ingredients .yield {
|
||||
margin-left:3em;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,9 +1,11 @@
|
|||
let script = document.currentScript;
|
||||
|
||||
console.log("data!", data);
|
||||
|
||||
|
||||
FRACTION_MAP = {
|
||||
'1/2': '\u00BD',
|
||||
'1/4': '\u00BC',
|
||||
'1/2': '\u00BD',
|
||||
'3/4': '\u00BE',
|
||||
'1/3': '\u2153',
|
||||
'2/3': '\u2154',
|
||||
|
|
@ -24,6 +26,16 @@ FRACTION_MAP = {
|
|||
}
|
||||
}
|
||||
|
||||
function getStringProperty(stringOrArray, prop) {
|
||||
if (Array.isArray(stringOrArray)) {
|
||||
stringOrArray = stringOrArray.pop();
|
||||
}
|
||||
if (prop) {
|
||||
stringOrArray = stringOrArray[prop]
|
||||
}
|
||||
return stringOrArray;
|
||||
}
|
||||
|
||||
const m = (selector, ...args) => {
|
||||
var attrs = (args[0] && typeof args[0] === 'object' && !Array.isArray(args[0]) && !(args[0] instanceof HTMLElement)) ? args.shift() : {};
|
||||
|
||||
|
|
@ -57,12 +69,23 @@ const m = (selector, ...args) => {
|
|||
return node;
|
||||
};
|
||||
|
||||
function clean(html) {
|
||||
let doc = new DOMParser().parseFromString(html, 'text/html');
|
||||
return doc.body.textContent || "";
|
||||
}
|
||||
|
||||
function formatTime(time) {
|
||||
const timeRE = /(?<sign>-)?P(?:(?<years>[.,\d]+)Y)?(?:(?<months>[.,\d]+)M)?(?:(?<weeks>[.,\d]+)W)?(?:(?<days>[.,\d]+)D)?T(?:(?<hours>[.,\d]+)H)?(?:(?<minutes>[.,\d]+)M)?(?:(?<seconds>[.,\d]+)S)?/
|
||||
let duration = time.match(timeRE).groups;
|
||||
console.log("match", duration)
|
||||
if (duration) {
|
||||
time = [];
|
||||
|
||||
if (duration.minutes > 60) {
|
||||
duration.hours = Math.floor(duration.minutes / 60);
|
||||
duration.minutes = duration.minutes % 60
|
||||
}
|
||||
|
||||
if (duration.hours > 0) time.push(duration.hours + "h");
|
||||
if (duration.minutes > 0) time.push(duration.minutes + "m");
|
||||
time = time.join(" ");
|
||||
|
|
@ -83,12 +106,25 @@ function highlightStep(e) {
|
|||
|
||||
}
|
||||
|
||||
const ingredientMatch = /^(?:A )?([\/0-9\u00BC-\u00BE\u2153-\u215E\u2009]+) ?(.*)/
|
||||
function ingredientEl(string, terms) {
|
||||
//console.log("terms", terms);
|
||||
|
||||
let match = FRACTION_MAP.replace(clean(string)).match(ingredientMatch);
|
||||
//console.log("match",match )
|
||||
if (match) {
|
||||
let els = match[2].split(/\s/);
|
||||
els = els.map(s => terms?.has(s) ? m("i", s + " ") : s + " ")
|
||||
return [m("span.quantity", match[1]), els]
|
||||
}
|
||||
if (string == "-") return m("hr");
|
||||
return [m("span.quantity", ""), (string)];
|
||||
}
|
||||
|
||||
function render() {
|
||||
let data = document.body.innerHTML;
|
||||
document.body.innerText = "";
|
||||
delete document.documentElement.style.display;
|
||||
try {
|
||||
var json = JSON.parse(data);
|
||||
var json = data; //JSON.parse(data);
|
||||
if (json["@type"] != "Recipe") {
|
||||
json = (json["@graph"] ?? json).find((item) => item["@type"] == "Recipe")
|
||||
}
|
||||
|
|
@ -100,15 +136,25 @@ function render() {
|
|||
if (!json) return;
|
||||
let image = json.image;
|
||||
if (Array.isArray(image)) image = image.shift();
|
||||
image = image.url || image;
|
||||
image = image?.url || image;
|
||||
instructions = json.recipeInstructions;
|
||||
if (Array.isArray(instructions)) {
|
||||
if (Array.isArray(instructions[0])) instructions = instructions.flat()
|
||||
} else {
|
||||
instructions = [{ text: 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 rating = json.aggregateRating;
|
||||
|
||||
|
||||
document.body.appendChild(
|
||||
m("article.recipe", {},
|
||||
image ? m(".thumbnail.noprint", { style: "background-image:url(" + image + ");" }) : null,
|
||||
|
|
@ -118,30 +164,39 @@ function render() {
|
|||
m("h1", json.name),
|
||||
m(".metadata",
|
||||
// json.nutrition?.calories ? m("div", (json.nutrition?.calories) + (parseFloat(json.nutrition?.calories) != NaN ? " calories" : "")) : null,
|
||||
json.totalTime ? m("div", formatTime(json.totalTime)) : undefined,
|
||||
m("div", json.recipeYield),
|
||||
json.author?.name ? m(".author", (json.author?.name)) : null,
|
||||
(rating = json.aggregateRating) ? [
|
||||
parseFloat(rating.ratingValue).toFixed(1),
|
||||
"\u2606".repeat(1),
|
||||
rating.ratingCount ? " (" + rating.ratingCount + ")" : null
|
||||
].join(" ") : null,
|
||||
|
||||
// m(".rating", (json.aggregateRating?.ratingValue), (json.aggregateRating?.ratingCount)),
|
||||
m("a.action.noprint", { onclick: () => window.print() }, "print"),
|
||||
m("a.action.noprint", { href: json.mainEntityOfPage }, "link"),
|
||||
|
||||
),
|
||||
m(".description", json.description),
|
||||
m(".description",
|
||||
clean(json.description),
|
||||
json.author?.name ? m("span.author", (" —" + json.author?.name)) : null,
|
||||
|
||||
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"),
|
||||
|
||||
),
|
||||
|
||||
),
|
||||
m(".columns",
|
||||
m(".ingredients",
|
||||
json.recipeIngredient?.map(i => m("div.ingredient", { onclick: markIngredient }, FRACTION_MAP.replace(i)))
|
||||
m("div.yield", ingredientEl(getStringProperty(json.recipeYield))),
|
||||
|
||||
json.recipeIngredient?.map(i => m("div.ingredient", { onclick: markIngredient }, ingredientEl(i, terms)))
|
||||
),
|
||||
m(".instructions",
|
||||
instructions.map(i => m("div.step", { onclick: highlightStep }, i.text))
|
||||
json.totalTime ? m("div", formatTime(json.totalTime)) : undefined,
|
||||
instructions
|
||||
)
|
||||
)
|
||||
),
|
||||
)
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -31,10 +31,10 @@ function decompressDataURI(dataURI, preamble, callback) {
|
|||
var base64Index = dataURI.indexOf(LZMA64_MARKER);
|
||||
if (base64Index > 0) {
|
||||
var base64 = dataURI.substring(base64Index + LZMA64_MARKER.length);
|
||||
zipToString(base64, function(result) {
|
||||
stringToData(result, function(data) {
|
||||
if (!data) return callback(undefined);
|
||||
callback(dataURI.substring(0, base64Index) + BASE64_MARKER + (preamble || '') + data.split(',')[1])
|
||||
zipToString(base64, function(string) {
|
||||
stringToData(string, function(data) {
|
||||
if (!data) return callback();
|
||||
callback(dataURI.substring(0, base64Index) + BASE64_MARKER + (preamble || '') + data.split(',')[1], string)
|
||||
})
|
||||
})
|
||||
} else {
|
||||
|
|
@ -43,6 +43,7 @@ function decompressDataURI(dataURI, preamble, callback) {
|
|||
}
|
||||
|
||||
function zipToString(data, callback) {
|
||||
let data = data.replace("-","");
|
||||
var array = base64ToByteArray(data);
|
||||
LZMA.decompress(array, function(result, error) {
|
||||
if (!(typeof result === 'string')) result = new Uint8Array(result)
|
||||
|
|
|
|||
Loading…
Reference in a new issue