[Tex/LaTex] ConTeXt: Wrapped text misbehaves at page breaks

contextcontext-mkivpage-breakingpandocwrap

On this site, a solution for text wrapping based on descriptions in Pandoc-generated ConTeXt documents was previously formulated. Although satisfactory for a one-page minimum working example, the then proposed solution still contains a pair of pitfalls.

One problem is that figure floats with text wrapping near a page break will misbehave as depicted below.

output1

\setuppapersize [A4][A4]
\setuplayout    [width=middle,  backspace=1.5in, cutspace=1.5in,
                 height=middle, topspace=0.75in, bottomspace=0.75in]

\setuppagenumbering[location={footer,center}]

\setuptolerance[horizontal, tolerant, stretch]

\setupexternalfigures [location=default]

% Keep old definitions
\let\oldplacefigure\placefigure
\let\oldexternalfigure\externalfigure

% For full text-width figures
\def\placefigure[#1]#2#3{%
  \def\externalfigure[##1]{\oldexternalfigure[##1][wfactor=fit]}%
  \oldplacefigure[#1]{#2}{#3}%
  \let\externalfigure\oldexternalfigure% Reset for in-line figures
  }

% For figures with wrapped text
\definedescription[description][
  headstyle=bold,
  style=normal,
  location=hanging,
  width=4cm
  ]

\def\startdescription#1{%
  \def\externalfigure[##1]{\oldexternalfigure[##1][width=4cm]}%
  \oldplacefigure[left,high,none]{}{#1}%
  \let\externalfigure\oldexternalfigure% Reset for in-line figures
  }
\def\stopdescription{\endgraf}

\starttext
\input douglas.tex

\input linden.tex

\input linden.tex

\section{Section near page end}

\startdescription{{\externalfigure[cow]}}
  \input linden.tex
\stopdescription

\input bryson.tex

Additional unit tests:

Yeah, but I produce milk! \externalfigure[cow][height=31pt]

\placefigure[here,nonumber]{Large milk cow}{\externalfigure[cow]}
\stoptext

Question

How can this problem be solved without changing anything between \starttext and \stoptext? (Remember, the whole idea is about fully automated document generation starting from Pandoc MarkDown.)

As an absolute ConTeXt-novice, I would think that perhaps something with penalties would be possible or I would hope for similar functionality as offered by the needspace LaTeX package.

Edit

I also tried the relatively new \starthanging[left]{#1} environment, with and without the [n=...] argument (the latter in the assumption that an image height could be measured in text line units). The results using \starthanging are equally unsatisfactory (see below);

  • The cow image is placed partly in the bottom margin,
  • The text continues being wrapped on the next page, and
  • (Not shown) When the wrapped text is short, the next paragraph will not be wrapped and overlap with the image.

Hence, a solution using \placefigure as outlined earlier looks more promising.

output3

Best Answer

Here is a solution that checks if the figure will fit on a page; if not, it inserts a pagebreak. Note that this will result in ugly page breaks (but then the only way to avoid this is to rewrite the text). While I was at it, I also removed the overwrite of in-built ConTeXt macros and used the available hooks to change the figure dimensions.

\setuppapersize [A4][A4]
\setuplayout    [width=middle,  backspace=1.5in, cutspace=1.5in,
                 height=middle, topspace=0.75in, bottomspace=0.75in]

\setuppagenumbering[location={footer,center}]

\setuptolerance[horizontal, tolerant, stretch]

% Set inter-paragraph spacing
%\setupwhitespace[medium]% TOGGLE ON/OFF

\setupexternalfigures [location=default]

\startsetups placefigure
  \setupexternalfigure
    [wfactor=fit]
\stopsetups

% Floats do no have a before or a setup key
\appendtoks \setups{placefigure} \to \everyinsidefloat

\definemeasure[pageheight][\dimexpr(\pagegoal-\pagetotal-2\lineheight)]

\define[1]\startdescription
  {%\everyinsidefloat\emptytoks
   \setbox\scratchbox\vbox{\setupexternalfigure[width=4cm]#1}%
   \ifdim\ht\scratchbox>\dimexpr\measure{pageheight}\relax
      \page
   \fi
   \startplacefigure[location={left,high,none}]
     \box\scratchbox
   \stopplacefigure}

\define\stopdescription{\endgraf}

\starttext
\input douglas.tex

\input linden.tex

\input linden.tex

\section{Section near page end}

\startdescription{{\externalfigure[cow]}}
  \input linden.tex
\stopdescription

\input bryson.tex

Additional unit tests:

Yeah, but I produce milk! \externalfigure[cow][height=31pt]

\placefigure[here,nonumber]{Large milk cow}{\externalfigure[cow]}
\stoptext

enter image description here

Related Question