3

I'm trying to create a recipe summary table like the one at the bottom of this page using latex. My eventual goal is to be able to take my recipe collection written in cooklang and display them as these diagrams using a python script, but I'm stuck on making the initial diagram in latex.

These answers are the closest I could find during my research, but neither show a way to turn recipe structure into a diagram. There might also be some other issue I'm overlooking, since the author of the site formats the recipe summaries manually.

I'm pretty new to latex, hopefully I'm missing something obvious, but I don't see a way to describe the structure I want, as opposed to manually formatting the output. I got a lot of the way there using the struktex, since the cookingforengineers.com diagram looks a lot like a Nassi-Shneiderman diagram, but I'm still not happy with the output.

Minimum Working Example:

\documentclass{article}
\usepackage{struktex}
\begin{document}
\begin{struktogramm}(100,50)

\assign{Cool and Cut}
\ifthenelse[20]{1}{1}{350°F for 20 min}{Crust}{Filling}
    \sub{350°F for 20 min}
    \sub{refrigerate for 30 min.}
    \sub{line 9x13" pan}
        \ifthenelse[10]{1}{1}{Process}{}{}
            \ifthenelse[10]{1}{1}{Mix}{}{}
            \change
            \ifend
            \assign{Flour}
            \assign{Sugar}
            \assign{Cornstarch}
            \assign{Salt}
        \change
            \assign{Butter}
        \ifend
\change
    \ifthenelse[30]{1}{1}{Mix}{}{}
        \assign{Lemon Zest}
        \assign{Lemon Juice}
        \assign{Whole Milk}
    \change
        \ifthenelse[10]{1}{1}{Whisk}{}{}
            \assign{Eggs}
            \assign{Sugar}
        \change
            \assign{Flour}
            \assign{Salt}       
        \ifend          
    \ifend
\ifend 
\end{struktogramm}
\end{document}

What I want:

  1. Tabular flowchart layout
  2. Gives recipe structure at a glance
  3. Diagram layout follows recipe order (i.e. ingredients first)

I've sort of solved 1 and 2 with the above code, but I'm not sure how to get 3. I suspect I'll need to abandon the struktex package altogether, but I haven't found a better way to get the layout I want without resorting to manual formatting.

Why my example doesn't fit my needs:

  1. Diagram layout is opposite to recipe order
  2. Differences in recipe component lengths leave gaps (like under "butter" and "whole milk")
  3. Vertical layout limits ingredient lengths for reasonable page widths

1 Answer 1

3

Greetings and welcome to tex.stackexchange!

I, too, have been looking at Michael Chu's tabular recipe notation format for quite some time. It seems an interesting way of revealing aspects of a recipe's structure. It is of note that Mr. Chu has elected to attempt to patent the format (though the note “patent pending” has been on his web site for over 15 years): I cannot locate the application so I have no idea what novel and non-obvious process (the United States Patent and Trademark Office's characterization, in part, of a patent) would be covered by the patent. According to Mr. Chu, he codes the original in HTML and then finalizes the result in Illustrator.

From the first, I felt that TeX could do the job, and so it can with some help from TikZ. The following code does reasonably well to suit my purposes. I have commented the code (which is verbose, I admit) reasonably well.

\documentclass[border=5mm]{standalone}

\usepackage{fontspec,xcolor,tikz,xparse,keyval}
\usetikzlibrary{calc,positioning,backgrounds}

\newcounter{stepB}
\newlength{\stagewd}
\newlength{\columnoffset}
\newcounter{stage}
\newcounter{ingnum}
\newcounter{ingnumtmp}
\newif\ifshownums

%% color defaults:
\colorlet{titlefill}{orange!30}
\colorlet{ingredfill}{yellow!80!red!20}
\colorlet{taskfill}{cyan!20}
\colorlet{stagebackground}{gray!80!red!20}

\makeatletter %% keyval
\define@key{engin}{shownums}[true]{\csname shownums#1\endcsname}
\define@key{engin}{titlefill}{\colorlet{titlefill}{#1}}
\define@key{engin}{ingredfill}{\colorlet{ingredfill}{#1}}
\define@key{engin}{taskfill}{\colorlet{taskfill}{#1}}
\define@key{engin}{stagebackground}{\colorlet{stagebackground}{#1}}
\makeatother

%% Dissect ingredient listing
\NewDocumentCommand{\ingredlist}{ >{\SplitList{;}}m }{\par\ProcessList{#1}{\fooaux}}
\NewDocumentCommand{\fooaux}{m} {\fooauxa{#1}}
\NewDocumentCommand{\fooauxa}{m}{% Format ingredients, each in its own node
    \stepcounter{ingnum}
    \stepcounter{ingnumtmp}
    \ifnum \theingnumtmp=0 % nodes containing indidual ingredients, first ingredient
        \node[boxy] (A1) {\strut#1\strut};
    \else % next ingredients
        \node[boxy,below = 0pt of A\theingnumtmp] (A\theingnum) {\strut#1\strut};
    \fi
    \ifshownums % show ingredient numbers.
        \node[left,anchor=south east] at (A\theingnum.south east) {\tiny I-\theingnum};% 
    \fi
}

\NewDocumentEnvironment{recipe}{ O{} m m }{% #1 Ingredients, csv; #2 optional title
    \setlength{\stagewd}{0in}%
    \setlength{\columnoffset}{0pt}%
    \setcounter{ingnum}{0}%
    \setcounter{ingnumtmp}{-1}%
    \setkeys{engin}{#1}%
    \noindent
    \begin{tikzpicture}[node distance=0pt]
        \tikzset{boxy/.style={draw,text width=1.35in,outer sep=0pt,
            fill=ingredfill,font=\bfseries\hangindent1.25em}}%
        \ingredlist{#3}%
        % tasks and stages follow
}{% finish up and decorate
        \ifnum\thestage=0 % avoid error if no stages, just listing ingredients
        \else
            \draw[ultra thick,purple] (A1.north east) -- (A\theingnum.south east);
            \ifnum\thestage=1 % Avoid error if only one stage
            \else
                \foreach \nn in {2,...,\thestage} {\draw[very thick] (A1.north -| S\nn) --
                    (S\nn |- A\theingnum.south);}
            \fi
            \ifshownums % show stage designation
                \foreach\nnn in {1,...,\thestage}
                    \node[font=\bfseries\tiny,inner sep=0pt,below right =1pt and 1.5pt of S\nnn]
                        {\romannumeral\nnn};% stages marked with Alpha
            \fi
            \draw[ultra thick,fill=titlefill]% Title
                (A1.north west) rectangle node[font=\huge\bfseries]{\itshape#2}
                ($(B\thestepB |- S1) + (0,2.5*\baselineskip)$);
            \begin{scope}[on background layer]% tasks background
                \fill[stagebackground] (S1) rectangle (A\theingnum.south west -| B\thestepB);
                \foreach \ni in {1,...,\theingnum} \draw (A\ni.south west) --
                    (A\ni.south -| S\thestage);
            \end{scope}
            \draw[ultra thick] (A1.north west) rectangle
                (A\theingnum.south west -| B\thestepB);
        \fi
    \end{tikzpicture}%
}

%%  1[width, for new column -- use \stagewd to repeat or alter]; 2start; 3end;4 text; *note
%%  Note that the  fourth argument is delimited by `;' which has nothing to do with TikZ
\NewDocumentCommand{\tk}{o u{ } u{ } u{;} s}{%
    \IfBooleanF{#5}{\stepcounter{stepB}}%
    \IfNoValueF{#1}{%There is a column width specified
        \stepcounter{stage}%
        \setlength{\columnoffset}{\dimexpr\columnoffset + \stagewd\relax}%
        \setlength{\stagewd}{\dimexpr#1\relax}% Timing! Argument can be expression
        \coordinate (S\thestage) at ($(A1.north east) + (\columnoffset,0)$);% Stage 
        \coordinate (SH\thestage) at ($(A1.north east) + (\columnoffset+\stagewd/2,0)$);% Stage mid
    }%
    \draw[fill=taskfill] (S\thestage |- A#2.north east)% UL
        rectangle node[text width = \stagewd-6pt,align=center]% node
            {\IfBooleanT{#5}{\itshape\bfseries\color{red}}\strut#4\strut} % content
        ($(S\thestage |- A#3.south east) + (\stagewd,0in)$) coordinate (B\thestepB); % LR
    \IfBooleanF{#5}{\ifshownums\node[font=\tiny,above left=0pt and 0pt of B\thestepB]
        {\thestepB};\fi}%
}

\setmainfont{STIX Two Text}

\begin{document}

% On the left, are the ingredients in the order used. On the right, the method
% is divided into columns, each a *stage* in the process; each stage (column) contains tasks.

% The recipe environment takes three arguments:
%   #1 Optional keyval choices:
        % <shownums> or <shownums=true> shows ingredient, stage and task numbers
        %   omitting <shownums> or <shownums=false> hides the numbers
        % Background colors for the title, stages and tasks can be assigned using
        %   <titlefill>, <ingredfill>, <taskfill>, and <stagebackground>
%   #2 Title
%   #3 A comma-separated list of ingredients; a textual comma has to be enclosed in braces {}

% A good starting point would be to initiate the recipe environment with only
% the ingredients, using [shownums]. This will show the ingredient row numbers
% making it easier to indicate the tasks.

% The \tk macro is used for the stages and tasks
%   An optional argument to \tk (eg [1in]) initiates a new stage column
%   and specifies the width of the current stage column.
%   Manner of use: \tk[<dimen>]<from row> <to row> <ingredient>,
%%      -->>[...] starts new column -- can contain expression; use \stagewd only after first stage 
%   or: \tk <from row> <to row> <ingredient>, -->>continues with task in stage column

% Optional argument to recipe is for keyval


\thispagestyle{empty}

\centering

\begin{recipe}[shownums,stagebackground=red!10]{Toll House Cookies}{%
    %% the ingredients, ;-separated
    1 cup  butter;
    ¾ cup  granulated sugar;
    ¾ cup  brown sugar;
    1 tsp.  vanilla;
    2 large  eggs;
    2¾ cup  flour;
    1 tsp  baking soda;
    ½ tsp.  salt;
    2 cups  chocolate chips;
    1 cup  nuts, chopped}
    %% |=====8><-----| %% the method
    \tk[1in]1 1 Soften;
    \tk 5 5 Room temp.;*
    \tk  6 8 Combine;
    \tk[\stagewd-0.25in]1 4 Beat until smooth;
    \tk[1in]1 5 Beat in one egg  at a time;
    \tk[1in]1 8 Gradually beat in flour mixture;
    \tk[1in]1 10 Form into $\approx$1-inch balls and place on baking sheet;
    \tk[1in]1 10 Bake at 375°F for 10 minutes;
\end{recipe}

\end{document}

TNR

The same with shownums=false:

TRN shownums=false

2
  • This is exactly what I've been looking for! I spent most of yesterday wrestling with this python library which seemed interesting: github.com/mossblaser/recipe_grid , but I ran into several issues, there was no line breaking and no way to control the colors in a cell. Your solution fixes both of these. It'll take me a while to be able to understand all that TeX, I think I have a new summer project! Jun 28, 2022 at 3:03
  • 1
    Glad you may find this useful. Have taken a look at recipe_grid and learned a few things. I've thought of some additions to the TeX code here -- nothing crucial, just a few enhancements. Stay tuned. So as to avoid any risk of ambiguity, I'm referring to my code as 'recipe lattice format'.
    – sgmoye
    Jun 28, 2022 at 12:12

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .