Merge branch 'LukeSmithxyz:master' into master
commit
5f8fd430de
@ -1,12 +0,0 @@
|
||||
<!--
|
||||
- Recipes should be `.md` files in the `src/` directory. Look at already
|
||||
existing `.md` files for examples or see [example](example.md).
|
||||
- File names should be the name of the dish with words separated by hyphens
|
||||
(`-`). Not underscores, and definitely not spaces.
|
||||
- Recipe must be based, i.e. good traditional and substantial food. Nothing
|
||||
ironic, meme-tier hyper-sugary, meat-substitute, etc.
|
||||
- Be sure to add a small number of relevant tags to your recipe (and remove
|
||||
the dummy tags). Try to use already existing tags.
|
||||
- Don't include salt and pepper and other ubiquitous things in the ingredients
|
||||
list.
|
||||
-->
|
@ -1,12 +0,0 @@
|
||||
on: pull_request
|
||||
|
||||
jobs:
|
||||
check_files:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- name: Check files for compliance
|
||||
run: .github/workflows/scripts/check-files.sh
|
||||
|
@ -1,153 +0,0 @@
|
||||
#!/bin/sh
|
||||
set -eu
|
||||
|
||||
SIZE_LIMIT=150000
|
||||
FAIL=0
|
||||
|
||||
check_size() {
|
||||
size="$(stat --printf="%s" "$1")"
|
||||
if [ "$size" -gt "$SIZE_LIMIT" ]; then
|
||||
echo "File $1 is bigger than specified $SIZE_LIMIT limit"
|
||||
FAIL=1
|
||||
fi
|
||||
}
|
||||
|
||||
check_file_name() {
|
||||
fileName="$1"
|
||||
expectedFolder="$2"
|
||||
|
||||
shouldname="${expectedFolder}/$(basename "$fileName" |
|
||||
iconv --to-code=utf-8 |
|
||||
tr '[:upper:]' '[:lower:]' |
|
||||
tr '_ ' '-')"
|
||||
|
||||
if [ "$shouldname" != "$fileName" ]; then
|
||||
echo "$1 should be named $shouldname."
|
||||
FAIL=1
|
||||
fi
|
||||
}
|
||||
|
||||
check_webp_name() {
|
||||
check_file_name "$1" "data/pix"
|
||||
}
|
||||
|
||||
check_recipe_name() {
|
||||
check_file_name "$1" "src"
|
||||
}
|
||||
|
||||
check_recipe_content() {
|
||||
errMsgs="$(awk '
|
||||
BEGIN {
|
||||
HAS_TITLE = 0;
|
||||
HAS_TAGS = 0;
|
||||
HAS_INVALID_TAGS = 0;
|
||||
NUM_TAGS = 0;
|
||||
HAS_INGREDIENTS = 0;
|
||||
HAS_DIRECTIONS = 0;
|
||||
HAS_CONSECUTIVE_EMPTY_LINES = 0;
|
||||
|
||||
CONSECUTIVE_EMPTY_LINES = 0;
|
||||
}
|
||||
|
||||
# First line should be the title
|
||||
NR == 1 && /^# / {
|
||||
HAS_TITLE = 1;
|
||||
next;
|
||||
}
|
||||
|
||||
$0 == "## Ingredients" {
|
||||
HAS_INGREDIENTS = 1;
|
||||
}
|
||||
|
||||
$0 == "## Directions" {
|
||||
HAS_DIRECTIONS = 1;
|
||||
}
|
||||
|
||||
$0 == "" {
|
||||
CONSECUTIVE_EMPTY_LINES++
|
||||
if (CONSECUTIVE_EMPTY_LINES >= 2) {
|
||||
HAS_CONSECUTIVE_EMPTY_LINES = 1;
|
||||
}
|
||||
}
|
||||
|
||||
$0 != "" {
|
||||
CONSECUTIVE_EMPTY_LINES = 0;
|
||||
}
|
||||
|
||||
END {
|
||||
# Last line should be the tags list
|
||||
if ($1 == ";tags:") {
|
||||
HAS_TAGS = 1;
|
||||
NUM_TAGS = NF - 1;
|
||||
|
||||
# Loop through all the tags
|
||||
for (i = 2; i <= NF; i++) {
|
||||
# Make sure that each tag only contains lowercase letters and hyphens
|
||||
if ($i !~ "^[a-z-]+$") {
|
||||
HAS_INVALID_TAGS = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!HAS_TITLE) {
|
||||
print "Recipe does not have a properly formatted title on the first line."
|
||||
}
|
||||
|
||||
if (!HAS_TAGS) {
|
||||
print "Recipe does not have a properly formatted tags on the last line."
|
||||
} else {
|
||||
if (HAS_INVALID_TAGS) {
|
||||
print "Recipe has invalid tags. Tags must be separated by spaces and contain only lowercase letters or hyphens (-)";
|
||||
}
|
||||
|
||||
if (NUM_TAGS < 2) {
|
||||
print "Recipe only has " NUM_TAGS " tags. Add some more."
|
||||
} else if (NUM_TAGS > 5) {
|
||||
print "Recipe has " NUM_TAGS " tags which is too many. Remove some tags."
|
||||
}
|
||||
}
|
||||
|
||||
if (!HAS_INGREDIENTS) {
|
||||
print "Recipe does not have an ingredients list."
|
||||
}
|
||||
|
||||
if (!HAS_DIRECTIONS) {
|
||||
print "Recipe does not have a directions section."
|
||||
}
|
||||
|
||||
if (HAS_CONSECUTIVE_EMPTY_LINES) {
|
||||
print "Recipe has at least 2 consecutive empty lines.";
|
||||
}
|
||||
}
|
||||
' "$1")"
|
||||
|
||||
if [ -n "$errMsgs" ]; then
|
||||
echo "$errMsgs"
|
||||
FAIL=1
|
||||
fi
|
||||
}
|
||||
|
||||
while IFS= read -r file; do
|
||||
echo "Checking '$file'"
|
||||
case "$file" in
|
||||
# Ignore these files
|
||||
index.md) ;;
|
||||
.github/*.md) ;;
|
||||
|
||||
*.webp)
|
||||
check_size "$file"
|
||||
check_webp_name "$file"
|
||||
;;
|
||||
*.md)
|
||||
check_recipe_name "$file"
|
||||
check_recipe_content "$file"
|
||||
;;
|
||||
esac
|
||||
# Separate each file for easier reading.
|
||||
echo ""
|
||||
done <<EOF
|
||||
$(git diff --name-only "$(git merge-base origin/master HEAD)")
|
||||
EOF
|
||||
|
||||
exit $FAIL
|
@ -1,4 +1,10 @@
|
||||
rss.xml
|
||||
atom.xml
|
||||
blog
|
||||
tags
|
||||
/themes/
|
||||
|
||||
# Generated files by hugo
|
||||
/public/
|
||||
/resources/_gen/
|
||||
/assets/jsconfig.json
|
||||
hugo_stats.json
|
||||
|
||||
# Temporary lock file while building
|
||||
/.hugo_build.lock
|
||||
|
@ -1,121 +0,0 @@
|
||||
Creative Commons Legal Code
|
||||
|
||||
CC0 1.0 Universal
|
||||
|
||||
CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE
|
||||
LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN
|
||||
ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS
|
||||
INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES
|
||||
REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS
|
||||
PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM
|
||||
THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED
|
||||
HEREUNDER.
|
||||
|
||||
Statement of Purpose
|
||||
|
||||
The laws of most jurisdictions throughout the world automatically confer
|
||||
exclusive Copyright and Related Rights (defined below) upon the creator
|
||||
and subsequent owner(s) (each and all, an "owner") of an original work of
|
||||
authorship and/or a database (each, a "Work").
|
||||
|
||||
Certain owners wish to permanently relinquish those rights to a Work for
|
||||
the purpose of contributing to a commons of creative, cultural and
|
||||
scientific works ("Commons") that the public can reliably and without fear
|
||||
of later claims of infringement build upon, modify, incorporate in other
|
||||
works, reuse and redistribute as freely as possible in any form whatsoever
|
||||
and for any purposes, including without limitation commercial purposes.
|
||||
These owners may contribute to the Commons to promote the ideal of a free
|
||||
culture and the further production of creative, cultural and scientific
|
||||
works, or to gain reputation or greater distribution for their Work in
|
||||
part through the use and efforts of others.
|
||||
|
||||
For these and/or other purposes and motivations, and without any
|
||||
expectation of additional consideration or compensation, the person
|
||||
associating CC0 with a Work (the "Affirmer"), to the extent that he or she
|
||||
is an owner of Copyright and Related Rights in the Work, voluntarily
|
||||
elects to apply CC0 to the Work and publicly distribute the Work under its
|
||||
terms, with knowledge of his or her Copyright and Related Rights in the
|
||||
Work and the meaning and intended legal effect of CC0 on those rights.
|
||||
|
||||
1. Copyright and Related Rights. A Work made available under CC0 may be
|
||||
protected by copyright and related or neighboring rights ("Copyright and
|
||||
Related Rights"). Copyright and Related Rights include, but are not
|
||||
limited to, the following:
|
||||
|
||||
i. the right to reproduce, adapt, distribute, perform, display,
|
||||
communicate, and translate a Work;
|
||||
ii. moral rights retained by the original author(s) and/or performer(s);
|
||||
iii. publicity and privacy rights pertaining to a person's image or
|
||||
likeness depicted in a Work;
|
||||
iv. rights protecting against unfair competition in regards to a Work,
|
||||
subject to the limitations in paragraph 4(a), below;
|
||||
v. rights protecting the extraction, dissemination, use and reuse of data
|
||||
in a Work;
|
||||
vi. database rights (such as those arising under Directive 96/9/EC of the
|
||||
European Parliament and of the Council of 11 March 1996 on the legal
|
||||
protection of databases, and under any national implementation
|
||||
thereof, including any amended or successor version of such
|
||||
directive); and
|
||||
vii. other similar, equivalent or corresponding rights throughout the
|
||||
world based on applicable law or treaty, and any national
|
||||
implementations thereof.
|
||||
|
||||
2. Waiver. To the greatest extent permitted by, but not in contravention
|
||||
of, applicable law, Affirmer hereby overtly, fully, permanently,
|
||||
irrevocably and unconditionally waives, abandons, and surrenders all of
|
||||
Affirmer's Copyright and Related Rights and associated claims and causes
|
||||
of action, whether now known or unknown (including existing as well as
|
||||
future claims and causes of action), in the Work (i) in all territories
|
||||
worldwide, (ii) for the maximum duration provided by applicable law or
|
||||
treaty (including future time extensions), (iii) in any current or future
|
||||
medium and for any number of copies, and (iv) for any purpose whatsoever,
|
||||
including without limitation commercial, advertising or promotional
|
||||
purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each
|
||||
member of the public at large and to the detriment of Affirmer's heirs and
|
||||
successors, fully intending that such Waiver shall not be subject to
|
||||
revocation, rescission, cancellation, termination, or any other legal or
|
||||
equitable action to disrupt the quiet enjoyment of the Work by the public
|
||||
as contemplated by Affirmer's express Statement of Purpose.
|
||||
|
||||
3. Public License Fallback. Should any part of the Waiver for any reason
|
||||
be judged legally invalid or ineffective under applicable law, then the
|
||||
Waiver shall be preserved to the maximum extent permitted taking into
|
||||
account Affirmer's express Statement of Purpose. In addition, to the
|
||||
extent the Waiver is so judged Affirmer hereby grants to each affected
|
||||
person a royalty-free, non transferable, non sublicensable, non exclusive,
|
||||
irrevocable and unconditional license to exercise Affirmer's Copyright and
|
||||
Related Rights in the Work (i) in all territories worldwide, (ii) for the
|
||||
maximum duration provided by applicable law or treaty (including future
|
||||
time extensions), (iii) in any current or future medium and for any number
|
||||
of copies, and (iv) for any purpose whatsoever, including without
|
||||
limitation commercial, advertising or promotional purposes (the
|
||||
"License"). The License shall be deemed effective as of the date CC0 was
|
||||
applied by Affirmer to the Work. Should any part of the License for any
|
||||
reason be judged legally invalid or ineffective under applicable law, such
|
||||
partial invalidity or ineffectiveness shall not invalidate the remainder
|
||||
of the License, and in such case Affirmer hereby affirms that he or she
|
||||
will not (i) exercise any of his or her remaining Copyright and Related
|
||||
Rights in the Work or (ii) assert any associated claims and causes of
|
||||
action with respect to the Work, in either case contrary to Affirmer's
|
||||
express Statement of Purpose.
|
||||
|
||||
4. Limitations and Disclaimers.
|
||||
|
||||
a. No trademark or patent rights held by Affirmer are waived, abandoned,
|
||||
surrendered, licensed or otherwise affected by this document.
|
||||
b. Affirmer offers the Work as-is and makes no representations or
|
||||
warranties of any kind concerning the Work, express, implied,
|
||||
statutory or otherwise, including without limitation warranties of
|
||||
title, merchantability, fitness for a particular purpose, non
|
||||
infringement, or the absence of latent or other defects, accuracy, or
|
||||
the present or absence of errors, whether or not discoverable, all to
|
||||
the greatest extent permissible under applicable law.
|
||||
c. Affirmer disclaims responsibility for clearing rights of other persons
|
||||
that may apply to the Work or any use thereof, including without
|
||||
limitation any person's Copyright and Related Rights in the Work.
|
||||
Further, Affirmer disclaims responsibility for obtaining any necessary
|
||||
consents, permissions or other rights required for any use of the
|
||||
Work.
|
||||
d. Affirmer understands and acknowledges that Creative Commons is not a
|
||||
party to this document and has no duty or obligation with respect to
|
||||
this CC0 or use of the Work.
|
@ -0,0 +1,24 @@
|
||||
This is free and unencumbered software released into the public domain.
|
||||
|
||||
Anyone is free to copy, modify, publish, use, compile, sell, or
|
||||
distribute this software, either in source code form or as a compiled
|
||||
binary, for any purpose, commercial or non-commercial, and by any
|
||||
means.
|
||||
|
||||
In jurisdictions that recognize copyright laws, the author or authors
|
||||
of this software dedicate any and all copyright interest in the
|
||||
software to the public domain. We make this dedication for the benefit
|
||||
of the public at large and to the detriment of our heirs and
|
||||
successors. We intend this dedication to be an overt act of
|
||||
relinquishment in perpetuity of all present and future rights to this
|
||||
software under copyright law.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
For more information, please refer to <https://unlicense.org>
|
@ -1,198 +0,0 @@
|
||||
#!/usr/bin/make -f
|
||||
|
||||
BLOG := $(MAKE) -f $(lastword $(MAKEFILE_LIST)) --no-print-directory
|
||||
ifneq ($(filter-out help,$(MAKECMDGOALS)),)
|
||||
include config
|
||||
endif
|
||||
|
||||
# The following can be configured in config
|
||||
BLOG_DATE_FORMAT_INDEX ?= %x
|
||||
BLOG_DATE_FORMAT ?= %x %X
|
||||
BLOG_TITLE ?= blog
|
||||
BLOG_DESCRIPTION ?= blog
|
||||
BLOG_URL_ROOT ?= http://localhost/blog
|
||||
BLOG_FEED_MAX ?= 20
|
||||
BLOG_FEEDS ?= rss atom
|
||||
BLOG_SRC ?= articles
|
||||
|
||||
|
||||
.PHONY: help init build deploy clean taglist
|
||||
|
||||
ARTICLES = $(shell git ls-tree HEAD --name-only -- $(BLOG_SRC)/*.md 2>/dev/null)
|
||||
TAGFILES = $(patsubst $(BLOG_SRC)/%.md,tags/%,$(ARTICLES))
|
||||
|
||||
help:
|
||||
$(info make init|build|deploy|clean|taglist)
|
||||
|
||||
init:
|
||||
mkdir -p $(BLOG_SRC) data templates
|
||||
printf '<!DOCTYPE html><html><head><title>$$TITLE</title></head><body>' > templates/header.html
|
||||
printf '</body></html>' > templates/footer.html
|
||||
printf '' > templates/index_header.html
|
||||
printf '<p>Tags:' > templates/tag_list_header.html
|
||||
printf '<a href="$$URL">$$NAME</a>' > templates/tag_entry.html
|
||||
printf ', ' > templates/tag_separator.html
|
||||
printf '</p>' > templates/tag_list_footer.html
|
||||
printf '<h2>Articles</h2><ul id=artlist>' > templates/article_list_header.html
|
||||
printf '<li><a href="$$URL">$$DATE $$TITLE</a></li>' > templates/article_entry.html
|
||||
printf '' > templates/article_separator.html
|
||||
printf '</ul>' > templates/article_list_footer.html
|
||||
printf '' > templates/index_footer.html
|
||||
printf '' > templates/tag_index_header.html
|
||||
printf '' > templates/tag_index_footer.html
|
||||
printf '' > templates/article_header.html
|
||||
printf '' > templates/article_footer.html
|
||||
printf 'blog\n' > .git/info/exclude
|
||||
|
||||
build: blog/index.html tagpages $(patsubst $(BLOG_SRC)/%.md,blog/%.html,$(ARTICLES)) $(patsubst %,blog/%.xml,$(BLOG_FEEDS))
|
||||
|
||||
deploy: build
|
||||
rsync -rLtvz $(BLOG_RSYNC_OPTS) blog/ data/ $(BLOG_REMOTE)
|
||||
|
||||
clean:
|
||||
rm -rf blog tags
|
||||
|
||||
config:
|
||||
printf 'BLOG_REMOTE:=%s\n' \
|
||||
'$(shell printf "Blog remote (eg: host:/var/www/html): ">/dev/tty; head -n1)' \
|
||||
> $@
|
||||
|
||||
tags/%: $(BLOG_SRC)/%.md
|
||||
mkdir -p tags
|
||||
grep -ih '^; *tags:' "$<" | cut -d: -f2- | tr -c '[^a-z\-]' ' ' | sed 's/ */\n/g' | sed '/^$$/d' | sort -u > $@
|
||||
|
||||
blog/index.html: index.md $(ARTICLES) $(TAGFILES) $(addprefix templates/,$(addsuffix .html,header index_header tag_list_header tag_entry tag_separator tag_list_footer article_list_header article_entry article_separator article_list_footer index_footer footer))
|
||||
mkdir -p blog
|
||||
TITLE="$(BLOG_TITLE)"; \
|
||||
PAGE_TITLE="$(BLOG_TITLE)"; \
|
||||
export TITLE; \
|
||||
export PAGE_TITLE; \
|
||||
envsubst < templates/header.html > $@; \
|
||||
envsubst < templates/index_header.html >> $@; \
|
||||
envsubst < templates/tag_list_header.html >> $@; \
|
||||
first=true; \
|
||||
for t in $(shell cat $(TAGFILES) | sort -u); do \
|
||||
"$$first" || envsubst < templates/tag_separator.html; \
|
||||
NAME="$$t" \
|
||||
URL="@$$t.html" \
|
||||
envsubst < templates/tag_entry.html; \
|
||||
first=false; \
|
||||
done >> $@; \
|
||||
envsubst < templates/tag_list_footer.html >> $@; \
|
||||
envsubst < templates/article_list_header.html >> $@; \
|
||||
first=true; \
|
||||
echo $(ARTICLES); \
|
||||
for f in $(ARTICLES); do \
|
||||
printf '%s ' "$$f"; \
|
||||
git log -n 1 --diff-filter=A --date="format:%s $(BLOG_DATE_FORMAT_INDEX)" --pretty=format:'%ad%n' -- "$$f"; \
|
||||
done | sort | cut -d" " -f1,3- | while IFS=" " read -r FILE DATE; do \
|
||||
"$$first" || envsubst < templates/article_separator.html; \
|
||||
URL="`printf '%s' "\$$FILE" | sed 's,^$(BLOG_SRC)/\(.*\).md,\1,'`.html" \
|
||||
DATE="$$DATE" \
|
||||
TITLE="`head -n1 "\$$FILE" | sed -e 's/^# //g'`" \
|
||||
envsubst < templates/article_entry.html; \
|
||||
first=false; \
|
||||
done >> $@; \
|
||||
envsubst < templates/article_list_footer.html >> $@; \
|
||||
markdown < index.md >> $@; \
|
||||
envsubst < templates/index_footer.html >> $@; \
|
||||
envsubst < templates/footer.html >> $@; \
|
||||
|
||||
|
||||
blog/tag/%.html: $(ARTICLES) $(addprefix templates/,$(addsuffix .html,header tag_header index_entry tag_footer footer))
|
||||
|
||||
.PHONY: tagpages
|
||||
tagpages: $(TAGFILES)
|
||||
+$(BLOG) $(patsubst %,blog/@%.html,$(shell cat $(TAGFILES) | sort -u))
|
||||
|
||||
blog/@%.html: $(TAGFILES) $(addprefix templates/,$(addsuffix .html,header tag_index_header tag_list_header tag_entry tag_separator tag_list_footer article_list_header article_entry article_separator article_list_footer tag_index_footer footer))
|
||||
mkdir -p blog
|
||||
PAGE_TITLE="Articles tagged $* -- $(BLOG_TITLE)"; \
|
||||
TAGS="$*"; \
|
||||
TITLE="$(BLOG_TITLE)"; \
|
||||
export PAGE_TITLE; \
|
||||
export TAGS; \
|
||||
export TITLE; \
|
||||
envsubst < templates/header.html > $@; \
|
||||
envsubst < templates/tag_index_header.html >> $@; \
|
||||
envsubst < templates/article_list_header.html >> $@; \
|
||||
first=true; \
|
||||
for f in $(shell awk '$$0 == "$*" { gsub("tags", "$(BLOG_SRC)", FILENAME); print FILENAME ".md"; nextfile; }' $(TAGFILES)); do \
|
||||
printf '%s ' "$$f"; \
|
||||
git log -n 1 --diff-filter=A --date="format:%s $(BLOG_DATE_FORMAT_INDEX)" --pretty=format:'%ad%n' -- "$$f"; \
|
||||
done | sort | cut -d" " -f1,3- | while IFS=" " read -r FILE DATE; do \
|
||||
"$$first" || envsubst < templates/article_separator.html; \
|
||||
URL="`printf '%s' "\$$FILE" | sed 's,^$(BLOG_SRC)/\(.*\).md,\1,'`.html" \
|
||||
DATE="$$DATE" \
|
||||
TITLE="`head -n1 "\$$FILE" | sed -e 's/^# //g'`" \
|
||||
envsubst < templates/article_entry.html; \
|
||||
first=false; \
|
||||
done >> $@; \
|
||||
envsubst < templates/article_list_footer.html >> $@; \
|
||||
envsubst < templates/tag_index_footer.html >> $@; \
|
||||
envsubst < templates/footer.html >> $@; \
|
||||
|
||||
|
||||
blog/%.html: $(BLOG_SRC)/%.md $(addprefix templates/,$(addsuffix .html,header article_header tag_link_header tag_link tag_link_footer article_footer footer))
|
||||
mkdir -p blog
|
||||
TITLE="$(shell head -n1 $< | sed 's/^# \+//')"; \
|
||||
export TITLE; \
|
||||
PAGE_TITLE="$${TITLE} Recipe -- $(BLOG_TITLE)"; \
|
||||
export PAGE_TITLE; \
|
||||
AUTHOR="$(shell git log --format="%an" -- "$<" | tail -n 1)"; \
|
||||
export AUTHOR; \
|
||||
DATE_POSTED="$(shell git log -n 1 --diff-filter=A --date="format:$(BLOG_DATE_FORMAT)" --pretty=format:'%ad' -- "$<")"; \
|
||||
export DATE_POSTED; \
|
||||
DATE_EDITED="$(shell git log -n 1 --date="format:$(BLOG_DATE_FORMAT)" --pretty=format:'%ad' -- "$<")"; \
|
||||
export DATE_EDITED; \
|
||||
TAGS="$(shell grep -i '^; *tags:' "$<" | cut -d: -f2- | paste -sd ',')"; \
|
||||
export TAGS; \
|
||||
envsubst < templates/header.html > $@; \
|
||||
envsubst < templates/article_header.html >> $@; \
|
||||
sed -e '/^;/d' < $< | markdown -f fencedcode >> $@; \
|
||||
envsubst < templates/tag_link_header.html >> $@; \
|
||||
for i in $${TAGS} ; do \
|
||||
TAG_NAME="$$i" \
|
||||
TAG_LINK="./@$$i.html" \
|
||||
envsubst < templates/tag_link.html >> $@; \
|
||||
done; \
|
||||
envsubst < templates/tag_link_footer.html >> $@; \
|
||||
envsubst < templates/article_footer.html >> $@; \
|
||||
envsubst < templates/footer.html >> $@; \
|
||||
|
||||
blog/rss.xml: $(ARTICLES)
|
||||
printf '<?xml version="1.0" encoding="UTF-8"?>\n<rss version="2.0">\n<channel>\n<title>%s</title>\n<link>%s</link>\n<description>%s</description>\n' \
|
||||
"$(BLOG_TITLE)" "$(BLOG_URL_ROOT)" "$(BLOG_DESCRIPTION)" > $@
|
||||
for f in $(ARTICLES); do \
|
||||
printf '%s ' "$$f"; \
|
||||
git log -n 1 --diff-filter=A --date="format:%s %a, %d %b %Y %H:%M:%S %z" --pretty=format:'%ad%n' -- "$$f"; \
|
||||
done | sort -k2nr | head -n $(BLOG_FEED_MAX) | cut -d" " -f1,3- | while IFS=" " read -r FILE DATE; do \
|
||||
printf '<item>\n<title>%s</title>\n<link>%s</link>\n<guid>%s</guid>\n<pubDate>%s</pubDate>\n<description><![CDATA[%s]]></description>\n</item>\n' \
|
||||
"`head -n 1 $$FILE | sed 's/^# //'`" \
|
||||
"$(BLOG_URL_ROOT)`basename $$FILE | sed 's/\.md/\.html/'`" \
|
||||
"$(BLOG_URL_ROOT)`basename $$FILE | sed 's/\.md/\.html/'`" \
|
||||
"$$DATE" \
|
||||
"`markdown < $$FILE`"; \
|
||||
done >> $@
|
||||
printf '</channel>\n</rss>\n' >> $@
|
||||
|
||||
blog/atom.xml: $(ARTICLES)
|
||||
printf '<?xml version="1.0" encoding="UTF-8"?>\n<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">\n<title type="text">%s</title>\n<subtitle type="text">%s</subtitle>\n<updated>%s</updated>\n<link rel="alternate" type="text/html" href="%s"/>\n<id>%s</id>\n<link rel="self" type="application/atom+xml" href="%s"/>\n' \
|
||||
"$(BLOG_TITLE)" "$(BLOG_DESCRIPTION)" "$(shell date +%Y-%m-%dT%H:%M:%SZ)" "$(BLOG_URL_ROOT)" "$(BLOG_URL_ROOT)atom.xml" "$(BLOG_URL_ROOT)/atom.xml" > $@
|
||||
for f in $(ARTICLES); do \
|
||||
printf '%s ' "$$f"; \
|
||||
git log -n 1 --diff-filter=A --date="format:%s %Y-%m-%dT%H:%M:%SZ" --pretty=format:'%ad %aN%n' -- "$$f"; \
|
||||
done | sort -k2nr | head -n $(BLOG_FEED_MAX) | cut -d" " -f1,3- | while IFS=" " read -r FILE DATE AUTHOR; do \
|
||||
printf '<entry>\n<title type="text">%s</title>\n<link rel="alternate" type="text/html" href="%s"/>\n<id>%s</id>\n<published>%s</published>\n<updated>%s</updated>\n<author><name>%s</name></author>\n<summary type="html"><![CDATA[%s]]></summary>\n</entry>\n' \
|
||||
"`head -n 1 $$FILE | sed 's/^# //'`" \
|
||||
"$(BLOG_URL_ROOT)`basename $$FILE | sed 's/\.md/\.html/'`" \
|
||||
"$(BLOG_URL_ROOT)`basename $$FILE | sed 's/\.md/\.html/'`" \
|
||||
"$$DATE" \
|
||||
"`git log -n 1 --date="format:%Y-%m-%dT%H:%M:%SZ" --pretty=format:'%ad' -- "$$FILE"`" \
|
||||
"$$AUTHOR" \
|
||||
"`markdown < $$FILE`"; \
|
||||
done >> $@
|
||||
printf '</feed>\n' >> $@
|
||||
|
||||
taglist:
|
||||
grep -RIh '^;tags:' src | cut -d' ' -f2- | tr ' ' '\n' | sort | uniq
|
@ -0,0 +1,6 @@
|
||||
---
|
||||
title: "{{ replace .Name "-" " " | title }}"
|
||||
date: {{ .Date }}
|
||||
draft: true
|
||||
---
|
||||
|
@ -1,6 +0,0 @@
|
||||
BLOG_TITLE:=Based Cooking
|
||||
BLOG_REMOTE:=/var/www/based.cooking
|
||||
BLOG_DATE_FORMAT_INDEX:=%F
|
||||
BLOG_DATE_FORMAT:=%F
|
||||
BLOG_SRC:=src
|
||||
BLOG_URL_ROOT:=https://based.cooking/
|
@ -0,0 +1,14 @@
|
||||
baseURL = 'https://based.cooking/'
|
||||
languageCode = 'en-us'
|
||||
title = 'Based Cooking'
|
||||
theme = 'lugo'
|
||||
|
||||
[params]
|
||||
favicon = "/favicon.svg"
|
||||
stylesheet = "/style.css"
|
||||
indexarticles = 50
|
||||
|
||||
[markup]
|
||||
[markup.goldmark]
|
||||
[markup.goldmark.renderer]
|
||||
unsafe = true
|
@ -0,0 +1,84 @@
|
||||
---
|
||||
title: "🍲 Based Cooking 🍳"
|
||||
description: 'The fast-loading recipe site with cooking only and no ads.'
|
||||
---
|
||||
|
||||
## What do you want to cook?
|
||||
|
||||
<div class="search js-only">
|
||||
<input type="text" id="search" placeholder="Search ALL Recipes...">
|
||||
<button id="clear-search">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="ionicon" viewBox="0 0 512 512"><title>Backspace</title><path d="M135.19 390.14a28.79 28.79 0 0021.68 9.86h246.26A29 29 0 00432 371.13V140.87A29 29 0 00403.13 112H156.87a28.84 28.84 0 00-21.67 9.84v0L46.33 256l88.86 134.11z" fill="none" stroke="currentColor" stroke-linejoin="round" stroke-width="32"></path><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="32" d="M336.67 192.33L206.66 322.34M336.67 322.34L206.66 192.33M336.67 192.33L206.66 322.34M336.67 322.34L206.66 192.33"></path></svg>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
// @license magnet:?xt=urn:btih:5ac446d35272cc2e4e85e4325b146d0b7ca8f50c&dn=unlicense.txt Unlicense
|
||||
|
||||
document.addEventListener("DOMContentLoaded", () => {
|
||||
for (e of document.getElementsByClassName("js-only")) {
|
||||
e.classList.remove("js-only");
|
||||
}
|
||||
|
||||
const recipes = document.querySelectorAll("#artlist li");
|
||||
const search = document.getElementById("search");
|
||||
const oldheading = document.getElementById("newest-recipes");
|
||||
const clearSearch = document.getElementById("clear-search");
|
||||
const artlist = document.getElementById("artlist");
|
||||
|
||||
search.addEventListener("input", () => {
|
||||
// grab search input value
|
||||
const searchText = search.value.toLowerCase().trim().normalize('NFD').replace(/\p{Diacritic}/gu, "");
|
||||
const searchTerms = searchText.split(" ");
|
||||
const hasFilter = searchText.length > 0;
|
||||
|
||||
artlist.classList.toggle("list-searched", hasFilter);
|
||||
oldheading.classList.toggle("hidden", hasFilter);
|
||||
|
||||
// for each recipe hide all but matched
|
||||
recipes.forEach(recipe => {
|
||||
const searchString = `${recipe.textContent} ${recipe.dataset.tags}`.toLowerCase().normalize('NFD').replace(/\p{Diacritic}/gu, "");
|
||||
const isMatch = searchTerms.every(term => searchString.includes(term));
|
||||
|
||||
recipe.hidden = !isMatch;
|
||||
recipe.classList.toggle("matched-recipe", hasFilter && isMatch);
|
||||
})
|
||||
})
|
||||
|
||||
clearSearch.addEventListener("click", () => {
|
||||
search.value = "";
|
||||
recipes.forEach(recipe => {
|
||||
recipe.hidden = false;
|
||||
recipe.classList.remove("matched-recipe");
|
||||
})
|
||||
|
||||
artlist.classList.remove("list-searched");
|
||||
oldheading.classList.remove("hidden");
|
||||
})
|
||||
})
|
||||
// @license-end
|
||||
</script>
|
||||
|
||||
## Newest Recipes
|
||||
|
||||
{{< artlist >}}
|
||||
|
||||
## Or Browse by Category...
|
||||
|
||||
{{< tagcloud >}}
|
||||
|
||||
## About this site
|
||||
|
||||
Founded to provide a simple online cookbook without ads and obese web design.
|
||||
See the story of this site unfold in three videos:
|
||||
|
||||
- [A Demonstration of Modern Web Bloat](https://odysee.com/@Luke:7/a-demonstration-of-modern-web-bloat:f)
|
||||
- [The War Against Web Bloat Continues...](https://odysee.com/@Luke:7/the-war-against-web-bloat-continues...:a)
|
||||
- [SoyDevs DESTROYED Epic Style by Based Cooking!](https://odysee.com/@Luke:7/soydevs-destroyed-epic-style-by-based:6)
|
||||
|
||||
## It's easy to contribute!
|
||||
|
||||
New recipes can be submitted [on Github](https://github.com/lukesmithxyz/based.cooking).
|
||||
We are funded by you only, not 20MB of ads or privacy-violating trackers per page.
|
||||
|
||||
{{< crypto >}}
|
@ -0,0 +1,37 @@
|
||||
---
|
||||
title: "Apple Chicken"
|
||||
tags: ['spanish', 'chicken', 'oven']
|
||||
date: 2022-07-11
|
||||
author: miraunpajaro
|
||||
---
|
||||
|
||||
![Applechicken](/pix/apple_chicken.webp)
|
||||
Baked chicken with apples and onions. Suprinsingly good and simple combination.
|
||||
|
||||
- ⏲️ Prep time: 10 min
|
||||
- 🍳 Cook time: 40 min
|
||||
- 🍽️ Servings: 4
|
||||
|
||||
## Ingredients
|
||||
|
||||
- Chicken breast or similar.
|
||||
- Onions.
|
||||
- Nuez moscada.
|
||||
- Apples.
|
||||
- Potatoes.
|
||||
- Cream or creme fraiche.
|
||||
- Salt.
|
||||
- Pepper.
|
||||
- One glass (33c) of wine or cognac.
|
||||
## Directions
|
||||
|
||||
1. Heat the oven to 200C and prepare an oven tray.
|
||||
2. Mix the chicken with nuez moscada, salt and pepper.
|
||||
3. Remove the center of the apples, fill with nuez moscada and butter.
|
||||
4. Put the chicken in the oven tray.
|
||||
5. Put the chicken, onions and apple in the oven tray.
|
||||
6. Add salt and pepper.
|
||||
7. Cook in the oven for 40 min.
|
||||
8. While the chicken is the oven prepare mushed potatoes. First you boil them until they are soft (keep the skin on). Once they are soft, peel them. Then mush them with a fork and add milk or creme fraiche.
|
||||
9. Add the wine or the cognac. Cook until the chicken is well cooked.
|
||||
10. Enjoy.
|
@ -0,0 +1,32 @@
|
||||
---
|
||||
title: Autumn Soup
|
||||
tags: ['vegetable', 'soup']
|
||||
date: 2022-08-04
|
||||
author: joel-maxuel
|
||||
---
|
||||
|
||||
You can cook the veggies on the stove instead of baking them, just pay more attention to avoid burning. You can also use pumpkin instead of squash.
|
||||
|
||||
- ⏲️ Prep time: 20 min
|
||||
- 🍳 Cook time: 40 min
|
||||
- 🍽️ Servings: 4
|
||||
|
||||
## Ingredients
|
||||
|
||||
- 1 Medium Squash
|
||||
- 3 Potatoes
|
||||
- 4 Carrots
|
||||
- 1 Small Onion
|
||||
- 1 Chicken Bullion Cube
|
||||
- 1 cup Water
|
||||
- 2 cups Milk
|
||||
- Salt
|
||||
- Pepper
|
||||
|
||||
## Directions
|
||||
|
||||
1. Peel and chop squash, potatoes, carrots, and onion, add to oven-safe pot.
|
||||
2. Add bullion and enough water to avoid burning (1 cup), place pot in oven (350F) to bake until veggies are soft.
|
||||
3. If there is too much stock, don't be scared to pour some down the drain.
|
||||
4. Puree (I use electric beaters) while adding the milk.
|
||||
5. Add the salt and pepper, as desired.
|
@ -0,0 +1,31 @@
|
||||
---
|
||||
title: "Baby Back Ribs"
|
||||
date: 2022-04-15
|
||||
tags: ['pork', 'american', 'supper', 'southern']
|
||||
author: crazywillbear
|
||||
---
|
||||
|
||||
Some classic and delicious baby back ribs. Keep in mind that if you do not have a smoker, a grill with some tin-foil wrapped smoking wood with poked holes will suffice.
|
||||
|
||||
## Ingredients
|
||||
|
||||
- Applewood (or other sweet cooking wood such as cherry or maple)
|
||||
- 2 baby back rib racks
|
||||
- 1 container of barbecue rub ([Traeger Pork and Poultry Rub](https://www.traeger.com/rubs-spices/pork-poultry) is recommended)
|
||||
- Tin foil
|
||||
- Bag of brown sugar
|
||||
- Bottle of honey
|
||||
- Barbecue Sauce ([Oakland Dust, The One BBQ Sauce](https://www.sincerelysf.com/products/oakland-dust-the-one-bbq-sauce-1) is recommended)
|
||||
- (Optional) A stick of butter
|
||||
|
||||
## Directions
|
||||
|
||||
1. Preheat your smoker to 180 degrees Fahrenheit using applewood.
|
||||
2. Take the membrane off of the back of the ribs if your butcher hasn't already done so ([tutorial](https://www.youtube.com/watch?v=uQVIMKDpZfg))
|
||||
3. Cover both sides of the ribs heavily in your barbecue rub, and let sit at room temp for 30 minutes.
|
||||
4. Place the ribs bone down (meat up) on your smoker, and let smoke at 180 degrees Fahrenheit for 3 hours.
|
||||
5. Take the meat out and place on top of two sheets of tin foil. Then, apply a generous amount of brown sugar and honey to both sides of the ribs, followed by a small amount of the barbecue rub. If you have butter, cut it into slices and add it on the meat side (butter is optional).
|
||||
6. Wrap your ribs in the tin foil and place them back on the smoker at 225 degrees Fahrenheit for 2 hours.
|
||||
7. Take your ribs out of the foil and place them bone down (meat up) on your smoker.
|
||||
8. Apply a generous helping of your barbecue sauce to the ribs once every 30 minutes for an hour (twice).
|
||||
9. Take out of smoker and cover in tin foil, allow to sit for 10-30 minutes before serving.
|
@ -0,0 +1,27 @@
|
||||
---
|
||||
title: Banana and oatmeal cookies
|
||||
tags: ['snack', 'quick', 'dessert']
|
||||
date: 2022-07-12
|
||||
author: "Éric G."
|
||||
---
|
||||
|
||||
- ⏲️ Prep time: 3 min
|
||||
- 🍳 Cook time: 20 min
|
||||
- 🍽️ Serving : 3
|
||||
|
||||
## Ingredients
|
||||
|
||||
- 2 ripe bananas (250 g/9 oz peeled)
|
||||
- 100g (3.5 oz) of oatmeal
|
||||
- 1 table spoon of cinnamon powder (optional)
|
||||
- 1 table spoon of honey (optional)
|
||||
|
||||
## Directions
|
||||
|
||||
1. Pre-heat the oven to 180°C (350°F)
|
||||
2. Peel the bananas and squash them not too finely in a bowl.
|
||||
3. Incorporate the oatmeal.
|
||||
4. Incorporate cinnamon powder and/or honey (optional).
|
||||
5. On the oven tray, place parchment paper and form discs of the mix, each around 8 cm (3 in)
|
||||
6. Cook with rotating heat for around 20 minutes, until outside becomes golden and slightly crispy.
|
||||
7. Eat warm or cold. Can be kept a couple of days in a sealed container.
|
@ -0,0 +1,24 @@
|
||||
---
|
||||
title: "Hamburger dressing"
|
||||
date: 2021-04-06
|
||||
tags: ['sauce', 'basic', 'dressing']
|
||||
author: brox
|
||||
---
|
||||
|
||||
![burger-dressing](/pix/burger-dressing.webp)
|
||||
|
||||
A delicious home made hamburger dressing 🍔
|
||||
|
||||
- ⏲️ Prep time: 1 min
|
||||
- 🍳 Cook time: 1 min
|
||||
|
||||
## Ingredients
|
||||
|
||||
- 3 tbsp [mayonnese or aioli](/mayonnaise-or-aioli)
|
||||
- 2 tbsp ketchup
|
||||
- 1 tbsp sriracha
|
||||
- 1 clove garlic, if using mayonnese and not aioli (optional)
|
||||
|
||||
## Directions
|
||||
|
||||
1. Mix ingredients in a bowl
|
@ -0,0 +1,41 @@
|
||||
---
|
||||
title: 'Butter-based biscuit and cookies'
|
||||
author: 'Arnaud Poittevin'
|
||||
date: 2022-06-29
|
||||
tags: ['snack', 'side', 'dough']
|
||||
---
|
||||
|
||||
This recipe is some basic recommandations for making butter based biscuits (aka shortbread, sablés, cookies ...). The complexity comes from the presence of butter mostly.
|
||||
|
||||
- ⏲️ Prep time: 10 min
|
||||
- ⏲️ Wait time: 1h
|
||||
- 🍳 Cook time: 15 min
|
||||
|
||||
## Ingredients
|
||||
|
||||
- Butter
|
||||
- Flour
|
||||
- White sugar
|
||||
- Eggs (optionnal)
|
||||
|
||||
## Directions
|
||||
|
||||
### Prepare the dough
|
||||
|
||||
1. Mix the sugar and eggs until it gets white
|
||||
2. Add the "Pommade" butter and mix thoroughly until the preparation is airy. "pommade" is french for ointment, this is a specific state of butter that is nor liquid nor solid.
|
||||
3. Gradually add the flour
|
||||
|
||||
### Let it sit
|
||||
|
||||
6. The dough should not be sticky and made into a ball wrapped in cellophane/film
|
||||
7. Put the dough ball 1h in the fridge (15 minutes in the freezer if you are in a hurry **less consistent**). The dough needs to be cold when putting in the oven to prevent butter from flowing out and separating from the dough
|
||||
|
||||
### Cooking the dough
|
||||
|
||||
8. Heat your oven to 200 °C with the cooking tray
|
||||
9. Quickly shape the dough so it remains cold. Most important is the thickness, the thicker it is the longer it has to cook and the more chances the butter flows out.
|
||||
10. Transfer the baking paper with the uncooked shortbreads on the hot cooking tray
|
||||
11. Let cook for 12 to 15 minutes to your liking, the brown colour means the sugar has caramelized and it is crunchy
|
||||
12. Work is not done, when out of the oven, the shortbreads will fill soft and crumbly, they need 1 or 2 minutes of cooling before being solid enough to handle
|
||||
13. Whenever possible transfer the shortbreads on a grid or "oven shelf" so air flow can circulate **Necessary for the texture of the shortbread** otherwise moisture will remain inside and will be less crunchy
|
@ -0,0 +1,37 @@
|
||||
---
|
||||
title: "Ceviche"
|
||||
tags: ['seafood', 'peruvian']
|
||||
author: jacob-smith
|
||||
date: 2022-04-16
|
||||
---
|
||||
|
||||
Ceviche is a South American dish which originated in Peru. The following recipe will only cover
|
||||
the bare minimum ingredients, so feel free to experiment by adding things like garlic, ginger, peppers
|
||||
tomatoes, cilantro, other citrus juices, and anything else you feel might taste good in there.
|
||||
|
||||
- ⏲️ Prep time: 10 min
|
||||
|
||||
## Ingredients
|
||||
|
||||
- Seafood
|
||||
- Red Onion
|
||||
- Lime Juice
|
||||
|
||||
## Directions
|
||||
|
||||
1. Slice your onion as thinly as you can then let them all sit in a
|
||||
bowl of cold water for a while. Soaking your onion slices like this
|
||||
will make it so that their flavor is not as strong so that it won't
|
||||
overpower everything.
|
||||
2. While your onion is soaking cut your chosen seafood into cubes.
|
||||
Ceviche can be made with any type of seafood but fish with white
|
||||
meat native to South America, or things like shrimp and octopus are best. Season your cubed seafood generously with salt
|
||||
and pepper and place in a bowl.
|
||||
3. Squeeze the juice of several limes onto your seafood, remember when
|
||||
shopping for limes the softer ones will have the most juice. You
|
||||
want to get good coverage over all your meat but it is important to
|
||||
remember that there is such a thing as too much lime.
|
||||
4. Add the onion slices then cover and let sit in the fridge. You can
|
||||
get away with eating it after only an hour but ceviche gets better
|
||||
as it ages so it may be best to have more patience and let it sit
|
||||
overnight.
|
@ -0,0 +1,48 @@
|
||||
---
|
||||
title: "Cheese"
|
||||
date: 2022-04-16
|
||||
tags: ['basic', 'cheesefare']
|
||||
author: "SuperDuperDeou"
|
||||
---
|
||||
|
||||
The success of this recipe depends entirely on the quality of the milk. The fresher the milk the better. Your regular UHT milk won't work, because the necessary bacteria have been killed.
|
||||
|
||||
You do not necessary need cow milk, basically every animal milk will work, but the cheese will have vastly different (not necessarily worse) characteristics.
|
||||
|
||||
## Ingredients
|
||||
|
||||
- thermometer
|
||||
- 1 cheesecloth
|
||||
- 1 cheese recipient
|
||||
- 2l of milk
|
||||
- 25g of table salt (optional with aging)
|
||||
- 2g of rennet
|
||||
- Some coarse salt
|
||||
- Oil and vinegar (for aging)
|
||||
|
||||
## Directions
|
||||
|
||||
### Preparation
|
||||
|
||||
Pour the milk and the salt into a pot, stir it well, and heat it up to 35°C.
|
||||
Once the temperature has been reached, add the rennet and stir well.
|
||||
Let it cook until it solidifies (about 1 and a half hours), then cut in 1x1cm squares.
|
||||
Let it rest for half an hour.
|
||||
Pour the cheese into the cheesecloth and il drip until it has completely separated from the liquid part (whey).
|
||||
Place the cheese into the recipient.
|
||||
Cover both sides of the cheese with coarse salt, repeat this operation twice, waiting 1 hour between two saltings.
|
||||
Store in the fridge.
|
||||
|
||||
|
||||
### Aging (optional)
|
||||
|
||||
Store the cheese in a chill place (around 12°C).
|
||||
Every day of aging, flip the cheese upside-down.
|
||||
For the first two weeks, also cover it with oil and vinegar every day.
|
||||
|
||||
|
||||
## Extra: Uses for the whey
|
||||
|
||||
You might have noticed you've obtained way more whey than cheese, it's normal, so you probably want to use it in some way instead of throwing it away.
|
||||
|
||||
If they like acids, you can feed it to your plants: it's pretty much giving them water and fertilizer in one go, you can feed it to your animals, since it's a great source of proteins, it's the prime ingredient of another cheese called "Ricotta", it can be used instead of water in sever recipes, and many other: you can even drink it. People have engineered ways to use the whey since the dawn of cheese.
|
@ -0,0 +1,31 @@
|
||||
---
|
||||
title: Chicken Satay with Peanut Sauce
|
||||
tags: ['chicken', 'thai', 'asian']
|
||||
date: 2022-07-10
|
||||
author: "Eric Lindberg"
|
||||
---
|
||||
|
||||
- ⏲️ Prep time: 10 min
|
||||
- 🍳 Cook time: 15 min
|
||||
- 🍽️ Servings: 4
|
||||
|
||||
## Ingredients
|
||||
|
||||
- 2 lbs boneless chicken breast or thigh
|
||||
- 1.5 tbsp oyster sauce
|
||||
- 1 tbsp ground tumeric
|
||||
- 2 tbsp sugar
|
||||
- 2 tbsp coconut milk
|
||||
- 3 tbsp peanut butter (creamy)
|
||||
- 1 tbsp massaman curry paste
|
||||
- water to thin peanut sauce
|
||||
|
||||
## Directions
|
||||
|
||||
1. Cut the chicken into 1/2 inch thick strips.
|
||||
2. Mix chicken with oyster sauce, tumeric, 1 tbsp sugar and coconut milk. Allow chicken to marinade for at least an hour.
|
||||
3. Optionally, you can skewer the meat with wooden skewers.
|
||||
4. Grill chicken until cooked through.
|
||||
5. Mix peanut butter, 1 tbsp sugar and curry paste together in a small saucepan. Add enough water to thin to a thick sauce.
|
||||
6. Cook for 1-2 min stirring frequently.
|
||||
7. Serve chicken with peanut sauce for dipping.
|
@ -0,0 +1,30 @@
|
||||
---
|
||||
title: "Chicken Tenders Airfried"
|
||||
date: 2021-05-08
|
||||
tags: ['chicken', 'fry']
|
||||
author: mental-outlaw
|
||||
---
|
||||
|
||||
- ⏲️ Prep time: 5 min
|
||||
- 🍳 Cook time: 20 min
|
||||
|
||||
## Ingredients
|
||||
|
||||
- Raw chicken strips
|
||||
- Flour
|
||||
- Egg wash
|
||||
- Bread crumbs
|
||||
- Olive oil
|
||||
- Seasoning: salt and pepper with cayenne or paprika (optional)
|
||||
|
||||
## Directions
|
||||
|
||||
1. In a plate, mix a little over a table spoon of spices into your flour.
|
||||
2. Dip the chicken into the flour one strip at a time coating the entire surface.
|
||||
3. Dip the floured chicken into the eggwash.
|
||||
4. Press the chicken into the breadcrumbs trying to pick up as much as possible.
|
||||
5. Repeat until all strips have been floured egged and breaded.
|
||||
6. Coat both sides of the tenders with a light amount of olive oil.
|
||||
7. Place the tenders into your airfryer, do not layer them on top of each other.
|
||||
8. Set your airfryer to chicken mode and cook for 20 minutes at 360 degrees fahrenheit.
|
||||
9. Serve with honey mustard for maximum effect.
|
@ -0,0 +1,37 @@
|
||||
---
|
||||
title: "Chicken Tikka Masala"
|
||||
tags: ['chicken', 'slowcooked', 'indian']
|
||||
date: 2022-04-16
|
||||
---
|
||||
|
||||
- ⏲️ Prep time: 25 min
|
||||
- 🍳 Cook time: 4 hours
|
||||
- 🍽️ Servings: 8
|
||||
|
||||
## Ingredients
|
||||
|
||||
- 1 can (29 ounces) tomato puree
|
||||
- 1-1/2 cups plain yogurt
|
||||
- 1/2 large onion, finely chopped
|
||||
- 2 tablespoons olive oil
|
||||
- 4-1/2 teaspoons minced fresh gingerroot
|
||||
- 4 garlic cloves, minced
|
||||
- 1 tablespoon [garam masala](/garam-masala)
|
||||
- 2-1/2 teaspoons salt
|
||||
- 1-1/2 teaspoons ground cumin
|
||||
- 1 teaspoon paprika
|
||||
- 3/4 teaspoon pepper
|
||||
- 1/2 teaspoon cayenne pepper
|
||||
- 1/4 teaspoon ground cinnamon
|
||||
- 2-1/2 pounds boneless skinless chicken breasts, cut into 1-1/2-inch cubes
|
||||
- 1 jalapeno pepper, halved and seeded
|
||||
- 1 bay leaf
|
||||
- 1 tablespoon cornstarch
|
||||
- 1 cup heavy whipping cream
|
||||
- Hot cooked basmati rice
|
||||
- Chopped fresh cilantro, optional
|
||||
|
||||
## Directions
|
||||
|
||||
1. In a 5-qt. slow cooker, combine the first 13 ingredients (Can blend these first for convenience). Add chicken, jalapeno and bay leaf. Cook, covered, on low 4 hours or until chicken is tender. Remove jalapeno and bay leaf.
|
||||
2. In a small bowl, mix cornstarch and cream until smooth; gradually stir into sauce. Cook, covered, on high 15-20 minutes or until sauce is thickened. Serve with rice. If desired, sprinkle with cilantro.
|
@ -0,0 +1,40 @@
|
||||
---
|
||||
title: "Chipolata Sausage in Balsamic Vinegar"
|
||||
tags: ['beef', 'oven', 'italian']
|
||||
date: 2022-07-27
|
||||
author: "Kensix"
|
||||
---
|
||||
|
||||
Easy to prepare Italian dish with lots of flavour great for a relaxing evening dipping bread and sipping wine.
|
||||
|
||||
- ⏲️ Prep time: 5 min
|
||||
- 🍳 Cook time: 60 min
|
||||
- 🍽️ Servings: 4
|
||||
|
||||
## Ingredients
|
||||
|
||||
- 12 chipolata sausages
|
||||
- 4 red onions
|
||||
- 500g of cherry tomatoes (preferably mixed species)
|
||||
- 4 garlic cloves
|
||||
- Fresh basil leaves
|
||||
- Black balsamic vinegar
|
||||
- 1 loaf of ciabatta bread
|
||||
|
||||
## Directions
|
||||
|
||||
1. Pre-heat the oven to 200c (400f)
|
||||
2. Put the chipolata sausages in an oven dish
|
||||
3. Cut 4 red onions into quarters spread them out in the oven dish.
|
||||
4. Mince 2 of the garlic cloves and add them to the oven dish.
|
||||
5. Add the 2 remaining garlic cloves to the oven dish, This can be done with the skin to create a garlic spread for the bread.
|
||||
6. Add 3 tablespoons of oil to the oven dish and toss to cover everything in oil
|
||||
7. Put the dish in the oven for 30 minutes. Toss everything around at 15 minutes to ensure even baking.
|
||||
8. Cut half of the cherry tomatos in half keep the other half intact.
|
||||
9. After 30 minutes take the dish out of the oven.
|
||||
10. Add all the tomatoes to the oven dish.
|
||||
11. Add 3 tablespoons of balsamic vinegar to the oven dish.
|
||||
12. Put the dish back into the oven for another 30 minutes at 200c (400f)
|
||||
13. After 30 minutes take the dish out of the oven and reheat the oven as per instructions on the ciabatta bread.
|
||||
14. Tear the fresh basil leaves and add to the oven dish. Let it rest while you wait for the bread.
|
||||
15. Take the bread out of the oven and serve along with the oven dish. Bread can be used to dip in the oven dish.
|
@ -0,0 +1,56 @@
|
||||
---
|
||||
title: "Tunisian Couscous"
|
||||
date: 2022-07-26
|
||||
tags: ['tunisian']
|
||||
author: Sami Ben Romdhane
|
||||
---
|
||||
|
||||
|
||||
Credits to creator of recipe, Mike Benayoun , [(original recipe)](https://www.196flavors.com/tunisia-tunisian-couscous/).
|
||||
I decided to post it on here to be more available.
|
||||
|
||||
![couscous](/pix/couscous.webp)
|
||||
|
||||
Couscous is a staple in most Maghreb cuisines. It is known as the national dish in Tunisia, but also in Algeria and Morocco, as well as Mauritania and Libya. Tunisian couscous is one of the countless variations of this delicious and versatile dish.
|
||||
|
||||
- ⏲️ Prep time: 20 min
|
||||
- 🍳 Cook time: 1 hr 40 min
|
||||
- 🍽️ Servings: 6
|
||||
|
||||
## Ingredients
|
||||
|
||||
- 2 lb lamb stew meat , cut into large pieces
|
||||
- 6 cups couscous fine semolina (or medium)
|
||||
- 2 onions , finely chopped
|
||||
- 2 cloves garlic , pressed
|
||||
- 4 tablespoons tomato paste
|
||||
- 2 tablespoons harissa
|
||||
- 2 tablespoons ground caraway
|
||||
- 1 tablespoon ground coriander
|
||||
- 1 teaspoon chili powder
|
||||
- 4 turnips , cut in half
|
||||
- 6 medium carrots , peeled
|
||||
- 4 zucchini , peeled lengthwise, alternately leaving a layer of skin
|
||||
- 6 small potatoes , peeled
|
||||
- 10 oz. chickpeas (canned)
|
||||
- 4 green hot peppers , fried in oil (optional)
|
||||
- Vegetable oil
|
||||
- Salt
|
||||
- Pepper
|
||||
|
||||
## Equipment
|
||||
|
||||
- Tajine pot
|
||||
|
||||
## Directions
|
||||
|
||||
1. Add ½ cup (120ml) of oil into a large pan. Fry the onion over medium heat for 2 minutes.
|
||||
2. Add the garlic, tomato paste and harissa and continue frying for 2 minutes.
|
||||
3. Add the caraway, coriander, and chili powder. Mix and continue cooking for another 2 minutes.
|
||||
4. Add the lamb meat and mix well so that the pieces are covered with the sauce. Cook for 5 minutes stirring regularly.
|
||||
5. Cover with water. Add the turnips and carrots, and cook on low/medium heat for 45 minutes.
|
||||
6. Meanwhile, prepare the couscous semolina as indicated on the package, with boiling water, salt, and oil.
|
||||
7. After 45 minutes, add the zucchini, potatoes and chickpeas.
|
||||
8. Cook for at least another 30 to 40 minutes over low to medium heat. Monitor the cooking of the vegetables. If some vegetables are cooked before the meat, remove them from the pan and place them on a serving platter. Proceed in the same way with all the vegetables to prevent them from cooking too much.
|
||||
9. 10 minutes before the end of cooking, get a few ladles of broth (one at a time) and wet the couscous semolina. Mix the semolina well after each ladle until it gets moistened enough.
|
||||
10. Arrange the semolina in a tajine pot. Decorate the dish with the vegetables and the meat all around. Garnish with fried green hot peppers (optional).
|
@ -0,0 +1,26 @@
|
||||
---
|
||||
title: "Cream Cheese"
|
||||
date: 2022-04-16
|
||||
tags: ['basic', 'cheesefare']
|
||||
author: "SuperDuperDeou"
|
||||
---
|
||||
|
||||
## Ingredients
|
||||
|
||||
- thermometer
|
||||
- 1 cheesecloth
|
||||
- 1 cheese recipient
|
||||
- 250ml of fresh, non-UHT milk
|
||||
- 250ml of yogurt
|
||||
- 1lt of fresh cream
|
||||
- 5g of table salt
|
||||
- 6g of of citric acid (contained in 130ml of lemon juice)
|
||||
|
||||
## Directions
|
||||
|
||||
Mix the yogurt, the milk, the cream, the salt, and the sugar into a bowl.
|
||||
Heat the bowl to 80°C while stirring.
|
||||
Once the temperature has been reached, add the citric acid and mix well.
|
||||
Heat up to 90°C, then let it cool down until it reaches room temperature.
|
||||
Pour the cheese into the cheesecloth and let the whey drip.
|
||||
Store in the fridge.
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue