mirror of
https://github.com/hendricius/the-sourdough-framework
synced 2025-11-08 12:11:11 -06:00
Merge remote-tracking branch 'hendiricus/main' into supporters
This commit is contained in:
56
.github/workflows/docker-build-push.yml
vendored
56
.github/workflows/docker-build-push.yml
vendored
@@ -1,56 +0,0 @@
|
||||
name: Create and publish a Docker image
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
|
||||
env:
|
||||
REGISTRY: ghcr.io
|
||||
IMAGE_NAME: ${{ github.repository }}
|
||||
|
||||
jobs:
|
||||
build-and-push-image:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
packages: write
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Log in to the Container registry
|
||||
uses: docker/login-action@65b78e6e13532edd9afa3aa52ac7964289d1a9c1
|
||||
with:
|
||||
registry: ${{ env.REGISTRY }}
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
- name: Figure out branch name
|
||||
shell: bash
|
||||
run: echo "branch=${GITHUB_HEAD_REF:-${GITHUB_REF#refs/heads/}}" >> $GITHUB_OUTPUT
|
||||
id: extract_branch
|
||||
- name: Determine docker image tag
|
||||
shell: bash
|
||||
id: determine_tag
|
||||
run: |
|
||||
if [[ "${{ github.ref }}" == "refs/heads/main" ]]; then
|
||||
echo "tag=latest" >> $GITHUB_OUTPUT
|
||||
else
|
||||
echo "tag=${{ steps.extract_branch.outputs.branch }}" >> $GITHUB_OUTPUT
|
||||
fi
|
||||
|
||||
- name: Extract metadata (tags, labels) for Docker
|
||||
id: meta
|
||||
uses: docker/metadata-action@v5
|
||||
with:
|
||||
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
|
||||
# Buildx for caching
|
||||
- uses: docker/setup-buildx-action@v3
|
||||
- name: Build and push Docker image
|
||||
uses: docker/build-push-action@v5
|
||||
with:
|
||||
context: .
|
||||
push: true
|
||||
tags: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.determine_tag.outputs.tag }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
cache-from: type=gha
|
||||
cache-to: type=gha,mode=max
|
||||
38
.github/workflows/release-book-website.yml
vendored
38
.github/workflows/release-book-website.yml
vendored
@@ -4,12 +4,36 @@ on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
|
||||
env:
|
||||
IMAGE: ghcr.io/${{ github.repository }}:latest
|
||||
LATEST_IMAGE: ghcr.io/${{ github.repository }}:latest
|
||||
|
||||
jobs:
|
||||
build-and-push-image:
|
||||
uses: ./.github/workflows/docker-build-push.yml
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
packages: write
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Log in to the Container registry
|
||||
uses: docker/login-action@65b78e6e13532edd9afa3aa52ac7964289d1a9c1
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
# Buildx for caching
|
||||
- uses: docker/setup-buildx-action@v3
|
||||
- name: Build and push Docker image
|
||||
uses: docker/build-push-action@v5
|
||||
with:
|
||||
context: .
|
||||
push: true
|
||||
tags: ghcr.io/${{ github.repository }}:latest
|
||||
cache-from: type=gha
|
||||
cache-to: type=gha,mode=max
|
||||
|
||||
release-book-website:
|
||||
needs: build-and-push-image
|
||||
@@ -20,7 +44,7 @@ jobs:
|
||||
- name: Print dependency versions
|
||||
uses: addnab/docker-run-action@v3
|
||||
with:
|
||||
image: ${{ env.IMAGE }}
|
||||
image: ${{ env.LATEST_IMAGE }}
|
||||
options: -v ${{ github.workspace }}:/app
|
||||
run: |
|
||||
cd /app/book
|
||||
@@ -28,7 +52,7 @@ jobs:
|
||||
- name: Print build variables
|
||||
uses: addnab/docker-run-action@v3
|
||||
with:
|
||||
image: ${{ env.IMAGE }}
|
||||
image: ${{ env.LATEST_IMAGE }}
|
||||
options: -v ${{ github.workspace }}:/app
|
||||
run: |
|
||||
cd /app/book
|
||||
@@ -36,11 +60,11 @@ jobs:
|
||||
- name: Bake the book
|
||||
uses: addnab/docker-run-action@v3
|
||||
with:
|
||||
image: ${{ env.IMAGE }}
|
||||
image: ${{ env.LATEST_IMAGE }}
|
||||
options: -v ${{ github.workspace }}:/app
|
||||
run: |
|
||||
cd /app/book
|
||||
make -j bake
|
||||
make bake
|
||||
- name: Release baked book to S3
|
||||
uses: shallwefootball/s3-upload-action@master
|
||||
with:
|
||||
@@ -60,7 +84,7 @@ jobs:
|
||||
- name: Bake the website
|
||||
uses: addnab/docker-run-action@v3
|
||||
with:
|
||||
image: ${{ env.IMAGE }}
|
||||
image: ${{ env.LATEST_IMAGE }}
|
||||
options: -v ${{ github.workspace }}:/app
|
||||
run: |
|
||||
cd /app/book
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
name: Test building book and website with custom image
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
|
||||
jobs:
|
||||
build-and-push-image:
|
||||
uses: ./.github/workflows/docker-build-push.yml
|
||||
|
||||
test-building-book-website:
|
||||
needs: build-and-push-image
|
||||
uses: ./.github/workflows/test-book-website.yml
|
||||
with:
|
||||
docker-image: ghcr.io/${{ github.repository }}:${{ github.event.pull_request.head.ref }}
|
||||
14
.github/workflows/test-book-website-push.yml
vendored
14
.github/workflows/test-book-website-push.yml
vendored
@@ -1,14 +0,0 @@
|
||||
name: Test building book and website with default image
|
||||
|
||||
on:
|
||||
push:
|
||||
|
||||
jobs:
|
||||
build-and-push-image:
|
||||
uses: ./.github/workflows/docker-build-push.yml
|
||||
|
||||
test-building-book-website:
|
||||
needs: build-and-push-image
|
||||
uses: ./.github/workflows/test-book-website.yml
|
||||
with:
|
||||
docker-image: ghcr.io/${{ github.repository }}:latest
|
||||
18
.github/workflows/test-book-website.yml
vendored
18
.github/workflows/test-book-website.yml
vendored
@@ -1,11 +1,9 @@
|
||||
name: Test book and website for given image
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
docker-image:
|
||||
required: true
|
||||
type: string
|
||||
on: [push, pull_request]
|
||||
|
||||
env:
|
||||
DOCKER_IMAGE: ghcr.io/${{ github.repository }}:latest
|
||||
|
||||
jobs:
|
||||
test-book-website:
|
||||
@@ -16,7 +14,7 @@ jobs:
|
||||
- name: Print dependency versions
|
||||
uses: addnab/docker-run-action@v3
|
||||
with:
|
||||
image: ${{ inputs.docker-image }}
|
||||
image: ${{ env.DOCKER_IMAGE }}
|
||||
options: -v ${{ github.workspace }}:/app
|
||||
run: |
|
||||
cd /app/book
|
||||
@@ -24,7 +22,7 @@ jobs:
|
||||
- name: Print build variables
|
||||
uses: addnab/docker-run-action@v3
|
||||
with:
|
||||
image: ${{ inputs.docker-image }}
|
||||
image: ${{ env.DOCKER_IMAGE }}
|
||||
options: -v ${{ github.workspace }}:/app
|
||||
run: |
|
||||
cd /app/book
|
||||
@@ -32,7 +30,7 @@ jobs:
|
||||
- name: Test baking the release versions
|
||||
uses: addnab/docker-run-action@v3
|
||||
with:
|
||||
image: ${{ inputs.docker-image }}
|
||||
image: ${{ env.DOCKER_IMAGE }}
|
||||
options: -v ${{ github.workspace }}:/app
|
||||
run: |
|
||||
cd /app/book
|
||||
@@ -48,7 +46,7 @@ jobs:
|
||||
- name: Test building website
|
||||
uses: addnab/docker-run-action@v3
|
||||
with:
|
||||
image: ${{ inputs.docker-image }}
|
||||
image: ${{ env.DOCKER_IMAGE }}
|
||||
options: -v ${{ github.workspace }}:/app
|
||||
run: |
|
||||
cd /app/book
|
||||
|
||||
@@ -8,7 +8,7 @@ LABEL org.opencontainers.image.source="https://github.com/hendricius/the-sourdou
|
||||
# Print release information if needed
|
||||
RUN cat /etc/*release*
|
||||
|
||||
# Install base depdendencies
|
||||
# Install base dependencies
|
||||
RUN apt-get update && \
|
||||
apt-get install --yes -y --no-install-recommends \
|
||||
sudo \
|
||||
@@ -55,6 +55,11 @@ RUN wget https://github.com/mgieseki/dvisvgm/releases/download/3.1.2/dvisvgm-3.1
|
||||
make && \
|
||||
make install
|
||||
|
||||
RUN git clone https://github.com/michal-h21/make4ht.git && \
|
||||
cd make4ht && \
|
||||
make && \
|
||||
make install
|
||||
|
||||
# Make sure everything is UTF-8
|
||||
RUN echo "export LC_ALL=en_US.UTF-8" >> /root/.bashrc && \
|
||||
echo "export LANG=en_US.UTF-8" >> /root/.bashrc
|
||||
|
||||
@@ -84,6 +84,13 @@ size. This shrinks the book from more than 50MB down to ~5MB:
|
||||
|
||||
* [Download compiled B&W .epub version](https://www.the-bread-code.io/bw-book.epub)
|
||||
|
||||
If you prefer a very short version (about 10 pages) with main flowcharts and
|
||||
crucial information needed while you are in the kitchen, we also provide a
|
||||
"too long;didn't read" version you could print. Having read the full book is
|
||||
highly recommended to understand this leaflet:
|
||||
|
||||
* [Download a condensed version](https://www.the-bread-code.io/booklet.pdf)
|
||||
|
||||
## Online HTML version
|
||||
|
||||
Head over to [https://www.the-sourdough-framework.com](https://www.the-sourdough-framework.com)
|
||||
|
||||
@@ -18,12 +18,11 @@ rise, this is called oven spring. Your bread starts to build a crust of
|
||||
gel-like consistency, the crust is still extensible and can be stretched.
|
||||
|
||||
\begin{table}[htp!]
|
||||
\begin{center}
|
||||
\centering
|
||||
\input{tables/table-baking-process-stages.tex}
|
||||
\caption[Stages of dough during baking]{The different stages that
|
||||
your dough undergoes during the baking process.}%
|
||||
\label{tab:baking-stages}
|
||||
\end{center}
|
||||
\end{table}
|
||||
|
||||
At around \qty{60}{\degreeCelsius} (\qty{140}{\degF}) the microbes in your dough start to die.
|
||||
@@ -171,12 +170,11 @@ way.
|
||||
|
||||
\section{Building up steam}
|
||||
\begin{flowchart}[!htb]
|
||||
\begin{center}
|
||||
\centering
|
||||
\input{figures/fig-baking-process.tex}
|
||||
\caption[Different steaming methods]{A schematic visualization of the baking
|
||||
process using different sources of steam in a home oven.}%
|
||||
\label{fig:baking-process}
|
||||
\end{center}
|
||||
\end{flowchart}
|
||||
|
||||
\begin{figure}[!htb]
|
||||
@@ -206,7 +204,7 @@ way.
|
||||
\end{figure}
|
||||
|
||||
\begin{flowchart}[!htb]
|
||||
\begin{center}
|
||||
\centering
|
||||
\input{figures/fig-dutch-oven-process.tex}
|
||||
\caption[Baking process with a dutch oven]{A visualization of the baking
|
||||
process using a dutch oven (DO). The dough is steamed for the first half
|
||||
@@ -215,7 +213,6 @@ way.
|
||||
personal preference. Some bakers prefer a lighter crust and others a
|
||||
darker.}%
|
||||
\label{fig:dutch-oven-process}
|
||||
\end{center}
|
||||
\end{flowchart}
|
||||
|
||||
Dutch ovens are an ideal way to bake with a lot of
|
||||
@@ -277,12 +274,11 @@ created from the dough and water source stays
|
||||
around your dough.
|
||||
|
||||
\begin{flowchart}[!htb]
|
||||
\begin{center}
|
||||
\centering
|
||||
\input{figures/fig-inverted-tray-method.tex}
|
||||
\caption[Inverted tray baking process]{A schematic visualization the
|
||||
inverted tray baking method that works great for home ovens.}%
|
||||
\label{fig:inverted-tray-process}
|
||||
\end{center}
|
||||
\end{flowchart}
|
||||
|
||||
|
||||
@@ -335,11 +331,10 @@ crust color. In my case this is another 15--25~minutes typically.
|
||||
\section{Conclusions}
|
||||
|
||||
\begin{table}[!htb]
|
||||
\begin{center}
|
||||
\centering
|
||||
\input{tables/table-oven-baking-overview.tex}
|
||||
\caption[Different oven types]{An overview of different oven types and their
|
||||
different baking methods.}
|
||||
\end{center}
|
||||
\end{table}
|
||||
|
||||
Depending on your home oven, a different method
|
||||
|
||||
@@ -19,7 +19,7 @@ learn more about the yeast and bacterial microorganisms involved.
|
||||
|
||||
To understand the many enzymatic reactions that take place when flour
|
||||
and water are mixed, we must first understand seeds and their role in
|
||||
the lifecycle of wheat and other grains.
|
||||
the life cycle of wheat and other grains.
|
||||
|
||||
Seeds are the primary means by which many plants, including wheat,
|
||||
reproduce. Each seed contains the embryo of another plant, and must
|
||||
@@ -223,12 +223,11 @@ exception, skip ahead to the end of this section on
|
||||
page~\pageref{aggressive-yeast}.}
|
||||
|
||||
\begin{figure}[!htb]
|
||||
\begin{center}
|
||||
\centering
|
||||
\includegraphics[width=0.8\textwidth]{saccharomyces-cerevisiae-microscope}
|
||||
\caption[Brewer's yeast]{Saccharomyces cerevisiae: Brewer's yeast under the
|
||||
microscope.}%
|
||||
\label{saccharomyces-cerevisiae-microscope}
|
||||
\end{center}
|
||||
\end{figure}
|
||||
|
||||
Yeasts are saprotrophic fungi. This means that they do not produce their own
|
||||
|
||||
174
book/booklet.tex
Normal file
174
book/booklet.tex
Normal file
@@ -0,0 +1,174 @@
|
||||
\documentclass[paper=a4, twoside=false, fontsize=12pt]{scrbook}
|
||||
|
||||
% General packages
|
||||
\usepackage{sourdough}
|
||||
\usepackage[
|
||||
paperwidth=210mm,
|
||||
paperheight=260mm,
|
||||
top=10mm,
|
||||
bottom=80mm,
|
||||
inner=10mm,
|
||||
outer=10mm,
|
||||
marginparsep=7mm,
|
||||
marginparwidth=48mm,
|
||||
]{geometry}
|
||||
\usepackage{subcaption}
|
||||
|
||||
\pagenumbering{gobble}
|
||||
% Basic attributes
|
||||
\author{Hendrik Kleinwächter}
|
||||
\title{The Sourdough Framework\\\texttt{tl;dr Booklet Version}}
|
||||
\begin{document}
|
||||
\maketitle
|
||||
|
||||
\section*{Sourdough starter}
|
||||
\begin{flowchart}[!htb]
|
||||
\centering
|
||||
\input{figures/fig-starter-process.tex}
|
||||
\caption*{How to setup a sourdough starter}
|
||||
\end{flowchart}
|
||||
|
||||
\begin{flowchart}[!htb]
|
||||
\centering
|
||||
\input{figures/fig-starter-readiness.tex}
|
||||
\caption*{Preparing your starter for baking}
|
||||
\end{flowchart}
|
||||
|
||||
\begin{flowchart}[!htb]
|
||||
\centering
|
||||
\input{figures/fig-starter-maintenance.tex}
|
||||
\caption*{Maintaining your starter, change ratio as per starter hydration
|
||||
type}
|
||||
\end{flowchart}
|
||||
|
||||
\clearpage{}
|
||||
\section*{Baker's math}
|
||||
\begin{table}[!htb]
|
||||
\centering
|
||||
\input{tables/table-bakers-math-example.tex}
|
||||
\caption*{An example table demonstrating how to properly calculate using
|
||||
baker's math. All the ingredients are calculated as a percentage of the
|
||||
flour quantity.}
|
||||
\end{table}
|
||||
|
||||
\section*{Basic recipes}
|
||||
\subsection*{Flat bread}
|
||||
\input{recipes/flat-bread.tex}
|
||||
\clearpage{}
|
||||
|
||||
\subsection*{Freestanding \& sandwich wheat-based breads}
|
||||
\begin{table}[!htb]
|
||||
\centering
|
||||
\begin{tabular}{@{}lrrrp{0.4\linewidth}@{}}
|
||||
\toprule
|
||||
\thead{Ingredient}& & \thead{Percentage} & \thead{Calculation} & \thead{Comments} \\ \midrule
|
||||
Flour & \qty{400}{g} & & & \\
|
||||
Whole-wheat flour & \qty{100}{g} & & & \\
|
||||
Total flour & & \qty{100}{\percent} & \qty{500}{g} & \\
|
||||
Water & & \qty{60}{\percent} & \qty{300}{g} & \\
|
||||
Sourdough starter & & \qty{10}{\percent} & \qty{50}{g} & \\
|
||||
Salt & & \qty{2}{\percent} & \qty{10}{g} & \\ \midrule
|
||||
Flour & & \qty{100}{\percent} & & \\
|
||||
Water & & & & \\
|
||||
Sourdough starter & & & & \\
|
||||
Salt & & & & \\ \midrule
|
||||
Flour & & & & \\
|
||||
& & & & \\
|
||||
& & & & \\
|
||||
& & & & \\
|
||||
& & & & \\ \bottomrule
|
||||
\end{tabular}
|
||||
\caption*{Table for your own calculation using baker's math}
|
||||
\end{table}
|
||||
|
||||
\begin{flowchart}[!htb]
|
||||
\centering
|
||||
\input{figures/fig-wheat-sourdough-process.tex}
|
||||
\caption*{The whole process of making wheat based sourdough breads}
|
||||
\end{flowchart}
|
||||
|
||||
\begin{flowchart}[!htb]
|
||||
\centering
|
||||
\input{figures/fig-kneading-process.tex}
|
||||
\caption*{The kneading process to create dough strength}
|
||||
\end{flowchart}
|
||||
|
||||
\begin{flowchart}[!htb]
|
||||
\centering
|
||||
\input{figures/fig-bulk-fermentation.tex}
|
||||
\caption*{How to properly manage bulk fermentation}
|
||||
\end{flowchart}
|
||||
|
||||
\begin{figure*}[!htb]
|
||||
\centering
|
||||
\includegraphics[width=\textwidth]{stretch-and-fold-steps}
|
||||
\caption*{An overview of the steps involved to perform stretch and folds for
|
||||
wheat-based doughs. They are optional and should only be done when the dough
|
||||
flattened out a lot.}%
|
||||
\end{figure*}
|
||||
\clearpage{}
|
||||
|
||||
\section*{Shaping}
|
||||
|
||||
\begin{figure*}[!htb]
|
||||
\centering
|
||||
\begin{subfigure}{.475\linewidth}
|
||||
\includegraphics[width=\linewidth]{preshape-direction}
|
||||
\caption*{Preshaping: Drag the dough in the direction of the rough
|
||||
surface area.}%
|
||||
\end{subfigure}
|
||||
\begin{subfigure}{.475\linewidth}
|
||||
\includegraphics[width=\linewidth]{step-1-flour-applied}
|
||||
\caption*{Step 1: Apply flour to the dough's surface.}%
|
||||
\end{subfigure}\hfill % <-- "\hfill"
|
||||
\medskip % create some *vertical* separation between the graphs
|
||||
\begin{subfigure}{.475\linewidth}
|
||||
\includegraphics[width=\linewidth]{step-2-flipped-over}
|
||||
\caption*{Step 2: Flipp-over dough. Note how the sticky side is facing
|
||||
you while the floured side is facing the countertop.}
|
||||
\end{subfigure}\hfill % <-- "\hfill"
|
||||
\begin{subfigure}{.475\linewidth}
|
||||
\includegraphics[width=\linewidth]{step-3-rectangular}
|
||||
\caption*{Step 3: Make the dough rectangular, keep the sticky side
|
||||
facing you while the floured side is facing the countertop.}%
|
||||
\end{subfigure}
|
||||
\caption*{First steps of shaping process}
|
||||
\end{figure*}
|
||||
|
||||
\begin{figure*}[htb!]
|
||||
\centering
|
||||
\includegraphics[width=\textwidth]{step-4-folding}
|
||||
\caption*{Step 4: The process of folding a batard. Note how the rectangle
|
||||
is first glued together and then rolled inwards to create a dough roll.
|
||||
Ultimately the edges are sealed to create a more uniform dough.}%
|
||||
\end{figure*}
|
||||
\clearpage{}
|
||||
|
||||
\section*{Proofing}
|
||||
\begin{flowchart}[!htb]
|
||||
\centering
|
||||
\input{figures/fig-proofing-process.tex}
|
||||
\end{flowchart}
|
||||
\clearpage{}
|
||||
|
||||
\section*{Baking}
|
||||
\begin{flowchart}[!htb]
|
||||
\centering
|
||||
\input{figures/fig-baking-process.tex}
|
||||
\caption*{Summary of different bread baking processes}
|
||||
\end{flowchart}
|
||||
|
||||
|
||||
\begin{flowchart}[!htb]
|
||||
\centering
|
||||
\input{figures/fig-inverted-tray-method.tex}
|
||||
\caption*{Baking with the inverted tray method}
|
||||
\end{flowchart}
|
||||
|
||||
\begin{flowchart*}[!htb]
|
||||
\centering
|
||||
\input{figures/fig-dutch-oven-process.tex}
|
||||
\caption*{Baking with a Dutch Oven}
|
||||
\end{flowchart*}
|
||||
\clearpage{}
|
||||
\end{document}
|
||||
@@ -19,12 +19,11 @@ accessible, least effort type of bread you can make. If you are a busy person
|
||||
and/or don’t have an oven, this might be exactly the type of bread you should
|
||||
consider.
|
||||
\begin{table}[!htb]
|
||||
\begin{center}
|
||||
\centering
|
||||
\input{tables/table-overview-bread-types.tex}
|
||||
\caption[Different bread types]{An overview of different bread types
|
||||
and their respective complexity.}%
|
||||
\label{tab:bread-types-comparison}
|
||||
\end{center}
|
||||
\end{table}
|
||||
|
||||
\section{Flatbread}%
|
||||
@@ -57,7 +56,7 @@ pancake-like consistency, as you can see in
|
||||
Table~\ref{tab:flat-bread-ingredients}
|
||||
|
||||
\begin{table}[!htb]
|
||||
\begin{center}
|
||||
\centering
|
||||
\input{tables/table-flat-bread-pancake-recipe.tex}
|
||||
\caption[Flatbread recipe]{Flatbread or pancake recipe for 1 person.
|
||||
Multiply the ingredients to increase portion size. Refer to the
|
||||
@@ -65,7 +64,6 @@ Table~\ref{tab:flat-bread-ingredients}
|
||||
``\nameref{section:bakers-math}'' to learn how to understand and
|
||||
use the percentages properly.}%
|
||||
\label{tab:flat-bread-ingredients}
|
||||
\end{center}
|
||||
\end{table}
|
||||
|
||||
For a full recipe including the process of making such a flatbread, refer to
|
||||
@@ -80,13 +78,12 @@ few steps, you can stop buying bread forever. This works with
|
||||
any flour, including gluten-free options.
|
||||
|
||||
\begin{flowchart}[!htb]
|
||||
\begin{center}
|
||||
\centering
|
||||
\input{figures/fig-process-flat-bread.tex}
|
||||
\caption[The process to make a sourdough flatbread]{The process of making a flatbread is very
|
||||
simple, requiring very little effort. This type of bread is especially
|
||||
handy for busy bakers.}%
|
||||
\label{fig:flat-bread-process}
|
||||
\end{center}
|
||||
\end{flowchart}
|
||||
|
||||
This is my go-to recipe that I~use to make bread whenever
|
||||
@@ -106,13 +103,12 @@ warmer it is, the sooner it will be ready, consider
|
||||
using warm water if it is very cold where you live.
|
||||
|
||||
\begin{figure}[htb!]
|
||||
\begin{center}
|
||||
\centering
|
||||
\includegraphics[width=1.0\textwidth]{flat-bread-wheat}
|
||||
\caption[Wheat flatbread]{A flatbread made with purely wheat flour. The
|
||||
dough is drier at around \qty{60}{\percent} hydration. The drier dough
|
||||
is a little harder to mix. As wheat contains more gluten, the dough
|
||||
puffs up during the baking process.}
|
||||
\end{center}
|
||||
\end{figure}
|
||||
|
||||
This way you should have around \qty{11}{\gram} of sourdough ready in the evening. You will have
|
||||
@@ -135,12 +131,11 @@ when getting started. You can observe the dough more easily and see when
|
||||
it is ready.
|
||||
|
||||
\begin{figure}[htb]
|
||||
\begin{center}
|
||||
\centering
|
||||
\includegraphics[width=1.0\textwidth]{ethiopian-woman-checking-bread}
|
||||
\caption[Ethiopian \emph{injera}]{An Ethiopian woman baking an \emph{injera}
|
||||
made using teff flour. The image has been provided by Charliefleurene
|
||||
via Wikipedia.}
|
||||
\end{center}
|
||||
\end{figure}
|
||||
|
||||
If you used the flatbread option with less water, look at the size increase
|
||||
@@ -170,12 +165,11 @@ going to taste relatively sour. I~do this frequently to better evaluate the
|
||||
state of my doughs.
|
||||
|
||||
\begin{figure}[!htb]
|
||||
\begin{center}
|
||||
\centering
|
||||
\includegraphics[width=1.0\textwidth]{injera-pancake-texture.jpg}
|
||||
\caption[Teff sourdough pancake]{A sourdough pancake made with teff flour.
|
||||
The pockets come from evaporated water and \ch{CO2} created by the
|
||||
microbes. The image has been provided by Łukasz Nowak via Wikipedia.}
|
||||
\end{center}
|
||||
\end{figure}
|
||||
|
||||
If you are feeling lazy or don't have time, you could also use older sourdough starter
|
||||
@@ -208,13 +202,12 @@ pancake option, opt for around \qtyrange{0.1}{0.5}{\cm} depending on what you
|
||||
like.
|
||||
|
||||
\begin{figure}[htb]
|
||||
\begin{center}
|
||||
\centering
|
||||
\includegraphics[width=1.0\textwidth]{einkorn-crumb.jpg}
|
||||
\caption[Einkorn crum]{The crumb of a flatbread made with einkorn as flour.
|
||||
Einkorn is very low in gluten and thus does not trap as much \ch{CO2} as
|
||||
a wheat based dough. To make the dough fluffier use more water or
|
||||
consider adding more wheat to the mix of your dough.}
|
||||
\end{center}
|
||||
\end{figure}
|
||||
|
||||
After 2--4~minutes flip over the pancake or flatbread. Bake it for the same
|
||||
@@ -249,57 +242,10 @@ culinary applications. Whether you're scooping up a savory dip,
|
||||
wrapping a flavorful filling, or simply enjoying a piece with a drizzle
|
||||
of olive oil, these flatbreads are sure to impress.
|
||||
|
||||
\subsubsection*{Ingredients}
|
||||
\input{recipes/flat-bread.tex}
|
||||
|
||||
\begin{tabular}{r@{}rl@{}}
|
||||
\qty{400}{\gram} &~(\qty{100}{\percent}) & Flour (wheat, rye, corn, whatever you have at hand)\\
|
||||
\qty{320}{\gram} & (\qty{80}{\percent}) & Water, preferably at room temperature\\
|
||||
\qty{80}{\gram} & (\qty{20}{\percent}) & Active sourdough starter\\
|
||||
\qty{8}{\gram} & (\qty{2}{\percent}) & Salt\\
|
||||
\end{tabular}
|
||||
|
||||
\subsubsection*{Instructions}
|
||||
\begin{description}
|
||||
\item[Prepare the dough] In a large mixing bowl, combine the flour and water.
|
||||
Mix until you have a shaggy dough with no dry spots.
|
||||
|
||||
Add the sourdough starter and salt to the mixture. Incorporate them thoroughly
|
||||
until you achieve a smooth and homogenized dough.
|
||||
|
||||
\item[Fermentation:] Cover the bowl with a lid or plastic wrap. Allow the dough
|
||||
to rest and ferment until it has increased by at least \qty{50}{\percent}
|
||||
in size. Depending on the temperature and activity of your starter, this
|
||||
can take anywhere from 4 to 24~hours.
|
||||
|
||||
\item[Cooking preparation:] Once the dough has risen, heat a pan over medium heat.
|
||||
Lightly oil the pan, ensuring to wipe away any excess oil with a paper towel.
|
||||
|
||||
\item[Shaping and cooking:] With a ladle or your hands, scoop out a portion of
|
||||
the dough and place it onto the hot pan, spreading it gently like a pancake.
|
||||
|
||||
Cover the pan with a lid. This traps the steam and ensures even cooking
|
||||
from the top, allowing for easier flipping later.
|
||||
|
||||
After about 5~minutes, or when the bottom of the flatbread has a
|
||||
golden-brown crust, carefully flip it using a spatula.
|
||||
|
||||
\emph{Adjusting cook time.} If the flatbread appears too dark,
|
||||
remember to reduce the cooking time slightly for the next one.
|
||||
Conversely, if it's too pale, allow it to cook a bit longer before flipping.
|
||||
|
||||
Cook the flipped side for an additional 5~minutes or until it's also golden
|
||||
brown.
|
||||
|
||||
\item[Storing:] Once cooked, remove the flatbread from the pan and place it on a
|
||||
kitchen towel. Wrapping the breads in the towel will help retain their
|
||||
softness and prevent them from becoming overly crisp.
|
||||
Repeat the cooking process for the remaining dough.
|
||||
|
||||
\item[Serving suggestion:] Enjoy your sourdough flatbreads warm,
|
||||
paired with your favorite dips, spreads, or as a side to any meal.
|
||||
|
||||
\end{description}
|
||||
\section{Loaf pan bread}
|
||||
\section{Loaf pan bread}%
|
||||
\label{sec:loaf-pan-bread}
|
||||
|
||||
Loaf pan bread is made using the help of a special loaf pan
|
||||
or loaf tin. The edges of the pan provide additional support
|
||||
@@ -377,12 +323,11 @@ baking vessels in your oven. To make a freestanding loaf more steps
|
||||
and tools are required.
|
||||
|
||||
\begin{figure}[!htb]
|
||||
\begin{center}
|
||||
\centering
|
||||
\includegraphics[width=1.0\textwidth]{free-standing-loaf.jpg}
|
||||
\caption[Freestanding sourdough bread]{A freestanding sourdough bread. Note
|
||||
the incision known as an \emph{ear} and the oven spring clearly
|
||||
distinguish this type of bread from flatbread and loaf pan bread.}
|
||||
\end{center}
|
||||
\end{figure}
|
||||
|
||||
When using wheat, make sure to mix your dough enough to develop a gluten network.
|
||||
|
||||
@@ -29,11 +29,11 @@
|
||||
% Additional line for dinosaurs since it is so close
|
||||
\draw[line width=1pt] (11.9*\segmentwidth,1.49) -- (11.70*\segmentwidth,1.85);
|
||||
|
||||
% Special lines for december events since they are so close togehter
|
||||
% Special lines for december events since they are so close together
|
||||
\draw[line width=1pt] (12.0*\segmentwidth,3.0) -- (12.0*\segmentwidth,0.2); % Main branch
|
||||
\draw[line width=1pt] (12.0*\segmentwidth,3.0) -- (11.75*\segmentwidth,2.5); % Branch to first humans
|
||||
\draw[line width=1pt] (12.0*\segmentwidth,3.0) -- (11.75*\segmentwidth,3.0); % Branch to Jordan
|
||||
% Move pasteur down a bit so the lines look like they cross
|
||||
% Move Pasteur down a bit so the lines look like they cross
|
||||
\draw[line width=1pt] (12.0*\segmentwidth,2.99) -- (11.75*\segmentwidth,3.5); % Branch to Pasteur
|
||||
|
||||
% Draw months and month separators
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
\begin{tikzpicture}[node distance = 3cm, auto]
|
||||
\node [start] (init) {Make a starter};
|
||||
\node [start] (init) {Create a starter};
|
||||
\node [decision, right of=init, node distance=3.5cm] (decision_start) {Starter last fed within 3~days?};
|
||||
\node [block, right of=decision_start, text width=7em, node distance=4cm] (feed_no_branch)
|
||||
{Feed starter twice:\par \qty{48}{\hour} before\par \qtyrange{6}{12}{\hour} before};
|
||||
|
||||
@@ -17,12 +17,11 @@ Depending on which layers are still present, different names are used to describ
|
||||
type of flour.
|
||||
|
||||
\begin{table}[!htb]
|
||||
\begin{center}
|
||||
\centering
|
||||
\input{tables/table-flour-types.tex}
|
||||
\caption[Labelling of wheat flour]{A comparison of how different types
|
||||
of wheat flour are labelled in different countries.}%
|
||||
\label{tab:flour-types-comparison}
|
||||
\end{center}
|
||||
\end{table}
|
||||
|
||||
In Germany, the ash content is used to describe the flours. The lab will burn
|
||||
@@ -60,11 +59,10 @@ want the final bread to be too sour. Conversely you do not have to worry about
|
||||
the gluten degradation, removing a huge headache from the equation.
|
||||
|
||||
\begin{table}[!htb]
|
||||
\begin{center}
|
||||
\centering
|
||||
\input{tables/table-grains-bread-making-process.tex}
|
||||
\caption[Different types of grain]{An overview of different grain
|
||||
types and the steps involved in the respective bread making process.}
|
||||
\end{center}
|
||||
\end{table}
|
||||
|
||||
Because gluten has a special role, the rest of this chapter is dedicated to having a
|
||||
@@ -115,13 +113,12 @@ The long fermentation period also means that your microbes will enrich
|
||||
your dough with more flavor.
|
||||
|
||||
\begin{table}[!htb]
|
||||
\begin{center}
|
||||
\centering
|
||||
\input{tables/table-overview-w-values.tex}
|
||||
\caption[Fermentation time versus W-value]{An overview of different
|
||||
levels of W-values and the respective hydrations and fermentation
|
||||
times.}%
|
||||
\label{tab:w-value}
|
||||
\end{center}
|
||||
\end{table}
|
||||
|
||||
Generally, when aiming to
|
||||
|
||||
@@ -157,7 +157,7 @@ and pastries.
|
||||
|
||||
\item[Coil fold] A special stretch and folding technique. The coil fold is
|
||||
very gentle on the dough and is thus excellent throughout the bulk fermentation.
|
||||
By applying the coil fold the dough strength is improved by minimising damage
|
||||
By applying the coil fold the dough strength is improved by minimizing damage
|
||||
to the dough structure.
|
||||
|
||||
\item[Crumb] The inner texture of the bread, which is characterized by the size,
|
||||
@@ -285,7 +285,7 @@ depending on the initial reactants and cooking conditions can produce a wide var
|
||||
of end products with different tastes and aromas. Maillard reactions occur readily
|
||||
above \SI{150}{\celsius}, although will still occur much more slowly below that
|
||||
temperature. Optimal reaction rate occurs between \pHvalue{6.0} to \pHvalue{8.0},
|
||||
although it favours alkaline conditions.
|
||||
although it favors alkaline conditions.
|
||||
|
||||
\item[Maltose] A sugar produced from the enzymatic breakdown of starch by amylases.
|
||||
It's a primary food source for yeast during fermentation.
|
||||
@@ -404,7 +404,7 @@ unpredictable ways. It also provides a controlled aesthetic to the finished loaf
|
||||
|
||||
\item[Soaker] A mixture of grains or seeds with water that is left to soak overnight (or for a
|
||||
specified amount of time) before being incorporated into bread dough. This helps to
|
||||
soften and hydrate the grains or seeds (sesame, pumpkin, etc.), making them
|
||||
soften and hydrate the grains or seeds (sesame, pumpkin, \etc{}), making them
|
||||
easier to integrate into the dough and
|
||||
providing a moister crumb in the finished bread.
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@ waters, another single-celled life form, \emph{archaea}, also thrived. These
|
||||
organisms inhabit extreme environments, from boiling vents to icy waters.
|
||||
|
||||
\begin{figure}[!htb]
|
||||
\begin{center}
|
||||
\centering
|
||||
\input{figures/fig-life-planet-sourdough-timeline.tex}
|
||||
\caption[Sourdough microbiology timeline]{Timeline of significant events
|
||||
starting from the first day of Earth's existence,
|
||||
@@ -34,12 +34,11 @@ organisms inhabit extreme environments, from boiling vents to icy waters.
|
||||
marked at midnight. This visualization shows the pivotal steps
|
||||
of life and sourdough on earth.}%
|
||||
\label{fig:planet-timeline}
|
||||
\end{center}
|
||||
\end{figure}
|
||||
|
||||
Whoever comes first, bacteria or archaea, remains debated. For three
|
||||
months (or approximately 1.1~billion years), these life forms dominated
|
||||
the oceans. Then, on June~25 in an highly unlikely event, an archaeon consumed a bacterium.
|
||||
the oceans. Then, on June~25 in a highly unlikely event, an archaeon consumed a bacterium.
|
||||
Instead of digesting it, they formed a symbiotic relationship. This led to the
|
||||
first nucleated organisms, marking an evolutionary milestone. This event lead
|
||||
to the development of plants, fungi and also ultimately humans.
|
||||
@@ -70,12 +69,11 @@ Ancient Jordan~\cite{jordan+bread}. Looking at the earth's timeline sourdough
|
||||
bread can be considered a very recent invention.
|
||||
|
||||
\begin{figure}[!htb]
|
||||
\begin{center}
|
||||
\centering
|
||||
\input{figures/fig-sourdough-history-timeline.tex}
|
||||
\caption[Sourdough history timeline]{Timeline of significant discoveries and
|
||||
events leading to modern sourdough bread.}%
|
||||
\label{fig:sourdough-timeline}
|
||||
\end{center}
|
||||
\end{figure}
|
||||
|
||||
The exact origins of fermented
|
||||
|
||||
@@ -81,7 +81,7 @@ sometimes you are faced with issues you don't understand. In \qty{99.95}{\percen
|
||||
of all software bugs, the developer is the issue. Sometimes, however, the framework has a
|
||||
bug. That is when the developer must dig deeper to see the \emph{what} and the
|
||||
\emph{why} behind what
|
||||
the framework is doing. You will need to read other engineer's source code, and you will be forced
|
||||
the framework is doing. You will need to read other engineers' source code, and you will be forced
|
||||
to understand \emph{why} things are happening.
|
||||
|
||||
Being unhappy with what I~was baking, my engineering mindset took over, and I~had
|
||||
|
||||
@@ -31,10 +31,12 @@ chapters = baking basics bread-types cover flour-types history intro mix-ins\
|
||||
|
||||
src_tables := $(wildcard tables/table-*.tex)
|
||||
src_figures := $(wildcard figures/fig-*.tex) figures/flowcharts_tikz.tex
|
||||
src_recipes := $(wildcard recipes/*.tex)
|
||||
|
||||
src_tex := $(foreach directory, $(chapters), $(wildcard $(directory)/*.tex))
|
||||
src_tex += book.tex book_sans_serif.tex references.bib figures/vars.tex
|
||||
src_tex += supporters.csv sourdough.sty colors.tex
|
||||
src_tex += $(src_recipes)
|
||||
|
||||
images := $(wildcard images/*/*.jpg)
|
||||
images += $(wildcard images/*.jpg)
|
||||
@@ -55,6 +57,11 @@ ebook_src := $(src_all) tex4ebook.cfg book.mk4 book-ebook.css
|
||||
|
||||
website_src := $(src_all) website.cfg style.css
|
||||
|
||||
# This is more than what is actually needed but keeps the makefile simple
|
||||
# and latexmk will handle the rest
|
||||
booklet_src := $(src_figures) $(src_tables) $(src_recipes) $(images)
|
||||
booklet_src += booklet.tex
|
||||
|
||||
website_assets := $(wildcard ../website/assets/*)
|
||||
ruby_src := ../website/modify_build.rb $(website_assets)
|
||||
ruby_pkg := ../website/Gemfile ../website/Gemfile.lock
|
||||
@@ -83,6 +90,9 @@ tgt_figures := $(patsubst %.tex, %.png,$(src_figures))
|
||||
%.xbb: %.jpg
|
||||
ebb -x $<
|
||||
|
||||
booklet/booklet.pdf: $(booklet_src)
|
||||
$(LATEX) -output-directory=booklet booklet.tex
|
||||
|
||||
book_serif/book.pdf: $(src_all)
|
||||
$(LATEX) -output-directory=book_serif book.tex
|
||||
|
||||
@@ -97,7 +107,7 @@ epub/%.epub: %.tex $(ebook_src) cover/cover-page.xbb
|
||||
copy_ebook_files: build_ebook
|
||||
$(RSYNC) book-epub/ bw-book-epub/
|
||||
|
||||
# We not convert SVG to B&W or lower res for now as they are super small
|
||||
# We do not convert SVG to B&W or lower res for now as they are super small
|
||||
# anyway
|
||||
bw-book-epub/OEBPS/%.jpg: %.jpg
|
||||
mkdir -p $(dir $@)
|
||||
@@ -140,6 +150,8 @@ help:
|
||||
@echo ""
|
||||
@echo "build_ebook: builds only the colour ebook"
|
||||
@echo ""
|
||||
@echo "build_booklet: builds only the short booklet"
|
||||
@echo ""
|
||||
@echo "build_bw_ebook: builds the low res black & white ebook"
|
||||
@echo ""
|
||||
@echo "build_sans_serif_pdf: build accessible pdf only"
|
||||
@@ -160,6 +172,8 @@ help:
|
||||
@echo ""
|
||||
@echo "quick_ebook: compiles ebook but runs lulatex only once"
|
||||
@echo ""
|
||||
@echo "quick_booklet: compiles booklet but runs lulatex only once"
|
||||
@echo ""
|
||||
@echo "show_tools_version: Show version of tools used on the build machine"
|
||||
@echo ""
|
||||
@echo "print-X: print makefile variable X"
|
||||
@@ -170,10 +184,12 @@ help:
|
||||
|
||||
|
||||
# Finally actual project targets (i.e. build pdf and ebooks)
|
||||
.PHONY: build_pdf build_serif_pdf build_sans_serif_pdf build_ebook
|
||||
.PHONY: build_pdf build_booklet build_serif_pdf build_sans_serif_pdf build_ebook
|
||||
|
||||
build_pdf: build_serif_pdf build_sans_serif_pdf
|
||||
|
||||
build_booklet: booklet/booklet.pdf
|
||||
|
||||
build_serif_pdf: book_serif/book.pdf
|
||||
|
||||
build_sans_serif_pdf: book_sans_serif/book_sans_serif.pdf
|
||||
@@ -221,15 +237,17 @@ clean_website_build: clean_ebook_build
|
||||
clean: clean_ebook_build clean_figures clean_website_build
|
||||
$(CLEAN) -output-directory=book_serif book.tex
|
||||
$(CLEAN) -output-directory=book_sans_serif book_sans_serif.tex
|
||||
$(CLEAN) -output-directory=booklet booklet.tex
|
||||
-rm book*/*.{bbl,loc,.run.xml}
|
||||
-rm -rf book*-epub/META-INF
|
||||
-rm -rf book*-epub/OEBPS
|
||||
-rm book*-epub/mimetype
|
||||
-rm -rf *book-epub/META-INF
|
||||
-rm -rf *book-epub/OEBPS
|
||||
-rm *book-epub/mimetype
|
||||
|
||||
mrproper: clean
|
||||
$(CLEAN) -C $(src_figures)
|
||||
$(CLEAN) -C -output-directory=book_serif book.tex
|
||||
$(CLEAN) -C -output-directory=book_sans_serif book_sans_serif.tex
|
||||
$(CLEAN) -C -output-directory=booklet booklet.tex
|
||||
-rm figures/*.png
|
||||
-rm *.html
|
||||
-rm *.svg
|
||||
@@ -237,13 +255,14 @@ mrproper: clean
|
||||
-rm -rf release/
|
||||
-rm -rf book_serif/
|
||||
-rm -rf book_sans_serif/
|
||||
-rm -rf book-epub/
|
||||
-rm -rf booklet/
|
||||
-rm -rf *book-epub/
|
||||
-rm -rf $(website_dir)
|
||||
|
||||
# top level releases rules
|
||||
.PHONY: bake release_serif release_sans_serif
|
||||
|
||||
bake: release_serif release_sans_serif
|
||||
bake: release_serif release_sans_serif release_booklet
|
||||
|
||||
release:
|
||||
mkdir -p release
|
||||
@@ -256,6 +275,9 @@ release_serif: build_serif_pdf build_ebook build_bw_ebook | release
|
||||
release_sans_serif: build_sans_serif_pdf | release
|
||||
cp book_sans_serif/book_sans_serif.pdf release/TheBreadCode-The-Sourdough-Framework-sans-serif.pdf
|
||||
|
||||
release_booklet: build_booklet | release
|
||||
cp booklet/booklet.pdf release/TheBreadCode-The-Sourdough-Framework-booklet.pdf
|
||||
|
||||
# Website stuff
|
||||
.PHONY: html website
|
||||
$(website_dir)/book.html: $(website_src) cover/cover-page.xbb
|
||||
@@ -283,6 +305,9 @@ website: html ../website/_bundle_install_done $(ruby_src)
|
||||
quick: # run latex only once no biber, no references etc...
|
||||
$(LATEX) -e '$$max_repeat=1' -halt-on-error -output-directory=book_serif book.tex
|
||||
|
||||
quick_booklet:
|
||||
$(LATEX) -e '$$max_repeat=1' -halt-on-error -output-directory=booklet booklet.tex
|
||||
|
||||
quick_ebook: cover/cover-page.xbb # run latex only once no biber, ref etc...
|
||||
$(EBOOK) --mode draft book.tex
|
||||
|
||||
@@ -293,6 +318,9 @@ show_tools_version: # Show version of tools used on the build machine
|
||||
@echo ""
|
||||
- $(SHELL) --version
|
||||
@echo ""
|
||||
- @echo "PATH:"
|
||||
- @echo $(PATH) | tr ':' '\n'
|
||||
@echo ""
|
||||
- latexmk --version
|
||||
@echo ""
|
||||
- lualatex --version
|
||||
|
||||
@@ -111,7 +111,7 @@ usually moderately affect the color.
|
||||
\item Semolina (supports Mediterranean flavors)
|
||||
\item Cocoa (replace \qty{10}{\percent} of the flour for a black loaf, goes
|
||||
great with sweet toppings)
|
||||
\item Other non-wheat flours such as: Chickpea, corn, hemp, potato etc.
|
||||
\item Other non-wheat flours such as: Chickpea, corn, hemp, potato\dots{}
|
||||
\end{itemize}
|
||||
|
||||
\subsection{Liquids}
|
||||
@@ -134,15 +134,15 @@ affecting taste and texture.
|
||||
\item Eggs
|
||||
\item Fruit/vegetable juices (also see Section~\ref{section:colors})
|
||||
\item Milk (for sweet, soft breads)
|
||||
\item Milk alternatives such as: Almond, oat, soy etc.
|
||||
\item Milk alternatives such as: Almond, oat, soy\dots{}
|
||||
\item Mashed potatoes
|
||||
\item Mashed sweet potatoes. Bolo do caco is a typical bread from Madeira,
|
||||
made from \qty{50}{\percent} wheat flour and \qty{50}{\percent} mashed potatoes.
|
||||
\item Olive oil (Mediterranean)
|
||||
\item Other mashed vegetables such as: Beets, pumpkin, etc.
|
||||
\item Other mashed vegetables such as: Beets, pumpkin\dots{}
|
||||
\end{itemize}
|
||||
|
||||
\subsection{Colors}
|
||||
\subsection{Colors}%
|
||||
\label{section:colors}
|
||||
Some mix-ins will change the color and flavor of your bread. Common colorings
|
||||
include:
|
||||
@@ -201,17 +201,18 @@ dough.
|
||||
These are mostly powders or small bits.
|
||||
|
||||
\begin{itemize}
|
||||
\item Blueberry skins (press through a sieve to remove juice, raw blueberries
|
||||
\item Blueberry skins (press through a sieve to remove juice), raw
|
||||
blueberries
|
||||
\item Browned onions
|
||||
\item Candied fruits such as: Lemon, orange, pineapple, etc.
|
||||
\item Candied fruits such as: Lemon, orange, pineapple\dots{}
|
||||
\item Cinnamon
|
||||
\item Grated hard cheese such as: Gruyère, parmesan, etc.
|
||||
\item Mediterranean herbs such as: Marjoram, oregano, rosemary, thyme, etc.
|
||||
\item Grated hard cheese such as: Gruyère, parmesan\dots{}
|
||||
\item Mediterranean herbs such as: Marjoram, oregano, rosemary, thyme\dots{}
|
||||
\item Miso
|
||||
\item Molasses
|
||||
\item Sugar
|
||||
\item Spices such as: Anise, fennel, cinnamon, coriander, cumin, etc.
|
||||
\item Zests such as: Lime, Lemon, orange, etc.
|
||||
\item Spices such as: Anise, fennel, cinnamon, coriander, cumin\dots{}
|
||||
\item Zests such as: Lime, Lemon, orange\dots{}
|
||||
\end{itemize}
|
||||
|
||||
\subsection{Highlights}
|
||||
@@ -222,12 +223,12 @@ can often be complemented by some flavor or flour mix-in.
|
||||
\begin{itemize}
|
||||
\item Chocolate chunks or drops
|
||||
\item Chunks of black garlic
|
||||
\item Chunks of cheese such as: Cheddar, feta, etc.
|
||||
\item Chunks of cheese such as: Cheddar, feta\dots{}
|
||||
\item Cornflakes
|
||||
\item Dried fruits such as: Cranberries, dates, raisins, etc.
|
||||
\item Dried fruits such as: Cranberries, dates, raisins\dots{}
|
||||
\item Olives
|
||||
\item Pickled pepperoni
|
||||
\item Sundried tomatoes (squeeze out the oil if using pickled ones, or soak
|
||||
\item Sun-dried tomatoes (squeeze out the oil if using pickled ones, or soak
|
||||
dried ones in water)
|
||||
\end{itemize}
|
||||
|
||||
@@ -240,7 +241,7 @@ A few combinations where multiple mix-ins complement each other:
|
||||
\item Cheddar and jalapeño
|
||||
\item Cocoa, cacao nibs, whole hazelnuts
|
||||
\item Cranberry and walnuts
|
||||
\item Semolina, Mediterranean herbs, olives, sundried tomatoes
|
||||
\item Semolina, Mediterranean herbs, olives, sun-dried tomatoes
|
||||
\item Tomato juice instead of water with \qty{20}{\percent} rye flour
|
||||
\end{itemize}
|
||||
|
||||
@@ -310,6 +311,6 @@ ferment the dough in separate containers. Then Combine the two (or
|
||||
more) differently colored doughs by laminating and stacking the colored sheets
|
||||
of dough before the last folding, just before shaping. This way the colored
|
||||
layers won't mix and the resulting dough will have differently colored and
|
||||
tasting layers. \footnote{I once made an experimental dough by merging a wheat,
|
||||
tasting layers\footnote{I once made an experimental dough by merging a wheat,
|
||||
rye, spelt and einkorn dough into a single dough. The resulting dough was
|
||||
layered featuring different colors, textures, and flavors.}
|
||||
layered featuring different colors, textures, and flavors.}.
|
||||
|
||||
@@ -17,14 +17,13 @@ a denser crumb compared to wheat, as you can see in
|
||||
Picture~\ref{fig:rye-crumb}.
|
||||
|
||||
\begin{flowchart}[!htb]
|
||||
\begin{center}
|
||||
\centering
|
||||
\input{figures/fig-non-wheat-process.tex}
|
||||
\caption[Process for non-wheat sourdough bread]{A visualization of the
|
||||
process to make non-wheat sourdough bread. The process is much simpler
|
||||
than making wheat sourdough bread. There is no gluten development. The
|
||||
ingredients are simply mixed together.}%
|
||||
\label{flc:non-wheat-sourdough}
|
||||
\end{center}
|
||||
\end{flowchart}
|
||||
|
||||
For non-wheat flours---including rye, emmer, and einkorn---no gluten
|
||||
|
||||
53
book/recipes/flat-bread.tex
Normal file
53
book/recipes/flat-bread.tex
Normal file
@@ -0,0 +1,53 @@
|
||||
\subsubsection*{Ingredients}
|
||||
\begin{tabular}{r@{}rl@{}}
|
||||
\qty{400}{\gram} &~(\qty{100}{\percent}) & Flour (wheat, rye, corn, whatever
|
||||
you have at hand)\\
|
||||
\qty{320}{\gram} & (\qty{80}{\percent}) & Water, preferably at room
|
||||
temperature\\
|
||||
\qty{80}{\gram} & (\qty{20}{\percent}) & Active sourdough starter\\
|
||||
\qty{8}{\gram} & (\qty{2}{\percent}) & Salt\\
|
||||
\end{tabular}
|
||||
|
||||
\subsubsection*{Instructions}
|
||||
\begin{description}
|
||||
\item[Prepare the dough] In a large mixing bowl, combine the flour and water.
|
||||
Mix until you have a shaggy dough with no dry spots.
|
||||
|
||||
Add the sourdough starter and salt to the mixture. Incorporate them
|
||||
thoroughly until you achieve a smooth and homogenized dough.
|
||||
|
||||
\item[Fermentation:] Cover the bowl with a lid or plastic wrap. Allow the dough
|
||||
to rest and ferment until it has increased by at least \qty{50}{\percent}
|
||||
in size. Depending on the temperature and activity of your starter, this
|
||||
can take anywhere from 4 to 24~hours.
|
||||
|
||||
\item[Cooking preparation:] Once the dough has risen, heat a pan over medium
|
||||
heat. Lightly oil the pan, ensuring to wipe away any excess oil with a
|
||||
paper towel.
|
||||
|
||||
\item[Shaping and cooking:] With a ladle or your hands, scoop out a portion of
|
||||
the dough and place it onto the hot pan, spreading it gently like a
|
||||
pancake.
|
||||
|
||||
Cover the pan with a lid. This traps the steam and ensures even cooking
|
||||
from the top, allowing for easier flipping later.
|
||||
|
||||
After about 5~minutes, or when the bottom of the flatbread has a
|
||||
golden-brown crust, carefully flip it using a spatula.
|
||||
|
||||
\emph{Adjusting cook time.} If the flatbread appears too dark, remember to
|
||||
reduce the cooking time slightly for the next one. Conversely, if it's
|
||||
too pale, allow it to cook a bit longer before flipping.
|
||||
|
||||
Cook the flipped side for an additional 5~minutes or until it's also
|
||||
golden brown.
|
||||
|
||||
\item[Storing:] Once cooked, remove the flatbread from the pan and place it on
|
||||
a kitchen towel. Wrapping the breads in the towel will help retain their
|
||||
softness and prevent them from becoming overly crisp. Repeat the cooking
|
||||
process for the remaining dough.
|
||||
|
||||
\item[Serving suggestion:] Enjoy your sourdough flatbreads warm, paired with
|
||||
your favorite dips, spreads, or as a side to any meal.
|
||||
|
||||
\end{description}
|
||||
@@ -27,14 +27,13 @@ starter has half as much water as flour, as summarized in
|
||||
Table~\ref{tab:starter-types-comparison}.
|
||||
|
||||
\begin{table}[htp!]
|
||||
\begin{center}
|
||||
\centering
|
||||
\input{tables/table-starter-types.tex}
|
||||
\caption[Different types of sourdough]{A comparison of different
|
||||
sourdough starter types and their respective properties. The only
|
||||
difference is the amount of water (hydration) that is used when
|
||||
feeding the starter.}%
|
||||
\label{tab:starter-types-comparison}
|
||||
\end{center}
|
||||
\end{table}
|
||||
|
||||
You can change your starter type by just adjusting the feeding ratio of how
|
||||
@@ -123,19 +122,18 @@ starter's flavor by changing the type to a liquid starter.
|
||||
\label{section:liquid-starter}
|
||||
|
||||
\begin{figure}[!htb]
|
||||
\begin{center}
|
||||
\centering
|
||||
\includegraphics[width=0.5\textwidth]{sourdough-starter-liquid.jpg}
|
||||
\caption[Liquid starter]{A liquid sourdough starter features a high level of
|
||||
water. The high water amount boosts lactic acid producing bacteria.
|
||||
After a while the liquid and flour start to separate. Bubbles on the
|
||||
side of the flour indicate that the starter is ready to be used.}%
|
||||
\label{fig:liquid-sourdough-starter}
|
||||
\end{center}
|
||||
\end{figure}
|
||||
|
||||
|
||||
\begin{flowchart}[!htb]
|
||||
\begin{center}
|
||||
\centering
|
||||
\input{figures/fig-liquid-starter-conversion.tex}
|
||||
\caption[Converting to a liquid starter]{The process to convert your regular
|
||||
or stiff starter into a liquid starter. The whole process takes around
|
||||
@@ -149,7 +147,6 @@ starter's flavor by changing the type to a liquid starter.
|
||||
starter your created stiff starter will feature both dairy
|
||||
and vinegary notes.}%
|
||||
\label{flc:liquid-starter-conversion}
|
||||
\end{center}
|
||||
\end{flowchart}
|
||||
|
||||
The liquid starter is made at a hydration of around \qty{500}{\percent}. This means
|
||||
@@ -242,7 +239,7 @@ for a visual example of the starter's required hydration level.
|
||||
\end{figure}
|
||||
|
||||
\begin{flowchart}[!htb]
|
||||
\begin{center}
|
||||
\centering
|
||||
\input{figures/fig-stiff-starter-conversion.tex}
|
||||
\caption[Converting to a stiff starter]{The process to convert your regular
|
||||
starter into a stiff starter. The whole process takes around 3 days. The
|
||||
@@ -252,7 +249,6 @@ for a visual example of the starter's required hydration level.
|
||||
\qty{50}{\percent} hydration level for the starter. If the dough is too
|
||||
stiff consider increasing this to \qty{60}{\percent}.}%
|
||||
\label{fig:stiff-starter-conversion}
|
||||
\end{center}
|
||||
\end{flowchart}
|
||||
|
||||
In the stiffer environment the yeast thrives more. This means you will have
|
||||
@@ -302,13 +298,16 @@ pockets of air on the sides of your container. Use your nose to smell the
|
||||
starter. It should have a mild smell. It also tends to smell much more
|
||||
alcoholic than the other starters.
|
||||
|
||||
When using a stiff starter, use around \qtyrange{1}{20}{\percent} starter for your
|
||||
When using a stiff starter, use around \qtyrange{1}{20}{\percent} starter in terms of
|
||||
baker's math for your
|
||||
dough. This depends on the ripeness of your starter.
|
||||
In summer I~typically use around
|
||||
\qty{10}{\percent} and in winter around \qty{20}{\percent}. This way you can
|
||||
also control the fermentation speed.
|
||||
Mixing the starter can be a little bit annoying as it hardly homogenizes with
|
||||
the rest of the dough. In this case you can try to dissolve the starter in the
|
||||
\qtyrange{1}{10}{\percent} and in winter around \qty{20}{\percent}. This way you can
|
||||
also control the fermentation speed. If it is very hot where you live, consider
|
||||
lowering the starter amount to \qtyrange{1}{5}{\percent}. If it is very cold in your
|
||||
area consider increasing the starter amount up to \qty{30}{\percent}.
|
||||
Mixing the stiff starter can be a little bit annoying as it hardly homogenizes with
|
||||
the rest of the dough. In this case, you can try to dissolve the starter in the
|
||||
water you are about to use for your dough. This will make mixing a lot easier.
|
||||
|
||||
|
||||
|
||||
@@ -38,11 +38,10 @@ comes in handy. Let's look at the default recipe with baker's
|
||||
math and then adjust it for the \qty{1.4}{\kg} flour quantity.
|
||||
|
||||
\begin{table}[!htb]
|
||||
\begin{center}
|
||||
\centering
|
||||
\input{tables/table-bakers-math-example.tex}
|
||||
\caption[Baker's math example]{An example table demonstrating how to
|
||||
properly calculate using baker's math}
|
||||
\end{center}
|
||||
\end{table}
|
||||
|
||||
Note how each of the ingredients is calculated as a percentage
|
||||
@@ -55,12 +54,11 @@ more flour available the next day. As mentioned the next day
|
||||
we have \qty{1.4}{\kg} at hand (\qty{1400}{\gram}).
|
||||
|
||||
\begin{table}[!htb]
|
||||
\begin{center}
|
||||
\centering
|
||||
\input{tables/table-recipe-bakers-math.tex}
|
||||
\caption[Another baker's math example]{An example recipe that uses
|
||||
\qty{1400}{\gram} as its baseline and is then calculated using
|
||||
baker's math.}
|
||||
\end{center}
|
||||
\end{table}
|
||||
|
||||
For each ingredient we calculate the percentage
|
||||
@@ -133,12 +131,11 @@ I~like to use a glass and place another
|
||||
inverted one on top.
|
||||
|
||||
\begin{flowchart}[!htb]
|
||||
\begin{center}
|
||||
\centering
|
||||
\input{figures/fig-starter-process.tex}
|
||||
\caption[The full sourdough starter process]{The process of making a sourdough
|
||||
starter from scratch.}%
|
||||
\label{fig:sourdough-starter-process}
|
||||
\end{center}
|
||||
\end{flowchart}
|
||||
|
||||
Now an epic battle begins. In one study~\cite{yeasts+biocontrol+agent}
|
||||
@@ -272,14 +269,13 @@ yeast has been isolated like this from century old sourdough
|
||||
starters.
|
||||
|
||||
\begin{flowchart}[!htb]
|
||||
\begin{center}
|
||||
\centering
|
||||
\input{figures/fig-starter-readiness.tex}
|
||||
\caption[Determining sourdough starter readiness]{A flow chart showing you how to
|
||||
determine if your sourdough starter is ready to be used. For checking
|
||||
readiness look at a size increase and take note of your starter's smell.
|
||||
Both are important indicators to check for readiness.}%
|
||||
\label{fig:sourdough-starter-readiness}
|
||||
\end{center}
|
||||
\end{flowchart}
|
||||
|
||||
The key sign to look at is bubbles that you see in your starter
|
||||
@@ -346,7 +342,7 @@ yeast part of your sourdough and balance the fermentation.
|
||||
\section{Maintenance}
|
||||
|
||||
\begin{flowchart}[!htb]
|
||||
\begin{center}
|
||||
\centering
|
||||
\input{figures/fig-starter-maintenance.tex}
|
||||
\caption[Sourdough starter maintenance flowchart]{A full flowchart showing
|
||||
you how to conduct proper sourdough starter maintenance. You can use a
|
||||
@@ -356,7 +352,6 @@ yeast part of your sourdough and balance the fermentation.
|
||||
\qty{100}{\percent} hydration level. Adjust the water content
|
||||
accordingly when you use a stiff starter.}%
|
||||
\label{fig:sourdough-maintenance-process}
|
||||
\end{center}
|
||||
\end{flowchart}
|
||||
|
||||
You have made your sourdough starter and your first bread. How do you perform
|
||||
@@ -432,7 +427,7 @@ of water. This extra layer of water provides good protection from the top
|
||||
part drying out. As mold is aerobic it can not grow efficiently under
|
||||
water~\cite{mold+anaerobic}. Before using the starter again simply either stir
|
||||
the liquid into the dough or drain it. If you drain the liquid you can use it
|
||||
to make a lacto fermented hot sauce for instance.
|
||||
to make a lacto-fermented hot sauce for instance.
|
||||
|
||||
The colder it is the longer you preserve a good balance of yeast and
|
||||
bacteria. Generally, the warmer it is the faster the fermentation process is,
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
% Common abbreviations
|
||||
\newcommand{\ie}{\emph{i.e.}\@ifnextchar.{\!\@gobble}{}}
|
||||
\newcommand{\eg}{\emph{e.g.}\@ifnextchar.{\!\@gobble}{}}
|
||||
\newcommand{\etc}{etc\@ifnextchar.{}{.\@}}
|
||||
|
||||
% Consistent pH values
|
||||
\newcommand{\pHvalue}[1]{pH~\SI{#1}{}}
|
||||
|
||||
@@ -9,12 +9,11 @@ later time.
|
||||
A summary can be found in Table~\ref{table:bread-storage}, with details and
|
||||
explanation in th rest of this chapter.
|
||||
\begin{table}[!htb]
|
||||
\begin{center}
|
||||
\centering
|
||||
\input{tables/table-storing-bread-overview.tex}
|
||||
\caption[Options to store bread]{A table visualizing the advantages
|
||||
and disadvantages of different bread storing options.}%
|
||||
\label{table:bread-storage}
|
||||
\end{center}
|
||||
\end{table}
|
||||
|
||||
\section{Room temperature}
|
||||
|
||||
221
book/style.css
221
book/style.css
@@ -6,12 +6,15 @@
|
||||
--fw-bold: 800;
|
||||
--f-lh: 28px;
|
||||
--c-black: #282828;
|
||||
--c-black-background: #1c1819;
|
||||
--fs-xxxl: 32px;
|
||||
--fs-xxl: 26px;
|
||||
--fs-xl: 24px;
|
||||
--fs-l: 22px;
|
||||
--fs-m: 16px;
|
||||
--padding-hamburger: 5px;
|
||||
--c-beige: #F3EDE6;
|
||||
--border-radius: 7px;
|
||||
}
|
||||
|
||||
@media (min-width: 1200px){
|
||||
@@ -38,6 +41,7 @@ body{
|
||||
font-family: var(--ff-sans);
|
||||
font-weight: var(--fw-regular);
|
||||
font-size: var(--fs-m);
|
||||
color: var(--c-black);
|
||||
}
|
||||
|
||||
@media screen and (min-width: 57rem) {
|
||||
@@ -60,7 +64,6 @@ body{
|
||||
/* ****************** */
|
||||
|
||||
main.main-content,main.titlepage,div.footnotes{
|
||||
padding:1rem;
|
||||
}
|
||||
|
||||
.permalink {
|
||||
@@ -144,7 +147,7 @@ nav.TOC a, nav.TOC a:visited{
|
||||
|
||||
|
||||
body{
|
||||
background-color: var(--c-black);
|
||||
background-color: var(--c-beige);
|
||||
}
|
||||
|
||||
a {
|
||||
@@ -174,6 +177,7 @@ figure.texsource, figure.shellcommand, figure.htmlsource, figure.luasource, figu
|
||||
|
||||
.main-content {
|
||||
line-height: var(--f-lh);
|
||||
margin-left: 30px;
|
||||
}
|
||||
|
||||
div.footnotes {
|
||||
@@ -229,6 +233,7 @@ figcaption.caption {
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
width: 300px;
|
||||
}
|
||||
|
||||
.menu-items .chapterToc, .menu-items .likechapterToc {
|
||||
@@ -331,7 +336,7 @@ div.center {
|
||||
margin-right: 0 !important;
|
||||
}
|
||||
|
||||
main.titlepage h2.chapterHead {
|
||||
main.main-content h2.chapterHead, main.main-content h2.likechapterHead {
|
||||
margin-top: 0px;
|
||||
}
|
||||
|
||||
@@ -379,3 +384,213 @@ h4 {
|
||||
max-width: 100%;
|
||||
margin-top: 1em;
|
||||
}
|
||||
|
||||
img[alt~="PIC"], iframe, a img {
|
||||
border-radius: var(--border-radius);
|
||||
border: 2px solid var(--c-black);
|
||||
}
|
||||
|
||||
main.main-content, div.footnotes, main.titlepage {
|
||||
background-color: var(--c-beige);
|
||||
}
|
||||
|
||||
.main-content {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.wrapper {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.header {
|
||||
background-color: var(--c-black-background);
|
||||
width: 100%;
|
||||
height: 340px;
|
||||
display: flex;
|
||||
align-content: center;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
margin-bottom: 40px;
|
||||
}
|
||||
|
||||
.header img {
|
||||
border-radius: 0px;
|
||||
border: none;
|
||||
width: 710px;
|
||||
}
|
||||
|
||||
body {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.book-content {
|
||||
display: flex;
|
||||
padding: 0px 40px;
|
||||
max-width: 1200px;
|
||||
}
|
||||
|
||||
.TOC.menu {
|
||||
width: 330px;
|
||||
}
|
||||
|
||||
.main-content {
|
||||
width: 100%;
|
||||
margin-bottom: 40px;
|
||||
}
|
||||
|
||||
nav.TOC, nav.TOC a, nav.TOC a:visited {
|
||||
background-color: transparent;
|
||||
color: var(--c-black);
|
||||
}
|
||||
|
||||
.menu-group {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.menu-inner {
|
||||
border: 2px solid var(--c-black);
|
||||
border-radius: var(--border-radius);
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.menu-entry {
|
||||
padding: 1px;
|
||||
border-radius: var(--border-radius);
|
||||
}
|
||||
|
||||
.menu-arrow {
|
||||
width: 14px;
|
||||
border: none;
|
||||
border-radius: 0px;
|
||||
}
|
||||
|
||||
nav.TOC span:hover, nav.TOC span:hover *, nav.TOC span.chapterToc.selected, nav.TOC span.chapterToc.selected a {
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
.menu-entry:hover {
|
||||
background-color: #c8c8c8;
|
||||
}
|
||||
|
||||
p.flowchart-image-wrapper {
|
||||
background: white;
|
||||
padding: 20px;
|
||||
border-radius: var(--border-radius);
|
||||
border: 2px solid var(--c-black);
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.menu-items .menu-group:last-of-type .menu-arrow {
|
||||
display: none;
|
||||
}
|
||||
|
||||
blockquote {
|
||||
margin-left: 0px;
|
||||
margin-right: 0px;
|
||||
}
|
||||
|
||||
.crosslinks-bottom {
|
||||
margin-top: 1em;
|
||||
}
|
||||
|
||||
.crosslinks-bottom a {
|
||||
display: inline-block;
|
||||
border-radius: var(--border-radius);
|
||||
border: 2px solid var(--c-black);
|
||||
color: var(--c-black);
|
||||
padding: 4px;
|
||||
font-weight: bold;
|
||||
text-decoration: none;
|
||||
}
|
||||
.crosslinks-bottom a.prev {
|
||||
margin-right: 7px;
|
||||
}
|
||||
|
||||
.crosslinks-bottom a:hover {
|
||||
color: #444;
|
||||
}
|
||||
|
||||
.menu-group.selected .menu-inner {
|
||||
background-color: #c8c8c8;
|
||||
}
|
||||
|
||||
.TOC.menu {
|
||||
margin-bottom: 40px;
|
||||
}
|
||||
|
||||
.mobile-banner {
|
||||
display: none;
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.header {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.book-content {
|
||||
padding: 0px;
|
||||
display: flex;
|
||||
width: 100%;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.main-content {
|
||||
width: 100%;
|
||||
margin-left: 0px;
|
||||
box-sizing: border-box;
|
||||
padding: 0px 14px;
|
||||
margin-top: 20px;
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
.TOC.menu {
|
||||
width: 100%;
|
||||
max-width: 100%;
|
||||
background: var(--c-black-background);
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
nav.TOC, nav.TOC a, nav.TOC a:visited {
|
||||
color: #fff;
|
||||
}
|
||||
.menu-arrow {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.menu-inner {
|
||||
border: none;
|
||||
border-radius: 0px;
|
||||
}
|
||||
|
||||
.menu-group.selected .menu-inner {
|
||||
background: var(--c-black-background);
|
||||
}
|
||||
|
||||
p.flowchart-image-wrapper {
|
||||
padding: 5px;
|
||||
}
|
||||
|
||||
.menu-entry:hover {
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
.TOC.menu {
|
||||
margin-bottom: 0px;
|
||||
}
|
||||
|
||||
.mobile-banner {
|
||||
display: block;
|
||||
background-color: var(--c-black-background);
|
||||
padding: 5px;
|
||||
}
|
||||
.mobile-banner a img {
|
||||
border: none;
|
||||
border-radius: 0px;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ Andail,
|
||||
Andreas Schmid,
|
||||
Andrzej Mitelski,
|
||||
Anna G.,
|
||||
anonnn,
|
||||
Anonnn,
|
||||
Anthony Atkinson,
|
||||
Aurore,
|
||||
Beatriz,
|
||||
@@ -26,6 +26,7 @@ BTSkete,
|
||||
C Fazio,
|
||||
Cal Kotz,
|
||||
Case,
|
||||
Cédric Andrieu,
|
||||
Charlene Adkins,
|
||||
Chin Pui Ling,
|
||||
Chris DuBosq,
|
||||
@@ -35,7 +36,6 @@ Christiane B,
|
||||
Christine,
|
||||
Chrysanna,
|
||||
Colleen Guidone,
|
||||
Cédric Andrieu,
|
||||
Danieel,
|
||||
Daniel,
|
||||
David,
|
||||
@@ -48,7 +48,7 @@ Duivelsjong,
|
||||
Elaine Leung,
|
||||
Ellie,
|
||||
Ethan,
|
||||
Francois le Danois,
|
||||
François le Danois,
|
||||
Fredrik,
|
||||
Geoff,
|
||||
Guillermo,
|
||||
@@ -59,7 +59,6 @@ Ilsefa,
|
||||
Inma Mcleish,
|
||||
Jackie,
|
||||
Jacques Lucke,
|
||||
Jacques Lucke,
|
||||
Jan Chrillesen,
|
||||
Jan-Pieter Van Den Wittenboer,
|
||||
Jane,
|
||||
@@ -135,7 +134,6 @@ Smirnov,
|
||||
Spencer,
|
||||
Strambinha,
|
||||
Sue,
|
||||
Sue,
|
||||
Sune,
|
||||
Susan,
|
||||
Sven,
|
||||
@@ -145,7 +143,7 @@ Therealbruce,
|
||||
Tracy \& Paul Will,
|
||||
Usliv,
|
||||
Vassil Dichev,
|
||||
Vladimir
|
||||
Vladimir Smirnov,
|
||||
Voicu,
|
||||
Zika,
|
||||
Zoltan.
|
||||
|
||||
|
Can't render this file because it has a wrong number of fields in line 148.
|
@@ -7,7 +7,7 @@
|
||||
100 / 212 & Water evaporation & Water begins to evaporate and inflates your dough's alveoli.\\
|
||||
118 / 244 & Acetic acid evaporation & The vinegary tasting acid starts to evaporate, sourness decreases.\\
|
||||
122 / 252 & Lactic acid evaporation & The dairy tasting lactic acid begins to evaporate, sourness further decreases.\\
|
||||
140 / 284 & Maillard reaction & The maillard reaction starts to deform starches and proteins.
|
||||
140 / 284 & Maillard reaction & The Maillard reaction starts to deform starches and proteins.
|
||||
The dough starts browning.\\
|
||||
170 / 338 & Caramelization & Remaining sugars begin to caramelise giving your bread a distinct flavor.\\ \bottomrule
|
||||
\end{tabular}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
%TODO: Alignement is not great
|
||||
%TODO: Alignment is not great
|
||||
\begin{tabular}{@{}lll@{}}
|
||||
\toprule
|
||||
& \textbf{Flat breads} & \textbf{Pancakes} \\ \midrule
|
||||
|
||||
@@ -141,7 +141,7 @@ should dissipate within 12--24~hours, and you have
|
||||
the added advantage of automatically having
|
||||
room-temperature water.
|
||||
|
||||
Make sure to use whole grain flour (whole-wheat, whole-rye, etc.).
|
||||
Make sure to use whole grain flour (whole-wheat, whole-rye, \etc{}).
|
||||
These flours have more natural wild yeast and
|
||||
bacterial contamination. Making a starter
|
||||
from just white flour sometimes doesn't work.
|
||||
@@ -188,12 +188,11 @@ protecting your sourdough starter from aerobic mold entering through
|
||||
the top.
|
||||
|
||||
\begin{figure}[!htb]
|
||||
\begin{center}
|
||||
\centering
|
||||
\includegraphics[width=0.5\textwidth]{sourdough-starter-hooch}
|
||||
\caption[Hooch] {Hooch building on top of a sourdough
|
||||
starter~\cite{liquid+on+starter}.}%
|
||||
\label{fig:hooch}
|
||||
\end{center}
|
||||
\end{figure}
|
||||
|
||||
Simply stir your sourdough starter to homogenize the hooch back
|
||||
@@ -321,12 +320,11 @@ When tasting acetic acid, the flavor of your bread is often perceived
|
||||
as quite strong.
|
||||
|
||||
\begin{figure}[!htb]
|
||||
\begin{center}
|
||||
\centering
|
||||
\input{figures/fig-ethanol-oxidation.tex}
|
||||
\caption[Acetic acid creation]{Oxygen is required to create acetic
|
||||
acid~\cite{acetic+acid+production}.}%
|
||||
\label{fig:ethanol-oxidation}
|
||||
\end{center}
|
||||
\end{figure}
|
||||
|
||||
This is nothing bad. But if you would like to change
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 115 KiB After Width: | Height: | Size: 626 KiB |
@@ -45,11 +45,10 @@ that tastes much better than any store-bought bread.
|
||||
\section{The process}
|
||||
|
||||
\begin{flowchart}[!htb]
|
||||
\begin{center}
|
||||
\centering
|
||||
\input{figures/fig-wheat-sourdough-process.tex}
|
||||
\caption{The typical process of making a wheat-based sourdough bread.}%
|
||||
\label{fig:wheat-sourdough-process}
|
||||
\end{center}
|
||||
\end{flowchart}
|
||||
|
||||
The whole process of making great sourdough bread starts with
|
||||
@@ -99,7 +98,7 @@ doesn't have a good balance of yeast to bacteria, so will your
|
||||
main dough.
|
||||
|
||||
\begin{flowchart}[!htb]
|
||||
\begin{center}
|
||||
\centering
|
||||
\input{figures/fig-starter-readiness.tex}
|
||||
\caption[Process to prepare your starter before baking]{The process to check
|
||||
your sourdough starter when making wheat-based doughs. In practice
|
||||
@@ -110,7 +109,6 @@ main dough.
|
||||
shown water quantities, i.e., if the chart shows \qty{100}{\gram} of
|
||||
water, use \qtyrange{50}{60}{\gram} of water for your stiff starter.}%
|
||||
\label{fig:process-starter-wheat-sourdough}
|
||||
\end{center}
|
||||
\end{flowchart}
|
||||
|
||||
Generally, think of the dough you are mixing as a big starter with salt.
|
||||
@@ -137,7 +135,7 @@ the microorganisms.
|
||||
Some people use a 1:1:1 ratio to refresh the starter. This would
|
||||
be one part of the old starter (\qty{10}{\gram} for instance), 1 part of flour,
|
||||
and one part of water. I~think this is utter rubbish. As mentioned
|
||||
your starter is a gigantic dough. You would never opt for a 1:1:1 ratio to
|
||||
your starter is a miniature dough. You would never opt for a 1:1:1 ratio to
|
||||
make dough. You might use a maximum of \qty{20}{\percent} starter to
|
||||
make dough. That's why I~advocate using a 1:5:5 ratio or a
|
||||
1:10:10 ratio depending on how ripe your starter is. As I~almost
|
||||
@@ -520,12 +518,11 @@ value to \qtyrange{5}{10}{\percent}. The other option could be to place the doug
|
||||
environment and thus reduce the speed at which your microorganisms replicate.
|
||||
|
||||
\begin{table}[!htb]
|
||||
\begin{center}
|
||||
\centering
|
||||
\input{tables/table-starter-usage-activity.tex}
|
||||
\caption[Quantity of sourdough]{A table visualizing how much sourdough
|
||||
starter to use depending on temperature and the starter's activity
|
||||
level.}
|
||||
\end{center}
|
||||
\end{table}
|
||||
|
||||
Based on my experience and my sourdough, my ideal bread always takes around 8
|
||||
@@ -561,11 +558,10 @@ all the gases during the fermentation process. Without the gluten network,
|
||||
the gases would just diffuse out of your dough.
|
||||
|
||||
\begin{flowchart}[!htb]
|
||||
\begin{center}
|
||||
\centering
|
||||
\input{figures/fig-kneading-process.tex}
|
||||
\caption{The gluten development process for a wheat-based dough.}%
|
||||
\label{fig:wheat-sourdough-kneading-process}
|
||||
\end{center}
|
||||
\end{flowchart}
|
||||
|
||||
It might sound odd, but the most important part of kneading is waiting. By
|
||||
@@ -751,12 +747,11 @@ flavor of the resulting bread is better compared to a pale
|
||||
underfermented dough.
|
||||
|
||||
\begin{table}[!htb]
|
||||
\begin{center}
|
||||
\centering
|
||||
\input{tables/table-fermentation-effects.tex}
|
||||
\caption[Stages of sourdough fermentation]{The different stages of
|
||||
sourdough fermentation and the effects on crumb, alveoli, texture,
|
||||
and overall taste.}
|
||||
\end{center}
|
||||
\end{table}
|
||||
|
||||
The worst thing you can do when fermenting sourdough
|
||||
@@ -777,7 +772,7 @@ is much larger. The doughs are perfect to be made in a
|
||||
machine.
|
||||
|
||||
\begin{flowchart}[!htb]
|
||||
\begin{center}
|
||||
\centering
|
||||
\input{figures/fig-bulk-fermentation.tex}
|
||||
\caption[Process to check the bulk fermentation]{During the bulk
|
||||
fermentation, multiple doughs are fermented together in bulk. A
|
||||
@@ -785,7 +780,6 @@ machine.
|
||||
stage of fermentation is completed. This chart shows multiple available
|
||||
options to check on the bulk fermentation progress.}%
|
||||
\label{fig:bulk-fermentation}
|
||||
\end{center}
|
||||
\end{flowchart}
|
||||
|
||||
Experienced bakers will tell you to go by the look and feel of
|
||||
@@ -798,8 +792,7 @@ My go-to method for beginners is to use an \emph{Aliquot jar}.
|
||||
The aliquot is a sample that you extract from your dough. The
|
||||
sample is extracted after creating the initial dough strength.
|
||||
You monitor the aliquot's size increase to judge the
|
||||
level of fermentation of your main dough. The aliquot
|
||||
sample is extracted after creating dough strength. As your
|
||||
level of fermentation of your main dough. As your
|
||||
dough ferments, so does the content of your aliquot jar. The moment your
|
||||
sample reached a certain size, your main dough is ready
|
||||
to be shaped and proofed. The size increase you should
|
||||
@@ -814,12 +807,11 @@ up to \qty{100}{\percent} with subsequent bakes. Then identify a value
|
||||
that you are happy with.
|
||||
|
||||
\begin{table}[!htb]
|
||||
\begin{center}
|
||||
\centering
|
||||
\input{tables/table-dough-size-increase.tex}
|
||||
\caption[Increase of size versus protein content]{Reference values for
|
||||
how much size increase to aim for with an aliquot jar depending on
|
||||
the dough's protein content.}
|
||||
\end{center}
|
||||
\end{table}
|
||||
|
||||
The beauty of the aliquot is that no matter the surrounding
|
||||
@@ -896,12 +888,11 @@ bread didn't turn out the way you like, either shorten
|
||||
the fermentation or extend it a little bit.
|
||||
|
||||
\begin{table}[!htb]
|
||||
\begin{center}
|
||||
\centering
|
||||
\input{tables/table-ph-values-dough.tex}%
|
||||
\caption[Dough's pH during bread preparation]{Example pH values for
|
||||
the different breakpoints of my own sourdough process.}%
|
||||
\label{table:sample-ph-values}
|
||||
\end{center}
|
||||
\end{table}
|
||||
|
||||
The beauty of this method is its reliability. Once you have found
|
||||
@@ -921,7 +912,12 @@ as rough ballpark figures. Regardless, you need to find values
|
||||
that work for your setup.
|
||||
|
||||
Another limitation is the price. You will need to purchase
|
||||
a high-tech pH meter, ideally, a meter featuring a spearhead.
|
||||
a high-tech pH meter, ideally, a meter featuring a spearhead
|
||||
\footnote{Not every pH meter is suitable for measuring dough.
|
||||
Please refer to the manual to make sure it is certified for
|
||||
measuring the pH of liquid and semi-solid media. To receive
|
||||
accurate pH readings further ensure that your pH meter
|
||||
is properly calibrated.}.
|
||||
This way you can directly poke the meter deep into the dough.
|
||||
At the same time, automated temperature adjustments are a
|
||||
feature to look out for. Depending on the temperature,
|
||||
@@ -1120,12 +1116,11 @@ The step is required if you are making multiple loaves in one
|
||||
batch. It is optional if you are making a single loaf.
|
||||
|
||||
\begin{flowchart}[!htb]
|
||||
\begin{center}
|
||||
\centering
|
||||
\input{figures/fig-dividing-preshaping.tex}
|
||||
\caption[Is dividing your dough required check]{Dividing is only required when you are
|
||||
making multiple loaves in a single dough batch.}%
|
||||
\label{fig:dividing-decision-tree}
|
||||
\end{center}
|
||||
\end{flowchart}
|
||||
|
||||
The goal of dividing your dough into smaller pieces is to portion
|
||||
@@ -1235,12 +1230,11 @@ your environment.
|
||||
\section{Shaping}
|
||||
|
||||
\begin{flowchart}[!htb]
|
||||
\begin{center}
|
||||
\centering
|
||||
\input{figures/fig-shaping-process.tex}
|
||||
\caption[Sourdough shaping process]{A schematic visualization of the shaping process
|
||||
including checks for an overfermented dough.}%
|
||||
\label{fig:shaping-decision-tree}
|
||||
\end{center}
|
||||
\end{flowchart}
|
||||
|
||||
Shaping will give your dough the final shape before baking. After
|
||||
@@ -1460,13 +1454,12 @@ their biochemical processes. More research is needed on the topic
|
||||
of retarding and flavor development.
|
||||
|
||||
\begin{flowchart}[!htb]
|
||||
\begin{center}
|
||||
\centering
|
||||
\input{figures/fig-proofing-process.tex}
|
||||
\caption[Sourdough proofing process]{A schematic overview of the different steps of
|
||||
the sourdough proofing process. The proofing technique to choose depends
|
||||
on your availability and schedule.}%
|
||||
\label{fig:proofing-process}
|
||||
\end{center}
|
||||
\end{flowchart}
|
||||
|
||||
To me, the sole purpose of cold-proofing is its ability to allow you
|
||||
@@ -1676,7 +1669,7 @@ An additional trick that can help you to combine the benefits
|
||||
of room temperature-proofing and easy cold-proofing scoring
|
||||
is to place your dough in the freezer for 30~minutes before baking.
|
||||
Once you notice your dough is almost done proofing, move it to the
|
||||
freezer. The freezer will dry out the doughs's surface even further
|
||||
freezer. The freezer will dry out the dough's surface even further
|
||||
while also lowering its viscosity, making scoring easier.
|
||||
|
||||
Another interesting trick is to bake your dough for 30 seconds without steam.
|
||||
|
||||
6
makefile
6
makefile
@@ -5,6 +5,7 @@ DOCKER_CMD := docker run --rm -it -v $(PWD):/opt/repo --platform linux/x86_64 $(
|
||||
|
||||
.PHONY: bake build_pdf build_docker_image push_docker_image validate website
|
||||
.PHONY: print_os_version start_shell printvars show_tools_version mrproper
|
||||
.PHONY: build_serif_pdf build_ebook booklet
|
||||
|
||||
# Dockers targets
|
||||
build_docker_image:
|
||||
@@ -24,11 +25,14 @@ build_pdf:
|
||||
$(DOCKER_CMD) "cd /opt/repo/book && make"
|
||||
|
||||
bake:
|
||||
$(DOCKER_CMD) "cd /opt/repo/book && make -j bake"
|
||||
$(DOCKER_CMD) "cd /opt/repo/book && make bake"
|
||||
|
||||
website:
|
||||
$(DOCKER_CMD) "cd /opt/repo/book && make website"
|
||||
|
||||
booklet:
|
||||
$(DOCKER_CMD) "cd /opt/repo/book && make build_booklet"
|
||||
|
||||
mrproper:
|
||||
$(DOCKER_CMD) "cd /opt/repo/book && make mrproper"
|
||||
|
||||
|
||||
@@ -5,6 +5,8 @@ GEM
|
||||
method_source (1.0.0)
|
||||
nokogiri (1.15.3-arm64-darwin)
|
||||
racc (~> 1.4)
|
||||
nokogiri (1.15.3-x86_64-darwin)
|
||||
racc (~> 1.4)
|
||||
nokogiri (1.15.3-x86_64-linux)
|
||||
racc (~> 1.4)
|
||||
pry (0.14.2)
|
||||
@@ -14,6 +16,7 @@ GEM
|
||||
|
||||
PLATFORMS
|
||||
arm64-darwin-22
|
||||
x86_64-darwin-22
|
||||
x86_64-linux
|
||||
|
||||
DEPENDENCIES
|
||||
|
||||
BIN
website/assets/arrow.png
Normal file
BIN
website/assets/arrow.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 298 B |
BIN
website/assets/banner.png
Normal file
BIN
website/assets/banner.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 170 KiB |
BIN
website/assets/og_image_mixins.png
Normal file
BIN
website/assets/og_image_mixins.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 319 KiB |
@@ -52,19 +52,27 @@ class ModifyBuild
|
||||
text = fix_titles(text)
|
||||
text = fix_menu(text)
|
||||
text = fix_cover_page(text) if is_cover_page?(filename)
|
||||
text = add_header_banner(text)
|
||||
text = add_home_link_to_menu(text)
|
||||
text = fix_anchor_hyperlinks_menu(text)
|
||||
text = add_favicon(text)
|
||||
text = add_meta_tags(text, filename)
|
||||
text = remove_section_table_of_contents(text)
|
||||
text = mark_menu_as_selected_if_on_page(text, extract_file_from_path(filename))
|
||||
text = add_canonical_for_duplicates(text, extract_file_from_path(filename))
|
||||
text = include_javascript(text)
|
||||
text = add_text_to_coverpage(text, extract_file_from_path(filename))
|
||||
text = fix_js_dependency_link(text)
|
||||
text = fix_list_of_tables_figures_duplicates(text)
|
||||
text = add_anchors_to_headers(text)
|
||||
text = create_menu_groups(text)
|
||||
text = fix_top_links(text)
|
||||
text = fix_flowchart_background(text)
|
||||
text = remove_empty_menu_links(text)
|
||||
text = fix_bottom_cross_links(text)
|
||||
text = insert_mobile_header_graphic(text)
|
||||
text = fix_https_links(text)
|
||||
text = add_anchors_to_glossary_items(text) if is_glossary_page?(filename)
|
||||
text = mark_menu_as_selected_if_on_page(text, extract_file_from_path(filename))
|
||||
text = fix_menus_list_figures_tables(text) if is_list_figures_tables?(filename)
|
||||
text = fix_list_of_figures_tables_display(text) if is_list_figures_tables?(filename)
|
||||
File.open(filename, "w:UTF-8") {|file| file.puts text }
|
||||
@@ -76,6 +84,10 @@ class ModifyBuild
|
||||
end
|
||||
end
|
||||
|
||||
def is_glossary_page?(filename)
|
||||
filename.include?("Glossary.html")
|
||||
end
|
||||
|
||||
def is_list_figures_tables?(filename)
|
||||
["listfigurename.html", "listtablename.html", "listoflocname.html", "bibname.html"].any? do |name|
|
||||
filename.include?(name)
|
||||
@@ -147,6 +159,45 @@ class ModifyBuild
|
||||
doc.to_html
|
||||
end
|
||||
|
||||
def create_menu_groups(text)
|
||||
doc = build_doc(text)
|
||||
groups = build_groups(doc.css(".menu-items > span"))
|
||||
menu_el = doc.css(".menu-items")[0]
|
||||
html = ""
|
||||
groups.each do |group|
|
||||
out = ""
|
||||
group.each do |g|
|
||||
if g.to_html.length > 0
|
||||
out += %Q{<div class="menu-entry">#{g.to_html}</div>}
|
||||
end
|
||||
end
|
||||
html += %Q{<div class="menu-group">
|
||||
<div class="menu-inner">
|
||||
#{out}
|
||||
</div>
|
||||
<img class="menu-arrow" src="arrow.png" />
|
||||
</div>}
|
||||
end
|
||||
menu_el.inner_html = html
|
||||
doc.to_html
|
||||
end
|
||||
|
||||
def build_groups(menu_items)
|
||||
final_groups = []
|
||||
tmp_groups = []
|
||||
menu_items.each_with_index do |el, index|
|
||||
# Get next item and check if it is a lower entry level in the menu.
|
||||
next_item = menu_items[index + 1]
|
||||
if next_item && next_item["class"].include?("chapterToc") || next_item.nil?
|
||||
final_groups.push(tmp_groups.push(el))
|
||||
tmp_groups = []
|
||||
else
|
||||
tmp_groups.push(el)
|
||||
end
|
||||
end
|
||||
final_groups
|
||||
end
|
||||
|
||||
# By default the titles look boring. This changes the titles of all the
|
||||
# pages and adds the book name as appendix
|
||||
def fix_titles(text)
|
||||
@@ -232,7 +283,7 @@ class ModifyBuild
|
||||
content = doc.css("body > .main-content")[0]
|
||||
menu = doc.css("body > nav")[0]
|
||||
content = %Q{
|
||||
<main class="titlepage">
|
||||
<main class="titlepage main-content">
|
||||
<a href="Thehistoryofsourdough.html">
|
||||
<img src="cover-page.jpg" />
|
||||
<div class="version"><p>#{version}</p></div>
|
||||
@@ -252,7 +303,7 @@ class ModifyBuild
|
||||
menu = doc.css(".menu-items")[0]
|
||||
return text if menu.nil?
|
||||
|
||||
home_html = %Q{<span class="chapterToc home-link"><a href="/">The Sourdough Framework</a></span>}
|
||||
home_html = %Q{<span class="chapterToc home-link"><a href="/">🍞 The Sourdough Framework</a></span>}
|
||||
# Normally the flowcharts link should be automatically added, but there
|
||||
# seems to be a problem in the generation. See:
|
||||
# https://github.com/hendricius/the-sourdough-framework/pull/188 for more
|
||||
@@ -263,12 +314,12 @@ class ModifyBuild
|
||||
<span class="link_text">List of Flowcharts</span>
|
||||
</a>
|
||||
</span>
|
||||
<span class="chapterToc">
|
||||
<span class="chapterToc listtables-menu">
|
||||
<a href="listtablename.html">
|
||||
<span class="link_text">List of Tables</span>
|
||||
</a>
|
||||
</span>
|
||||
<span class="chapterToc">
|
||||
<span class="chapterToc listfigures-menu">
|
||||
<a href="listfigurename.html">
|
||||
<span class="link_text">List of Figures</span>
|
||||
</a>
|
||||
@@ -305,7 +356,7 @@ class ModifyBuild
|
||||
<span class="chapterToc">
|
||||
<a href="https://breadco.de/kofi">
|
||||
<span class="chapter_number">⭐️</span>
|
||||
<span class="link_text">Donate</span>
|
||||
<span class="link_text">Support me</span>
|
||||
</a>
|
||||
</span>
|
||||
}
|
||||
@@ -313,6 +364,38 @@ class ModifyBuild
|
||||
doc.to_html
|
||||
end
|
||||
|
||||
# Adds a header banner to each page
|
||||
def add_header_banner(text)
|
||||
doc = build_doc(text)
|
||||
body = doc.css("body")[0]
|
||||
footnotes = doc.css(".footnotes")[0]
|
||||
main = doc.css(".main-content")[0]
|
||||
menu = doc.css(".menu")[0]
|
||||
if main.nil? || menu.nil?
|
||||
#raise ArgumentError.new("Don't know how to handle")
|
||||
return doc.to_html
|
||||
end
|
||||
body.inner_html = %Q{
|
||||
<div class='wrapper'>
|
||||
#{build_header_html}
|
||||
<div class='book-content'>
|
||||
#{menu.to_html}
|
||||
<main class='main-content'>
|
||||
#{main.inner_html}
|
||||
#{footnotes ? footnotes.to_html : ''}
|
||||
</main>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
return doc.to_html
|
||||
end
|
||||
|
||||
def build_header_html
|
||||
%Q{
|
||||
<div class="header"><a href="/"><img src="banner.png"></a></div>
|
||||
}
|
||||
end
|
||||
|
||||
# Some of the menu links are added in the wrong order. Remove them since we
|
||||
# later on add them in the structure that we want.
|
||||
def remove_duplicate_entries_menu(text)
|
||||
@@ -430,13 +513,14 @@ class ModifyBuild
|
||||
"Sourdoughstartertypes.html" => "og_image_sourdough_starter_types.png",
|
||||
"Storingbread.html" => "og_image_storing_bread.png",
|
||||
"Thehistoryofsourdough.html" => "og_image_the_history_of_sourdough.png",
|
||||
"Wheatsourdough.html" => "og_image_troubleshooting.png",
|
||||
"Wheatsourdough.html" => "og_image_wheat_sourdough.png",
|
||||
"Troubleshooting.html" => "og_image_troubleshooting.png",
|
||||
"Mixins.html" => "og_image_mixins.png",
|
||||
}
|
||||
end
|
||||
|
||||
def mark_menu_as_selected_if_on_page(text, filename)
|
||||
doc = build_doc(text)
|
||||
return doc.to_html
|
||||
|
||||
selected = doc.css(".menu-items .chapterToc > a").find do |el|
|
||||
el["href"] == ""
|
||||
@@ -451,7 +535,17 @@ class ModifyBuild
|
||||
# Special case for the flowcharts page which is added by us to the menu.
|
||||
# This needs to be done for future manually added pages too
|
||||
if "listoflocname.html" == filename
|
||||
doc.css(".menu-items .chapterToc.flowcharts-menu")[0].add_class("selected")
|
||||
doc.css(".menu-items .chapterToc.flowcharts-menu")[0].ancestors(".menu-group")[0].add_class("selected")
|
||||
return doc.to_html
|
||||
end
|
||||
|
||||
if "listtablename.html" == filename
|
||||
doc.css(".menu-items .chapterToc.listtables-menu")[0].ancestors(".menu-group")[0].add_class("selected")
|
||||
return doc.to_html
|
||||
end
|
||||
|
||||
if "listfigurename.html" == filename
|
||||
doc.css(".menu-items .chapterToc.listfigures-menu")[0].ancestors(".menu-group")[0].add_class("selected")
|
||||
return doc.to_html
|
||||
end
|
||||
|
||||
@@ -460,7 +554,7 @@ class ModifyBuild
|
||||
# Fix that when the menu is selected the href is empty. This way users can
|
||||
# click the menu and the page will reload.
|
||||
selected["href"] = filename
|
||||
selected.parent.add_class("selected")
|
||||
selected.ancestors(".menu-group")[0].add_class("selected")
|
||||
doc.to_html
|
||||
end
|
||||
|
||||
@@ -491,14 +585,28 @@ class ModifyBuild
|
||||
def add_text_to_coverpage(text, filename)
|
||||
return text unless is_cover_page?(filename)
|
||||
doc = build_doc(text)
|
||||
content = doc.css(".titlepage")[0]
|
||||
raise ArgumentError.new(".titlepage not found in HTML") if content.nil?
|
||||
|
||||
content.add_class("main-content")
|
||||
content = doc.css(".main-content")[0]
|
||||
content.inner_html = "#{build_cover_page_content} #{content.inner_html}"
|
||||
doc.to_html
|
||||
end
|
||||
|
||||
def add_anchors_to_glossary_items(text)
|
||||
doc = build_doc(text)
|
||||
content = doc.css("dt.description")
|
||||
content.each do |el|
|
||||
term = el.css("span")[0]
|
||||
item_name = term&.text
|
||||
# No anchor for whatever reason
|
||||
next unless item_name
|
||||
|
||||
anchor = item_name.downcase.strip.gsub(' ', '-').gsub(/[^\w-]/, '')
|
||||
copy_link = %Q{<a href="#term-#{anchor}" class="permalink">🔗</a>}
|
||||
el.set_attribute("id", "term-#{anchor}")
|
||||
term.inner_html = "#{term.inner_html}#{copy_link}"
|
||||
end
|
||||
doc.to_html
|
||||
end
|
||||
|
||||
def build_cover_page_content
|
||||
%Q{
|
||||
<h2 class="chapterHead home-title">
|
||||
@@ -521,7 +629,9 @@ class ModifyBuild
|
||||
to everyone, I have decided to make it available as a free digital download.
|
||||
</p>
|
||||
|
||||
<img alt="One of my best Sourdough Breads" class="home-bread" src="bread.jpg" />
|
||||
<a href="bread.jpg">
|
||||
<img alt="One of my best Sourdough Breads" class="home-bread" src="bread.jpg" />
|
||||
</a>
|
||||
|
||||
<p class="noindent">
|
||||
However, producing and maintaining resources like this requires
|
||||
@@ -605,13 +715,10 @@ class ModifyBuild
|
||||
# this.
|
||||
def fix_menus_list_figures_tables(text)
|
||||
doc = build_doc(text)
|
||||
content = doc.css(".menu-items > .subsectionToc, .menu-items > .sectionToc")
|
||||
content = doc.css(".menu-group .subsectionToc, .menu-group .sectionToc")
|
||||
content.each do |node|
|
||||
node.remove
|
||||
node.ancestors(".menu-entry")[0].remove
|
||||
end
|
||||
doc.css(".menu-items > .lotToc").each(&:remove)
|
||||
doc.css(".menu-items > .lofToc").each(&:remove)
|
||||
doc.css(".menu-items > br").each(&:remove)
|
||||
doc.to_html
|
||||
end
|
||||
|
||||
@@ -623,7 +730,7 @@ class ModifyBuild
|
||||
doc.to_html
|
||||
end
|
||||
|
||||
# For some reason the depdency is missing a // in the url.
|
||||
# For some reason the dependency is missing a // in the url.
|
||||
def fix_js_dependency_link(text)
|
||||
text.gsub("https:/cdn.jsdelivr.net", "https://cdn.jsdelivr.net")
|
||||
end
|
||||
@@ -651,6 +758,63 @@ class ModifyBuild
|
||||
def fix_https_links(text)
|
||||
text.gsub(/https:\/(?!\/)/, 'https://')
|
||||
end
|
||||
|
||||
def fix_top_links(text)
|
||||
doc = build_doc(text)
|
||||
el = doc.css(".crosslinks-top")[0]
|
||||
el.remove if el
|
||||
doc.to_html
|
||||
end
|
||||
|
||||
def remove_empty_menu_links(text)
|
||||
doc = build_doc(text)
|
||||
menus = doc.css(".menu-group")
|
||||
menus.each do |m|
|
||||
element = m.css("span.chapterToc")[0]
|
||||
next unless element
|
||||
if element.inner_html == "" || element.inner_html == " "
|
||||
m.remove
|
||||
end
|
||||
end
|
||||
doc.to_html
|
||||
end
|
||||
|
||||
def insert_mobile_header_graphic(text)
|
||||
doc = build_doc(text)
|
||||
content = doc.css(".TOC.menu")[0]
|
||||
content.after('<div class="mobile-banner"><a href="/"><img src="banner.png" /></a></div>')
|
||||
doc.to_html
|
||||
end
|
||||
|
||||
def fix_flowchart_background(text)
|
||||
doc = build_doc(text)
|
||||
images = doc.css("img")
|
||||
images.each do |img|
|
||||
src = img.attr("src")
|
||||
is_flowchart = src.include?(".svg")
|
||||
next unless is_flowchart
|
||||
img.parent.add_class("flowchart-image-wrapper")
|
||||
|
||||
end
|
||||
doc.to_html
|
||||
end
|
||||
|
||||
def fix_bottom_cross_links(text)
|
||||
doc = build_doc(text)
|
||||
link_cont = doc.css(".crosslinks-bottom")[0]
|
||||
return doc.to_html unless link_cont
|
||||
|
||||
links = doc.css(".crosslinks-bottom a")
|
||||
prev_link = links.find {|l| l.inner_html == "prev" }
|
||||
next_link = links.find {|l| l.inner_html == "next" }
|
||||
prev_html = prev_link ? "<a class='prev' href='#{prev_link.attr('href')}'>Previous page</a>" : ''
|
||||
next_html = next_link ? "<a class='next' href='#{next_link.attr('href')}'>Next page</a>" : ''
|
||||
link_cont.inner_html = %Q{
|
||||
#{prev_html}
|
||||
#{next_html}
|
||||
}
|
||||
doc.to_html
|
||||
end
|
||||
end
|
||||
|
||||
ModifyBuild.build
|
||||
|
||||
Reference in New Issue
Block a user