mirror of
https://github.com/arfct/itty-bitty.git
synced 2026-03-11 08:54:33 +00:00
Add qr codes to recipes
This commit is contained in:
parent
946f0b57fc
commit
597a0482af
3 changed files with 157 additions and 83 deletions
|
|
@ -39,3 +39,11 @@ function renderScriptContent(data, origin) {
|
|||
window.addEventListener("message", function(e) {
|
||||
renderScriptContent(e.data, e.origin);
|
||||
}, false);
|
||||
|
||||
function QRCodeURL(url, options) {
|
||||
let size = options?.size ?? 547;
|
||||
let errorCorrection = options?.correction ?? 'L';
|
||||
let margin = options?.margin?.toString() || "1";
|
||||
console.log("margin", options?.margin);
|
||||
return `https://chart.googleapis.com/chart?cht=qr&chs=${size}x${size}&chld=${errorCorrection}|${margin}&choe=UTF-8&chl=${encodeURIComponent(url || location.href)}`;
|
||||
}
|
||||
|
|
@ -7,23 +7,27 @@ body {
|
|||
background-color: var(--background-color);
|
||||
color: var(--text-color);
|
||||
|
||||
--text-color:rgba(0,0,0,0.87);
|
||||
--text-color:
|
||||
rgba(0,0,0,0.87);
|
||||
--opaque-text-color:black;
|
||||
--disabled-text-color:rgba(16, 12, 12, 0.54);
|
||||
--disabled-text-color:
|
||||
rgba(16, 12, 12, 0.54);
|
||||
--hover-background-color:
|
||||
rgba(16, 12, 12, 0.07);
|
||||
--background-color:white;
|
||||
|
||||
}
|
||||
|
||||
.thumbnail {
|
||||
width: 100%;
|
||||
padding-top:28.125%;
|
||||
padding-top: 77%;
|
||||
max-height:1vh;
|
||||
background-color: gray;
|
||||
background-size: cover;
|
||||
background-position: center;
|
||||
margin-bottom:2em;
|
||||
box-sizing: border-box;
|
||||
/* margin: 0 -2em; */}
|
||||
/* margin: 0 -2em; */
|
||||
}
|
||||
|
||||
.ingredients:hover .noun {
|
||||
/* text-decoration:underline; */
|
||||
|
|
@ -96,7 +100,8 @@ ul.step {
|
|||
|
||||
span.number {
|
||||
margin-left: -27px;
|
||||
float:left;
|
||||
float:
|
||||
left;
|
||||
border: 1.5px solid var(--text-color);
|
||||
font-weight: 800;
|
||||
border-radius:10em;
|
||||
|
|
@ -105,9 +110,9 @@ span.number {
|
|||
text-align: center;
|
||||
font-size: 10px;
|
||||
line-height: 16px;
|
||||
opacity:0.7;
|
||||
opacity: 0.7;
|
||||
user-select: none;
|
||||
/* background: black; */
|
||||
/* background: black; */
|
||||
}
|
||||
|
||||
.complete span.number,
|
||||
|
|
@ -184,16 +189,27 @@ li:hover {
|
|||
}
|
||||
|
||||
.ingredients {
|
||||
font-weight: 500;
|
||||
font-size: 90%;
|
||||
font-weight: 600;
|
||||
font-size: 80%;
|
||||
/* position:sticky; */
|
||||
/* top: 0px; */
|
||||
/* padding-top: 1em; */
|
||||
flex: 0 1 35%;
|
||||
/* color: rgba(0,0,0,0.8); */}
|
||||
/* color: rgba(0,0,0,0.8); */
|
||||
/* color:rgb(0, 118, 173); */
|
||||
|
||||
}
|
||||
.noun {
|
||||
font-weight: 700;
|
||||
font-weight: 600;
|
||||
color: var(--opaque-text-color);
|
||||
|
||||
}
|
||||
.complete .noun {
|
||||
color:var(--disabled-text-color);
|
||||
}
|
||||
li:hover .noun {
|
||||
text-decoration: 1px dotted underline;
|
||||
/* background-color: var(--hover-background-color); */
|
||||
}
|
||||
|
||||
.instructions {
|
||||
|
|
@ -257,11 +273,12 @@ text-decoration: rgba(0,0,0,0.75) solid 0.5px line-through; /* Ignored in CSS1/C
|
|||
}
|
||||
|
||||
.instructions hr {
|
||||
width: 100px;
|
||||
width: 5em;
|
||||
height: 0.5px;
|
||||
background-color: currentColor;
|
||||
opacity: .3;
|
||||
border:none;
|
||||
opacity: 1;
|
||||
border:
|
||||
none;
|
||||
margin: 0.25em 0;
|
||||
}
|
||||
|
||||
|
|
@ -276,30 +293,37 @@ hr {
|
|||
opacity: 0.54; */
|
||||
}
|
||||
|
||||
a.action {
|
||||
/* border: none;
|
||||
background: none;
|
||||
text-transform: uppercase;
|
||||
text-decoration: none;
|
||||
color: currentColor;
|
||||
opacity: 0.;
|
||||
cursor: pointer;
|
||||
border: 1px solid currentColor;
|
||||
padding: 0 0.6em;
|
||||
border-radius: 1em;
|
||||
/* line-height: 16px;
|
||||
font-size: 14px;
|
||||
box-sizing: border-box;
|
||||
line-height: 17px; */
|
||||
border-radius:1em;
|
||||
cursor:pointer;
|
||||
.actions {
|
||||
display: flex;
|
||||
gap: 0.5em 1em;
|
||||
line-height:24px;
|
||||
margin-left: -4px;
|
||||
}
|
||||
|
||||
a.action {
|
||||
border-radius:50%;
|
||||
cursor: pointer;
|
||||
width: 1.5em;
|
||||
height: 1.5em;
|
||||
/* display: flex;
|
||||
align-items: center;
|
||||
justify-content: center; */
|
||||
text-align: center;
|
||||
line-height: 1.5em;
|
||||
background-color:
|
||||
var(--hover-background-color);
|
||||
}
|
||||
|
||||
a.action:hover {
|
||||
background-color:var(--hover-background-color);
|
||||
}
|
||||
a.action:hover:not(:active) .icon {
|
||||
opacity:1.0;
|
||||
/* text-decoration: none;
|
||||
box-shadow: 0 1px 1px currentColor;
|
||||
margin-top: -1px; */
|
||||
}
|
||||
|
||||
a.action .icon {
|
||||
margin-right: 0;
|
||||
opacity: 1.0;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 480px) {
|
||||
|
|
@ -335,22 +359,21 @@ a.action:hover:not(:active) .icon {
|
|||
}
|
||||
|
||||
.metadata .icon {
|
||||
font-size: 15px;
|
||||
vertical-align: middle;
|
||||
margin-top: -4px;
|
||||
margin-right: 4px;
|
||||
opacity:0.6;
|
||||
font-size: 15px;vertical-align: middle;margin-top: -4px;margin-right: 4px;opacity: .6;
|
||||
color:var(--text-color);
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
body {
|
||||
--text-color:white;
|
||||
--hover-background-color:rgba(255,255,255, 0.14);
|
||||
--background-color:#222;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@media print {
|
||||
body {
|
||||
font-size: 14px;
|
||||
|
|
@ -360,6 +383,40 @@ color:var(--text-color);
|
|||
}
|
||||
}
|
||||
|
||||
.instructions.numbered hr {margin: 0.7em 0;height: 1.5px;opacity: 10;}
|
||||
@media not print {
|
||||
.print-only {
|
||||
display:none;
|
||||
}
|
||||
}
|
||||
|
||||
.instructions.numbered {/* margin-top: -1.6em; */}
|
||||
.instructions.numbered hr {margin: 0.7em -1px;height: 1.5px;opacity: 0.2;width: auto;}
|
||||
|
||||
.instructions.numbered {/* margin-top: -1.6em; */}
|
||||
|
||||
|
||||
img.qr {
|
||||
width:100%;
|
||||
}
|
||||
|
||||
@media screen and (min-width: 1000px) {
|
||||
body {
|
||||
width:auto;
|
||||
margin:0;
|
||||
}
|
||||
.recipe {
|
||||
flex-direction: row;
|
||||
display: flex;
|
||||
max-width: unset;
|
||||
}
|
||||
|
||||
#thumbnail-container {width: 100%;height: 100vh;}
|
||||
|
||||
.thumbnail {
|
||||
max-height: 100vh;
|
||||
height: 100vh;
|
||||
}
|
||||
.recipe article {
|
||||
max-width:50em;
|
||||
padding: 4em;
|
||||
}
|
||||
}
|
||||
|
|
@ -25,8 +25,8 @@ FRACTION_MAP = {
|
|||
}
|
||||
|
||||
let ignoredTerms = [
|
||||
"teaspoon", "teaspoons", "tablespoon", "tablespoons", "cup", "cups", "taste", "more", "melted", "into", "wide", "pound", "pounds", "gram", "grams", "you", "ounce", "ounces", "thinly", "sliced",
|
||||
"pan", "finely", "ground", "garnish", "about", "cut", "and", "smashed", "each", "the", "medium", "large", "small", "for", "chopped", "minced", "grated", "box", "softened", "directed", "shredded", "cooked", "from", "frozen", "thawed"
|
||||
"note", "teaspoon", "teaspoons", "tablespoon", "tablespoons", "cup", "cups", "taste", "more", "melted", "into", "wide", "pound", "pounds", "gram", "grams", "you", "ounce", "ounces", "thinly", "sliced",
|
||||
"pan", "cube", "cubes", "finely", "ground", "garnish", "about", "cut", "and", "smashed", "each", "the", "medium", "large", "small", "for", "chopped", "minced", "grated", "box", "softened", "directed", "shredded", "cooked", "from", "frozen", "thawed"
|
||||
]
|
||||
|
||||
const replacements = {
|
||||
|
|
@ -142,7 +142,7 @@ function highlightStep(e) {
|
|||
|
||||
}
|
||||
|
||||
const ingredientMatch = /^(?:A )?([\/0-9 \u00BC-\u00BE\u2153-\u215E\u2009]*) (.*)/
|
||||
const ingredientMatch = /^(?:A )?([\/0-9 \u00BC-\u00BE\u2153-\u215E\u2009]*)\s(.*)/
|
||||
|
||||
|
||||
function ingredientEl(string, terms) {
|
||||
|
|
@ -164,6 +164,10 @@ function highlightTerms(string, terms) {
|
|||
return string.replace(pattern, match => `<span class="noun" id="term-${match}">${match}</span>`);
|
||||
}
|
||||
|
||||
function share() {
|
||||
parent.postMessage({share:{}}, "*");
|
||||
}
|
||||
|
||||
function render() {
|
||||
delete document.documentElement.style.display;
|
||||
document.body.childNodes.forEach((c) => document.body.removeChild(c))
|
||||
|
|
@ -286,50 +290,55 @@ function render() {
|
|||
|
||||
|
||||
document.body.appendChild(
|
||||
m("article.recipe", {},
|
||||
m(".recipe", {},
|
||||
image ? m("#thumbnail-container", m("#thumbnail.thumbnail.noprint", { style: "background-image:url(" + ");", onload: imgload })) : null,
|
||||
|
||||
m("header",
|
||||
m("img.publisher", { src: json.publisher?.image ?.[0]?.url ?? json.publisher ?.logo ?.url }),
|
||||
m("h1", title),
|
||||
m(".metadata",
|
||||
m("div", m("span.yield", m(".icon.material-icons-outlined", "restaurant"), yield)),
|
||||
m(".time",
|
||||
m(".icon.material-icons-outlined", "timer"),
|
||||
m("article",
|
||||
m("header",
|
||||
m("img.publisher", { src: json.publisher?.image ?.[0]?.url ?? json.publisher ?.logo ?.url }),
|
||||
m("h1", title),
|
||||
m(".metadata",
|
||||
m("div", m("span.yield", m(".icon.material-icons-outlined", "restaurant"), yield)),
|
||||
m(".time",
|
||||
m(".icon.material-icons-outlined", "timer"),
|
||||
|
||||
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,
|
||||
// ")"
|
||||
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) ? m("div.rating",
|
||||
m(".icon.material-icons-outlined", "grade"),
|
||||
parseFloat(rating.ratingValue).toFixed(1), " ",
|
||||
// ratingCount ? m("span.count", ratingCount.toString()) : null
|
||||
)
|
||||
: null,
|
||||
json.nutrition?.calories ?
|
||||
m("div", m(".icon.material-icons-outlined", "info"),
|
||||
(json.nutrition?.calories.toString().replace("calories", "Cal").replace("kcal", "Cal")) + (isNaN(json.nutrition?.calories) ? '' : ' Cal')) : null,
|
||||
|
||||
m("div.spacer"),
|
||||
m(".actions",
|
||||
m("a.action.noprint", { title:"Open original", href: json.mainEntityOfPage || json.url, target:"_blank"}, m(".icon.material-icons-outlined", "public")),
|
||||
m("a.action.noprint", { title:"Share", onclick: share}, m(".icon.material-icons-outlined", "share")),
|
||||
m("a.action.noprint", { title:"Show steps as list", href: "#", onclick: () => {reformat = !reformat; render(); return false;}}, m(".icon.material-icons-outlined", "notes")),
|
||||
m("a.action.noprint", { title:"Print", href: "#", onclick: () => window.print() }, m(".icon.material-icons-outlined", "print")),
|
||||
)
|
||||
),
|
||||
(rating) ? m("div.rating",
|
||||
m(".icon.material-icons-outlined", "grade"),
|
||||
parseFloat(rating.ratingValue).toFixed(1), " ",
|
||||
// ratingCount ? m("span.count", ratingCount.toString()) : null
|
||||
)
|
||||
: null,
|
||||
json.nutrition?.calories ? m("div", m(".icon.material-icons-outlined", "info"), (json.nutrition?.calories) + (parseFloat(json.nutrition?.calories) != NaN ? " calories" : "")) : null,
|
||||
json.description ? m(".description",
|
||||
clean(json.description),
|
||||
json.author?.name ? m("span.author", (" —" + json.author?.name)) : null,
|
||||
|
||||
m("div.spacer"),
|
||||
m("a.action.noprint", { title:"Open original", href: json.mainEntityOfPage || json.url, target:"_blank"}, m(".icon.material-icons-outlined", "link")),
|
||||
m("a.action.noprint", { title:"Show steps as list", href: "#", onclick: () => {reformat = !reformat; render(); return false;}}, m(".icon.material-icons-outlined", "format_list_numbered")),
|
||||
m("a.action.noprint", { title:"Print", href: "#", onclick: () => window.print() }, m(".icon.material-icons-outlined", "print")),
|
||||
m("p"),
|
||||
|
||||
) : null,
|
||||
|
||||
),
|
||||
json.description ? m(".description",
|
||||
clean(json.description),
|
||||
json.author?.name ? m("span.author", (" —" + json.author?.name)) : null,
|
||||
|
||||
m("p"),
|
||||
|
||||
) : null,
|
||||
|
||||
),
|
||||
m(".columns",
|
||||
m(".ingredients", ingredients),
|
||||
m(reformat ? ".instructions.numbered" : ".instructions", instructions)
|
||||
),
|
||||
m("main.columns",
|
||||
m("section.ingredients", ingredients, m("img.qr.print-only", {src:QRCodeURL(params.originalURL, {margin:0})})),
|
||||
m(reformat ? "section.instructions.numbered" : "section.instructions", instructions)
|
||||
),
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue